From 9d4592730a552189dad85087a743c1673cc145f3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 7 Oct 2019 21:31:49 +0700 Subject: [PATCH] fix for problem with contained resources --- .../fhir/r4/validation/InstanceValidator.java | 4 +- .../fhir/r5/validation/InstanceValidator.java | 21 +- .../validation-examples/manifest.json | 3 + .../resources/validation-examples/q-bp.xml | 467 ++++++++++++++++++ 4 files changed, 483 insertions(+), 12 deletions(-) create mode 100644 org.hl7.fhir.validation/src/test/resources/validation-examples/q-bp.xml diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java index ea729a473..bfb96dc89 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java @@ -1743,7 +1743,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (xhtml != null) { // if it is null, this is an error already noted in the parsers // check that the namespace is there and correct. String ns = xhtml.getNsDecl(); - rule(errors, IssueType.INVALID, e.line(), e.col(), path, FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"')"); + rule(errors, IssueType.INVALID, e.line(), e.col(), path, FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"', should be '"+FormatUtilities.XHTML_NS+"')"); // check that inner namespaces are all correct checkInnerNS(errors, e, path, xhtml.getChildNodes()); rule(errors, IssueType.INVALID, e.line(), e.col(), path, "div".equals(xhtml.getName()), "Wrong name on the XHTML ('"+ns+"') - must start with div"); @@ -1796,7 +1796,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat for (XhtmlNode node : list) { if (node.getNodeType() == NodeType.Element) { String ns = node.getNsDecl(); - rule(errors, IssueType.INVALID, e.line(), e.col(), path, ns == null || FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"')"); + rule(errors, IssueType.INVALID, e.line(), e.col(), path, ns == null || FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"', should be '"+FormatUtilities.XHTML_NS+"')"); checkInnerNS(errors, e, path, node.getChildNodes()); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java index 4a1a53749..6dc4d063b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/r5/validation/InstanceValidator.java @@ -1756,7 +1756,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (xhtml != null) { // if it is null, this is an error already noted in the parsers // check that the namespace is there and correct. String ns = xhtml.getNsDecl(); - rule(errors, IssueType.INVALID, e.line(), e.col(), path, FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"')"); + rule(errors, IssueType.INVALID, e.line(), e.col(), path, FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"', should be '"+FormatUtilities.XHTML_NS+"')"); // check that inner namespaces are all correct checkInnerNS(errors, e, path, xhtml.getChildNodes()); rule(errors, IssueType.INVALID, e.line(), e.col(), path, "div".equals(xhtml.getName()), "Wrong name on the XHTML ('"+ns+"') - must start with div"); @@ -1809,7 +1809,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat for (XhtmlNode node : list) { if (node.getNodeType() == NodeType.Element) { String ns = node.getNsDecl(); - rule(errors, IssueType.INVALID, e.line(), e.col(), path, ns == null || FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"')"); + rule(errors, IssueType.INVALID, e.line(), e.col(), path, ns == null || FormatUtilities.XHTML_NS.equals(ns), "Wrong namespace on the XHTML ('"+ns+"', should be '"+FormatUtilities.XHTML_NS+"')"); checkInnerNS(errors, e, path, node.getChildNodes()); } } @@ -4310,13 +4310,14 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L public void checkInvariants(ValidatorHostContext hostContext, List errors, StructureDefinition profile, ElementDefinition definition, Element resource, Element element, NodeStack stack) throws FHIRException { - if (resource.getName().equals("contained")) { - NodeStack ancestor = stack; - while (ancestor != null && ancestor.element != null && (!ancestor.element.isResource() || "contained".equals(ancestor.element.getName()))) - ancestor = ancestor.parent; - if (ancestor != null && ancestor.element != null) - checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, ancestor.element, element); - } else + // this was an old work around for resource/rootresource issue. +// if (resource.getName().equals("contained")) { +// NodeStack ancestor = stack; +// while (ancestor != null && ancestor.element != null && (!ancestor.element.isResource() || "contained".equals(ancestor.element.getName()))) +// ancestor = ancestor.parent; +// if (ancestor != null && ancestor.element != null) +// checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, ancestor.element, element); +// } else checkInvariants(hostContext, errors, stack.getLiteralPath(), profile, definition, null, null, resource, element); if (definition.getFixed()!=null) checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), definition.getSliceName(), null); @@ -4560,7 +4561,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, "Resource requires an id, but none is present"); else if (idstatus == IdStatus.PROHIBITED && (element.getNamedChild("id") != null)) rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, "Resource has an id, but none is allowed"); - start(hostContext, errors, resource, element, defn, stack); // root is both definition and type + start(hostContext, errors, element, element, defn, stack); // root is both definition and type } } diff --git a/org.hl7.fhir.validation/src/test/resources/validation-examples/manifest.json b/org.hl7.fhir.validation/src/test/resources/validation-examples/manifest.json index 2ff28f987..001fd8089 100644 --- a/org.hl7.fhir.validation/src/test/resources/validation-examples/manifest.json +++ b/org.hl7.fhir.validation/src/test/resources/validation-examples/manifest.json @@ -911,6 +911,9 @@ "errorCount": 0 } }, + "q-bp.xml": { + "errorCount": 0 + }, "valueset-slicing-meds-bad.xml" : { "version" : "3.0", "codesystems": [ diff --git a/org.hl7.fhir.validation/src/test/resources/validation-examples/q-bp.xml b/org.hl7.fhir.validation/src/test/resources/validation-examples/q-bp.xml new file mode 100644 index 000000000..37ca44387 --- /dev/null +++ b/org.hl7.fhir.validation/src/test/resources/validation-examples/q-bp.xml @@ -0,0 +1,467 @@ + + + + + + + + + + +
div +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <status value="active"/> + <subjectType value="Patient"/> + <date value="2017-10-17T01:39:42.162Z"/> + <publisher value="Telstra Health"/> + <description value="GP Assessment report that should be completed when providing an assessment ..."/> + <useContext> + <code> + <system value="http://terminology.hl7.org/CodeSystem/usage-context-type"/> + <code value="focus"/> + <display value="Clinical Focus"/> + </code> + <valueCodeableConcept> + <coding> + <code value="bowel"/> + <display value="Bowel Cancer Registry"/> + </coding> + </valueCodeableConcept> + </useContext> + <item> + <linkId value="part-details"/> + <text value="Participant details"/> + <type value="group"/> + <repeats value="false"/> + <item> + <linkId value="participant-id"/> + <text value="Participant ID number"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.identifier.where(system='http://ns.electronichealth.net.au/id/hi/mc').value.first()"/> + </valueExpression> + </extension> + <linkId value="medicare-number"/> + <text value="Medicare number"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.identifier.where(system='http://ns.electronichealth.net.au/id/hi/dva').value.first()"/> + </valueExpression> + </extension> + <linkId value="dva-number"/> + <text value="DVA number"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.name.first().family.first()"/> + </valueExpression> + </extension> + <linkId value="family-name"/> + <text value="Family name"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.name.first().given.first()"/> + </valueExpression> + </extension> + <linkId value="given-names"/> + <text value="Given name(s)"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.birthDate"/> + </valueExpression> + </extension> + <linkId value="dob"/> + <text value="Date of birth"/> + <type value="date"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.gender"/> + </valueExpression> + </extension> + <linkId value="gender"/> + <text value="Gender"/> + <type value="choice"/> + <repeats value="false"/> + <answerValueSet value="https://sqlonfhir-dstu2.azurewebsites.net/fhir/ValueSet/administrative-gender"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPatient.telecom.where(system='phone').select(($this.where(use='mobile') | $this.where(use='home')).first().value)"/> + </valueExpression> + </extension> + <linkId value="contact-number"/> + <text value="Contact telephone number"/> + <type value="string"/> + <item> + <linkId value="contact-number-tooltip"/> + <text value="(mobile or land line including area code)"/> + <type value="text"/> + </item> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%PrePopQuery.entry.resource.total"/> + </valueExpression> + </extension> + <linkId value="related-persons"/> + <text value="Number of active RelatedPersons"/> + <type value="integer"/> + </item> + </item> + <item> + <linkId value="symptoms"/> + <text value="Symptoms present at time of assessment following a positive FOBT result"/> + <type value="group"/> + <repeats value="false"/> + <item> + <linkId value="5d1f7a32-5601-483a-8881-2c2437c72e9a"/> + <type value="group"/> + <repeats value="false"/> + <item> + <linkId value="5d1f7a32-5601-483a-8881-2c2437c72e9a-grouptext"/> + <text value="(Mark all those that apply)"/> + <type value="text"/> + </item> + <item> + <linkId value="no-symptoms"/> + <text value="No Symptoms"/> + <type value="boolean"/> + </item> + <item> + <linkId value="longer-standing"/> + <text value="Longer standing rectal bleeding (> 6 months)"/> + <type value="boolean"/> + </item> + <item> + <linkId value="iron-deficiency"/> + <text value="Iron deficiency anaemia"/> + <type value="boolean"/> + </item> + </item> + <item> + <linkId value="46923fac-09ee-4288-8a2e-b4ed70bf7869"/> + <type value="group"/> + <repeats value="false"/> + <item> + <linkId value="recent-onset"/> + <text value="Recent onset rectal bleeding ( ≤ 6 months)"/> + <type value="boolean"/> + </item> + <item> + <linkId value="significant-change"/> + <text value="Significant change in bowel habits"/> + <type value="boolean"/> + </item> + <item> + <linkId value="abdominal-pain"/> + <text value="Abdominal pain"/> + <type value="boolean"/> + </item> + </item> + </item> + <item> + <linkId value="0f9c0385-32ef-4c33-980f-502eab10dd15"/> + <text value="Assessment outcome following a positive FOBT result"/> + <type value="group"/> + <repeats value="false"/> + <item> + <extension url="http://standards.healthconnex.com.au/fhir/StructureDefinition/Questionnaire-hcx-horizontal"> + <valueBoolean value="true"/> + </extension> + <linkId value="assess-outcome"/> + <type value="choice"/> + <repeats value="false"/> + <answerOption> + <valueCoding> + <code value="Y"/> + <display value="Referred for colonoscopy"/> + </valueCoding> + </answerOption> + <answerOption> + <valueCoding> + <code value="N"/> + <display value="Not referred for colonoscopy"/> + </valueCoding> + </answerOption> + <item> + <linkId value="group-specialist-clinic"/> + <text value="Specialist/clinic name and suburb:"/> + <type value="group"/> + <enableWhen> + <question value="assess-outcome"/> + <operator value="="/> + <answerCoding> + <code value="Y"/> + </answerCoding> + </enableWhen> + <repeats value="false"/> + <item> + <linkId value="group-specialist-clinic-grouplabel"/> + <text value="(e.g. name of specialist and/or hospital/clinic and location)"/> + <type value="text"/> + </item> + <item> + <linkId value="specialist-clinic-name"/> + <text value="Specialist/Clinic Name"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl"> + <valueCodeableConcept> + <coding> + <system value="http://hl7.org/fhir/questionnaire-item-control"/> + <code value="autocomplete"/> + </coding> + </valueCodeableConcept> + </extension> + <linkId value="specialist-location"/> + <text value="Location/Suburb"/> + <type value="choice"/> + <repeats value="false"/> + <answerValueSet value="https://sqlonfhir-ci2.azurewebsites.net/fhir/ValueSet/hcxdir-locality"/> + </item> + <item> + <linkId value="specialist-contact-number"/> + <text value="Contact-telephone number"/> + <type value="string"/> + </item> + </item> + <item> + <linkId value="group-not-referred"/> + <text value="Reason for not referring colonoscopy"/> + <type value="group"/> + <enableWhen> + <question value="assess-outcome"/> + <operator value="="/> + <answerCoding> + <code value="N"/> + </answerCoding> + </enableWhen> + <repeats value="false"/> + <item> + <linkId value="previous-diagnosis"/> + <text value="Bowel cancer previously diagnosed"/> + <type value="boolean"/> + </item> + <item> + <linkId value="recent-colonoscopy"/> + <text value="Recent colonoscopy ( *lt; 18 months)"/> + <type value="boolean"/> + </item> + <item> + <linkId value="significant-comorbidity"/> + <text value="Significant co-morbidity"/> + <type value="boolean"/> + </item> + <item> + <linkId value="limited-life-expectancy"/> + <text value="Limited life expectancy"/> + <type value="boolean"/> + </item> + <item> + <linkId value="patient-declined"/> + <text value="Patient declines colonoscopy"/> + <type value="boolean"/> + </item> + <item> + <linkId value="other-conditions"/> + <text value="Other medical condition(s)"/> + <type value="boolean"/> + </item> + </item> + </item> + </item> + <item> + <linkId value="group-other-exams"/> + <text value="Was the patient referred for other examinations(s)?"/> + <type value="group"/> + <repeats value="false"/> + <item> + <linkId value="referred-other-exam"/> + <type value="choice"/> + <repeats value="false"/> + <answerOption> + <valueCoding> + <code value="N"/> + <display value="No"/> + </valueCoding> + </answerOption> + <answerOption> + <valueCoding> + <code value="Y"/> + <display value="Yes"/> + </valueCoding> + </answerOption> + <item> + <linkId value="group-referred-others"/> + <type value="group"/> + <enableWhen> + <question value="referred-other-exam"/> + <operator value="="/> + <answerCoding> + <code value="Y"/> + </answerCoding> + </enableWhen> + <repeats value="false"/> + <item> + <linkId value="exam-dcbe"/> + <text value="Double contrast barium enema"/> + <type value="boolean"/> + </item> + <item> + <linkId value="exam-ctc"/> + <text value="CT colonography"/> + <type value="boolean"/> + </item> + <item> + <linkId value="exam-sigmoidoscopy"/> + <text value="Sigmoidoscopy"/> + <type value="boolean"/> + </item> + <item> + <linkId value="exam-other"/> + <text value="Other"/> + <type value="boolean"/> + <item> + <linkId value="e58ed410-25e0-49bf-bbeb-a79d52d0acc6"/> + <type value="group"/> + <enableWhen> + <question value="exam-other"/> + <operator value="="/> + <answerBoolean value="true"/> + </enableWhen> + <repeats value="false"/> + <item> + <linkId value="exam-other-details"/> + <text value="Please specify"/> + <type value="text"/> + </item> + </item> + </item> + </item> + </item> + </item> + <item> + <linkId value="provider-details"/> + <text value="Provider details"/> + <type value="group"/> + <repeats value="false"/> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPractitioner.identifier.where(system='http://ns.electronichealth.net.au/id/hi/prn').first().value"/> + </valueExpression> + </extension> + <linkId value="provider-number"/> + <text value="Provider number for payment"/> + <type value="string"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="today()"/> + </valueExpression> + </extension> + <linkId value="date-consult"/> + <text value="Date of consultation"/> + <type value="date"/> + </item> + <item> + <extension url="http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"> + <valueExpression> + <language value="text/fhirpath"/> + <expression value="%LaunchPractitioner.name.first().select(given.first() + ' ' + family.first())"/> + </valueExpression> + </extension> + <linkId value="provider-name"/> + <text value="Name"/> + <type value="string"/> + </item> + </item> +</Questionnaire>