Merge pull request #197 from ahdis/oliveregger_cdatitle

Deserializing CDA ST and ED elements from JSON fix
This commit is contained in:
Grahame Grieve 2020-06-10 08:47:13 +10:00 committed by GitHub
commit b01c64dc2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 76 deletions

View File

@ -183,7 +183,7 @@ public class JsonParser extends ParserBase {
} }
public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) { public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) {
if (property.isChoice()) { if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) {
for (TypeRefComponent type : property.getDefinition().getType()) { for (TypeRefComponent type : property.getDefinition().getType()) {
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode()); String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) { if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) {

View File

@ -184,7 +184,7 @@ public class JsonParser extends ParserBase {
} }
public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) { public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) {
if (property.isChoice()) { if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) {
for (TypeRefComponent type : property.getDefinition().getType()) { for (TypeRefComponent type : property.getDefinition().getType()) {
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode()); String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) { if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) {

View File

@ -210,6 +210,10 @@ public class XmlParser extends ParserBase {
return "h:"; return "h:";
if (ns.equals("urn:hl7-org:v3")) if (ns.equals("urn:hl7-org:v3"))
return "v3:"; return "v3:";
if (ns.equals("urn:hl7-org:sdtc"))
return "sdtc:";
if (ns.equals("urn:ihe:pharm"))
return "pharm:";
return "?:"; return "?:";
} }
@ -538,9 +542,29 @@ public class XmlParser extends ParserBase {
xml.setDefaultNamespace(e.getProperty().getXmlNamespace()); xml.setDefaultNamespace(e.getProperty().getXmlNamespace());
if (hasTypeAttr(e)) if (hasTypeAttr(e))
xml.namespace("http://www.w3.org/2001/XMLSchema-instance", "xsi"); xml.namespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");
addNamespaces(xml, e);
composeElement(xml, e, e.getType(), true); composeElement(xml, e, e.getType(), true);
xml.end(); xml.end();
}
private void addNamespaces(IXMLWriter xml, Element e) throws IOException {
String ns = e.getProperty().getXmlNamespace();
if (ns!=null && !xml.getDefaultNamespace().equals(ns)){
if (!xml.namespaceDefined(ns)) {
String prefix = pathPrefix(ns);
if (prefix.endsWith(":")) {
prefix = prefix.substring(0, prefix.length()-1);
}
if ("?".equals(prefix)) {
xml.namespace(ns);
} else {
xml.namespace(ns, prefix);
}
}
}
for (Element c : e.getChildren()) {
addNamespaces(xml, c);
}
} }
private boolean hasTypeAttr(Element e) { private boolean hasTypeAttr(Element e) {
@ -584,9 +608,9 @@ public class XmlParser extends ParserBase {
if (isText(element.getProperty())) { if (isText(element.getProperty())) {
if (linkResolver != null) if (linkResolver != null)
xml.link(linkResolver.resolveProperty(element.getProperty())); xml.link(linkResolver.resolveProperty(element.getProperty()));
xml.enter(elementName); xml.enter(element.getProperty().getXmlNamespace(),elementName);
xml.text(element.getValue()); xml.text(element.getValue());
xml.exit(elementName); xml.exit(element.getProperty().getXmlNamespace(),elementName);
} else if (!element.hasChildren() && !element.hasValue()) { } else if (!element.hasChildren() && !element.hasValue()) {
if (element.getExplicitType() != null) if (element.getExplicitType() != null)
xml.attribute("xsi:type", element.getExplicitType()); xml.attribute("xsi:type", element.getExplicitType());
@ -614,10 +638,10 @@ public class XmlParser extends ParserBase {
if (linkResolver != null) if (linkResolver != null)
xml.link(linkResolver.resolveProperty(element.getProperty())); xml.link(linkResolver.resolveProperty(element.getProperty()));
if (element.hasChildren()) { if (element.hasChildren()) {
xml.enter(elementName); xml.enter(element.getProperty().getXmlNamespace(), elementName);
for (Element child : element.getChildren()) for (Element child : element.getChildren())
composeElement(xml, child, child.getName(), false); composeElement(xml, child, child.getName(), false);
xml.exit(elementName); xml.exit(element.getProperty().getXmlNamespace(),elementName);
} else } else
xml.element(elementName); xml.element(elementName);
} }
@ -630,16 +654,16 @@ public class XmlParser extends ParserBase {
String av = child.getValue(); String av = child.getValue();
if (ToolingExtensions.hasExtension(child.getProperty().getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat")) if (ToolingExtensions.hasExtension(child.getProperty().getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat"))
av = convertForDateFormatToExternal(ToolingExtensions.readStringExtension(child.getProperty().getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat"), av); av = convertForDateFormatToExternal(ToolingExtensions.readStringExtension(child.getProperty().getDefinition(), "http://www.healthintersections.com.au/fhir/StructureDefinition/elementdefinition-dateformat"), av);
xml.attribute(child.getName(), av); xml.attribute(child.getProperty().getXmlNamespace(),child.getProperty().getXmlName(), av);
} }
} }
if (linkResolver != null) if (linkResolver != null)
xml.link(linkResolver.resolveProperty(element.getProperty())); xml.link(linkResolver.resolveProperty(element.getProperty()));
xml.enter(elementName); xml.enter(element.getProperty().getXmlNamespace(),elementName);
if (!root && element.getSpecial() != null) { if (!root && element.getSpecial() != null) {
if (linkResolver != null) if (linkResolver != null)
xml.link(linkResolver.resolveProperty(element.getProperty())); xml.link(linkResolver.resolveProperty(element.getProperty()));
xml.enter(element.getType()); xml.enter(element.getProperty().getXmlNamespace(),element.getType());
} }
for (Element child : element.getChildren()) { for (Element child : element.getChildren()) {
if (isText(child.getProperty())) { if (isText(child.getProperty())) {
@ -650,8 +674,8 @@ public class XmlParser extends ParserBase {
composeElement(xml, child, child.getName(), false); composeElement(xml, child, child.getName(), false);
} }
if (!root && element.getSpecial() != null) if (!root && element.getSpecial() != null)
xml.exit(element.getType()); xml.exit(element.getProperty().getXmlNamespace(),element.getType());
xml.exit(elementName); xml.exit(element.getProperty().getXmlNamespace(),elementName);
} }
} }

View File

@ -1,11 +1,14 @@
package org.hl7.fhir.r5.test; package org.hl7.fhir.r5.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine;
@ -13,22 +16,33 @@ import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion; import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class CDARoundTripTests { public class CDARoundTripTests {
// private SimpleWorkerContext context; private static SimpleWorkerContext context;
// old-test private FHIRPathEngine fp; private static FHIRPathEngine fp;
@BeforeAll @BeforeAll
public static void setUp() throws Exception { public static void setUp() throws Exception {
// old-test context = new SimpleWorkerContext(); FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
// old-test PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION); context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r4.core", "4.0.1"));
// old-test context.loadFromPackage(pcm.loadPackage("hl7.fhir.core", "dev"), null, "StructureDefinition"); fp = new FHIRPathEngine(context);
// old-test context.loadFromPackage(pcm.loadPackage("hl7.fhir.cda", "dev"), null, "StructureDefinition");
// old-test fp = new FHIRPathEngine(context); context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "any.xml"), "any.xml", null);
} context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ii.xml"), "ii.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cd.xml"), "cd.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ce.xml"), "ce.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null);
for (StructureDefinition sd : context.getStructures()) {
if (!sd.hasSnapshot()) {
System.out.println("generate snapshot for " + sd.getUrl());
context.generateSnapshot(sd, true);
}
}
}
// old-test // old-test
// @Test // @Test
@ -172,29 +186,57 @@ public class CDARoundTripTests {
// FhirFormat.TURTLE, OutputStyle.PRETTY, null); // FhirFormat.TURTLE, OutputStyle.PRETTY, null);
// } // }
public void assertsExample(Element cdaExample) {
@Test Assertions.assertEquals("2.16.840.1.113883.3.27.1776", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.templateId.root")));
public void testSimple() throws IOException { Assertions.assertEquals("SoEN", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.code.displayName")));
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION); Assertions.assertEquals("SoEN2", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.code.sdtcDisplayName")));
SimpleWorkerContext context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r4.core", "4.0.1")); Assertions.assertEquals("c266", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.id.extension")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "any.xml"), "any.xml", null); Assertions.assertEquals("2.16.840.1.113883.19.4", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.id.root")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ii.xml"), "ii.xml", null); Assertions.assertEquals("X-34133-9", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.code.code")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cd.xml"), "cd.xml", null); Assertions.assertEquals("2.16.840.1.113883.6.1", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.code.codeSystem")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ce.xml"), "ce.xml", null); Assertions.assertEquals("LOINC", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.code.codeSystemName")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "ed.xml"), "ed.xml", null); Assertions.assertEquals("Episode Note", fp.evaluateToString(null, cdaExample, cdaExample, cdaExample, fp.parse("ClinicalDocument.title.dataString")));
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "st.xml"), "st.xml", null);
context.loadFromFile(TestingUtilities.loadTestResourceStream("validator", "cda", "cda.xml"), "cda.xml", null);
for (StructureDefinition sd : context.getStructures()) {
if (!sd.hasSnapshot()) {
System.out.println("generate snapshot for " + sd.getUrl());
context.generateSnapshot(sd, true);
}
}
Element cda = Manager.parse(context, TestingUtilities.loadTestResourceStream("validator", "cda", "example.xml"), FhirFormat.XML);
FHIRPathEngine fp = new FHIRPathEngine(context);
Assertions.assertEquals("2.16.840.1.113883.3.27.1776", fp.evaluateToString(null, cda, cda, cda, fp.parse("ClinicalDocument.templateId.root")));
Assertions.assertEquals("SoEN", fp.evaluateToString(null, cda, cda, cda, fp.parse("ClinicalDocument.code.displayName")));
Assertions.assertEquals("SoEN2", fp.evaluateToString(null, cda, cda, cda, fp.parse("ClinicalDocument.code.sdtcDisplayName")));
} }
@Test
/**
* Deserializes a simplified CDA example into the logical model and checks that
* xml deserialization/serialization
*
* @throws IOException
*/
public void testClinicalDocumentXmlParser() throws IOException {
Element cda = Manager.parse(context, TestingUtilities.loadTestResourceStream("validator", "cda", "example.xml"),
FhirFormat.XML);
assertsExample(cda);
ByteArrayOutputStream baosXml = new ByteArrayOutputStream();
Manager.compose(context, cda, baosXml, FhirFormat.XML, OutputStyle.PRETTY, null);
Element cdaXmlRoundtrip = Manager.parse(context, new ByteArrayInputStream(baosXml.toString().getBytes()), FhirFormat.XML);
assertsExample(cdaXmlRoundtrip);
}
@Test
/**
* Deserializes a simplified CDA example into the logical model and checks that
* json deserialization/serialization works
*
* @throws IOException
*/
public void testClinicalDocumentJsonParser() throws IOException {
Element cda = Manager.parse(context, TestingUtilities.loadTestResourceStream("validator", "cda", "example.xml"),
FhirFormat.XML);
assertsExample(cda);
ByteArrayOutputStream baosJson = new ByteArrayOutputStream();
Manager.compose(context, cda, baosJson, FhirFormat.JSON, OutputStyle.PRETTY, null);
Element cdaJsonRoundtrip = Manager.parse(context, new ByteArrayInputStream(baosJson.toString().getBytes()),
FhirFormat.JSON);
assertsExample(cdaJsonRoundtrip);
}
} }