use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class BundleValidator method checkAllInterlinked.
private void checkAllInterlinked(List<ValidationMessage> errors, List<Element> entries, NodeStack stack, Element bundle, boolean isError) {
List<EntrySummary> entryList = new ArrayList<>();
int i = 0;
for (Element entry : entries) {
Element r = entry.getNamedChild(RESOURCE);
if (r != null) {
EntrySummary e = new EntrySummary(i, entry, r);
entryList.add(e);
// System.out.println("Found entry "+e.dbg());
}
i++;
}
for (EntrySummary e : entryList) {
Set<String> references = findReferences(e.getEntry());
for (String ref : references) {
Element tgt = resolveInBundle(entries, ref, e.getEntry().getChildValue(FULL_URL), e.getResource().fhirType(), e.getResource().getIdBase());
if (tgt != null) {
EntrySummary t = entryForTarget(entryList, tgt);
if (t != null) {
if (t != e) {
// System.out.println("Entry "+e.getIndex()+" refers to "+t.getIndex()+" by ref '"+ref+"'");
e.getTargets().add(t);
} else {
// System.out.println("Entry "+e.getIndex()+" refers to itself by '"+ref+"'");
}
}
}
}
}
Set<EntrySummary> visited = new HashSet<>();
visitLinked(visited, entryList.get(0));
boolean foundRevLinks;
do {
foundRevLinks = false;
for (EntrySummary e : entryList) {
if (!visited.contains(e)) {
// System.out.println("Not visited "+e.getIndex()+" - check for reverse links");
boolean add = false;
for (EntrySummary t : e.getTargets()) {
if (visited.contains(t)) {
add = true;
}
}
if (add) {
warning(errors, IssueType.INFORMATIONAL, e.getEntry().line(), e.getEntry().col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), isExpectedToBeReverse(e.getResource().fhirType()), I18nConstants.BUNDLE_BUNDLE_ENTRY_REVERSE, (e.getEntry().getChildValue(FULL_URL) != null ? "'" + e.getEntry().getChildValue(FULL_URL) + "'" : ""));
// System.out.println("Found reverse links for "+e.getIndex());
foundRevLinks = true;
visitLinked(visited, e);
}
}
}
} while (foundRevLinks);
i = 0;
for (EntrySummary e : entryList) {
Element entry = e.getEntry();
if (isError) {
rule(errors, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : ""));
} else {
warning(errors, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : ""));
}
i++;
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class BundleValidator method followResourceLinks.
private void followResourceLinks(Element entry, Map<String, Element> visitedResources, Map<Element, Element> candidateEntries, List<Element> candidateResources, List<ValidationMessage> errors, NodeStack stack, int depth) {
Element resource = entry.getNamedChild(RESOURCE);
if (visitedResources.containsValue(resource))
return;
visitedResources.put(entry.getNamedChildValue(FULL_URL), resource);
String type = null;
Set<String> references = findReferences(resource);
for (String reference : references) {
// We don't want errors when just retrieving the element as they will be caught (with better path info) in subsequent processing
IndexedElement r = getFromBundle(stack.getElement(), reference, entry.getChildValue(FULL_URL), new ArrayList<ValidationMessage>(), stack.addToLiteralPath("entry[" + candidateResources.indexOf(resource) + "]"), type, "transaction".equals(stack.getElement().getChildValue(TYPE)));
if (r != null && !visitedResources.containsValue(r.getMatch())) {
followResourceLinks(candidateEntries.get(r.getMatch()), visitedResources, candidateEntries, candidateResources, errors, stack, depth + 1);
}
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class BundleValidator method validateDocumentReference.
public void validateDocumentReference(List<ValidationMessage> errors, List<Element> entries, Element composition, NodeStack stack, String fullUrl, String id, boolean repeats, String propName, String title) {
if (repeats) {
List<Element> list = new ArrayList<>();
composition.getNamedChildren(propName, list);
int i = 1;
for (Element elem : list) {
validateBundleReference(errors, entries, elem, title + "." + propName, stack.push(elem, i, null, null), fullUrl, "Composition", id);
i++;
}
} else {
Element elem = composition.getNamedChild(propName);
if (elem != null) {
validateBundleReference(errors, entries, elem, title + "." + propName, stack.push(elem, -1, null, null), fullUrl, "Composition", id);
}
}
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method checkTimeOption.
private void checkTimeOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, boolean openChoice) {
Element v = answer.getNamedChild("valueTime");
NodeStack ns = stack.push(v, -1, null, null);
if (qItem.getAnswerOption().size() > 0) {
List<TimeType> list = new ArrayList<TimeType>();
for (QuestionnaireItemAnswerOptionComponent components : qItem.getAnswerOption()) {
try {
list.add(components.getValueTimeType());
} 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_NOOPTIONSTIME);
} else {
boolean found = false;
for (TimeType item : list) {
if (item.getValue().equals(v.primitiveValue())) {
found = true;
break;
}
}
if (!found) {
rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTIME, v.primitiveValue());
}
}
} else
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS);
}
use of org.hl7.fhir.validation.instance.utils.NodeStack in project org.hl7.fhir.core by hapifhir.
the class QuestionnaireValidator method validateQuestionannaireResponse.
public void validateQuestionannaireResponse(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack) throws FHIRException {
if (questionnaireMode == QuestionnaireMode.NONE) {
return;
}
Element q = element.getNamedChild("questionnaire");
String questionnaire = null;
if (q != null) {
/*
* q.getValue() is correct for R4 content, but we'll also accept the second
* option just in case we're validating raw STU3 content. Being lenient here
* isn't the end of the world since if someone is actually doing the reference
* wrong in R4 content it'll get flagged elsewhere by the validator too
*/
if (isNotBlank(q.getValue())) {
questionnaire = q.getValue();
} else if (isNotBlank(q.getChildValue("reference"))) {
questionnaire = q.getChildValue("reference");
}
}
boolean ok = questionnaireMode == QuestionnaireMode.REQUIRED ? 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);
if (ok) {
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) {
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")) {
ok = hint(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
} else {
ok = warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
}
if (ok) {
boolean inProgress = "in-progress".equals(element.getNamedChildValue("status"));
validateQuestionannaireResponseItems(hostContext, qsrc, qsrc.q().getItem(), errors, element, stack, inProgress, element, new QStack(qsrc, element));
}
}
}
Aggregations