diff --git a/pom.xml b/pom.xml
index c8b12a0..676259d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
7.2.1
1.20.0
2.0.13
- 2.2.0
+ 3.0.0-test.1
@@ -177,7 +177,7 @@
download-single
- https://github.com/medizininformatik-initiative/fhir-ontology-generator/raw/v${ontology.version}/example/mii_core_data_set/ontology/mapping.zip
+ https://github.com/medizininformatik-initiative/fhir-ontology-generator/raw/v${ontology.version}/example/fdpg-ontology/mapping.zip
${project.build.directory}
diff --git a/src/main/java/de/numcodex/sq2cql/model/MappingContext.java b/src/main/java/de/numcodex/sq2cql/model/MappingContext.java
index 8c328c2..f42576e 100644
--- a/src/main/java/de/numcodex/sq2cql/model/MappingContext.java
+++ b/src/main/java/de/numcodex/sq2cql/model/MappingContext.java
@@ -21,10 +21,10 @@
public class MappingContext {
private final Map mappings;
- private final TermCodeNode conceptTree;
+ private final MappingTreeBase conceptTree;
private final Map codeSystemDefinitions;
- private MappingContext(Map mappings, TermCodeNode conceptTree,
+ private MappingContext(Map mappings, MappingTreeBase conceptTree,
Map codeSystemDefinitions) {
this.mappings = mappings;
this.conceptTree = conceptTree;
@@ -48,7 +48,7 @@ public static MappingContext of() {
* @param codeSystemAliases a map of code system URLs to their aliases
* @return the mapping context
*/
- public static MappingContext of(Map mappings, TermCodeNode conceptTree,
+ public static MappingContext of(Map mappings, MappingTreeBase conceptTree,
Map codeSystemAliases) {
return new MappingContext(Map.copyOf(mappings), conceptTree, codeSystemAliases.entrySet().stream()
.collect(Collectors.toConcurrentMap(Map.Entry::getKey,
diff --git a/src/main/java/de/numcodex/sq2cql/model/MappingTreeBase.java b/src/main/java/de/numcodex/sq2cql/model/MappingTreeBase.java
new file mode 100644
index 0000000..c3072b6
--- /dev/null
+++ b/src/main/java/de/numcodex/sq2cql/model/MappingTreeBase.java
@@ -0,0 +1,17 @@
+package de.numcodex.sq2cql.model;
+
+
+import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+public record MappingTreeBase(List moduleRoots) {
+
+ public Stream expand(ContextualTermCode termCode) {
+ var key = termCode.termCode().code();
+
+ return moduleRoots.stream().flatMap(moduleRoot ->
+ moduleRoot.isModuleMatching(termCode) ? moduleRoot.expand(key) : Stream.empty());
+ }
+}
diff --git a/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleEntry.java b/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleEntry.java
new file mode 100644
index 0000000..e220ccd
--- /dev/null
+++ b/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleEntry.java
@@ -0,0 +1,16 @@
+package de.numcodex.sq2cql.model;
+
+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)
+public record MappingTreeModuleEntry(String key, List children) {
+ @JsonCreator
+ static MappingTreeModuleEntry fromJson(@JsonProperty("key") String key,
+ @JsonProperty("children") List children) {
+ return new MappingTreeModuleEntry(key, children);
+ }
+}
diff --git a/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleRoot.java b/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleRoot.java
new file mode 100644
index 0000000..1d0cae2
--- /dev/null
+++ b/src/main/java/de/numcodex/sq2cql/model/MappingTreeModuleRoot.java
@@ -0,0 +1,40 @@
+package de.numcodex.sq2cql.model;
+
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import de.numcodex.sq2cql.model.common.TermCode;
+import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
+
+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 entries) {
+ @JsonCreator
+ static MappingTreeModuleRoot fromJson(@JsonProperty("context") TermCode context,
+ @JsonProperty("system") String system,
+ @JsonProperty("entries") List entries) {
+ return new MappingTreeModuleRoot(
+ context,
+ system,
+ entries.stream().collect(Collectors.toMap(MappingTreeModuleEntry::key, identity())));
+ }
+
+ public Stream 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));
+ }
+
+ boolean isModuleMatching(ContextualTermCode contextualTermCode) {
+ return context.equals(contextualTermCode.context()) &&
+ system.equals(contextualTermCode.termCode().system()) &&
+ entries.containsKey(contextualTermCode.termCode().code());
+ }
+}
diff --git a/src/main/java/de/numcodex/sq2cql/model/TermCodeNode.java b/src/main/java/de/numcodex/sq2cql/model/TermCodeNode.java
deleted file mode 100644
index 99cad59..0000000
--- a/src/main/java/de/numcodex/sq2cql/model/TermCodeNode.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package de.numcodex.sq2cql.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import de.numcodex.sq2cql.model.common.TermCode;
-import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-import static java.util.Objects.requireNonNull;
-
-/**
- * @author Alexander Kiel
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public record TermCodeNode(ContextualTermCode contextualTermCode, List children) {
-
- public TermCodeNode {
- requireNonNull(contextualTermCode);
- children = List.copyOf(children);
- }
-
- public static TermCodeNode of(ContextualTermCode termCode) {
- return new TermCodeNode(termCode, List.of());
- }
-
- public static TermCodeNode of(ContextualTermCode termCode, TermCodeNode... children) {
- return new TermCodeNode(termCode, List.of(children));
- }
-
- @JsonCreator
- public static TermCodeNode of(@JsonProperty("context") TermCode context,
- @JsonProperty("termCode") TermCode termCode,
- @JsonProperty("children") TermCodeNode... children) {
- var contextualTermCode = ContextualTermCode.of(context,
- requireNonNull(termCode, "missing JSON property: termCode"));
- return new TermCodeNode(contextualTermCode,
- children == null ? List.of() : List.of(children));
- }
-
- public Stream expand(ContextualTermCode termCode) {
- if (requireNonNull(termCode).equals(this.contextualTermCode)) {
- return leafConcepts();
- } else if (children.isEmpty()) {
- return Stream.of();
- } else {
- return children.stream().flatMap(n -> n.expand(termCode));
- }
- }
-
- private Stream leafConcepts() {
- if (children.isEmpty()) {
- return Stream.of(contextualTermCode);
- } else {
- return Stream.concat(Stream.of(contextualTermCode),
- children.stream().flatMap(TermCodeNode::leafConcepts));
- }
- }
-}
diff --git a/src/main/java/de/numcodex/sq2cql/model/structured_query/AbstractCriterion.java b/src/main/java/de/numcodex/sq2cql/model/structured_query/AbstractCriterion.java
index 544fd3c..c3446f2 100644
--- a/src/main/java/de/numcodex/sq2cql/model/structured_query/AbstractCriterion.java
+++ b/src/main/java/de/numcodex/sq2cql/model/structured_query/AbstractCriterion.java
@@ -71,7 +71,7 @@ static Container retrieveExpr(MappingContext mappingContext,
}
private static String referenceName(TermCode termCode) {
- return "%s".formatted(termCode.display() + termCode.code() + "Ref");
+ return termCode.code() + "Ref";
}
public abstract T appendAttributeFilter(AttributeFilter attributeFilter);
diff --git a/src/test/java/de/numcodex/sq2cql/AcceptanceTest.java b/src/test/java/de/numcodex/sq2cql/AcceptanceTest.java
index 98e143d..8efc183 100644
--- a/src/test/java/de/numcodex/sq2cql/AcceptanceTest.java
+++ b/src/test/java/de/numcodex/sq2cql/AcceptanceTest.java
@@ -7,7 +7,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import de.numcodex.sq2cql.model.structured_query.StructuredQuery;
import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.r4.model.*;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Library;
+import org.hl7.fhir.r4.model.Measure;
+import org.hl7.fhir.r4.model.MeasureReport;
+import org.hl7.fhir.r4.model.Parameters;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@@ -32,9 +36,8 @@
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
-import java.util.zip.ZipFile;
+import java.util.stream.Stream;
import static de.numcodex.sq2cql.Util.createTranslator;
import static java.lang.String.format;
@@ -78,41 +81,14 @@ private static Bundle createBundle(Library library, Measure measure) {
}
public static List getTestQueriesReturningOnePatient() throws URISyntaxException, IOException {
- var exclusions = Set.of("new_testdata/1-age.json",
- // Blaze can't parse the unit [arb'U]/mL https://github.com/samply/blaze/issues/1234
- "new_testdata/ObservationLab-38dfe76b-ae35-8290-6d80-ab08c963d148",
- "new_testdata/ObservationLab-16408169-a38d-8afc-fdd2-ed7af97ccc57",
- "new_testdata/ObservationLab-0fa07a3f-2e29-5065-6fa2-31e959acdd98",
- "new_testdata/ObservationLab-43eb280e-7901-7990-64e3-22cfa51de78b",
- "new_testdata/ObservationLab-09c67417-306a-a871-feef-71cbc915d113",
- "new_testdata/ObservationLab-26184c80-edf6-b1e0-ee8f-0e0999755cb9",
- "new_testdata/ObservationLab-9d44c93e-7799-a8e2-b368-c5539c30ceaa",
- "new_testdata/ObservationLab-755a3ac1-32ae-2a20-1ac9-02ee25777cf0",
- "new_testdata/ObservationLab-8ec9ea98-6581-f934-9bcf-b1c4f87e3560",
- "new_testdata/ObservationLab-315e8080-7425-f4e9-3891-aef5ebe0572c",
- "new_testdata/ObservationLab-44c8fd00-1a0f-f218-9eb8-83257add8fed",
- "new_testdata/ObservationLab-7a2be049-40d2-d16f-3db6-12f46df2fc82",
- "new_testdata/ObservationLab-78c5a976-1786-72e8-006b-8fd6af157ed9",
- "new_testdata/ObservationLab-254bf7ae-1d0a-b994-f20b-575d4e28e674",
- "new_testdata/ObservationLab-4bf41e10-1c62-2f82-d081-3d923aca43f2",
- // Blaze can't parse the unit /[HPF]
- "new_testdata/ObservationLab-bf7b68ae-1f89-41b6-e6a1-a40bf031f4b9",
- "new_testdata/ObservationLab-b080e003-5e7f-503c-4b13-47f601d6d903",
- "new_testdata/ObservationLab-3dd0c866-0649-def5-0fb2-de1ea0b976c2",
- "new_testdata/ObservationLab-98b33c6e-0a14-b90a-7795-e98680ee526e",
- // Blaze can't parse the unit /100{WBCs}
- "new_testdata/ObservationLab-d2d07223-0b20-ee0f-8505-0a17d2e1ed4d"
- );
- try (var zipFile = new ZipFile(resourcePath("returningOnePatient.zip").toString())) {
- return zipFile.stream()
- .filter(entry -> !exclusions.contains(entry.toString()))
- .map(entry -> {
- try {
- return new ObjectMapper().readValue(zipFile.getInputStream(entry), StructuredQuery.class);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }).toList();
+ try (Stream paths = Files.list(resourcePath("returningOnePatient"))) {
+ return paths.map(path -> {
+ try {
+ return new ObjectMapper().readValue(Files.readString(path), StructuredQuery.class);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }).toList();
}
}
diff --git a/src/test/java/de/numcodex/sq2cql/EvaluationIT.java b/src/test/java/de/numcodex/sq2cql/EvaluationIT.java
index a607782..4db9a2c 100644
--- a/src/test/java/de/numcodex/sq2cql/EvaluationIT.java
+++ b/src/test/java/de/numcodex/sq2cql/EvaluationIT.java
@@ -5,9 +5,7 @@
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.StringParam;
import com.fasterxml.jackson.databind.ObjectMapper;
-import de.numcodex.sq2cql.model.Mapping;
-import de.numcodex.sq2cql.model.MappingContext;
-import de.numcodex.sq2cql.model.TermCodeNode;
+import de.numcodex.sq2cql.model.*;
import de.numcodex.sq2cql.model.common.TermCode;
import de.numcodex.sq2cql.model.structured_query.ContextualConcept;
import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
@@ -31,6 +29,7 @@
import java.util.Map;
import java.util.UUID;
+import static de.numcodex.sq2cql.Util.createTreeWithoutChildren;
import static de.numcodex.sq2cql.model.common.Comparator.LESS_THAN;
import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -42,8 +41,9 @@
public class EvaluationIT {
static final TermCode CONTEXT = TermCode.of("context", "context", "context");
- static final ContextualTermCode ROOT = ContextualTermCode.of(CONTEXT, TermCode.of("", "", ""));
- static final ContextualTermCode BLOOD_PRESSURE = ContextualTermCode.of(CONTEXT, TermCode.of("http://loinc.org", "85354-9",
+ static final String BLOOD_PRESSURE_CODE = "85354-9";
+ static final String BLOOD_PRESSURE_SYSTEM = "http://loinc.org";
+ static final ContextualTermCode BLOOD_PRESSURE = ContextualTermCode.of(CONTEXT, TermCode.of(BLOOD_PRESSURE_SYSTEM, BLOOD_PRESSURE_CODE,
"Blood pressure panel with all children optional"));
static final TermCode DIASTOLIC_BLOOD_PRESSURE = TermCode.of("http://loinc.org", "8462-4",
"Diastolic blood pressure");
@@ -99,7 +99,7 @@ public void evaluateBloodPressure() throws Exception {
var valueFhirPath = format("component.where(code.coding.exists(system = '%s' and code = '%s')).value.first()",
DIASTOLIC_BLOOD_PRESSURE.system(), DIASTOLIC_BLOOD_PRESSURE.code());
var mappings = Map.of(BLOOD_PRESSURE, Mapping.of(BLOOD_PRESSURE, "Observation", valueFhirPath));
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(BLOOD_PRESSURE));
+ var conceptTree = createTreeWithoutChildren(BLOOD_PRESSURE);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
var translator = Translator.of(mappingContext);
var criterion = NumericCriterion.of(ContextualConcept.of(BLOOD_PRESSURE), LESS_THAN, BigDecimal.valueOf(80), "mm[Hg]");
@@ -157,7 +157,7 @@ public void evaluateBloodPressureAttribute() throws Exception {
}
""");
var mappings = Map.of(BLOOD_PRESSURE, mapping);
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(BLOOD_PRESSURE));
+ var conceptTree = createTreeWithoutChildren(BLOOD_PRESSURE);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
var translator = Translator.of(mappingContext);
var structuredQuery = readStructuredQuery("""
diff --git a/src/test/java/de/numcodex/sq2cql/MedicationAdministrationTest.java b/src/test/java/de/numcodex/sq2cql/MedicationAdministrationTest.java
index 7f6cc7c..7b174e7 100644
--- a/src/test/java/de/numcodex/sq2cql/MedicationAdministrationTest.java
+++ b/src/test/java/de/numcodex/sq2cql/MedicationAdministrationTest.java
@@ -43,7 +43,7 @@ public void translateMedicationAdministration() throws Exception {
context Unfiltered
- define HeparinB01AB01Ref:
+ define B01AB01Ref:
from [Medication: Code 'B01AB01' from atc] M
return 'Medication/' + M.id
@@ -51,7 +51,7 @@ public void translateMedicationAdministration() throws Exception {
define Criterion:
exists (from [MedicationAdministration] M
- where M.medication.reference in HeparinB01AB01Ref)
+ where M.medication.reference in B01AB01Ref)
define InInitialPopulation:
Criterion
@@ -74,7 +74,7 @@ public void translateMedicationAdministrationTimeRestriction() throws Exception
context Unfiltered
- define HeparinB01AB01Ref:
+ define B01AB01Ref:
from [Medication: Code 'B01AB01' from atc] M
return 'Medication/' + M.id
@@ -82,7 +82,7 @@ public void translateMedicationAdministrationTimeRestriction() throws Exception
define Criterion:
exists (from [MedicationAdministration] M
- where M.medication.reference in HeparinB01AB01Ref and
+ where M.medication.reference in B01AB01Ref and
(ToDate(M.effective as dateTime) in Interval[@2024-01-01, @2024-02-01] or
M.effective overlaps Interval[@2024-01-01, @2024-02-01]))
@@ -107,7 +107,7 @@ public void translateMedicationAdministrationDoubleCriteria() throws Exception {
context Unfiltered
- define HeparinB01AB01Ref:
+ define B01AB01Ref:
from [Medication: Code 'B01AB01' from atc] M
return 'Medication/' + M.id
@@ -115,13 +115,13 @@ public void translateMedicationAdministrationDoubleCriteria() throws Exception {
define "Criterion 1":
exists (from [MedicationAdministration] M
- where M.medication.reference in HeparinB01AB01Ref and
+ where M.medication.reference in B01AB01Ref and
(ToDate(M.effective as dateTime) in Interval[@2024-01-01, @2024-02-01] or
M.effective overlaps Interval[@2024-01-01, @2024-02-01]))
define "Criterion 2":
exists (from [MedicationAdministration] M
- where M.medication.reference in HeparinB01AB01Ref and
+ where M.medication.reference in B01AB01Ref and
(ToDate(M.effective as dateTime) in Interval[@2023-01-01, @2023-02-01] or
M.effective overlaps Interval[@2023-01-01, @2023-02-01]))
@@ -142,29 +142,29 @@ public void translateMedicationAdministrationTwoCriteria() throws Exception {
library Retrieve version '1.0.0'
using FHIR version '4.0.0'
include FHIRHelpers version '4.0.0'
-
+
codesystem atc: 'http://fhir.de/CodeSystem/bfarm/atc'
-
+
context Unfiltered
-
- define "AcetylsalicylsäureB01AC06Ref":
- from [Medication: Code 'B01AC06' from atc] M
- return 'Medication/' + M.id
-
- define HeparinB01AB01Ref:
+
+ define B01AB01Ref:
from [Medication: Code 'B01AB01' from atc] M
return 'Medication/' + M.id
-
+
+ define B01AC06Ref:
+ from [Medication: Code 'B01AC06' from atc] M
+ return 'Medication/' + M.id
+
context Patient
-
+
define "Criterion 1":
exists (from [MedicationAdministration] M
- where M.medication.reference in HeparinB01AB01Ref)
-
+ where M.medication.reference in B01AB01Ref)
+
define "Criterion 2":
exists (from [MedicationAdministration] M
- where M.medication.reference in "AcetylsalicylsäureB01AC06Ref")
-
+ where M.medication.reference in B01AC06Ref)
+
define InInitialPopulation:
"Criterion 1" and
"Criterion 2"
diff --git a/src/test/java/de/numcodex/sq2cql/SpecimenTest.java b/src/test/java/de/numcodex/sq2cql/SpecimenTest.java
index 11eaab2..59c8c77 100644
--- a/src/test/java/de/numcodex/sq2cql/SpecimenTest.java
+++ b/src/test/java/de/numcodex/sq2cql/SpecimenTest.java
@@ -35,45 +35,54 @@ public void translate() throws Exception {
var library = translator.toCql(structuredQuery);
assertThat(library).printsTo("""
- library Retrieve version '1.0.0'
- using FHIR version '4.0.0'
- include FHIRHelpers version '4.0.0'
-
- codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
- codesystem snomed: 'http://snomed.info/sct'
-
- context Patient
-
- define "Diagnose E13.9":
- [Condition: Code 'E13.9' from icd10] union
- [Condition: Code 'E13.91' from icd10] union
- [Condition: Code 'E13.90' from icd10]
-
- define Criterion:
- exists (from [Specimen: Code '119364003' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '258590006' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866034009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '2421000181104' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866035005' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '442427000' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '737089009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
-
- define InInitialPopulation:
- Criterion
+ library Retrieve version '1.0.0'
+ using FHIR version '4.0.0'
+ include FHIRHelpers version '4.0.0'
+
+ codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
+ codesystem snomed: 'http://snomed.info/sct'
+
+ context Patient
+
+ define "Diagnose E13.9":
+ [Condition: Code 'E13.9' from icd10] union
+ [Condition: Code 'E13.91' from icd10] union
+ [Condition: Code 'E13.90' from icd10]
+
+ define Criterion:
+ exists (from [Specimen: Code '119364003' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '737089009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442427000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122591000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '258590006' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122589008' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866035005' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122590004' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866034009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442166002' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
+
+ define InInitialPopulation:
+ Criterion
""");
}
@@ -85,55 +94,64 @@ public void translateExclusion() throws Exception {
var library = translator.toCql(structuredQuery);
assertThat(library).printsTo("""
- library Retrieve version '1.0.0'
- using FHIR version '4.0.0'
- include FHIRHelpers version '4.0.0'
-
- codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
- codesystem snomed: 'http://snomed.info/sct'
-
- context Patient
-
- define "Criterion 1":
- Patient.gender = 'female'
-
- define Inclusion:
- "Criterion 1"
-
- define "Diagnose E13.9":
- [Condition: Code 'E13.9' from icd10] union
- [Condition: Code 'E13.91' from icd10] union
- [Condition: Code 'E13.90' from icd10]
-
- define "Criterion 2":
- exists (from [Specimen: Code '119364003' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '258590006' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866034009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '2421000181104' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866035005' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '442427000' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '737089009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
-
- define Exclusion:
- "Criterion 2"
-
- define InInitialPopulation:
- Inclusion and
- not Exclusion
+ library Retrieve version '1.0.0'
+ using FHIR version '4.0.0'
+ include FHIRHelpers version '4.0.0'
+
+ codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
+ codesystem snomed: 'http://snomed.info/sct'
+
+ context Patient
+
+ define "Criterion 1":
+ Patient.gender = 'female'
+
+ define Inclusion:
+ "Criterion 1"
+
+ define "Diagnose E13.9":
+ [Condition: Code 'E13.9' from icd10] union
+ [Condition: Code 'E13.91' from icd10] union
+ [Condition: Code 'E13.90' from icd10]
+
+ define "Criterion 2":
+ exists (from [Specimen: Code '119364003' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '737089009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442427000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122591000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '258590006' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122589008' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866035005' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122590004' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866034009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442166002' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
+
+ define Exclusion:
+ "Criterion 2"
+
+ define InInitialPopulation:
+ Inclusion and
+ not Exclusion
""");
}
@@ -145,49 +163,58 @@ public void translateTwoInclusion() throws Exception {
var library = translator.toCql(structuredQuery);
assertThat(library).printsTo("""
- library Retrieve version '1.0.0'
- using FHIR version '4.0.0'
- include FHIRHelpers version '4.0.0'
-
- codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
- codesystem snomed: 'http://snomed.info/sct'
-
- context Patient
-
- define "Criterion 1":
- Patient.gender = 'female'
-
- define "Diagnose E13.9":
- [Condition: Code 'E13.9' from icd10] union
- [Condition: Code 'E13.91' from icd10] union
- [Condition: Code 'E13.90' from icd10]
-
- define "Criterion 2":
- exists (from [Specimen: Code '119364003' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '258590006' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866034009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '2421000181104' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866035005' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '442427000' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '737089009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
-
- define InInitialPopulation:
- "Criterion 1" and
- "Criterion 2"
+ library Retrieve version '1.0.0'
+ using FHIR version '4.0.0'
+ include FHIRHelpers version '4.0.0'
+
+ codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
+ codesystem snomed: 'http://snomed.info/sct'
+
+ context Patient
+
+ define "Criterion 1":
+ Patient.gender = 'female'
+
+ define "Diagnose E13.9":
+ [Condition: Code 'E13.9' from icd10] union
+ [Condition: Code 'E13.91' from icd10] union
+ [Condition: Code 'E13.90' from icd10]
+
+ define "Criterion 2":
+ exists (from [Specimen: Code '119364003' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '737089009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442427000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122591000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '258590006' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122589008' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866035005' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122590004' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866034009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442166002' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
+
+ define InInitialPopulation:
+ "Criterion 1" and
+ "Criterion 2"
""");
}
@@ -199,47 +226,56 @@ public void translateTwoReferenceCriteria() throws Exception {
var library = translator.toCql(structuredQuery);
assertThat(library).printsTo("""
- library Retrieve version '1.0.0'
- using FHIR version '4.0.0'
- include FHIRHelpers version '4.0.0'
-
- codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
- codesystem snomed: 'http://snomed.info/sct'
-
- context Patient
-
- define "Diagnose E13.9 and Diagnose E13.1":
- [Condition: Code 'E13.9' from icd10] union
- [Condition: Code 'E13.91' from icd10] union
- [Condition: Code 'E13.90' from icd10] union
- [Condition: Code 'E13.1' from icd10] union
- [Condition: Code 'E13.11' from icd10]
-
- define Criterion:
- exists (from [Specimen: Code '119364003' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '258590006' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866034009' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '2421000181104' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '866035005' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '442427000' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
- exists (from [Specimen: Code '737089009' from snomed] S
- with "Diagnose E13.9 and Diagnose E13.1" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
-
- define InInitialPopulation:
- Criterion
+ library Retrieve version '1.0.0'
+ using FHIR version '4.0.0'
+ include FHIRHelpers version '4.0.0'
+
+ codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
+ codesystem snomed: 'http://snomed.info/sct'
+
+ context Patient
+
+ define "Diagnose E13.9 and Diagnose E13.1":
+ [Condition: Code 'E13.9' from icd10] union
+ [Condition: Code 'E13.91' from icd10] union
+ [Condition: Code 'E13.90' from icd10] union
+ [Condition: Code 'E13.1' from icd10] union
+ [Condition: Code 'E13.11' from icd10]
+
+ define Criterion:
+ exists (from [Specimen: Code '119364003' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '737089009' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442427000' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122591000' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '258590006' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122589008' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866035005' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '122590004' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '866034009' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id) or
+ exists (from [Specimen: Code '442166002' from snomed] S
+ with "Diagnose E13.9 and Diagnose E13.1" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id)
+
+ define InInitialPopulation:
+ Criterion
""");
}
@@ -251,53 +287,65 @@ public void translateAndBodySite() throws Exception {
var library = translator.toCql(structuredQuery);
assertThat(library).printsTo("""
- library Retrieve version '1.0.0'
- using FHIR version '4.0.0'
- include FHIRHelpers version '4.0.0'
-
- codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
- codesystem icd_o_3: 'urn:oid:2.16.840.1.113883.6.43.1'
- codesystem snomed: 'http://snomed.info/sct'
-
- context Patient
-
- define "Diagnose E13.9":
- [Condition: Code 'E13.9' from icd10] union
- [Condition: Code 'E13.91' from icd10] union
- [Condition: Code 'E13.90' from icd10]
-
- define Criterion:
- exists (from [Specimen: Code '119364003' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '258590006' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '866034009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '2421000181104' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '866035005' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '442427000' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
- exists (from [Specimen: Code '737089009' from snomed] S
- with "Diagnose E13.9" C
- such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
- where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3)
-
- define InInitialPopulation:
- Criterion
+ library Retrieve version '1.0.0'
+ using FHIR version '4.0.0'
+ include FHIRHelpers version '4.0.0'
+
+ codesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'
+ codesystem icd_o_3: 'urn:oid:2.16.840.1.113883.6.43.1'
+ codesystem snomed: 'http://snomed.info/sct'
+
+ context Patient
+
+ define "Diagnose E13.9":
+ [Condition: Code 'E13.9' from icd10] union
+ [Condition: Code 'E13.91' from icd10] union
+ [Condition: Code 'E13.90' from icd10]
+
+ define Criterion:
+ exists (from [Specimen: Code '119364003' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '737089009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '442427000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '122591000' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '258590006' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '122589008' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '866035005' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '122590004' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '866034009' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3) or
+ exists (from [Specimen: Code '442166002' from snomed] S
+ with "Diagnose E13.9" C
+ such that S.extension.where(url='https://www.medizininformatik-initiative.de/fhir/ext/modul-biobank/StructureDefinition/Diagnose').first().value.as(Reference).reference contains 'Condition/' + C.id
+ where S.collection.bodySite.coding contains Code 'C44.6' from icd_o_3)
+
+ define InInitialPopulation:
+ Criterion
""");
}
}
diff --git a/src/test/java/de/numcodex/sq2cql/TranslatorTest.java b/src/test/java/de/numcodex/sq2cql/TranslatorTest.java
index 7708375..a079034 100644
--- a/src/test/java/de/numcodex/sq2cql/TranslatorTest.java
+++ b/src/test/java/de/numcodex/sq2cql/TranslatorTest.java
@@ -1,10 +1,7 @@
package de.numcodex.sq2cql;
import com.fasterxml.jackson.databind.ObjectMapper;
-import de.numcodex.sq2cql.model.AttributeMapping;
-import de.numcodex.sq2cql.model.Mapping;
-import de.numcodex.sq2cql.model.MappingContext;
-import de.numcodex.sq2cql.model.TermCodeNode;
+import de.numcodex.sq2cql.model.*;
import de.numcodex.sq2cql.model.common.TermCode;
import de.numcodex.sq2cql.model.structured_query.*;
import org.junit.jupiter.api.Nested;
@@ -15,6 +12,7 @@
import java.util.Map;
import static de.numcodex.sq2cql.Assertions.assertThat;
+import static de.numcodex.sq2cql.Util.*;
import static de.numcodex.sq2cql.model.common.Comparator.LESS_THAN;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -118,7 +116,7 @@ void nonExpandableConcept() {
@Test
void nonMappableConcept() {
- var conceptTree = TermCodeNode.of(C71, TermCodeNode.of(C71_0), TermCodeNode.of(C71_1));
+ var conceptTree = createTreeWithChildren(C71, C71_0, C71_1);
var mappingContext = MappingContext.of(Map.of(), conceptTree, CODE_SYSTEM_ALIASES);
var message = assertThrows(TranslationException.class, () -> Translator.of(mappingContext)
@@ -136,7 +134,7 @@ void usage_Documentation() {
TermCode.of("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "C71.1",
"Malignant neoplasm of brain"));
var mappings = Map.of(c71_1, Mapping.of(c71_1, "Condition"));
- var conceptTree = TermCodeNode.of(c71_1);
+ var conceptTree = createTreeWithoutChildren(c71_1);
var codeSystemAliases = Map.of("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "icd10");
var mappingContext = MappingContext.of(mappings, conceptTree, codeSystemAliases);
@@ -167,7 +165,7 @@ void timeRestriction() {
"Malignant neoplasm of brain"));
var mappings = Map.of(c71_1,
Mapping.of(c71_1, "Condition", null, null, List.of(), List.of(), "onset"));
- var conceptTree = TermCodeNode.of(c71_1);
+ var conceptTree = createTreeWithoutChildren(c71_1);
var codeSystemAliases = Map.of("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "icd10");
var mappingContext = MappingContext.of(mappings, conceptTree, codeSystemAliases);
@@ -201,7 +199,7 @@ void timeRestriction_missingPathInMapping() {
"Malignant neoplasm of brain"));
var mappings = Map.of(c71_1,
Mapping.of(c71_1, "Condition", null, null, List.of(), List.of(), null));
- var conceptTree = TermCodeNode.of(c71_1);
+ var conceptTree = createTreeWithoutChildren(c71_1);
var codeSystemAliases = Map.of("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "icd10");
var mappingContext = MappingContext.of(mappings, conceptTree, codeSystemAliases);
var query = StructuredQuery.of(List.of(List.of(ConceptCriterion.of(ContextualConcept.of(c71_1),
@@ -220,8 +218,9 @@ void test_Task1() {
Mapping.of(C71_1, "Condition", null, null, List.of(),
List.of(VERIFICATION_STATUS_ATTR_MAPPING)), TMZ,
Mapping.of(TMZ, "MedicationStatement"));
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(TMZ),
- TermCodeNode.of(C71, TermCodeNode.of(C71_0), TermCodeNode.of(C71_1)));
+ var conceptTree = new MappingTreeBase(List.of(
+ createTreeRootWithoutChildren(TMZ),
+ createTreeRootWithChildren(C71, C71_0, C71_1)));
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
var structuredQuery = StructuredQuery.of(List.of(List.of(
ConceptCriterion.of(ContextualConcept.of(C71))
@@ -270,8 +269,10 @@ void test_Task2() {
Mapping.of(HYPERTENSION, "Condition", null, null, List.of(),
List.of(VERIFICATION_STATUS_ATTR_MAPPING)), SERUM, Mapping.of(SERUM, "Specimen"), LIPID,
Mapping.of(LIPID, "MedicationStatement"));
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(HYPERTENSION), TermCodeNode.of(SERUM),
- TermCodeNode.of(LIPID));
+ var conceptTree = new MappingTreeBase(List.of(
+ createTreeRootWithoutChildren(HYPERTENSION),
+ createTreeRootWithoutChildren(SERUM),
+ createTreeRootWithoutChildren(LIPID)));
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
var structuredQuery = StructuredQuery.of(List.of(List.of(
ConceptCriterion.of(ContextualConcept.of(HYPERTENSION))
@@ -324,7 +325,7 @@ void geccoTask2() {
Mapping.of(G47_31, "Condition", null, null,
List.of(CodingModifier.of("verificationStatus.coding", CONFIRMED)), List.of()),
TOBACCO_SMOKING_STATUS, Mapping.of(TOBACCO_SMOKING_STATUS, "Observation", "value"));
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(COPD), TermCodeNode.of(G47_31));
+ var conceptTree = new MappingTreeBase(List.of(createTreeRootWithoutChildren(COPD), createTreeRootWithoutChildren(G47_31)));
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
var structuredQuery = StructuredQuery.of(
List.of(List.of(ValueSetCriterion.of(ContextualConcept.of(FRAILTY_SCORE), VERY_FIT, WELL))),
@@ -467,7 +468,7 @@ void onlyFixedCriteria() throws Exception {
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(COMBINED_CONSENT));
+ var conceptTree = createTreeWithoutChildren(COMBINED_CONSENT);
var mappings = Map.of(COMBINED_CONSENT, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -549,7 +550,7 @@ void numericAgeTranslation() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(AGE));
+ var conceptTree = createTreeWithoutChildren(AGE);
var mappings = Map.of(AGE, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -625,7 +626,7 @@ void ageRangeTranslation() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(AGE));
+ var conceptTree = createTreeWithoutChildren(AGE);
var mappings = Map.of(AGE, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -701,7 +702,7 @@ void numericAgeTranslationInHours() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(AGE));
+ var conceptTree = createTreeWithoutChildren(AGE);
var mappings = Map.of(AGE, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -777,7 +778,7 @@ void patientGender() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(GENDER));
+ var conceptTree = createTreeWithoutChildren(GENDER);
var mappings = Map.of(GENDER, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -844,7 +845,7 @@ void consent() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(CONSENT_MDAT));
+ var conceptTree = createTreeWithoutChildren(CONSENT_MDAT);
var mappings = Map.of(CONSENT_MDAT, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
@@ -938,7 +939,7 @@ void bloodPressure() throws Exception {
]
}
""");
- var conceptTree = TermCodeNode.of(ROOT, TermCodeNode.of(BLOOD_PRESSURE));
+ var conceptTree = createTreeWithoutChildren(BLOOD_PRESSURE);
var mappings = Map.of(BLOOD_PRESSURE, mapping);
var mappingContext = MappingContext.of(mappings, conceptTree, CODE_SYSTEM_ALIASES);
diff --git a/src/test/java/de/numcodex/sq2cql/Util.java b/src/test/java/de/numcodex/sq2cql/Util.java
index 8afcd58..46f305f 100644
--- a/src/test/java/de/numcodex/sq2cql/Util.java
+++ b/src/test/java/de/numcodex/sq2cql/Util.java
@@ -2,13 +2,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Functions;
-import de.numcodex.sq2cql.model.Mapping;
-import de.numcodex.sq2cql.model.MappingContext;
-import de.numcodex.sq2cql.model.TermCodeNode;
+import de.numcodex.sq2cql.model.*;
import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
import java.io.IOException;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipFile;
@@ -38,17 +37,18 @@ public interface Util {
entry("http://fhir.de/CodeSystem/bfarm/ops", "oops"));
private static Map readMappings(ZipFile zipFile) throws IOException {
- try (var in = zipFile.getInputStream(zipFile.getEntry("ontology/mapping/mapping_cql.json"))) {
+ try (var in = zipFile.getInputStream(zipFile.getEntry("mapping/cql/mapping_cql.json"))) {
var mapper = new ObjectMapper();
return Arrays.stream(mapper.readValue(in, Mapping[].class))
.collect(Collectors.toMap(Mapping::key, Functions.identity()));
}
}
- private static TermCodeNode readConceptTree(ZipFile zipFile) throws IOException {
- try (var in = zipFile.getInputStream(zipFile.getEntry("ontology/mapping/mapping_tree.json"))) {
+ private static MappingTreeBase readConceptTree(ZipFile zipFile) throws IOException {
+ try (var in = zipFile.getInputStream(zipFile.getEntry("mapping/mapping_tree.json"))) {
var mapper = new ObjectMapper();
- return mapper.readValue(in, TermCodeNode.class);
+ return new MappingTreeBase(
+ Arrays.stream(mapper.readValue(in, MappingTreeModuleRoot[].class)).toList());
}
}
@@ -60,4 +60,25 @@ static Translator createTranslator() throws Exception {
return Translator.of(mappingContext);
}
}
+
+ static MappingTreeBase createTreeWithoutChildren(ContextualTermCode c) {
+ return new MappingTreeBase(List.of(new MappingTreeModuleRoot(c.context(), c.termCode().system(), Map.of(c.termCode().code(),
+ new MappingTreeModuleEntry(c.termCode().code(), List.of())))));
+ }
+
+ static MappingTreeBase createTreeWithChildren(ContextualTermCode c, ContextualTermCode child1, ContextualTermCode child2) {
+ return new MappingTreeBase(List.of(createTreeRootWithChildren(c, child1, child2)));
+ }
+
+ static MappingTreeModuleRoot createTreeRootWithChildren(ContextualTermCode c, ContextualTermCode child1, ContextualTermCode child2) {
+ return new MappingTreeModuleRoot(c.context(), c.termCode().system(), Map.of(
+ c.termCode().code(), new MappingTreeModuleEntry(c.termCode().code(), List.of(child1.termCode().code(), child2.termCode().code())),
+ child1.termCode().code(), new MappingTreeModuleEntry(child1.termCode().code(), List.of()),
+ child2.termCode().code(), new MappingTreeModuleEntry(child2.termCode().code(), List.of())));
+ }
+
+ static MappingTreeModuleRoot createTreeRootWithoutChildren(ContextualTermCode c) {
+ return new MappingTreeModuleRoot(c.context(), c.termCode().system(), Map.of(
+ c.termCode().code(), new MappingTreeModuleEntry(c.termCode().code(), List.of())));
+ }
}
diff --git a/src/test/java/de/numcodex/sq2cql/model/MappingContextTest.java b/src/test/java/de/numcodex/sq2cql/model/MappingContextTest.java
index 917b451..9163eac 100644
--- a/src/test/java/de/numcodex/sq2cql/model/MappingContextTest.java
+++ b/src/test/java/de/numcodex/sq2cql/model/MappingContextTest.java
@@ -8,6 +8,7 @@
import java.util.List;
import java.util.Map;
+import static de.numcodex.sq2cql.Util.createTreeWithoutChildren;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -38,7 +39,7 @@ void expandConcept_EmptyTree() {
@Test
void expandConcept_MissingMapping() {
- var context = MappingContext.of(Map.of(), TermCodeNode.of(C1), Map.of());
+ var context = MappingContext.of(Map.of(), createTreeWithoutChildren(C1), Map.of());
var termCodes = context.expandConcept(ContextualConcept.of(C1)).toList();
diff --git a/src/test/java/de/numcodex/sq2cql/model/MappingTreeBaseTest.java b/src/test/java/de/numcodex/sq2cql/model/MappingTreeBaseTest.java
new file mode 100644
index 0000000..53cc47d
--- /dev/null
+++ b/src/test/java/de/numcodex/sq2cql/model/MappingTreeBaseTest.java
@@ -0,0 +1,288 @@
+package de.numcodex.sq2cql.model;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.numcodex.sq2cql.model.common.TermCode;
+import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class MappingTreeBaseTest {
+ static final TermCode CONTEXT_1 = TermCode.of("context1", "context1", "context1");
+ static final TermCode CONTEXT_2 = TermCode.of("context2", "context2", "context2");
+ static final String SYSTEM_1 = "sys1";
+ static final String SYSTEM_2 = "sys2";
+ static final String C1 = "c1";
+ static final String C2 = "c2";
+ static final String C3 = "c3";
+ static final String C4 = "c4";
+ static final String C5 = "c5";
+
+
+ private static ContextualTermCode contextualTermCodeOf(TermCode context, String system, String code) {
+ return new ContextualTermCode(context, new TermCode(system, code, "display"));
+ }
+
+ @Test
+ void expand_empty() {
+ var base = new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1, Map.of())));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void expand_noMatch_differentCode() {
+ var base = new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2)).toList();
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void expand_noMatch_differentContext() {
+ var base = new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of())))));
+
+ var result = base.expand(
+ contextualTermCodeOf(new TermCode("", "different-context", ""), SYSTEM_1, C2))
+ .toList();
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void expand_noMatch_differentSystem() {
+ var base = new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, "system2", C2)).toList();
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void expand_oneModule_twoEntries_withoutChildren() {
+ var base = new MappingTreeBase(List.of(new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of()),
+ C2, new MappingTreeModuleEntry(C2, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1));
+ }
+
+ @Test
+ void expand_twoModules_sameContext_differentSystem_withoutChildren() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of()),
+ C2, new MappingTreeModuleEntry(C2, List.of()))),
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_2,
+ Map.of(C3, new MappingTreeModuleEntry(C3, List.of()),
+ C4, new MappingTreeModuleEntry(C4, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2));
+ }
+
+ @Test
+ void expand_twoModules_sameSystem_differentContext_withoutChildren() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of()),
+ C2, new MappingTreeModuleEntry(C2, List.of()))),
+ new MappingTreeModuleRoot(CONTEXT_2, SYSTEM_1,
+ Map.of(C3, new MappingTreeModuleEntry(C3, List.of()),
+ C4, new MappingTreeModuleEntry(C4, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2));
+ }
+
+ @Test
+ void expand_oneChild_withNoReference() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2))))));
+
+ assertThatThrownBy(() -> base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList())
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ void expand_oneChild_onFirstLayer() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2)),
+ C2, new MappingTreeModuleEntry(C2, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2));
+ }
+
+ @Test
+ void expand_twoChildren_onFirstLayer() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2, C3)),
+ C2, new MappingTreeModuleEntry(C2, List.of()),
+ C3, new MappingTreeModuleEntry(C3, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C3));
+ }
+
+ @Test
+ void expand_twoChildren_onFirstAndSecondLayer() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2, C3)),
+ C2, new MappingTreeModuleEntry(C2, List.of(C4)),
+ C3, new MappingTreeModuleEntry(C3, List.of(C5)),
+ C4, new MappingTreeModuleEntry(C4, List.of()),
+ C5, new MappingTreeModuleEntry(C5, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C3),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C4),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C5));
+ }
+
+ @Test
+ void expand_oneChild_onThreeLayers() {
+ var base = new MappingTreeBase(List.of(
+ new MappingTreeModuleRoot(CONTEXT_1, SYSTEM_1,
+ Map.of(C1, new MappingTreeModuleEntry(C1, List.of(C2)),
+ C2, new MappingTreeModuleEntry(C2, List.of(C3)),
+ C3, new MappingTreeModuleEntry(C3, List.of(C4, C5)),
+ C4, new MappingTreeModuleEntry(C4, List.of()),
+ C5, new MappingTreeModuleEntry(C5, List.of())))));
+
+ var result = base.expand(contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1)).toList();
+
+ assertThat(result).containsExactlyInAnyOrder(
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C1),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C2),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C3),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C4),
+ contextualTermCodeOf(CONTEXT_1, SYSTEM_1, C5));
+ }
+
+ @Test
+ void fromJson() throws Exception {
+ var base = parse("""
+ [
+ {
+ "entries": [
+ {
+ "key": "C1",
+ "parents": [],
+ "children": []
+ }
+ ],
+ "context": {
+ "system": "sys1",
+ "code": "code1",
+ "display": "display"
+ },
+ "system": "module-system"
+ }
+ ]
+ """);
+
+ assertThat(base.moduleRoots().get(0).context())
+ .isEqualTo(new TermCode("sys1", "code1", "display"));
+ assertThat(base.moduleRoots().get(0).system()).isEqualTo("module-system");
+ assertThat(base.moduleRoots().get(0).entries().get("C1")).isNotNull();
+ }
+
+ @Test
+ void fromJson_AdditionalPropertyIsIgnored() throws Exception {
+ var base = parse("""
+ [
+ {
+ "foo-133831": "bar-133841",
+ "entries": [
+ {
+ "key": "C1",
+ "parents": [],
+ "children": []
+ }
+ ],
+ "context": {
+ "system": "sys1",
+ "code": "code1",
+ "display": "display"
+ },
+ "system": "module-system"
+ }
+ ]
+ """);
+
+ assertThat(base.moduleRoots().get(0).context())
+ .isEqualTo(new TermCode("sys1", "code1", "display"));
+ assertThat(base.moduleRoots().get(0).system()).isEqualTo("module-system");
+ assertThat(base.moduleRoots().get(0).entries().get("C1")).isNotNull();
+ }
+
+ @Test
+ void fromJson_withChildren() throws Exception {
+ var base = parse("""
+ [
+ {
+ "entries": [
+ {
+ "key": "C1",
+ "parents": [],
+ "children": ["C2"]
+ },
+ {
+ "key": "C2",
+ "parents": [],
+ "children": []
+ }
+ ],
+ "context": {
+ "system": "sys1",
+ "code": "code1",
+ "display": "display"
+ },
+ "system": "module-system"
+ }
+ ]
+ """);
+
+ assertThat(base.moduleRoots().get(0).context())
+ .isEqualTo(new TermCode("sys1", "code1", "display"));
+ assertThat(base.moduleRoots().get(0).system()).isEqualTo("module-system");
+ assertThat(base.moduleRoots().get(0).entries().get("C1").children()).containsExactly("C2");
+ assertThat(base.moduleRoots().get(0).entries().get("C2")).isNotNull();
+ }
+
+ static MappingTreeBase parse(String s) throws JsonProcessingException {
+ return new MappingTreeBase(Arrays.stream(new ObjectMapper().readValue(s, MappingTreeModuleRoot[].class)).toList());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/de/numcodex/sq2cql/model/TermCodeNodeTest.java b/src/test/java/de/numcodex/sq2cql/model/TermCodeNodeTest.java
deleted file mode 100644
index b1d9894..0000000
--- a/src/test/java/de/numcodex/sq2cql/model/TermCodeNodeTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package de.numcodex.sq2cql.model;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import de.numcodex.sq2cql.model.common.TermCode;
-import de.numcodex.sq2cql.model.structured_query.ContextualTermCode;
-import org.junit.jupiter.api.Test;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/**
- * @author Alexander Kiel
- */
-class TermCodeNodeTest {
-
-
- static final TermCode CONTEXT = TermCode.of("context", "context", "context");
- static final ContextualTermCode ROOT = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "root", "root"));
- static final ContextualTermCode C1 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c1", "c1"));
- static final ContextualTermCode C2 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c2", "c2"));
- 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 ContextualTermCode C111 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c111", "c111"));
- static final ContextualTermCode C112 = ContextualTermCode.of(CONTEXT, TermCode.of("foo", "c112", "c112"));
-
- @Test
- void noChildren() {
- var node = TermCodeNode.of(ROOT);
-
- assertTrue(node.children().isEmpty());
- }
-
- @Test
- void expandSelfLeaf() {
- var node = TermCodeNode.of(ROOT);
-
- assertEquals(Set.of(ROOT), node.expand(ROOT).collect(Collectors.toSet()));
- }
-
- @Test
- void expandSelf() {
- var node = TermCodeNode.of(ROOT, TermCodeNode.of(C1), TermCodeNode.of(C2));
-
- assertEquals(Set.of(ROOT, C1, C2), node.expand(ROOT).collect(Collectors.toSet()));
- }
-
- @Test
- void expandChildAndSelf() {
- var c1 = TermCodeNode.of(C1, TermCodeNode.of(C11), TermCodeNode.of(C12));
- var node = TermCodeNode.of(ROOT, c1, TermCodeNode.of(C2));
-
- assertEquals(Set.of(C1, C11, C12), node.expand(C1).collect(Collectors.toSet()));
- }
-
- @Test
- void expandChildDeep() {
- var c11 = TermCodeNode.of(C11, TermCodeNode.of(C111), TermCodeNode.of(C112));
- var c1 = TermCodeNode.of(C1, c11, TermCodeNode.of(C12));
- var node = TermCodeNode.of(ROOT, c1, TermCodeNode.of(C2));
-
- assertEquals(Set.of(C1, C11, C12, C111, C112), node.expand(C1).collect(Collectors.toSet()));
- }
-
- @Test
- void fromJson() throws Exception {
- var mapper = new ObjectMapper();
-
- var conceptNode = mapper.readValue("""
- {
- "context": {
- "system": "context-152133",
- "code": "context-152136",
- "display": "context-152144"
- },
- "termCode": {
- "system": "system-143705",
- "code": "code-143708",
- "display": "display-143716"
- },
- "children": []
- }
- """, TermCodeNode.class);
- assertEquals(ContextualTermCode.of(TermCode.of("context-152133", "context-152136", "context-152144"),
- TermCode.of("system-143705", "code-143708", "display-143716")), conceptNode.contextualTermCode());
- }
-
- @Test
- void fromJson_AdditionalPropertyIsIgnored() throws Exception {
- var mapper = new ObjectMapper();
-
- var conceptNode = mapper.readValue("""
- {"foo-152133": "bar-152136",
- "termCode": {
- "system": "system-143705",
- "code": "code-143708",
- "display": "display-143716"
- },
- "children": []
- }
- """, TermCodeNode.class);
-
- assertEquals("system-143705", conceptNode.contextualTermCode().termCode().system());
- }
-
- @Test
- void fromJson_WithChildren() throws Exception {
- var mapper = new ObjectMapper();
-
- var conceptNode = mapper.readValue("""
- {
- "context": {
- "system": "context-152133",
- "code": "context-152136",
- "display": "context-152144"
- },
- "termCode": {
- "system": "system-143705",
- "code": "code-143708",
- "display": "display-143716"
- },
- "children": [
- {"context": {
- "system": "child-1-context-155856",
- "code": "child-1-context-155858",
- "display": "child-1-context-155900"
- },
- "termCode": {
- "system": "child-1-system-155856",
- "code": "child-1-code-155858",
- "display": "child-1-display-155900"
- }},
- {
- "context": {
- "system": "child-2-context-155956",
- "code": "child-2-context-155958",
- "display": "child-2-context-160000"
- },
- "termCode": {
- "system": "child-2-system-155958",
- "code": "child-2-code-160000",
- "display": "child-2-display-160002"
- }}
- ]
- }
- """, TermCodeNode.class);
-
- assertEquals(ContextualTermCode.of(
- TermCode.of("context-152133", "context-152136", "context-152144"),
- TermCode.of("system-143705", "code-143708", "display-143716")), conceptNode.contextualTermCode());
- assertEquals(ContextualTermCode.of(
- TermCode.of("child-1-context-155856", "child-1-context-155858", "child-1-context-155900"),
- TermCode.of("child-1-system-155856", "child-1-code-155858", "child-1-display-155900")),
- conceptNode.children().get(0).contextualTermCode());
- assertEquals(ContextualTermCode.of(
- TermCode.of("child-2-context-155956", "child-2-context-155958", "child-2-context-160000"),
- TermCode.of("child-2-system-155958", "child-2-code-160000", "child-2-display-160002")),
- conceptNode.children().get(1).contextualTermCode());
-
- }
-}
diff --git a/src/test/java/de/numcodex/sq2cql/model/structured_query/ConceptCriterionTest.java b/src/test/java/de/numcodex/sq2cql/model/structured_query/ConceptCriterionTest.java
index bc51885..1c14cf5 100644
--- a/src/test/java/de/numcodex/sq2cql/model/structured_query/ConceptCriterionTest.java
+++ b/src/test/java/de/numcodex/sq2cql/model/structured_query/ConceptCriterionTest.java
@@ -1,10 +1,7 @@
package de.numcodex.sq2cql.model.structured_query;
import com.fasterxml.jackson.databind.ObjectMapper;
-import de.numcodex.sq2cql.model.AttributeMapping;
-import de.numcodex.sq2cql.model.Mapping;
-import de.numcodex.sq2cql.model.MappingContext;
-import de.numcodex.sq2cql.model.TermCodeNode;
+import de.numcodex.sq2cql.model.*;
import de.numcodex.sq2cql.model.common.TermCode;
import de.numcodex.sq2cql.model.cql.CodeSystemDefinition;
import org.junit.jupiter.api.Test;
@@ -15,6 +12,8 @@
import java.util.Set;
import static de.numcodex.sq2cql.Assertions.assertThat;
+import static de.numcodex.sq2cql.Util.createTreeWithChildren;
+import static de.numcodex.sq2cql.Util.createTreeWithoutChildren;
import static de.numcodex.sq2cql.model.common.Comparator.LESS_THAN;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -209,7 +208,7 @@ void fromJson_BloodPressureRange() throws Exception {
void toCql() {
var criterion = ConceptCriterion.of(ContextualConcept.of(C71));
var mappingContext = MappingContext.of(Map.of(C71, Mapping.of(C71, "Condition")),
- TermCodeNode.of(C71), CODE_SYSTEM_ALIASES);
+ createTreeWithoutChildren(C71), CODE_SYSTEM_ALIASES);
var container = criterion.toCql(mappingContext);
@@ -233,7 +232,7 @@ void toCql_WithMultipleTermCodes() {
ContextualConcept.of(CONTEXT, Concept.of(C71_1_TC, C71_2_TC)));
var mappings = Map.of(C71_1, Mapping.of(C71_1, "Condition"), C71_2,
Mapping.of(C71_2, "Condition"));
- var mappingContext = MappingContext.of(mappings, TermCodeNode.of(C71), CODE_SYSTEM_ALIASES);
+ var mappingContext = MappingContext.of(mappings, createTreeWithoutChildren(C71), CODE_SYSTEM_ALIASES);
var container = criterion.toCql(mappingContext);
@@ -258,7 +257,7 @@ void toCql_WithAttributeFilter() {
.appendAttributeFilter(ValueSetAttributeFilter.of(VERIFICATION_STATUS, CONFIRMED));
var mapping = Mapping.of(C71, "Condition", null, null, List.of(),
List.of(AttributeMapping.of("Coding", VERIFICATION_STATUS, "verificationStatus.coding")));
- var mappingContext = MappingContext.of(Map.of(C71, mapping), TermCodeNode.of(C71),
+ var mappingContext = MappingContext.of(Map.of(C71, mapping), createTreeWithoutChildren(C71),
CODE_SYSTEM_ALIASES);
var container = criterion.toCql(mappingContext);
@@ -290,7 +289,7 @@ void toCql_Expanded_WithAttributeFilter() {
var mapping2 = Mapping.of(C71_2, "Condition", null, null, List.of(),
List.of(AttributeMapping.of("Coding", VERIFICATION_STATUS, "verificationStatus.coding")));
var mappingContext = MappingContext.of(Map.of(C71_1, mapping1, C71_2, mapping2),
- TermCodeNode.of(C71, TermCodeNode.of(C71_1), TermCodeNode.of(C71_2)), CODE_SYSTEM_ALIASES);
+ createTreeWithChildren(C71, C71_1, C71_2), CODE_SYSTEM_ALIASES);
var container = criterion.toCql(mappingContext);
@@ -373,7 +372,7 @@ void toCql_FixedCriteria_Coding() {
var criterion = ConceptCriterion.of(ContextualConcept.of(C71));
var mappingContext = MappingContext.of(Map.of(C71, Mapping.of(C71, "Condition", null, null,
List.of(CodingModifier.of("verificationStatus.coding", CONFIRMED)), List.of())),
- TermCodeNode.of(C71), CODE_SYSTEM_ALIASES);
+ createTreeWithoutChildren(C71), CODE_SYSTEM_ALIASES);
var container = criterion.toCql(mappingContext);
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient.zip b/src/test/resources/de/numcodex/sq2cql/returningOnePatient.zip
deleted file mode 100644
index 23a9807..0000000
Binary files a/src/test/resources/de/numcodex/sq2cql/returningOnePatient.zip and /dev/null differ
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Diagnose-f728b4fa-4248-5e3a-0a5d-2f346baa9455 b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Diagnose-f728b4fa-4248-5e3a-0a5d-2f346baa9455
new file mode 100644
index 0000000..cc10a80
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Diagnose-f728b4fa-4248-5e3a-0a5d-2f346baa9455
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "I08.0", "display": "", "system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm"}], "context": {"code": "Diagnose", "display": "Diagnose", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/MedicationAdministration-aedab7b5-e2aa-55a7-4951-03edfd05a5f5 b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/MedicationAdministration-aedab7b5-e2aa-55a7-4951-03edfd05a5f5
new file mode 100644
index 0000000..c17b868
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/MedicationAdministration-aedab7b5-e2aa-55a7-4951-03edfd05a5f5
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "P01CA", "display": "", "system": "http://fhir.de/CodeSystem/bfarm/atc"}], "context": {"code": "Medikamentenverabreichung", "display": "Verabreichung von Medikamenten", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/ObservationLab-0a02da60-749d-4601-df98-377981bd5336 b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/ObservationLab-0a02da60-749d-4601-df98-377981bd5336
new file mode 100644
index 0000000..f3e8de4
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/ObservationLab-0a02da60-749d-4601-df98-377981bd5336
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "800-3", "display": "", "system": "http://loinc.org"}], "context": {"code": "Laboruntersuchung", "display": "Laboruntersuchung", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Procedure-d7de701d-8eaf-b323-5f65-380029c836e0 b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Procedure-d7de701d-8eaf-b323-5f65-380029c836e0
new file mode 100644
index 0000000..d2c20ad
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Procedure-d7de701d-8eaf-b323-5f65-380029c836e0
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "5-403.05", "display": "", "system": "http://fhir.de/CodeSystem/bfarm/ops"}], "context": {"code": "Procedure", "display": "Prozedur", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Specimen-e3e70682-c209-4cac-629f-6fbed82c07cd b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Specimen-e3e70682-c209-4cac-629f-6fbed82c07cd
new file mode 100644
index 0000000..3b9734e
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Specimen-e3e70682-c209-4cac-629f-6fbed82c07cd
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "396997002", "display": "", "system": "http://snomed.info/sct"}], "context": {"code": "Specimen", "display": "Bioprobe", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file
diff --git a/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Todesursache-31307e46-af79-7546-7e51-68dc5690f74d b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Todesursache-31307e46-af79-7546-7e51-68dc5690f74d
new file mode 100644
index 0000000..8f72173
--- /dev/null
+++ b/src/test/resources/de/numcodex/sq2cql/returningOnePatient/Todesursache-31307e46-af79-7546-7e51-68dc5690f74d
@@ -0,0 +1 @@
+{"inclusionCriteria": [[{"attributeFilters": [], "termCodes": [{"code": "S14.11", "display": "", "system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm"}], "context": {"code": "Diagnose", "display": "Diagnose", "system": "fdpg.mii.cds", "version": "1.0.0"}}]], "version": "http://to_be_decided.com/draft-1/schema#"}
\ No newline at end of file