use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method validateQuestionannaireResponseItems.
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>();
element.getNamedChildren("item", items);
// now, sort into stacks
Map<String, List<ElementWithIndex>> map = new HashMap<String, List<ElementWithIndex>>();
int lastIndex = -1;
int counter = 0;
for (Element item : items) {
String linkId = item.getNamedChildValue("linkId");
if (rule(errors, IssueType.REQUIRED, item.line(), item.col(), stack.getLiteralPath(), !Utilities.noString(linkId), I18nConstants.QUESTIONNAIRE_QR_ITEM_NOLINKID)) {
int index = getLinkIdIndex(qItems, linkId);
if (index == -1) {
QuestionnaireItemComponent qItem = findQuestionnaireItem(qsrc, linkId);
if (qItem != null) {
rule(errors, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index > -1, misplacedItemError(qItem));
NodeStack ns = stack.push(item, counter, null, null);
validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, item, ns, inProgress, questionnaireResponseRoot, qstack.push(qItem, item));
} else
rule(errors, IssueType.NOTFOUND, item.line(), item.col(), stack.getLiteralPath(), index > -1, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTFOUND, linkId);
} else {
rule(errors, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index >= lastIndex, I18nConstants.QUESTIONNAIRE_QR_ITEM_ORDER);
lastIndex = index;
// we'll treat it as not existing for the purposes of enableWhen validation
if (item.hasChildren("answer") || item.hasChildren("item")) {
List<ElementWithIndex> mapItem = map.computeIfAbsent(linkId, key -> new ArrayList<>());
mapItem.add(new ElementWithIndex(item, counter));
}
}
}
counter++;
}
// ok, now we have a list of known items, grouped by linkId. We've made an error for anything out of order
for (QuestionnaireItemComponent qItem : qItems) {
List<ElementWithIndex> mapItem = map.get(qItem.getLinkId());
validateQuestionnaireResponseItem(hostContext, qsrc, errors, element, stack, inProgress, questionnaireResponseRoot, qItem, mapItem, qstack);
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method checkCodingOption.
private void checkCodingOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueCoding");
String system = v.getNamedChildValue("system");
String code = v.getNamedChildValue("code");
NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) {
List<Coding> list = new ArrayList<Coding>();
for (QuestionnaireItemAnswerOptionComponent components : qItem.getAnswerOption()) {
try {
if (components.getValue() != null) {
list.add(components.getValueCoding());
}
} catch (FHIRException e) {
// If it's the wrong type, just keep going
}
}
if (list.isEmpty() && !openChoice) {
rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSCODING);
} else {
boolean found = false;
for (Coding item : list) {
if (ObjectUtil.equals(item.getSystem(), system) && ObjectUtil.equals(item.getCode(), code)) {
found = true;
break;
}
}
if (!found) {
rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOCODING, system, code);
}
}
} else
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODINGNOOPTIONS);
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method validateAnswerCode.
private void validateAnswerCode(List<ValidationMessage> errors, Element value, NodeStack stack, QuestionnaireWithContext qSrc, String ref, boolean theOpenChoice) {
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))) {
try {
Coding c = ObjectConverter.readAsCoding(value);
if (isBlank(c.getCode()) && isBlank(c.getSystem()) && isNotBlank(c.getDisplay())) {
if (theOpenChoice) {
return;
}
}
long t = System.nanoTime();
ValidationContextCarrier vc = makeValidationContext(errors, qSrc);
ValidationResult res = context.validateCode(new ValidationOptions(stack.getWorkingLang()), c, vs, vc);
timeTracker.tx(t, "vc " + c.getSystem() + "#" + c.getCode() + " '" + c.getDisplay() + "'");
if (!res.isOk()) {
txRule(errors, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode());
} else if (res.getSeverity() != null) {
super.addValidationMessage(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null);
}
} catch (Exception e) {
warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODING, e.getMessage());
}
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method checkIntegerOption.
private void checkIntegerOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueInteger");
NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) {
List<IntegerType> list = new ArrayList<IntegerType>();
for (QuestionnaireItemAnswerOptionComponent components : qItem.getAnswerOption()) {
try {
list.add(components.getValueIntegerType());
} catch (FHIRException e) {
// If it's the wrong type, just keep going
}
}
if (list.isEmpty() && !openChoice) {
rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSINTEGER);
} else {
boolean found = false;
for (IntegerType item : list) {
if (item.getValue() == Integer.parseInt(v.primitiveValue())) {
found = true;
break;
}
}
if (!found) {
rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOINTEGER, v.primitiveValue());
}
}
} else
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_INTNOOPTIONS);
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method validateAnswerCode.
private void validateAnswerCode(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean theOpenChoice) {
Element v = answer.getNamedChild("valueCoding");
NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0)
checkCodingOption(errors, answer, stack, qSrc, qItem, theOpenChoice);
else // validateAnswerCode(errors, v, stack, qItem.getOption());
if (qItem.hasAnswerValueSet())
validateAnswerCode(errors, v, stack, qSrc, qItem.getAnswerValueSet(), theOpenChoice);
else
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONS);
}
Aggregations