forked from molgenis/molgenis
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request molgenis#7732 from tommydeboer/feature/icd10-decor…
…ator Add ICD-10 Expander Decorator
- Loading branch information
Showing
12 changed files
with
701 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.molgenis</groupId> | ||
<artifactId>molgenis</artifactId> | ||
<version>7.1.0-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>molgenis-data-icd10</artifactId> | ||
|
||
<name>data-icd10</name> | ||
<description>ICD-10 related functionality</description> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>test-jar</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.molgenis</groupId> | ||
<artifactId>molgenis-data</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<!-- third party dependencies --> | ||
<dependency> | ||
<groupId>org.springframework</groupId> | ||
<artifactId>spring-context-support</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.code.findbugs</groupId> | ||
<artifactId>findbugs-annotations</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
<!-- test dependencies --> | ||
<dependency> | ||
<groupId>org.molgenis</groupId> | ||
<artifactId>molgenis-test</artifactId> | ||
<version>${project.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
18 changes: 18 additions & 0 deletions
18
molgenis-data-icd10/src/main/java/org/molgenis/data/icd10/CollectionsQueryTransformer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.molgenis.data.icd10; | ||
|
||
import org.molgenis.data.Entity; | ||
import org.molgenis.data.Query; | ||
|
||
/** | ||
* Transforms a query on an attribute that refers to a ICD-10 repository | ||
*/ | ||
public interface CollectionsQueryTransformer | ||
{ | ||
/** | ||
* @param query the query to transform | ||
* @param icd10EntityTypeId the EntityType that contains the ICD-10 identifiers | ||
* @param expandAttribute the attribute on which to apply the query transformation | ||
* @return a query containing expanded ICD-10 codes | ||
*/ | ||
Query<Entity> transformQuery(Query<Entity> query, String icd10EntityTypeId, String expandAttribute); | ||
} |
86 changes: 86 additions & 0 deletions
86
...nis-data-icd10/src/main/java/org/molgenis/data/icd10/CollectionsQueryTransformerImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.molgenis.data.icd10; | ||
|
||
import com.google.common.collect.TreeTraverser; | ||
import org.molgenis.data.DataService; | ||
import org.molgenis.data.Entity; | ||
import org.molgenis.data.Query; | ||
import org.molgenis.data.QueryRule; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
import static java.util.Collections.singletonList; | ||
import static java.util.Objects.requireNonNull; | ||
import static java.util.stream.Collectors.toList; | ||
|
||
@Component | ||
public class CollectionsQueryTransformerImpl implements CollectionsQueryTransformer | ||
{ | ||
private static final TreeTraverser<QueryRule> RULE_TRAVERSER = TreeTraverser.using(QueryRule::getNestedRules); | ||
|
||
private final Icd10ClassExpander icd10ClassExpander; | ||
private final DataService dataService; | ||
|
||
CollectionsQueryTransformerImpl(Icd10ClassExpander icd10ClassExpander, DataService dataService) | ||
{ | ||
this.icd10ClassExpander = requireNonNull(icd10ClassExpander); | ||
this.dataService = requireNonNull(dataService); | ||
} | ||
|
||
@Override | ||
public Query<Entity> transformQuery(Query<Entity> query, String icd10EntityTypeId, String expandAttribute) | ||
{ | ||
if (query != null && query.getRules() != null && !query.getRules().isEmpty()) | ||
{ | ||
query.getRules() | ||
.forEach(rule -> RULE_TRAVERSER.preOrderTraversal(rule) | ||
.filter(nestedRule -> isTransformableRule(nestedRule, expandAttribute)) | ||
.forEach(nestedRule -> transformQueryRule(nestedRule, | ||
icd10EntityTypeId))); | ||
} | ||
|
||
return query; | ||
} | ||
|
||
private void transformQueryRule(QueryRule rule, String icd10EntityTypeId) | ||
{ | ||
List<Object> queryValues; | ||
|
||
switch (rule.getOperator()) | ||
{ | ||
case EQUALS: | ||
queryValues = singletonList(rule.getValue()); | ||
rule.setOperator(QueryRule.Operator.IN); | ||
break; | ||
case IN: | ||
//noinspection unchecked | ||
queryValues = (List<Object>) rule.getValue(); | ||
break; | ||
default: | ||
throw new IllegalStateException("Can't expand queries other than IN or EQUALS"); | ||
} | ||
|
||
List<Entity> diseaseTypes = dataService.findAll(icd10EntityTypeId, queryValues.stream()).collect(toList()); | ||
|
||
rule.setValue(expandDiseaseTypes(diseaseTypes)); | ||
} | ||
|
||
/** | ||
* Returns <code>true</code> if a rule is 'IN' or 'EQUALS' on the attribute that should be expanded | ||
*/ | ||
private boolean isTransformableRule(QueryRule nestedRule, String expandAttribute) | ||
{ | ||
return nestedRule != null && nestedRule.getField() != null && nestedRule.getField().equals(expandAttribute) && ( | ||
nestedRule.getOperator() == QueryRule.Operator.IN | ||
|| nestedRule.getOperator() == QueryRule.Operator.EQUALS); | ||
} | ||
|
||
/** | ||
* Expand ICD-10 entities with all their children, grandchildren, etc. | ||
*/ | ||
private Collection<Entity> expandDiseaseTypes(List<Entity> diseaseTypes) | ||
{ | ||
return icd10ClassExpander.expandClasses(diseaseTypes); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
molgenis-data-icd10/src/main/java/org/molgenis/data/icd10/Icd10ClassExpander.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.molgenis.data.icd10; | ||
|
||
import org.molgenis.data.Entity; | ||
|
||
import java.util.Collection; | ||
|
||
/** | ||
* Expands a list of 'eu_bbmri_eric_disease_types' entities to include all of their children. | ||
*/ | ||
public interface Icd10ClassExpander | ||
{ | ||
Collection<Entity> expandClasses(Collection<Entity> diseaseClasses); | ||
} |
89 changes: 89 additions & 0 deletions
89
molgenis-data-icd10/src/main/java/org/molgenis/data/icd10/Icd10ClassExpanderImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package org.molgenis.data.icd10; | ||
|
||
import com.google.common.collect.TreeTraverser; | ||
import org.molgenis.data.Entity; | ||
import org.springframework.stereotype.Component; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.util.Collection; | ||
import java.util.stream.Stream; | ||
import java.util.stream.StreamSupport; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
@Component | ||
public class Icd10ClassExpanderImpl implements Icd10ClassExpander | ||
{ | ||
private static final String DISEASE_CLASS_CHILDREN_ATTRIBUTE_NAME = "children"; | ||
|
||
@Override | ||
public Collection<Entity> expandClasses(Collection<Entity> diseaseClasses) | ||
{ | ||
return diseaseClasses.stream() | ||
.flatMap(this::expandClass) | ||
.map(this::toDiseaseClass) | ||
.distinct() | ||
.map(this::toEntity) | ||
.collect(toList()); | ||
} | ||
|
||
private Stream<Entity> expandClass(Entity diseaseClass) | ||
{ | ||
Iterable<Entity> diseaseClasses = new DiseaseClassTreeTraverser().postOrderTraversal(diseaseClass); | ||
return StreamSupport.stream(diseaseClasses.spliterator(), false); | ||
} | ||
|
||
private DiseaseClass toDiseaseClass(Entity entity) | ||
{ | ||
return new DiseaseClass(entity); | ||
} | ||
|
||
private Entity toEntity(DiseaseClass diseaseClass) | ||
{ | ||
return diseaseClass.getEntity(); | ||
} | ||
|
||
/** | ||
* Disease class entity wrapper with equals and hashCode implementation. | ||
*/ | ||
private static class DiseaseClass | ||
{ | ||
private final Entity entity; | ||
|
||
private DiseaseClass(Entity entity) | ||
{ | ||
this.entity = entity; | ||
} | ||
|
||
private Entity getEntity() | ||
{ | ||
return entity; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) | ||
{ | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
|
||
DiseaseClass that = (DiseaseClass) o; | ||
|
||
return entity.getIdValue().equals(that.entity.getIdValue()); | ||
} | ||
|
||
@Override | ||
public int hashCode() | ||
{ | ||
return entity.getIdValue().hashCode(); | ||
} | ||
} | ||
|
||
private static class DiseaseClassTreeTraverser extends TreeTraverser<Entity> | ||
{ | ||
@Override | ||
public Iterable<Entity> children(@Nonnull Entity diseaseClassEntity) | ||
{ | ||
return diseaseClassEntity.getEntities(DISEASE_CLASS_CHILDREN_ATTRIBUTE_NAME); | ||
} | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
molgenis-data-icd10/src/main/java/org/molgenis/data/icd10/Icd10ExpanderDecorator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.molgenis.data.icd10; | ||
|
||
import org.molgenis.data.AbstractRepositoryDecorator; | ||
import org.molgenis.data.Entity; | ||
import org.molgenis.data.Query; | ||
import org.molgenis.data.Repository; | ||
import org.molgenis.data.aggregation.AggregateQuery; | ||
import org.molgenis.data.aggregation.AggregateResult; | ||
import org.molgenis.data.support.AggregateQueryImpl; | ||
|
||
import java.util.stream.Stream; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
class Icd10ExpanderDecorator extends AbstractRepositoryDecorator<Entity> | ||
{ | ||
private final CollectionsQueryTransformer queryTransformer; | ||
private final String icd10EntityTypeId; | ||
private final String expandAttribute; | ||
|
||
Icd10ExpanderDecorator(Repository<Entity> delegateRepository, CollectionsQueryTransformer queryTransformer, | ||
String icd10EntityTypeId, String expandAttribute) | ||
{ | ||
super(delegateRepository); | ||
this.queryTransformer = requireNonNull(queryTransformer); | ||
this.icd10EntityTypeId = requireNonNull(icd10EntityTypeId); | ||
this.expandAttribute = requireNonNull(expandAttribute); | ||
} | ||
|
||
@Override | ||
public long count(Query<Entity> query) | ||
{ | ||
query = query != null ? transformQuery(query) : null; | ||
return delegate().count(query); | ||
} | ||
|
||
@Override | ||
public Entity findOne(Query<Entity> query) | ||
{ | ||
query = query != null ? transformQuery(query) : null; | ||
return delegate().findOne(query); | ||
} | ||
|
||
@Override | ||
public Stream<Entity> findAll(Query<Entity> query) | ||
{ | ||
query = query != null ? transformQuery(query) : null; | ||
return delegate().findAll(query); | ||
} | ||
|
||
@Override | ||
public AggregateResult aggregate(AggregateQuery aggregateQuery) | ||
{ | ||
Query<Entity> q = aggregateQuery.getQuery(); | ||
Query<Entity> transformedQuery = q != null ? transformQuery(q) : null; | ||
aggregateQuery = new AggregateQueryImpl(aggregateQuery.getAttributeX(), aggregateQuery.getAttributeY(), | ||
aggregateQuery.getAttributeDistinct(), transformedQuery); | ||
return delegate().aggregate(aggregateQuery); | ||
} | ||
|
||
private Query<Entity> transformQuery(Query<Entity> query) | ||
{ | ||
return queryTransformer.transformQuery(query, icd10EntityTypeId, expandAttribute); | ||
} | ||
} |
Oops, something went wrong.