fix OID translation case
This commit is contained in:
parent
089f539801
commit
ba4628eb28
|
@ -1098,6 +1098,10 @@ public abstract class BaseWorkerContext implements IWorkerContext {
|
|||
@Override
|
||||
public String oid2Uri(String oid) {
|
||||
synchronized (lock) {
|
||||
if (oid != null && oid.startsWith("urn:oid:")) {
|
||||
oid = oid.substring(8);
|
||||
}
|
||||
|
||||
String uri = OIDUtils.getUriForOid(oid);
|
||||
if (uri != null)
|
||||
return uri;
|
||||
|
|
|
@ -248,6 +248,7 @@ public interface IWorkerContext {
|
|||
* @throws FHIRException
|
||||
*/
|
||||
public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException;
|
||||
public void generateSnapshot(StructureDefinition mr, boolean ifLogical);
|
||||
|
||||
// -- Terminology services ------------------------------------------------------
|
||||
|
||||
|
@ -543,4 +544,5 @@ public interface IWorkerContext {
|
|||
|
||||
public String getLinkForUrl(String corePath, String s);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -593,10 +593,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException {
|
||||
generateSnapshot(p, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSnapshot(StructureDefinition p, boolean logical) throws DefinitionException, FHIRException {
|
||||
if (!p.hasSnapshot() && (logical || p.getKind() != StructureDefinitionKind.LOGICAL)) {
|
||||
if (!p.hasBaseDefinition())
|
||||
|
|
|
@ -176,7 +176,7 @@ public class Property {
|
|||
if (definition.getType().size() > 0)
|
||||
return definition.getType().size() == 1 && ("Resource".equals(definition.getType().get(0).getCode()) || "DomainResource".equals(definition.getType().get(0).getCode()));
|
||||
else
|
||||
return !definition.getPath().contains(".") && structure.getKind() == StructureDefinitionKind.RESOURCE;
|
||||
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE || structure.getKind() == StructureDefinitionKind.LOGICAL);
|
||||
}
|
||||
|
||||
public boolean isList() {
|
||||
|
|
|
@ -17,6 +17,8 @@ import org.hl7.fhir.r5.elementmodel.Element;
|
|||
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.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionDifferentialComponent;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.utilities.cache.PackageCacheManager;
|
||||
|
@ -25,158 +27,184 @@ import org.junit.Before;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
public class CDARoundTripTests {
|
||||
|
||||
private SimpleWorkerContext context;
|
||||
private FHIRPathEngine fp;
|
||||
// private SimpleWorkerContext context;
|
||||
// old-test private FHIRPathEngine fp;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
context = new SimpleWorkerContext();
|
||||
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
context.loadFromPackage(pcm.loadPackage("hl7.fhir.core", "dev"), null, "StructureDefinition");
|
||||
context.loadFromPackage(pcm.loadPackage("hl7.fhir.cda", "dev"), null, "StructureDefinition");
|
||||
fp = new FHIRPathEngine(context);
|
||||
// old-test context = new SimpleWorkerContext();
|
||||
// old-test PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
// old-test context.loadFromPackage(pcm.loadPackage("hl7.fhir.core", "dev"), null, "StructureDefinition");
|
||||
// old-test context.loadFromPackage(pcm.loadPackage("hl7.fhir.cda", "dev"), null, "StructureDefinition");
|
||||
// old-test fp = new FHIRPathEngine(context);
|
||||
}
|
||||
|
||||
// old-test
|
||||
// @Test
|
||||
// public void testCDA() throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
// try {
|
||||
//
|
||||
// InputStream fileSource = TestingUtilities.loadTestResourceStream("cda", "cda-original.xml");
|
||||
// String roundTrip = TestingUtilities.tempFile("cda", "cda-roundtrip.xml");
|
||||
// String jsonRoundTrip = TestingUtilities.tempFile("cda", "cda-roundtrip.json");
|
||||
//
|
||||
// Element e = Manager.parse(context, fileSource, FhirFormat.XML);
|
||||
//
|
||||
// Manager.compose(context, e, new FileOutputStream(roundTrip), FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e, new FileOutputStream(jsonRoundTrip), FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
//
|
||||
//// <typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/>
|
||||
//// assertEquals("POCD_HD000040", fp.evaluateToString(e, "typeId.extension"));
|
||||
//// assertEquals("2.16.840.1.113883.1.3", fp.evaluateToString(e, "typeId.root"));
|
||||
//// <templateId root="2.16.840.1.113883.3.27.1776"/>
|
||||
//// assertEquals("2.16.840.1.113883.3.27.1776", fp.evaluateToString(e, "templateId.root"));
|
||||
//// <id extension="c266" root="2.16.840.1.113883.19.4"/>
|
||||
// assertEquals("2.16.840.1.113883.19.4", fp.evaluateToString(e, "id.root"));
|
||||
// assertEquals("c266", fp.evaluateToString(e, "id.extension"));
|
||||
//
|
||||
//// <title>Good Health Clinic Consultation Note</title>
|
||||
// assertEquals("Good Health Clinic Consultation Note", fp.evaluateToString(e, "title.dataString"));
|
||||
//// <effectiveTime value="20000407"/>
|
||||
// assertEquals("2000-04-07", fp.evaluateToString(e, "effectiveTime.value"));
|
||||
//// <confidentialityCode code="N" codeSystem="2.16.840.1.113883.5.25"/>
|
||||
// assertEquals("N", fp.evaluateToString(e, "confidentialityCode.code"));
|
||||
// assertEquals("2.16.840.1.113883.5.25", fp.evaluateToString(e, "confidentialityCode.codeSystem"));
|
||||
//// <languageCode code="en-US"/>
|
||||
// assertEquals("en-US", fp.evaluateToString(e, "languageCode.code"));
|
||||
//// <setId extension="BB35" root="2.16.840.1.113883.19.7"/>
|
||||
// assertEquals("BB35", fp.evaluateToString(e, "setId.extension"));
|
||||
// assertEquals("2.16.840.1.113883.19.7", fp.evaluateToString(e, "setId.root"));
|
||||
//// <versionNumber value="2"/>
|
||||
// assertEquals("2", fp.evaluateToString(e, "versionNumber.value"));
|
||||
//// <recordTarget>
|
||||
//// <patientRole>
|
||||
//// <id extension="12345" root="2.16.840.1.113883.19.5"/>
|
||||
// assertEquals("12345", fp.evaluateToString(e, "recordTarget.patientRole.id.extension"));
|
||||
// assertEquals("2.16.840.1.113883.19.5", fp.evaluateToString(e, "recordTarget.patientRole.id.root"));
|
||||
//// <patient>
|
||||
//// <name>
|
||||
//// <family>Levin</family>
|
||||
// assertEquals("Levin", fp.evaluateToString(e, "recordTarget.patientRole.patient.name.family.dataString"));
|
||||
//// <given>Henry</given>
|
||||
// assertEquals("Henry", fp.evaluateToString(e, "recordTarget.patientRole.patient.name.given.dataString"));
|
||||
//// <suffix>the 7th</suffix>
|
||||
//// </name>
|
||||
//// <administrativeGenderCode code="M" codeSystem="2.16.840.1.113883.5.1"/>
|
||||
//// <birthTime value="19320924"/>
|
||||
//// </patient>
|
||||
//// <providerOrganization>
|
||||
//// <id root="2.16.840.1.113883.19.5"/>
|
||||
//// </providerOrganization>
|
||||
//// </patientRole>
|
||||
//// </recordTarget>
|
||||
//
|
||||
//// <component>
|
||||
//// <structuredBody>
|
||||
//// <component>
|
||||
//// <section>
|
||||
//
|
||||
//// <component>
|
||||
//// <section>
|
||||
//// <code code="8709-8" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
|
||||
//// <title>Skin Exam</title>
|
||||
//// <text>Erythematous rash, palmar surface, left index finger.
|
||||
//// <renderMultiMedia referencedObject="MM1"/>
|
||||
//// </text>
|
||||
//
|
||||
// assertEquals("Skin Exam", fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').title.dataString"));
|
||||
// // <div>Erythematous rash, palmar surface, left index finger.
|
||||
// // <img src="MM1"/></div>
|
||||
// String text = fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').text");
|
||||
// assertTrue(text.contains("<img src=\"MM1\"/>"));
|
||||
// } catch (Exception e) {
|
||||
// System.out.println(e.getMessage());
|
||||
// e.printStackTrace();
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Ignore
|
||||
// public void testDCI() throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
// try {
|
||||
// Element e = Manager.parse(context,
|
||||
// new FileInputStream("C:\\work\\org.hl7.fhir.us\\ccda-to-fhir-maps\\cda\\IAT2-Discharge_Summary-DCI.xml"),
|
||||
// FhirFormat.XML);
|
||||
//
|
||||
// Manager.compose(context, e, new FileOutputStream("C:\\temp\\ccda.xml"), FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
//// Manager.compose(context, e, new FileOutputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge_Summary-DCI.out.json"), FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
//// Manager.compose(context, e, new FileOutputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge_Summary-DCI.out.ttl"), FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
// } catch (Exception e) {
|
||||
// System.out.println(e.getMessage());
|
||||
// e.printStackTrace();
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Ignore
|
||||
// public void testEpic()
|
||||
// throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
// Element e = Manager.parse(context,
|
||||
// new FileInputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.xml"),
|
||||
// FhirFormat.XML);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.xml"),
|
||||
// FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.json"),
|
||||
// FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.ttl"),
|
||||
// FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
// }
|
||||
//
|
||||
// @Ignore
|
||||
// public void testDHIT()
|
||||
// throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
// Element e = Manager.parse(context,
|
||||
// new FileInputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.xml"),
|
||||
// FhirFormat.XML);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.xml"),
|
||||
// FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.json"),
|
||||
// FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e,
|
||||
// new FileOutputStream(
|
||||
// "C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.ttl"),
|
||||
// FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
// }
|
||||
|
||||
|
||||
@Test
|
||||
public void testCDA() throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
try {
|
||||
|
||||
InputStream fileSource = TestingUtilities.loadTestResourceStream("cda", "cda-original.xml");
|
||||
String roundTrip = TestingUtilities.tempFile("cda", "cda-roundtrip.xml");
|
||||
String jsonRoundTrip = TestingUtilities.tempFile("cda", "cda-roundtrip.json");
|
||||
|
||||
Element e = Manager.parse(context, fileSource, FhirFormat.XML);
|
||||
|
||||
Manager.compose(context, e, new FileOutputStream(roundTrip), FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
Manager.compose(context, e, new FileOutputStream(jsonRoundTrip), FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
|
||||
// <typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/>
|
||||
// assertEquals("POCD_HD000040", fp.evaluateToString(e, "typeId.extension"));
|
||||
// assertEquals("2.16.840.1.113883.1.3", fp.evaluateToString(e, "typeId.root"));
|
||||
// <templateId root="2.16.840.1.113883.3.27.1776"/>
|
||||
// assertEquals("2.16.840.1.113883.3.27.1776", fp.evaluateToString(e, "templateId.root"));
|
||||
// <id extension="c266" root="2.16.840.1.113883.19.4"/>
|
||||
assertEquals("2.16.840.1.113883.19.4", fp.evaluateToString(e, "id.root"));
|
||||
assertEquals("c266", fp.evaluateToString(e, "id.extension"));
|
||||
|
||||
// <title>Good Health Clinic Consultation Note</title>
|
||||
assertEquals("Good Health Clinic Consultation Note", fp.evaluateToString(e, "title.dataString"));
|
||||
// <effectiveTime value="20000407"/>
|
||||
assertEquals("2000-04-07", fp.evaluateToString(e, "effectiveTime.value"));
|
||||
// <confidentialityCode code="N" codeSystem="2.16.840.1.113883.5.25"/>
|
||||
assertEquals("N", fp.evaluateToString(e, "confidentialityCode.code"));
|
||||
assertEquals("2.16.840.1.113883.5.25", fp.evaluateToString(e, "confidentialityCode.codeSystem"));
|
||||
// <languageCode code="en-US"/>
|
||||
assertEquals("en-US", fp.evaluateToString(e, "languageCode.code"));
|
||||
// <setId extension="BB35" root="2.16.840.1.113883.19.7"/>
|
||||
assertEquals("BB35", fp.evaluateToString(e, "setId.extension"));
|
||||
assertEquals("2.16.840.1.113883.19.7", fp.evaluateToString(e, "setId.root"));
|
||||
// <versionNumber value="2"/>
|
||||
assertEquals("2", fp.evaluateToString(e, "versionNumber.value"));
|
||||
// <recordTarget>
|
||||
// <patientRole>
|
||||
// <id extension="12345" root="2.16.840.1.113883.19.5"/>
|
||||
assertEquals("12345", fp.evaluateToString(e, "recordTarget.patientRole.id.extension"));
|
||||
assertEquals("2.16.840.1.113883.19.5", fp.evaluateToString(e, "recordTarget.patientRole.id.root"));
|
||||
// <patient>
|
||||
// <name>
|
||||
// <family>Levin</family>
|
||||
assertEquals("Levin", fp.evaluateToString(e, "recordTarget.patientRole.patient.name.family.dataString"));
|
||||
// <given>Henry</given>
|
||||
assertEquals("Henry", fp.evaluateToString(e, "recordTarget.patientRole.patient.name.given.dataString"));
|
||||
// <suffix>the 7th</suffix>
|
||||
// </name>
|
||||
// <administrativeGenderCode code="M" codeSystem="2.16.840.1.113883.5.1"/>
|
||||
// <birthTime value="19320924"/>
|
||||
// </patient>
|
||||
// <providerOrganization>
|
||||
// <id root="2.16.840.1.113883.19.5"/>
|
||||
// </providerOrganization>
|
||||
// </patientRole>
|
||||
// </recordTarget>
|
||||
|
||||
// <component>
|
||||
// <structuredBody>
|
||||
// <component>
|
||||
// <section>
|
||||
|
||||
// <component>
|
||||
// <section>
|
||||
// <code code="8709-8" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC"/>
|
||||
// <title>Skin Exam</title>
|
||||
// <text>Erythematous rash, palmar surface, left index finger.
|
||||
// <renderMultiMedia referencedObject="MM1"/>
|
||||
// </text>
|
||||
|
||||
assertEquals("Skin Exam", fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').title.dataString"));
|
||||
// <div>Erythematous rash, palmar surface, left index finger.
|
||||
// <img src="MM1"/></div>
|
||||
String text = fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').text");
|
||||
assertTrue(text.contains("<img src=\"MM1\"/>"));
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
public void testSimple() throws IOException {
|
||||
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
SimpleWorkerContext context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.r4.core", "4.0.1"));
|
||||
context.loadFromFile(TestingUtilities.loadTestResourceStream("r5", "cda", "any.xml"), "any.xml", null);
|
||||
context.loadFromFile(TestingUtilities.loadTestResourceStream("r5", "cda", "ii.xml"), "ii.xml", null);
|
||||
context.loadFromFile(TestingUtilities.loadTestResourceStream("r5", "cda", "cd.xml"), "cd.xml", null);
|
||||
context.loadFromFile(TestingUtilities.loadTestResourceStream("r5", "cda", "ce.xml"), "ce.xml", null);
|
||||
context.loadFromFile(TestingUtilities.loadTestResourceStream("r5", "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("r5", "cda", "example.xml"), FhirFormat.XML);
|
||||
FHIRPathEngine fp = new FHIRPathEngine(context);
|
||||
Assert.assertEquals("2.16.840.1.113883.3.27.1776", fp.evaluateToString(null, cda, cda, cda, fp.parse("ClinicalDocument.templateId.root")));
|
||||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testDCI() throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
try {
|
||||
Element e = Manager.parse(context,
|
||||
new FileInputStream("C:\\work\\org.hl7.fhir.us\\ccda-to-fhir-maps\\cda\\IAT2-Discharge_Summary-DCI.xml"),
|
||||
FhirFormat.XML);
|
||||
|
||||
Manager.compose(context, e, new FileOutputStream("C:\\temp\\ccda.xml"), FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e, new FileOutputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge_Summary-DCI.out.json"), FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
// Manager.compose(context, e, new FileOutputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge_Summary-DCI.out.ttl"), FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testEpic()
|
||||
throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
Element e = Manager.parse(context,
|
||||
new FileInputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.xml"),
|
||||
FhirFormat.XML);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.xml"),
|
||||
FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.json"),
|
||||
FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-Discharge-Homework-Epic.out.ttl"),
|
||||
FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void testDHIT()
|
||||
throws FHIRFormatError, DefinitionException, FileNotFoundException, IOException, FHIRException {
|
||||
Element e = Manager.parse(context,
|
||||
new FileInputStream("C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.xml"),
|
||||
FhirFormat.XML);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.xml"),
|
||||
FhirFormat.XML, OutputStyle.PRETTY, null);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.json"),
|
||||
FhirFormat.JSON, OutputStyle.PRETTY, null);
|
||||
Manager.compose(context, e,
|
||||
new FileOutputStream(
|
||||
"C:\\work\\org.hl7.fhir.test\\ccda-to-fhir-maps\\testdocuments\\IAT2-DS-Homework-DHIT.out.ttl"),
|
||||
FhirFormat.TURTLE, OutputStyle.PRETTY, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,9 @@ public class OIDUtils {
|
|||
*/
|
||||
|
||||
public static String getUriForOid(String r) {
|
||||
if (r == null) {
|
||||
return null;
|
||||
}
|
||||
if (r.equals("2.16.840.1.113883.6.96"))
|
||||
return "http://snomed.info/sct";
|
||||
if (r.equals("2.16.840.1.113883.6.1"))
|
||||
|
|
|
@ -135,7 +135,10 @@ public class VersionUtilities {
|
|||
if (version == null)
|
||||
return null;
|
||||
|
||||
if (Utilities.charCount(version, '.') == 2) {
|
||||
if (Utilities.charCount(version, '.') == 1) {
|
||||
String[] p = version.split("\\.");
|
||||
return p[0]+"."+p[1];
|
||||
} else if (Utilities.charCount(version, '.') == 2) {
|
||||
String[] p = version.split("\\.");
|
||||
return p[0]+"."+p[1];
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ValidationOptions {
|
|||
public boolean isGuessSystem() {
|
||||
return guessSystem;
|
||||
}
|
||||
|
||||
|
||||
private ValidationOptions copy() {
|
||||
ValidationOptions n = new ValidationOptions(language);
|
||||
n.useServer = useServer;
|
||||
|
|
|
@ -84,6 +84,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.ConstraintSeverity;
|
|||
import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
|
@ -112,6 +113,7 @@ import org.hl7.fhir.r5.model.SampledData;
|
|||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionSnapshotComponent;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
||||
import org.hl7.fhir.r5.model.TimeType;
|
||||
|
@ -166,6 +168,7 @@ import ca.uhn.fhir.util.ObjectUtil;
|
|||
|
||||
public class InstanceValidator extends BaseValidator implements IResourceValidator {
|
||||
|
||||
|
||||
public class ValidatorHostContext {
|
||||
private Object appContext;
|
||||
private Element container; // bundle, or parameters
|
||||
|
@ -1135,6 +1138,245 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return res;
|
||||
}
|
||||
|
||||
private boolean checkTerminologyCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, NodeStack stack, StructureDefinition logical) {
|
||||
boolean res = true;
|
||||
if (!noTerminologyChecks && theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, "Binding for " + path + " missing (cc)")) {
|
||||
if (binding.hasValueSet()) {
|
||||
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, "ValueSet " + describeReference(binding.getValueSet()) + " not found by validator")) {
|
||||
try {
|
||||
CodeableConcept cc = convertToCodeableConcept(element, logical);
|
||||
if (!cc.hasCoding()) {
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED)
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "No code provided, and a code is required from the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl());
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "No code provided, and a code must be provided from the value set " + describeReference(ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet")) + " (max value set " + valueset.getUrl()+")");
|
||||
else
|
||||
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "No code provided, and a code should be provided from the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl()+")");
|
||||
}
|
||||
} else {
|
||||
long t = System.nanoTime();
|
||||
|
||||
// Check whether the codes are appropriate for the type of binding we have
|
||||
boolean bindingsOk = true;
|
||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
boolean atLeastOneSystemIsSupported = false;
|
||||
for (Coding nextCoding : cc.getCoding()) {
|
||||
String nextSystem = nextCoding.getSystem();
|
||||
if (isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
atLeastOneSystemIsSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!atLeastOneSystemIsSupported && binding.getStrength() == BindingStrength.EXAMPLE) {
|
||||
// ignore this since we can't validate but it doesn't matter..
|
||||
} else {
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang), cc, valueset); // we're going to validate the codings directly
|
||||
if (!vr.isOk()) {
|
||||
bindingsOk = false;
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " and a code from this value set is required (class = "+vr.getErrorClass().toString()+")");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " and a code should come from this value set unless it has no suitable code (class = "+vr.getErrorClass().toString()+")");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " and a code is recommended to come from this value set (class = "+vr.getErrorClass().toString()+")");
|
||||
} else {
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED)
|
||||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "None of the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl()+", and a code from this value set is required) (codes = "+ccSummary(cc)+")");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
|
||||
if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "None of the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code) (codes = "+ccSummary(cc)+")");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED) {
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "None of the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code is recommended to come from this value set) (codes = "+ccSummary(cc)+")");
|
||||
}
|
||||
}
|
||||
} else if (vr.getMessage()!=null) {
|
||||
res = false;
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
} else {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
// Then, for any codes that are in code systems we are able
|
||||
// to validate, we'll validate that the codes actually exist
|
||||
if (bindingsOk) {
|
||||
for (Coding nextCoding : cc.getCoding()) {
|
||||
String nextCode = nextCoding.getCode();
|
||||
String nextSystem = nextCoding.getSystem();
|
||||
if (isNotBlank(nextCode) && isNotBlank(nextSystem) && context.supportsSystem(nextSystem)) {
|
||||
ValidationResult vr = context.validateCode(new ValidationOptions(stack.workingLang), nextSystem, nextCode, null);
|
||||
if (!vr.isOk()) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Code {0} is not a valid code in code system {1}", nextCode, nextSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating CodeableConcept");
|
||||
}
|
||||
// special case: if the logical model has both CodeableConcept and Coding mappings, we'll also check the first coding.
|
||||
if (getMapping("http://hl7.org/fhir/terminology-pattern", logical, logical.getSnapshot().getElementFirstRep()).contains("Coding")) {
|
||||
checkTerminologyCoding(errors, path, element, profile, theElementCntext, true, true, stack, logical);
|
||||
}
|
||||
}
|
||||
} else if (binding.hasValueSet()) {
|
||||
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Binding by URI reference cannot be checked");
|
||||
} else if (!noBindingMsgSuppressed) {
|
||||
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Binding for path " + path + " has no source, so can't be checked");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void checkTerminologyCoding(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay, NodeStack stack, StructureDefinition logical) {
|
||||
Coding c = convertToCoding(element, logical);
|
||||
String code = c.getCode();
|
||||
String system = c.getSystem();
|
||||
String display = c.getDisplay();
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), "Coding.system must be an absolute reference, not a local reference");
|
||||
|
||||
if (system != null && code != null && !noTerminologyChecks) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), "The Coding references a value set, not a code system (\""+system+"\")");
|
||||
try {
|
||||
if (checkCode(errors, element, path, code, system, display, checkDisplay, stack))
|
||||
if (theElementCntext != null && theElementCntext.hasBinding()) {
|
||||
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, "Binding for " + path + " missing")) {
|
||||
if (binding.hasValueSet()) {
|
||||
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
|
||||
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, valueset != null, "ValueSet " + describeReference(binding.getValueSet()) + " not found by validator")) {
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ValidationResult vr = null;
|
||||
if (binding.getStrength() != BindingStrength.EXAMPLE) {
|
||||
vr = context.validateCode(new ValidationOptions(stack.workingLang), c, valueset);
|
||||
}
|
||||
txTime = txTime + (System.nanoTime() - t);
|
||||
if (vr != null && !vr.isOk()) {
|
||||
if (vr.IsNoService())
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided could not be validated in the absence of a terminology server");
|
||||
else if (vr.getErrorClass() != null && !vr.getErrorClass().isInfrastructure()) {
|
||||
if (binding.getStrength() == BindingStrength.REQUIRED)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl()+", and a code from this value set is required)");
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code)");
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "Could not confirm that the codes provided are in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code is recommended to come from this value set)");
|
||||
} else if (binding.getStrength() == BindingStrength.REQUIRED)
|
||||
txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The Coding provided is not in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code is required from this value set)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"))
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
|
||||
else
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The Coding provided is not in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code should come from this value set unless it has no suitable code)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED)
|
||||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The Coding provided is not in the value set " + describeReference(binding.getValueSet()) + " (" + valueset.getUrl() + ", and a code is recommended to come from this value set)"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding");
|
||||
}
|
||||
}
|
||||
} else if (binding.hasValueSet()) {
|
||||
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Binding by URI reference cannot be checked");
|
||||
} else if (!inCodeableConcept && !noBindingMsgSuppressed) {
|
||||
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Binding for path " + path + " has no source, so can't be checked");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CodeableConcept convertToCodeableConcept(Element element, StructureDefinition logical) {
|
||||
CodeableConcept res = new CodeableConcept();
|
||||
for (ElementDefinition ed : logical.getSnapshot().getElement()) {
|
||||
if (Utilities.charCount(ed.getPath(), '.') == 1) {
|
||||
List<String> maps = getMapping("http://hl7.org/fhir/terminology-pattern", logical, ed);
|
||||
for (String m : maps) {
|
||||
String name = tail(ed.getPath());
|
||||
List<Element> list = new ArrayList<>();
|
||||
element.getNamedChildren(name, list);
|
||||
if (!list.isEmpty()) {
|
||||
if ("Coding.code".equals(m)) {
|
||||
res.getCodingFirstRep().setCode(list.get(0).primitiveValue());
|
||||
} else if ("Coding.system[fmt:OID]".equals(m)) {
|
||||
String oid = list.get(0).primitiveValue();
|
||||
String url = context.oid2Uri(oid);
|
||||
if (url != null) {
|
||||
res.getCodingFirstRep().setSystem(url);
|
||||
} else {
|
||||
res.getCodingFirstRep().setSystem("urn:oid:"+oid);
|
||||
}
|
||||
} else if ("Coding.version".equals(m)) {
|
||||
res.getCodingFirstRep().setVersion(list.get(0).primitiveValue());
|
||||
} else if ("Coding.display".equals(m)) {
|
||||
res.getCodingFirstRep().setDisplay(list.get(0).primitiveValue());
|
||||
} else if ("CodeableConcept.text".equals(m)) {
|
||||
res.setText(list.get(0).primitiveValue());
|
||||
} else if ("CodeableConcept.coding".equals(m)) {
|
||||
StructureDefinition c = context.fetchTypeDefinition(ed.getTypeFirstRep().getCode());
|
||||
for (Element e : list) {
|
||||
res.addCoding(convertToCoding(e, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private Coding convertToCoding(Element element, StructureDefinition logical) {
|
||||
Coding res = new Coding();
|
||||
for (ElementDefinition ed : logical.getSnapshot().getElement()) {
|
||||
if (Utilities.charCount(ed.getPath(), '.') == 1) {
|
||||
List<String> maps = getMapping("http://hl7.org/fhir/terminology-pattern", logical, ed);
|
||||
for (String m : maps) {
|
||||
String name = tail(ed.getPath());
|
||||
List<Element> list = new ArrayList<>();
|
||||
element.getNamedChildren(name, list);
|
||||
if (!list.isEmpty()) {
|
||||
if ("Coding.code".equals(m)) {
|
||||
res.setCode(list.get(0).primitiveValue());
|
||||
} else if ("Coding.system[fmt:OID]".equals(m)) {
|
||||
String oid = list.get(0).primitiveValue();
|
||||
String url = context.oid2Uri(oid);
|
||||
if (url != null) {
|
||||
res.setSystem(url);
|
||||
} else {
|
||||
res.setSystem("urn:oid:"+oid);
|
||||
}
|
||||
} else if ("Coding.version".equals(m)) {
|
||||
res.setVersion(list.get(0).primitiveValue());
|
||||
} else if ("Coding.display".equals(m)) {
|
||||
res.setDisplay(list.get(0).primitiveValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc, NodeStack stack) {
|
||||
// TODO Auto-generated method stub
|
||||
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
|
||||
|
@ -4194,7 +4436,18 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
} else if (type.equals("Resource")) {
|
||||
validateContains(hostContext, errors, ei.path, ei.definition, definition, resource, ei.element, localStack, idStatusForEntry(element, ei)); // if
|
||||
// (str.matches(".*([.,/])work\\1$"))
|
||||
}
|
||||
} else if (Utilities.isAbsoluteUrl(type)) {
|
||||
StructureDefinition defn = context.fetchTypeDefinition(type);
|
||||
if (defn != null && hasMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep())) {
|
||||
List<String> txtype = getMapping("http://hl7.org/fhir/terminology-pattern", defn, defn.getSnapshot().getElementFirstRep());
|
||||
if (txtype.contains("CodeableConcept")) {
|
||||
checkTerminologyCodeableConcept(errors, ei.path, ei.element, profile, ei.definition, stack, defn);
|
||||
thisIsCodeableConcept = true;
|
||||
} else if (txtype.contains("Coding")) {
|
||||
checkTerminologyCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept, checkDisplayInContext, stack, defn);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), ei.definition != null, "Unrecognised Content " + ei.name))
|
||||
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, false, true);
|
||||
|
@ -4283,6 +4536,44 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasMapping(String url, StructureDefinition defn, ElementDefinition elem) {
|
||||
String id = null;
|
||||
for (StructureDefinitionMappingComponent m : defn.getMapping()) {
|
||||
if (url.equals(m.getUri())) {
|
||||
id = m.getIdentity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id != null) {
|
||||
for (ElementDefinitionMappingComponent m : elem.getMapping()) {
|
||||
if (id.equals(m.getIdentity())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<String> getMapping(String url, StructureDefinition defn, ElementDefinition elem) {
|
||||
List<String> res = new ArrayList<>();
|
||||
String id = null;
|
||||
for (StructureDefinitionMappingComponent m : defn.getMapping()) {
|
||||
if (url.equals(m.getUri())) {
|
||||
id = m.getIdentity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id != null) {
|
||||
for (ElementDefinitionMappingComponent m : elem.getMapping()) {
|
||||
if (id.equals(m.getIdentity())) {
|
||||
res.add(m.getMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void checkMustSupport(StructureDefinition profile, ElementInfo ei) {
|
||||
String usesMustSupport = profile.getUserString("usesMustSupport");
|
||||
if (usesMustSupport == null) {
|
||||
|
|
|
@ -23,11 +23,14 @@ import org.hl7.fhir.r5.formats.XmlParser;
|
|||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.r5.validation.InstanceValidator;
|
||||
import org.hl7.fhir.r5.validation.ValidationEngine;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.json.JSONUtil;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.validation.tests.utilities.TestUtilities;
|
||||
|
@ -72,7 +75,6 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
|
||||
private String name;
|
||||
private JsonObject content;
|
||||
private static String veVersion;
|
||||
|
||||
public ValidationTestSuite(String name, JsonObject content) {
|
||||
this.name = name;
|
||||
|
@ -81,7 +83,8 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
|
||||
private static final String DEF_TX = "http://tx.fhir.org";
|
||||
// private static final String DEF_TX = "http://local.fhir.org:960";
|
||||
private static ValidationEngine ve;
|
||||
private static Map<String, ValidationEngine> ve = new HashMap<>();
|
||||
private static ValidationEngine vCurr;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
|
@ -92,27 +95,28 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
if (content.has("version"))
|
||||
v = content.get("version").getAsString();
|
||||
|
||||
if (ve == null || !v.equals(veVersion)) {
|
||||
v = VersionUtilities.getMajMin(v);
|
||||
if (!ve.containsKey(v)) {
|
||||
if (v.startsWith("5.0"))
|
||||
ve = new ValidationEngine("hl7.fhir.r5.core#current", DEF_TX, null, FhirPublication.R5, true);
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r5.core#current", DEF_TX, null, FhirPublication.R5, true));
|
||||
else if (v.startsWith("3.0"))
|
||||
ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, true);
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, true));
|
||||
else if (v.startsWith("4.0"))
|
||||
ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, true);
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, true));
|
||||
else if (v.startsWith("1.0"))
|
||||
ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, true);
|
||||
ve.put(v, new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, true));
|
||||
else
|
||||
throw new Exception("unknown version "+v);
|
||||
TestingUtilities.fcontext = ve.getContext();
|
||||
veVersion = v;
|
||||
}
|
||||
vCurr = ve.get(v);
|
||||
TestingUtilities.fcontext = vCurr.getContext();
|
||||
|
||||
if (content.has("use-test") && !content.get("use-test").getAsBoolean())
|
||||
return;
|
||||
|
||||
String testCaseContent = TestingUtilities.loadTestResource("validator", name.substring(name.indexOf(".")+1));
|
||||
|
||||
InstanceValidator val = ve.getValidator();
|
||||
InstanceValidator val = vCurr.getValidator();
|
||||
val.setDebug(false);
|
||||
if (content.has("allowed-extension-domain"))
|
||||
val.getExtensionDomains().add(content.get("allowed-extension-domain").getAsString());
|
||||
|
@ -127,7 +131,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
if (content.has("questionnaire")) {
|
||||
String filename = content.get("questionnaire").getAsString();
|
||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||
ve.getContext().cacheResource(loadResource(filename, contents, v));
|
||||
vCurr.getContext().cacheResource(loadResource(filename, contents, v));
|
||||
}
|
||||
if (content.has("codesystems")) {
|
||||
for (JsonElement je : content.getAsJsonArray("codesystems")) {
|
||||
|
@ -152,7 +156,6 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
val.validate(null, errors, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.XML);
|
||||
checkOutcomes(errors, content);
|
||||
if (content.has("profile")) {
|
||||
List<ValidationMessage> errorsProfile = new ArrayList<ValidationMessage>();
|
||||
JsonObject profile = content.getAsJsonObject("profile");
|
||||
if (profile.has("supporting")) {
|
||||
for (JsonElement e : profile.getAsJsonArray("supporting")) {
|
||||
|
@ -167,12 +170,37 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
System.out.println("Name: " + name+" - profile : "+profile.get("source").getAsString());
|
||||
v = content.has("version") ? content.get("version").getAsString() : Constants.VERSION;
|
||||
StructureDefinition sd = loadProfile(filename, contents, v, messages);
|
||||
List<ValidationMessage> errorsProfile = new ArrayList<ValidationMessage>();
|
||||
if (name.startsWith("Json."))
|
||||
val.validate(null, errorsProfile, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.JSON, sd);
|
||||
else
|
||||
val.validate(null, errorsProfile, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), FhirFormat.XML, sd);
|
||||
checkOutcomes(errorsProfile, profile);
|
||||
}
|
||||
}
|
||||
if (content.has("logical")) {
|
||||
JsonObject logical = content.getAsJsonObject("logical");
|
||||
if (logical.has("supporting")) {
|
||||
for (JsonElement e : logical.getAsJsonArray("supporting")) {
|
||||
String filename = e.getAsString();
|
||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||
MetadataResource mr = (MetadataResource) loadResource(filename, contents, v);
|
||||
if (mr instanceof StructureDefinition) {
|
||||
val.getContext().generateSnapshot((StructureDefinition) mr, true);
|
||||
}
|
||||
val.getContext().cacheResource(mr);
|
||||
}
|
||||
}
|
||||
List<ValidationMessage> errorsLogical = new ArrayList<ValidationMessage>();
|
||||
Element le = val.validate(null, errorsLogical, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), (name.startsWith("Json.")) ? FhirFormat.JSON : FhirFormat.XML);
|
||||
if (logical.has("expressions")) {
|
||||
FHIRPathEngine fp = new FHIRPathEngine(val.getContext());
|
||||
for (JsonElement e : logical.getAsJsonArray("expressions")) {
|
||||
String exp = e.getAsString();
|
||||
Assert.assertTrue(fp.evaluateToBoolean(null, le, le, le, fp.parse(exp)));
|
||||
}
|
||||
}
|
||||
checkOutcomes(errorsLogical, logical);
|
||||
}
|
||||
}
|
||||
|
||||
public StructureDefinition loadProfile(String filename, String contents, String v, List<ValidationMessage> messages) throws IOException, FHIRFormatError, FileNotFoundException, FHIRException, DefinitionException {
|
||||
|
@ -339,7 +367,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
|
||||
@Override
|
||||
public ValueSet resolveValueSet(Object appContext, String url) {
|
||||
return ve.getContext().fetchResource(ValueSet.class, url);
|
||||
return vCurr.getContext().fetchResource(ValueSet.class, url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue