Skip to content

Commit

Permalink
Update Mapping Tree
Browse files Browse the repository at this point in the history
Fixes: #191
  • Loading branch information
bastianschaffer committed Sep 2, 2024
1 parent feee53e commit 122b70e
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 336 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.mvn
.idea/
cache
target
/ontology/mapping.zip
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<properties>
<java.version>17</java.version>
<testcontainers.version>1.19.8</testcontainers.version>
<ontology.version>2.2.0</ontology.version>
<ontology.version>3.0.0-test.1</ontology.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -206,9 +206,10 @@
<goal>wget</goal>
</goals>
<configuration>
<url>https://github.com/medizininformatik-initiative/fhir-ontology-generator/raw/v${ontology.version}/example/mii_core_data_set/ontology/mapping.zip</url>
<url>https://github.com/medizininformatik-initiative/fhir-ontology-generator/raw/v${ontology.version}/example/fdpg-ontology/mapping.zip</url>
<outputFileName>mapping.zip</outputFileName>
<outputDirectory>ontology/</outputDirectory>
<skipCache>true</skipCache>
</configuration>
</execution>
</executions>
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/de/medizininformatikinitiative/flare/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import de.medizininformatikinitiative.flare.model.mapping.Mapping;
import de.medizininformatikinitiative.flare.model.mapping.MappingContext;
import de.medizininformatikinitiative.flare.model.mapping.TermCodeNode;
import de.medizininformatikinitiative.flare.model.mapping.MappingTreeBase;
import de.medizininformatikinitiative.flare.model.mapping.MappingTreeModuleRoot;
import de.medizininformatikinitiative.flare.model.sq.ContextualTermCode;

