fix bundle link resolution (remove overloaded use of 'root resource')

This commit is contained in:
Grahame Grieve 2021-12-17 16:20:09 +11:00
parent e4d3047138
commit 3d2400bb55
2 changed files with 33 additions and 13 deletions

View File

@ -305,9 +305,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else if (item instanceof Element) {
Element e = (Element) item;
if (e.getSpecial() == SpecialElement.CONTAINED) {
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource(), ctxt.getGroupingResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
} else if (e.getSpecial() != null) {
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e, ctxt.getRootResource(), ctxt.getRootResource()), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
} else {
self.validateResource(new ValidatorHostContext(ctxt.getAppContext(), e), valerrors, e, e, sd, IdStatus.OPTIONAL, new NodeStack(context, null, e, validationLanguage));
}
@ -2891,7 +2891,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !isSuspiciousReference(ref), I18nConstants.REFERENCE_REF_SUSPICIOUS, ref);
ResolvedReference we = localResolve(ref, stack, errors, path, hostContext.getRootResource(), element);
ResolvedReference we = localResolve(ref, stack, errors, path, hostContext.getRootResource(), hostContext.getGroupingResource(), element);
String refType;
if (ref.startsWith("#")) {
refType = "contained";
@ -3586,7 +3586,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return true;
}
private ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element source) {
private ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element groupingResource, Element source) {
if (ref.startsWith("#")) {
// work back through the parent list.
// really, there should only be one level for this (contained resources cannot contain
@ -3686,11 +3686,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
stack = stack.getParent();
}
// we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity.
if (rootResource != null && BUNDLE.equals(rootResource.fhirType())) {
String type = rootResource.getChildValue(TYPE);
Element entry = getEntryForSource(rootResource, source);
if (groupingResource != null && BUNDLE.equals(groupingResource.fhirType())) { // it could also be a Parameters resource - that case isn't handled yet
String type = groupingResource.getChildValue(TYPE);
Element entry = getEntryForSource(groupingResource, source);
fullUrl = entry.getChildValue(FULL_URL);
IndexedElement res = getFromBundle(rootResource, ref, fullUrl, errors, path, type, "transaction".equals(type));
IndexedElement res = getFromBundle(groupingResource, ref, fullUrl, errors, path, type, "transaction".equals(type));
if (res == null) {
return null;
} else {
@ -3767,7 +3767,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private Element resolve(Object appContext, String ref, NodeStack stack, List<ValidationMessage> errors, String path) throws IOException, FHIRException {
Element local = localResolve(ref, stack, errors, path, null, null).getFocus();
Element local = localResolve(ref, stack, errors, path, null, null, null).getFocus();
if (local != null)
return local;
if (fetcher == null)
@ -4600,7 +4600,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ValidatorHostContext hc = null;
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
resource = element;
hc = hostContext.forEntry(element);
assert Utilities.existsInList(hostContext.getRootResource().fhirType(), "Bundle", "Parameters");
hc = hostContext.forEntry(element, hostContext.getRootResource()); // root becomes the grouping resource (should be either bundle or parameters)
} else {
hc = hostContext.forContained(element);
}

View File

@ -16,6 +16,7 @@ public class ValidatorHostContext {
private Element resource;
// the resource that is the scope of id resolution - either the same as resource, or the resource the contains that resource. This can only be one level deep.
private Element rootResource;
private Element groupingResource; // either a bundle or a parameters that holds the rootResource (for reference resolution)
private StructureDefinition profile; // the profile that contains the content being validated
private boolean checkSpecials = true;
@ -29,7 +30,7 @@ public class ValidatorHostContext {
this.appContext = appContext;
this.resource = element;
this.rootResource = element;
// no container
// no groupingResource (Bundle or Parameters)
dump("creating");
}
@ -37,7 +38,15 @@ public class ValidatorHostContext {
this.appContext = appContext;
this.resource = element;
this.rootResource = root;
// no container
// no groupingResource (Bundle or Parameters)
dump("creating");
}
public ValidatorHostContext(Object appContext, Element element, Element root, Element groupingResource) {
this.appContext = appContext;
this.resource = element;
this.rootResource = root;
this.groupingResource = groupingResource;
dump("creating");
}
@ -65,6 +74,10 @@ public class ValidatorHostContext {
return this;
}
public Element getGroupingResource() {
return groupingResource;
}
public StructureDefinition getProfile() {
return profile;
}
@ -106,15 +119,17 @@ public class ValidatorHostContext {
res.rootResource = resource;
res.resource = element;
res.profile = profile;
res.groupingResource = groupingResource;
res.dump("forContained");
return res;
}
public ValidatorHostContext forEntry(Element element) {
public ValidatorHostContext forEntry(Element element, Element groupingResource) {
ValidatorHostContext res = new ValidatorHostContext(appContext);
res.rootResource = element;
res.resource = element;
res.profile = profile;
res.groupingResource = groupingResource;
res.dump("forEntry");
return res;
}
@ -124,6 +139,7 @@ public class ValidatorHostContext {
res.resource = resource;
res.rootResource = rootResource;
res.profile = profile;
res.groupingResource = groupingResource;
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
res.dump("forProfile "+profile.getUrl());
return res;
@ -134,6 +150,7 @@ public class ValidatorHostContext {
res.resource = resource;
res.rootResource = resource;
res.profile = profile;
res.groupingResource = groupingResource;
res.checkSpecials = false;
res.dump("forLocalReference "+profile.getUrl());
return res;
@ -151,6 +168,7 @@ public class ValidatorHostContext {
res.resource = resource;
res.rootResource = resource;
res.profile = profile;
res.groupingResource = null;
res.checkSpecials = false;
res.dump("forRemoteReference "+profile.getUrl());
return res;
@ -160,6 +178,7 @@ public class ValidatorHostContext {
ValidatorHostContext res = new ValidatorHostContext(appContext);
res.resource = resource;
res.rootResource = resource;
res.groupingResource = groupingResource;
res.profile = profile;
res.checkSpecials = false;
res.sliceRecords = new HashMap<String, List<ValidationMessage>>();