fix problem resolving nested contained value sets in QuestionnaireResponses + fix NPE rendering questionnaire + fix bug validating profile on resource at root of Bundle

This commit is contained in:
Grahame Grieve 2021-12-03 06:51:23 +11:00
parent 4babbd9724
commit d303dba48d
8 changed files with 144 additions and 79 deletions

View File

@ -792,7 +792,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
private void listOptions(Questionnaire q, QuestionnaireItemComponent i, XhtmlNode select) { private void listOptions(Questionnaire q, QuestionnaireItemComponent i, XhtmlNode select) {
if (i.hasAnswerValueSet()) { if (i.hasAnswerValueSet()) {
ValueSet vs = null; ValueSet vs = null;
if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) { if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
if (vs != null && !vs.hasUrl()) { if (vs != null && !vs.hasUrl()) {
vs = vs.copy(); vs = vs.copy();

View File

@ -348,6 +348,7 @@ public class I18nConstants {
public static final String REFERENCE_REF_RESOURCETYPE = "Reference_REF_ResourceType"; public static final String REFERENCE_REF_RESOURCETYPE = "Reference_REF_ResourceType";
public static final String REFERENCE_REF_SUSPICIOUS = "REFERENCE_REF_SUSPICIOUS"; public static final String REFERENCE_REF_SUSPICIOUS = "REFERENCE_REF_SUSPICIOUS";
public static final String REFERENCE_REF_WRONGTARGET = "Reference_REF_WrongTarget"; public static final String REFERENCE_REF_WRONGTARGET = "Reference_REF_WrongTarget";
public static final String REFERENCE_REF_WRONGTARGET_LOAD = "REFERENCE_REF_WRONGTARGET_LOAD";
public static final String REFERENCE_TO__CANNOT_BE_RESOLVED = "reference_to__cannot_be_resolved"; public static final String REFERENCE_TO__CANNOT_BE_RESOLVED = "reference_to__cannot_be_resolved";
public static final String REFERENCE__REFERS_TO_A__NOT_A_VALUESET = "Reference__refers_to_a__not_a_ValueSet"; public static final String REFERENCE__REFERS_TO_A__NOT_A_VALUESET = "Reference__refers_to_a__not_a_ValueSet";
public static final String RESOURCE_RESOLUTION_SERVICES_NOT_PROVIDED = "Resource_resolution_services_not_provided"; public static final String RESOURCE_RESOLUTION_SERVICES_NOT_PROVIDED = "Resource_resolution_services_not_provided";

View File

@ -120,6 +120,7 @@ Reference_REF_NoType = Unable to determine type of target resource
Reference_REF_NotFound_Bundle = Bundled or contained reference not found within the bundle/resource {0} Reference_REF_NotFound_Bundle = Bundled or contained reference not found within the bundle/resource {0}
Reference_REF_ResourceType = Matching reference for reference {0} has resourceType {1} Reference_REF_ResourceType = Matching reference for reference {0} has resourceType {1}
Reference_REF_WrongTarget = The type ''{0}'' is not a valid Target for this element (must be one of {1}) Reference_REF_WrongTarget = The type ''{0}'' is not a valid Target for this element (must be one of {1})
REFERENCE_REF_WRONGTARGET_LOAD = The type ''{2}'' is not a valid Target for the element {0} (must be {1})
Resource_RES_ID_Malformed = Invalid Resource id Resource_RES_ID_Malformed = Invalid Resource id
Resource_RES_ID_Missing = Resource requires an id, but none is present Resource_RES_ID_Missing = Resource requires an id, but none is present
Resource_RES_ID_Prohibited = Resource has an id, but none is allowed Resource_RES_ID_Prohibited = Resource has an id, but none is allowed

View File

@ -13,4 +13,6 @@
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
</root> </root>
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
</configuration> </configuration>

View File

@ -31,8 +31,15 @@ package org.hl7.fhir.validation;
*/ */
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.JsonParser;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.*; import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager;
@ -45,6 +52,8 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source; import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.validation.instance.utils.IndexedElement; import org.hl7.fhir.validation.instance.utils.IndexedElement;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -986,4 +995,60 @@ public class BaseValidator {
return system; return system;
} }
} }
protected Resource loadContainedResource(List<ValidationMessage> errors, String path, Element resource, String id, Class class1) throws FHIRException {
for (Element contained : resource.getChildren("contained")) {
if (contained.getIdBase().equals(id)) {
return loadFoundResource(errors, path, contained, class1);
}
}
return null;
}
protected Resource loadFoundResource(List<ValidationMessage> errors, String path, Element resource, Class class1) throws FHIRException {
try {
FhirPublication v = FhirPublication.fromCode(context.getVersion());
ByteArrayOutputStream bs = new ByteArrayOutputStream();
new JsonParser(context).compose(resource, bs, OutputStyle.NORMAL, resource.getIdBase());
byte[] json = bs.toByteArray();
Resource r5 = null;
switch (v) {
case DSTU1:
rule(errors, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.UNSUPPORTED_VERSION_R1, resource.getIdBase());
return null; // this can't happen
case DSTU2:
org.hl7.fhir.dstu2.model.Resource r2 = new org.hl7.fhir.dstu2.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_10_50.convertResource(r2);
break;
case DSTU2016May:
org.hl7.fhir.dstu2016may.model.Resource r2a = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_14_50.convertResource(r2a);
break;
case STU3:
org.hl7.fhir.dstu3.model.Resource r3 = new org.hl7.fhir.dstu3.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_30_50.convertResource(r3);
break;
case R4:
org.hl7.fhir.r4.model.Resource r4 = new org.hl7.fhir.r4.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_40_50.convertResource(r4);
break;
case R5:
r5 = new org.hl7.fhir.r5.formats.JsonParser().parse(json);
break;
default:
return null; // this can't happen
}
if (class1.isInstance(r5))
return (Resource) r5;
else {
rule(errors, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.REFERENCE_REF_WRONGTARGET_LOAD, resource.getIdBase(), class1.toString(), r5.fhirType());
return null;
}
} catch (IOException e) {
throw new FHIRException(e);
}
}
} }

View File

@ -48,6 +48,7 @@ import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemEnableWhenComponent; import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemEnableWhenComponent;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemOperator; import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemOperator;
import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator.QuestionnaireWithContext;
import org.hl7.fhir.validation.instance.utils.ValidatorHostContext; import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
@ -85,17 +86,17 @@ public class EnableWhenEvaluator {
public static class QStack extends ArrayList<QuestionnaireAnswerPair> { public static class QStack extends ArrayList<QuestionnaireAnswerPair> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Questionnaire q; private QuestionnaireWithContext q;
private Element a; private Element a;
public QStack(Questionnaire q, Element a) { public QStack(QuestionnaireWithContext q, Element a) {
super(); super();
this.q = q; this.q = q;
this.a = a; this.a = a;
} }
public Questionnaire getQ() { public QuestionnaireWithContext getQ() {
return q; return q;
} }
@ -311,9 +312,9 @@ public class EnableWhenEvaluator {
* - any targetA in groupA are input for the enableWhen decision * - any targetA in groupA are input for the enableWhen decision
*/ */
private List<Element> findQuestionAnswers(QStack qstack, QuestionnaireItemComponent sourceQ, QuestionnaireItemEnableWhenComponent ew) { private List<Element> findQuestionAnswers(QStack qstack, QuestionnaireItemComponent sourceQ, QuestionnaireItemEnableWhenComponent ew) {
QuestionnaireItemComponent targetQ = qstack.getQ().getQuestion(ew.getQuestion()); QuestionnaireItemComponent targetQ = qstack.getQ().q().getQuestion(ew.getQuestion());
if (targetQ != null) { if (targetQ != null) {
QuestionnaireItemComponent groupQ = qstack.getQ().getCommonGroup(sourceQ, targetQ); QuestionnaireItemComponent groupQ = qstack.getQ().q().getCommonGroup(sourceQ, targetQ);
if (groupQ == null) { // root is Q itself if (groupQ == null) { // root is Q itself
return findOnItem(qstack.getA(), ew.getQuestion()); return findOnItem(qstack.getA(), ew.getQuestion());
} else { } else {

View File

@ -5386,6 +5386,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (first != null && typeMatchesDefn(first.getElement().getType(), defn)) { if (first != null && typeMatchesDefn(first.getElement().getType(), defn)) {
element = first.getElement(); element = first.getElement();
stack = first; stack = first;
resourceName = element.getType(); // todo: consider namespace...?
idstatus = IdStatus.OPTIONAL; // why? idstatus = IdStatus.OPTIONAL; // why?
} }
// todo: validate everything in this bundle. // todo: validate everything in this bundle.
@ -5404,7 +5405,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
// validate // validate
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), resourceName.equals(defn.getType()), I18nConstants.VALIDATION_VAL_PROFILE_WRONGTYPE,
defn.getType(), resourceName, defn.getUrl())) {
start(hostContext, errors, element, element, defn, stack); // root is both definition and type start(hostContext, errors, element, element, defn, stack); // root is both definition and type
} else {
System.out.println("what?");
}
} }
} }

View File

@ -26,6 +26,7 @@ import org.hl7.fhir.r5.elementmodel.ObjectConverter;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.DateType; import org.hl7.fhir.r5.model.DateType;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion; import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
import org.hl7.fhir.r5.model.FhirPublication; import org.hl7.fhir.r5.model.FhirPublication;
import org.hl7.fhir.r5.model.IntegerType; import org.hl7.fhir.r5.model.IntegerType;
@ -51,6 +52,7 @@ import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
import org.hl7.fhir.validation.TimeTracker; import org.hl7.fhir.validation.TimeTracker;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator; import org.hl7.fhir.validation.instance.EnableWhenEvaluator;
import org.hl7.fhir.validation.instance.EnableWhenEvaluator.QStack; import org.hl7.fhir.validation.instance.EnableWhenEvaluator.QStack;
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator.QuestionnaireWithContext;
import org.hl7.fhir.validation.instance.utils.NodeStack; import org.hl7.fhir.validation.instance.utils.NodeStack;
import org.hl7.fhir.validation.instance.utils.ValidatorHostContext; import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
@ -58,6 +60,37 @@ import ca.uhn.fhir.util.ObjectUtil;
public class QuestionnaireValidator extends BaseValidator { public class QuestionnaireValidator extends BaseValidator {
public static class QuestionnaireWithContext {
private Questionnaire q;
private Element container;
private String containerPath;
public static QuestionnaireWithContext fromQuestionnaire(Questionnaire q) {
if (q == null) {
return null;
}
QuestionnaireWithContext res = new QuestionnaireWithContext();
res.q = q;
return res;
}
public static QuestionnaireWithContext fromContainedResource(String path, Element e, Questionnaire q) {
if (q == null) {
return null;
}
QuestionnaireWithContext res = new QuestionnaireWithContext();
res.q = q;
res.container = e;
res.containerPath = path;
return res;
}
public Questionnaire q() {
return q;
}
}
private EnableWhenEvaluator myEnableWhenEvaluator; private EnableWhenEvaluator myEnableWhenEvaluator;
private FHIRPathEngine fpe; private FHIRPathEngine fpe;
private QuestionnaireMode questionnaireMode; private QuestionnaireMode questionnaireMode;
@ -191,7 +224,12 @@ public class QuestionnaireValidator extends BaseValidator {
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE) : rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE) :
hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE); hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE);
if (ok) { if (ok) {
Questionnaire qsrc = questionnaire.startsWith("#") ? loadQuestionnaire(element, questionnaire.substring(1)) : context.fetchResource(Questionnaire.class, questionnaire); QuestionnaireWithContext qsrc = null;
if (questionnaire.startsWith("#")) {
qsrc = QuestionnaireWithContext.fromContainedResource(stack.getLiteralPath(), element, (Questionnaire) loadContainedResource(errors, stack.getLiteralPath(), element, questionnaire.substring(1), Questionnaire.class));
} else {
qsrc = QuestionnaireWithContext.fromQuestionnaire(context.fetchResource(Questionnaire.class, questionnaire));
}
if (questionnaireMode == QuestionnaireMode.REQUIRED) { if (questionnaireMode == QuestionnaireMode.REQUIRED) {
ok = rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); ok = rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
} else if (questionnaire.startsWith("http://example.org")) { } else if (questionnaire.startsWith("http://example.org")) {
@ -201,66 +239,12 @@ public class QuestionnaireValidator extends BaseValidator {
} }
if (ok) { if (ok) {
boolean inProgress = "in-progress".equals(element.getNamedChildValue("status")); boolean inProgress = "in-progress".equals(element.getNamedChildValue("status"));
validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element)); validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.q().getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element));
} }
} }
} }
private Questionnaire loadQuestionnaire(Element resource, String id) throws FHIRException { private void validateQuestionnaireResponseItem(ValidatorHostContext hostContext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
try {
for (Element contained : resource.getChildren("contained")) {
if (contained.getIdBase().equals(id)) {
FhirPublication v = FhirPublication.fromCode(context.getVersion());
ByteArrayOutputStream bs = new ByteArrayOutputStream();
new JsonParser(context).compose(contained, bs, OutputStyle.NORMAL, id);
byte[] json = bs.toByteArray();
switch (v) {
case DSTU1:
throw new FHIRException(context.formatMessage(I18nConstants.UNSUPPORTED_VERSION_R1));
case DSTU2:
org.hl7.fhir.dstu2.model.Resource r2 = new org.hl7.fhir.dstu2.formats.JsonParser().parse(json);
Resource r5 = VersionConvertorFactory_10_50.convertResource(r2);
if (r5 instanceof Questionnaire)
return (Questionnaire) r5;
else
return null;
case DSTU2016May:
org.hl7.fhir.dstu2016may.model.Resource r2a = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_14_50.convertResource(r2a);
if (r5 instanceof Questionnaire)
return (Questionnaire) r5;
else
return null;
case STU3:
org.hl7.fhir.dstu3.model.Resource r3 = new org.hl7.fhir.dstu3.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_30_50.convertResource(r3);
if (r5 instanceof Questionnaire)
return (Questionnaire) r5;
else
return null;
case R4:
org.hl7.fhir.r4.model.Resource r4 = new org.hl7.fhir.r4.formats.JsonParser().parse(json);
r5 = VersionConvertorFactory_40_50.convertResource(r4);
if (r5 instanceof Questionnaire)
return (Questionnaire) r5;
else
return null;
case R5:
r5 = new org.hl7.fhir.r5.formats.JsonParser().parse(json);
if (r5 instanceof Questionnaire)
return (Questionnaire) r5;
else
return null;
}
}
}
return null;
} catch (IOException e) {
throw new FHIRException(e);
}
}
private void validateQuestionnaireResponseItem(ValidatorHostContext hostContext, Questionnaire qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
String text = element.getNamedChildValue("text"); String text = element.getNamedChildValue("text");
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), Utilities.noString(text) || text.equals(qItem.getText()), I18nConstants.QUESTIONNAIRE_QR_ITEM_TEXT, qItem.getLinkId()); rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), Utilities.noString(text) || text.equals(qItem.getText()), I18nConstants.QUESTIONNAIRE_QR_ITEM_TEXT, qItem.getLinkId());
@ -379,7 +363,7 @@ public class QuestionnaireValidator extends BaseValidator {
return !answers.isEmpty() || !qItem.getRequired() || qItem.getType() == QuestionnaireItemType.GROUP; return !answers.isEmpty() || !qItem.getRequired() || qItem.getType() == QuestionnaireItemType.GROUP;
} }
private void validateQuestionnaireResponseItem(ValidatorHostContext hostcontext, Questionnaire qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<Element> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) { private void validateQuestionnaireResponseItem(ValidatorHostContext hostcontext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<Element> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
if (elements.size() > 1) if (elements.size() > 1)
rule(errors, IssueType.INVALID, elements.get(1).line(), elements.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId()); rule(errors, IssueType.INVALID, elements.get(1).line(), elements.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId());
int i = 0; int i = 0;
@ -398,7 +382,7 @@ public class QuestionnaireValidator extends BaseValidator {
return -1; return -1;
} }
private void validateQuestionannaireResponseItems(ValidatorHostContext hostContext, Questionnaire qsrc, List<QuestionnaireItemComponent> qItems, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) { private void validateQuestionannaireResponseItems(ValidatorHostContext hostContext, QuestionnaireWithContext qsrc, List<QuestionnaireItemComponent> qItems, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
List<Element> items = new ArrayList<Element>(); List<Element> items = new ArrayList<Element>();
element.getNamedChildren("item", items); element.getNamedChildren("item", items);
// now, sort into stacks // now, sort into stacks
@ -437,7 +421,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
public void validateQuestionnaireResponseItem(ValidatorHostContext hostContext, Questionnaire qsrc, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QuestionnaireItemComponent qItem, List<Element> mapItem, QStack qstack) { public void validateQuestionnaireResponseItem(ValidatorHostContext hostContext, QuestionnaireWithContext qsrc, List<ValidationMessage> errors, Element element, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QuestionnaireItemComponent qItem, List<Element> mapItem, QStack qstack) {
boolean enabled = myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe); boolean enabled = myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe);
if (mapItem != null) { if (mapItem != null) {
if (!enabled) { if (!enabled) {
@ -500,8 +484,8 @@ public class QuestionnaireValidator extends BaseValidator {
return null; return null;
} }
private QuestionnaireItemComponent findQuestionnaireItem(Questionnaire qSrc, String linkId) { private QuestionnaireItemComponent findQuestionnaireItem(QuestionnaireWithContext qSrc, String linkId) {
return findItem(qSrc.getItem(), linkId); return findItem(qSrc.q.getItem(), linkId);
} }
private QuestionnaireItemComponent findItem(List<QuestionnaireItemComponent> list, String linkId) { private QuestionnaireItemComponent findItem(List<QuestionnaireItemComponent> list, String linkId) {
@ -515,8 +499,13 @@ public class QuestionnaireValidator extends BaseValidator {
return null; return null;
} }
private void validateAnswerCode(List<ValidationMessage> errors, Element value, NodeStack stack, Questionnaire qSrc, String ref, boolean theOpenChoice) { private void validateAnswerCode(List<ValidationMessage> errors, Element value, NodeStack stack, QuestionnaireWithContext qSrc, String ref, boolean theOpenChoice) {
ValueSet vs = resolveBindingReference(qSrc, ref, qSrc.getUrl()); ValueSet vs = null;
if (ref.startsWith("#") && qSrc.container != null) {
vs = (ValueSet) loadContainedResource(errors, qSrc.containerPath, qSrc.container, ref.substring(1), ValueSet.class);
} else {
vs = resolveBindingReference(qSrc.q(), ref, qSrc.q().getUrl());
}
if (warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) { if (warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) {
try { try {
Coding c = ObjectConverter.readAsCoding(value); Coding c = ObjectConverter.readAsCoding(value);
@ -540,7 +529,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
private void validateAnswerCode(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean theOpenChoice) { private void validateAnswerCode(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean theOpenChoice) {
Element v = answer.getNamedChild("valueCoding"); Element v = answer.getNamedChild("valueCoding");
NodeStack ns = stack.push(v, -1, null, null); NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) if (qItem.getAnswerOption().size() > 0)
@ -552,11 +541,11 @@ public class QuestionnaireValidator extends BaseValidator {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONS); hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONS);
} }
private void checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, String type) { private void checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, String type) {
checkOption(errors, answer, stack, qSrc, qItem, type, false); checkOption(errors, answer, stack, qSrc, qItem, type, false);
} }
private void checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, String type, boolean openChoice) { private void checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, String type, boolean openChoice) {
if (type.equals("integer")) checkIntegerOption(errors, answer, stack, qSrc, qItem, openChoice); if (type.equals("integer")) checkIntegerOption(errors, answer, stack, qSrc, qItem, openChoice);
else if (type.equals("date")) checkDateOption(errors, answer, stack, qSrc, qItem, openChoice); else if (type.equals("date")) checkDateOption(errors, answer, stack, qSrc, qItem, openChoice);
else if (type.equals("time")) checkTimeOption(errors, answer, stack, qSrc, qItem, openChoice); else if (type.equals("time")) checkTimeOption(errors, answer, stack, qSrc, qItem, openChoice);
@ -564,7 +553,7 @@ public class QuestionnaireValidator extends BaseValidator {
else if (type.equals("Coding")) checkCodingOption(errors, answer, stack, qSrc, qItem, openChoice); else if (type.equals("Coding")) checkCodingOption(errors, answer, stack, qSrc, qItem, openChoice);
} }
private void checkIntegerOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean openChoice) { private void checkIntegerOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueInteger"); Element v = answer.getNamedChild("valueInteger");
NodeStack ns = stack.push(v, -1, null, null); NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) { if (qItem.getAnswerOption().size() > 0) {
@ -594,7 +583,7 @@ public class QuestionnaireValidator extends BaseValidator {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_INTNOOPTIONS); hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_INTNOOPTIONS);
} }
private void checkDateOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean openChoice) { private void checkDateOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueDate"); Element v = answer.getNamedChild("valueDate");
NodeStack ns = stack.push(v, -1, null, null); NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) { if (qItem.getAnswerOption().size() > 0) {
@ -624,7 +613,7 @@ public class QuestionnaireValidator extends BaseValidator {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_DATENOOPTIONS); hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_DATENOOPTIONS);
} }
private void checkTimeOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean openChoice) { private void checkTimeOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueTime"); Element v = answer.getNamedChild("valueTime");
NodeStack ns = stack.push(v, -1, null, null); NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) { if (qItem.getAnswerOption().size() > 0) {
@ -654,7 +643,7 @@ public class QuestionnaireValidator extends BaseValidator {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS); hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS);
} }
private void checkStringOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean openChoice) { private void checkStringOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueString"); Element v = answer.getNamedChild("valueString");
NodeStack ns = stack.push(v, -1, null, null); NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) { if (qItem.getAnswerOption().size() > 0) {
@ -689,7 +678,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
private void checkCodingOption(List<ValidationMessage> errors, Element answer, NodeStack stack, Questionnaire qSrc, QuestionnaireItemComponent qItem, boolean openChoice) { private void checkCodingOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueCoding"); Element v = answer.getNamedChild("valueCoding");
String system = v.getNamedChildValue("system"); String system = v.getNamedChildValue("system");
String code = v.getNamedChildValue("code"); String code = v.getNamedChildValue("code");