import java.io.BufferedInputStream;
Expand Down Expand Up @@ -79,11 +80,11 @@ static double durationSecondsSince(long startNanoTime) {
static MappingContext flareMappingContext(Clock clock) throws Exception {
var mapper = new ObjectMapper();
String ontologyZipFile = "ontology/mapping.zip";
String mappingFile = "ontology/mapping/mapping_fhir.json";
String conceptTreeFile = "ontology/mapping/mapping_tree.json";
String mappingFile = "mapping/fhir/mapping_fhir.json";
String conceptTreeFile = "mapping/mapping_tree.json";

Map<ContextualTermCode, Mapping> mappings = null;
TermCodeNode conceptTree = null;
MappingTreeBase conceptTree = null;

try (FileInputStream fis = new FileInputStream(ontologyZipFile);
BufferedInputStream bis = new BufferedInputStream(fis);
Expand All @@ -94,8 +95,8 @@ static MappingContext flareMappingContext(Clock clock) throws Exception {
mappings = Arrays.stream(mapper.readValue(readZipEntryContent(zis), Mapping[].class))
.collect(Collectors.toMap(Mapping::key, identity()));
} else if (ze.getName().equals(conceptTreeFile)) {
String treeString = readZipEntryContent(zis);
conceptTree = mapper.readValue(treeString, TermCodeNode.class);
conceptTree = new MappingTreeBase(
Arrays.stream(mapper.readValue(readZipEntryContent(zis), MappingTreeModuleRoot[].class)).toList());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
public class MappingContext {

private final Map<ContextualTermCode, Mapping> mappings;
private final TermCodeNode conceptTree;
private final MappingTreeBase conceptTree;
private final Clock clock;

private MappingContext(Map<ContextualTermCode, Mapping> mappings, TermCodeNode conceptTree, Clock clock) {
private MappingContext(Map<ContextualTermCode, Mapping> mappings, MappingTreeBase conceptTree, Clock clock) {
this.mappings = Map.copyOf(mappings);
this.conceptTree = requireNonNull(conceptTree);
this.clock = requireNonNull(clock);
Expand All @@ -37,7 +37,7 @@ private MappingContext(Map<ContextualTermCode, Mapping> mappings, TermCodeNode c
* @param conceptTree a tree of concepts to expand (can be null)
* @return the mapping context
*/
public static MappingContext of(Map<ContextualTermCode, Mapping> mappings, TermCodeNode conceptTree) {
public static MappingContext of(Map<ContextualTermCode, Mapping> mappings, MappingTreeBase conceptTree) {
return new MappingContext(mappings, conceptTree, Clock.systemDefaultZone());
}

Expand All @@ -49,7 +49,7 @@ public static MappingContext of(Map<ContextualTermCode, Mapping> mappings, TermC
* @param clock a clock that is used for time-related calculations
* @return the mapping context
*/
public static MappingContext of(Map<ContextualTermCode, Mapping> mappings, TermCodeNode conceptTree, Clock clock) {
public static MappingContext of(Map<ContextualTermCode, Mapping> mappings, MappingTreeBase conceptTree, Clock clock) {
return new MappingContext(mappings, conceptTree, clock);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.medizininformatikinitiative.flare.model.mapping;

import de.medizininformatikinitiative.flare.model.sq.ContextualTermCode;

import java.util.List;
import java.util.stream.Stream;

public record MappingTreeBase(List<MappingTreeModuleRoot> moduleRoots) {

public Stream<ContextualTermCode> expand(ContextualTermCode termCode) {
var key = termCode.termCode().code();

return moduleRoots.stream().flatMap(moduleRoot ->
isModuleMatching(termCode, moduleRoot) ? moduleRoot.expand(key) : Stream.empty());
}

private boolean isModuleMatching(ContextualTermCode termCode, MappingTreeModuleRoot moduleRoot) {
return termCode.context().equals(moduleRoot.context()) &&
moduleRoot.system().equals(termCode.termCode().system()) &&
moduleRoot.entries().containsKey(termCode.termCode().code());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package de.medizininformatikinitiative.flare.model.mapping;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
record MappingTreeModuleEntry(String key, List<String> children) {
@JsonCreator
static MappingTreeModuleEntry fromJson(@JsonProperty("key") String key,
@JsonProperty("children") List<String> children) {
return new MappingTreeModuleEntry(key, children);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.medizininformatikinitiative.flare.model.mapping;


import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.medizininformatikinitiative.flare.model.sq.ContextualTermCode;
import de.medizininformatikinitiative.flare.model.sq.TermCode;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.function.Function.identity;

@JsonIgnoreProperties(ignoreUnknown = true)
public record MappingTreeModuleRoot(TermCode context, String system, Map<String, MappingTreeModuleEntry> entries) {
@JsonCreator
static MappingTreeModuleRoot fromJson(@JsonProperty("context") TermCode context,
@JsonProperty("system") String system,
@JsonProperty("entries") List<MappingTreeModuleEntry> entries) {
return new MappingTreeModuleRoot(
context,
system,
entries.stream().collect(Collectors.toMap(MappingTreeModuleEntry::key, identity())));
}

public Stream<ContextualTermCode> expand(String key) {
var newTermCode = new ContextualTermCode(context, new TermCode(system, key, ""));

return Stream.concat(Stream.of(newTermCode), entries.get(key).children().stream().flatMap(this::expand));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Set;

import static de.medizininformatikinitiative.flare.model.translate.Operator.Name.UNION;
import static java.util.Objects.requireNonNull;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import de.medizininformatikinitiative.flare.model.sq.TermCode;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;

import static de.medizininformatikinitiative.flare.Assertions.assertThat;
Expand All @@ -13,36 +14,45 @@
class MappingContextTest {

static final TermCode CONTEXT = TermCode.of("context", "context", "context");
static final String SYSTEM = "sys";
static final ContextualTermCode ROOT = ContextualTermCode.of(CONTEXT, TermCode.of("root", "root", "root"));
static final ContextualTermCode C1 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c1", "c1"));
static final ContextualTermCode C11 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c11", "c11"));
static final ContextualTermCode C12 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c12", "c12"));
static final String C1 = "c1";
static final String C2 = "c2";

private ContextualTermCode contextualTermCodeOf(String code) {
return new ContextualTermCode(MappingContextTest.CONTEXT, new TermCode(MappingContextTest.SYSTEM, code, "display"));
}

@Test
void expandConcept_ConceptNotExpandable() {
var context = MappingContext.of(Map.of(), TermCodeNode.createNormal(ROOT));
var context = MappingContext.of(Map.of(), new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT, SYSTEM, Map.of()))));

var result = context.expandConcept(ContextualConcept.of(C1));
var result = context.expandConcept(ContextualConcept.of(contextualTermCodeOf(C1)));

assertThat(result).isLeftInstanceOf(ContextualConceptNotExpandableException.class);
}

@Test
void expandConcept_OneConcept() {
var context = MappingContext.of(Map.of(), TermCodeNode.createNormal(ROOT, TermCodeNode.createNormal(C1)));
var context = MappingContext.of(Map.of(), new MappingTreeBase(List.of(
new MappingTreeModuleRoot(CONTEXT, SYSTEM, Map.of(C1, new MappingTreeModuleEntry(C1, List.of()))))));

var result = context.expandConcept(ContextualConcept.of(C1));
var result = context.expandConcept(ContextualConcept.of(contextualTermCodeOf(C1)));

assertThat(result).isRightSatisfying(r -> assertThat(r).containsExactly(C1));
assertThat(result).isRightSatisfying(r -> assertThat(r).containsExactly(contextualTermCodeOf(C1)));
}

@Test
void expandConcept_TwoConcepts() {
var context = MappingContext.of(Map.of(), TermCodeNode.createAbstract(C1, TermCodeNode.createNormal(C11),
TermCodeNode.createNormal(C12)));
var context = MappingContext.of(Map.of(), new MappingTreeBase(List.of(
new MappingTreeModuleRoot(CONTEXT, SYSTEM, Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2)),
C2, new MappingTreeModuleEntry(C2, List.of()))))));

var result = context.expandConcept(ContextualConcept.of(C1));
var result = context.expandConcept(ContextualConcept.of(contextualTermCodeOf(C1)));

assertThat(result).isRightSatisfying(r -> assertThat(r).containsExactly(C11, C12));
assertThat(result).isRightSatisfying(r -> {
assertThat(r.get(0)).isEqualTo(contextualTermCodeOf(C1));
assertThat(r.get(1)).isEqualTo(contextualTermCodeOf(C2));
});
}
}
Loading

0 comments on commit 122b70e

Please sign in to comment.