change resolve interface (pass source as well) + don't validate perferred if any other profiles are specified + fix bug resolving references in bundles + pre-calculate bundle references

This commit is contained in:
Grahame Grieve 2020-01-27 21:14:40 +11:00
parent ab0f3f0996
commit 00080d7c48
1 changed files with 109 additions and 24 deletions

View File

@ -330,9 +330,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
@Override @Override
public Base resolveReference(Object appContext, String url) throws FHIRException { public Base resolveReference(Object appContext, String url, Base refContext) throws FHIRException {
ValidatorHostContext c = (ValidatorHostContext) appContext; ValidatorHostContext c = (ValidatorHostContext) appContext;
if (refContext != null && refContext.hasUserData("validator.bundle.resolution")) {
return (Base) refContext.getUserData("validator.bundle.resolution");
}
if (c.appContext instanceof Element) { if (c.appContext instanceof Element) {
Element bnd = (Element) c.appContext; Element bnd = (Element) c.appContext;
Base res = resolveInBundle(url, bnd); Base res = resolveInBundle(url, bnd);
@ -347,7 +351,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return res; return res;
if (externalHostServices != null) if (externalHostServices != null)
return externalHostServices.resolveReference(c.appContext, url); return externalHostServices.resolveReference(c.appContext, url, refContext);
else if (fetcher != null) else if (fetcher != null)
try { try {
return fetcher.fetch(c.appContext, url); return fetcher.fetch(c.appContext, url);
@ -478,7 +482,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean showMessagesFromReferences; private boolean showMessagesFromReferences;
private BestPracticeWarningLevel bpWarnings; private BestPracticeWarningLevel bpWarnings;
private String validationLanguage; private String validationLanguage;
private boolean baseOnly;
private List<String> extensionDomains = new ArrayList<String>(); private List<String> extensionDomains = new ArrayList<String>();
@ -818,7 +822,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
fetchCache.put(element.fhirType()+"/"+element.getIdBase(), element); fetchCache.put(element.fhirType()+"/"+element.getIdBase(), element);
resourceTracker.clear(); resourceTracker.clear();
executionId = UUID.randomUUID().toString(); executionId = UUID.randomUUID().toString();
baseOnly = profiles.isEmpty();
long t = System.nanoTime(); long t = System.nanoTime();
if (profiles == null || profiles.isEmpty()) { if (profiles == null || profiles.isEmpty()) {
@ -1061,8 +1065,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
else if (!noExtensibleWarnings) 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()+")"); 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) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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()+")"); 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 { } else {
if (binding.getStrength() == BindingStrength.REQUIRED) 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)+")"); 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)+")");
@ -1072,9 +1079,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (!noExtensibleWarnings) 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)+")"); 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) { } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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)+")"); 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) { } else if (vr.getMessage()!=null) {
res = false; res = false;
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage()); txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
@ -1165,8 +1174,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack);
else if (!noExtensibleWarnings) 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()+")"); 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) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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()+")"); 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 { } else {
if (binding.getStrength() == BindingStrength.REQUIRED) 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)+")"); 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)+")");
@ -1176,9 +1188,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (!noExtensibleWarnings) 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)+")"); 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) { } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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)+")"); 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) { } else if (vr.getMessage()!=null) {
res = false; res = false;
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage()); txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
@ -1256,8 +1270,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
else if (!noExtensibleWarnings) 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) + ", and a code should come from this value set unless it has no suitable code"); 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) + ", and a code should come from this value set unless it has no suitable code");
} else if (binding.getStrength() == BindingStrength.PREFERRED) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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) + ", and a code is recommended to come from this value set"); 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) + ", and a code is recommended to come from this value set");
}
}
} else if (binding.getStrength() == BindingStrength.REQUIRED) } 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) + ", and a code is required from this value set"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : "")); 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) + ", and a code is required from this value set"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
@ -1265,9 +1282,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
else 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) + ", and a code should come from this value set unless it has no suitable code"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : "")); 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) + ", 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) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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) + ", and a code is recommended to come from this value set"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : "")); 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) + ", and a code is recommended to come from this value set"+(vr.getMessage() != null ? " (error message = "+vr.getMessage()+")" : ""));
} }
}
}
} catch (Exception e) { } catch (Exception e) {
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding"); warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding");
} }
@ -1466,8 +1486,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
else if (!noExtensibleWarnings) 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) + ", and a code should come from this value set unless it has no suitable code"); 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) + ", and a code should come from this value set unless it has no suitable code");
} else if (binding.getStrength() == BindingStrength.PREFERRED) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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) + ", and a code is recommended to come from this value set"); 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) + ", and a code is recommended to come from this value set");
}
}
} else if (binding.getStrength() == BindingStrength.REQUIRED) } 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) + ", and a code is required from this value set. "+getErrorMessage(vr.getMessage())); 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) + ", and a code is required from this value set. "+getErrorMessage(vr.getMessage()));
else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
@ -1475,9 +1498,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), c, stack);
else 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) + ", and a code should come from this value set unless it has no suitable code. "+getErrorMessage(vr.getMessage())); 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) + ", and a code should come from this value set unless it has no suitable code. "+getErrorMessage(vr.getMessage()));
} else if (binding.getStrength() == BindingStrength.PREFERRED) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
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) + ", and a code is recommended to come from this value set. "+getErrorMessage(vr.getMessage())); 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) + ", and a code is recommended to come from this value set. "+getErrorMessage(vr.getMessage()));
} }
}
}
} catch (Exception e) { } catch (Exception e) {
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding"); warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Error "+e.getMessage()+" validating Coding");
} }
@ -2172,10 +2198,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), value, stack); checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), value, stack);
else if (!noExtensibleWarnings) else if (!noExtensibleWarnings)
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code should come from this value set unless it has no suitable code)"+getErrorMessage(vr.getMessage())); txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code should come from this value set unless it has no suitable code)"+getErrorMessage(vr.getMessage()));
} else if (binding.getStrength() == BindingStrength.PREFERRED) } else if (binding.getStrength() == BindingStrength.PREFERRED) {
if (baseOnly) {
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code is recommended to come from this value set)"+getErrorMessage(vr.getMessage())); txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, "The value provided ('"+value+"') is not in the value set " + describeReference(binding.getValueSet()) + " (" + vs.getUrl() + ", and a code is recommended to come from this value set)"+getErrorMessage(vr.getMessage()));
} }
} }
}
}
} else if (!noBindingMsgSuppressed) } else if (!noBindingMsgSuppressed)
hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !type.equals("code"), "Binding has no source, so can't be checked"); hint(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !type.equals("code"), "Binding has no source, so can't be checked");
} }
@ -3059,6 +3088,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return entry; return entry;
if (u == null) { if (u == null) {
Element resource = entry.getNamedChild("resource"); Element resource = entry.getNamedChild("resource");
if (resource != null) {
String et = resource.getType(); String et = resource.getType();
String eid = resource.getNamedChildValue("id"); String eid = resource.getNamedChildValue("id");
if (t.equals(et) && i.equals(eid)) if (t.equals(et) && i.equals(eid))
@ -3066,6 +3096,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
} }
}
return null; return null;
} }
} }
@ -3391,6 +3422,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private void start(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack) throws FHIRException { private void start(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack) throws FHIRException {
checkLang(resource, stack); checkLang(resource, stack);
if ("Bundle".equals(element.fhirType())) {
resolveBundleReferences(element, new ArrayList<Element>());
}
startInner(hostContext, errors, resource, element, defn, stack, hostContext.isCheckSpecials()); startInner(hostContext, errors, resource, element, defn, stack, hostContext.isCheckSpecials());
List<String> res = new ArrayList<>(); List<String> res = new ArrayList<>();
@ -3411,6 +3445,57 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
private void resolveBundleReferences(Element element, List<Element> bundles) {
if (!element.hasUserData("validator.bundle.resolved")) {
element.setUserData("validator.bundle.resolved", true);
List<Element> list = new ArrayList<Element>();
list.addAll(bundles);
list.add(0, element);
List<Element> entries = element.getChildrenByName("entry");
for (Element entry : entries) {
String fu = entry.getChildValue("fullUrl");
Element r = entry.getNamedChild("resource");
if (r != null) {
resolveBundleReferencesInResource(list, r, fu);
}
}
}
}
private void resolveBundleReferencesInResource(List<Element> bundles, Element r, String fu) {
r.setUserData("validator.bundle.resolution-resource", null);
if ("Bundle".equals(r.fhirType())) {
resolveBundleReferences(r, bundles);
} else {
for (Element child : r.getChildren()) {
resolveBundleReferencesForElement(bundles, r, fu, child);
}
}
}
private void resolveBundleReferencesForElement(List<Element> bundles, Element resource, String fu, Element element) {
if ("Reference".equals(element.fhirType())) {
String ref = element.getChildValue("reference");
if (!Utilities.noString(ref)) {
for (Element bundle : bundles) {
List<Element> entries = bundle.getChildren("entry");
Element tgt = resolveInBundle(entries, ref, fu, resource.fhirType(), resource.getIdBase());
if (tgt != null) {
element.setUserData("validator.bundle.resolution", tgt.getNamedChild("resource"));
return;
}
}
element.setUserData("validator.bundle.resolution-failed", ref);
}
} else {
element.setUserData("validator.bundle.resolution-noref", null);
for (Element child : element.getChildren()) {
resolveBundleReferencesForElement(bundles, resource, fu, child);
}
}
}
public void startInner(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack, boolean checkSpecials) { public void startInner(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element resource, Element element, StructureDefinition defn, NodeStack stack, boolean checkSpecials) {
// the first piece of business is to see if we've validated this resource against this profile before. // the first piece of business is to see if we've validated this resource against this profile before.
// if we have (*or if we still are*), then we'll just return our existing errors // if we have (*or if we still are*), then we'll just return our existing errors