diff --git a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/FHIRMappingLanguageTests.java b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/FHIRMappingLanguageTests.java
index 869c89008..303be9aaa 100644
--- a/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/FHIRMappingLanguageTests.java
+++ b/org.hl7.fhir.r4/src/test/java/org/hl7/fhir/r4/test/FHIRMappingLanguageTests.java
@@ -80,9 +80,8 @@ public class FHIRMappingLanguageTests implements ITransformerServices {
@BeforeClass
static public void setUp() throws Exception {
if (context == null) {
- context = new SimpleWorkerContext();
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
- context.loadFromPackage(pcm.loadPackageCacheLatest("hl7.fhir.core"), null, "StructureDefinition");
+ context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);
}
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/StructureMapUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/StructureMapUtilities.java
index 9c047ea71..de8895ce3 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/StructureMapUtilities.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/StructureMapUtilities.java
@@ -1170,11 +1170,13 @@ public class StructureMapUtilities {
target.addListMode(StructureMapTargetListMode.SHARE);
lexer.next();
target.setListRuleId(lexer.take());
- } else if (lexer.getCurrent().equals("first"))
- target.addListMode(StructureMapTargetListMode.FIRST);
- else
- target.addListMode(StructureMapTargetListMode.LAST);
- lexer.next();
+ } else {
+ if (lexer.getCurrent().equals("first"))
+ target.addListMode(StructureMapTargetListMode.FIRST);
+ else
+ target.addListMode(StructureMapTargetListMode.LAST);
+ lexer.next();
+ }
}
}
@@ -1219,7 +1221,7 @@ public class StructureMapUtilities {
}
public enum VariableMode {
- INPUT, OUTPUT
+ INPUT, OUTPUT, SHARED
}
public class Variable {
@@ -1277,16 +1279,25 @@ public class StructureMapUtilities {
return null;
}
- public String summary() {
- CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
- CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
- for (Variable v : list)
- if (v.mode == VariableMode.INPUT)
- s.append(v.summary());
- else
- t.append(v.summary());
- return "source variables ["+s.toString()+"], target variables ["+t.toString()+"]";
- }
+ public String summary() {
+ CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
+ CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
+ CommaSeparatedStringBuilder sh = new CommaSeparatedStringBuilder();
+ for (Variable v : list)
+ switch(v.mode) {
+ case INPUT:
+ s.append(v.summary());
+ break;
+ case OUTPUT:
+ t.append(v.summary());
+ break;
+ case SHARED:
+ sh.append(v.summary());
+ break;
+ }
+ return "source variables ["+s.toString()+"], target variables ["+t.toString()+"], shared variables ["+sh.toString()+"]";
+ }
+
}
public class TransformContext {
@@ -1379,7 +1390,7 @@ public class StructureMapUtilities {
if (source != null) {
for (Variables v : source) {
for (StructureMapGroupRuleTargetComponent t : rule.getTarget()) {
- processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot);
+ processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot, vars);
}
if (rule.hasRule()) {
for (StructureMapGroupRuleComponent childrule : rule.getRule()) {
@@ -1781,7 +1792,7 @@ public class StructureMapUtilities {
return false;
}
- private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot) throws FHIRException {
+ private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot, Variables sharedVars) throws FHIRException {
Base dest = null;
if (tgt.hasContext()) {
dest = vars.get(VariableMode.OUTPUT, tgt.getContext());
@@ -1795,8 +1806,17 @@ public class StructureMapUtilities {
v = runTransform(ruleId, context, map, group, tgt, vars, dest, tgt.getElement(), srcVar, atRoot);
if (v != null && dest != null)
v = dest.setProperty(tgt.getElement().hashCode(), tgt.getElement(), v); // reset v because some implementations may have to rewrite v when setting the value
- } else if (dest != null)
- v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
+ } else if (dest != null) {
+ if (tgt.hasListMode(StructureMapTargetListMode.SHARE)) {
+ v = sharedVars.get(VariableMode.SHARED, tgt.getListRuleId());
+ if (v == null) {
+ v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
+ sharedVars.add(VariableMode.SHARED, tgt.getListRuleId(), v);
+ }
+ } else {
+ v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
+ }
+ }
if (tgt.hasVariable() && v != null)
vars.add(VariableMode.OUTPUT, tgt.getVariable(), v);
}
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/.gitignore b/org.hl7.fhir.r5/src/main/resources/fml/.gitignore
new file mode 100644
index 000000000..fa929750c
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/.gitignore
@@ -0,0 +1 @@
+*.out
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/manifest.xml b/org.hl7.fhir.r5/src/main/resources/fml/manifest.xml
new file mode 100644
index 000000000..89b3d6b31
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/manifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr.json b/org.hl7.fhir.r5/src/main/resources/fml/qr.json
new file mode 100644
index 000000000..f0d14a3c1
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr.json
@@ -0,0 +1,39 @@
+{
+ "resourceType": "QuestionnaireResponse",
+ "status": "in-progress",
+ "item": [
+ {
+ "linkId": "patient",
+ "text": "Patient",
+ "item": [
+ {
+ "linkId": "patient.lastname",
+ "text": "Name",
+ "answer": [
+ {
+ "valueString": "Brönnimann-Bertholet"
+ }
+ ]
+ },
+ {
+ "linkId": "patient.firstname",
+ "text": "Vorname",
+ "answer": [
+ {
+ "valueString": "Elisabeth"
+ }
+ ]
+ },
+ {
+ "linkId": "patient.sex",
+ "text": "Geschlecht",
+ "answer": [
+ {
+ "valueString": "female"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment-res.json b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment-res.json
new file mode 100644
index 000000000..c29553577
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment-res.json
@@ -0,0 +1,4 @@
+{
+ "resourceType" : "Patient",
+ "gender" : "female"
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment.map b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment.map
new file mode 100644
index 000000000..79ddfb89b
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-assignment.map
@@ -0,0 +1,8 @@
+map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" = "qr2patassignment"
+
+uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
+uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
+
+group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
+ src -> tgt.gender = 'female' "Simple Assignment";
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender-res.json b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender-res.json
new file mode 100644
index 000000000..c29553577
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender-res.json
@@ -0,0 +1,4 @@
+{
+ "resourceType" : "Patient",
+ "gender" : "female"
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender.map b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender.map
new file mode 100644
index 000000000..ee25265c6
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-gender.map
@@ -0,0 +1,12 @@
+map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" = "qr2patgender"
+
+uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
+uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
+
+group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
+ src.item as item -> tgt as patient then item(item, patient);
+}
+
+group item(source src, target tgt: Patient) {
+ src.item as item where linkId.value in ('patient.sex') -> tgt.gender = (item.answer.valueString);
+}
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared-res.json b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared-res.json
new file mode 100644
index 000000000..240a91c69
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared-res.json
@@ -0,0 +1,8 @@
+{
+ "resourceType" : "Patient",
+ "name" : [{
+ "family" : "Brönnimann-Bertholet",
+ "given" : ["Elisabeth"]
+ }],
+ "gender" : "female"
+}
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared.map b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared.map
new file mode 100644
index 000000000..178a5d658
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannameshared.map
@@ -0,0 +1,26 @@
+map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" = "qr2pathumannametwice"
+
+uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
+uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
+
+group entry(source src : QuestionnaireResponse, target tgt : Patient) {
+ src.item as item then item(item, tgt);
+}
+
+group item(source src, target tgt) {
+ src.item as item then item(item, tgt);
+ src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name share patientName then humanNameFamily(item, name);
+ src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name share patientName then humanNameGiven(item, name);
+ src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
+}
+
+group humanNameFamily(source src, target tgt: HumanName) {
+ src.answer as answer -> tgt.family = (answer.valueString);
+}
+group humanNameGiven(source src, target tgt: HumanName) {
+ src.answer as answer -> tgt.given = (answer.valueString);
+}
+
+group administrativeGender(source src, target tgt: code) {
+ src.answer as answer -> tgt = (answer.valueString);
+}
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice-res.json b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice-res.json
new file mode 100644
index 000000000..9d9bab7db
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice-res.json
@@ -0,0 +1,10 @@
+{
+ "resourceType" : "Patient",
+ "name" : [{
+ "family" : "Brönnimann-Bertholet"
+ },
+ {
+ "given" : ["Elisabeth"]
+ }],
+ "gender" : "female"
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice.map b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice.map
new file mode 100644
index 000000000..6de8b3c88
--- /dev/null
+++ b/org.hl7.fhir.r5/src/main/resources/fml/qr2pat-humannametwice.map
@@ -0,0 +1,26 @@
+map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" = "qr2pathumannametwice"
+
+uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
+uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
+
+group entry(source src : QuestionnaireResponse, target tgt : Patient) {
+ src.item as item then item(item, tgt);
+}
+
+group item(source src, target tgt) {
+ src.item as item then item(item, tgt);
+ src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name then humanNameFamily(item, name);
+ src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name then humanNameGiven(item, name);
+ src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
+}
+
+group humanNameFamily(source src, target tgt: HumanName) {
+ src.answer as answer -> tgt.family = (answer.valueString);
+}
+group humanNameGiven(source src, target tgt: HumanName) {
+ src.answer as answer -> tgt.given = (answer.valueString);
+}
+
+group administrativeGender(source src, target tgt: code) {
+ src.answer as answer -> tgt = (answer.valueString);
+}
diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRMappingLanguageTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRMappingLanguageTests.java
new file mode 100644
index 000000000..906aba456
--- /dev/null
+++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/FHIRMappingLanguageTests.java
@@ -0,0 +1,167 @@
+package org.hl7.fhir.r5.test;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.hl7.fhir.exceptions.FHIRException;
+import org.hl7.fhir.r5.context.SimpleWorkerContext;
+import org.hl7.fhir.r5.elementmodel.Manager;
+import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
+import org.hl7.fhir.r5.formats.IParser.OutputStyle;
+import org.hl7.fhir.r5.formats.JsonParser;
+import org.hl7.fhir.r5.model.Base;
+import org.hl7.fhir.r5.model.Coding;
+import org.hl7.fhir.r5.model.Resource;
+import org.hl7.fhir.r5.model.ResourceFactory;
+import org.hl7.fhir.r5.model.StructureDefinition;
+import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
+import org.hl7.fhir.r5.model.StructureMap;
+import org.hl7.fhir.r5.terminologies.ConceptMapEngine;
+import org.hl7.fhir.r5.test.utils.TestingUtilities;
+import org.hl7.fhir.r5.utils.StructureMapUtilities;
+import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
+import org.hl7.fhir.utilities.TextFile;
+import org.hl7.fhir.utilities.Utilities;
+import org.hl7.fhir.utilities.cache.PackageCacheManager;
+import org.hl7.fhir.utilities.cache.ToolsVersion;
+import org.hl7.fhir.utilities.xml.XMLUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+@RunWith(Parameterized.class)
+
+public class FHIRMappingLanguageTests implements ITransformerServices {
+
+ private List outputs = new ArrayList();
+
+ static private SimpleWorkerContext context;
+ static private JsonParser jsonParser;
+
+ @Parameters(name = "{index}: {0}")
+ public static Iterable