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) { } else if (item instanceof Element) {
Element e = (Element) item; Element e = (Element) item;
if (e.getSpecial() == SpecialElement.CONTAINED) { 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) { } 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 { } else {
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), 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); 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; String refType;
if (ref.startsWith("#")) { if (ref.startsWith("#")) {
refType = "contained"; refType = "contained";
@ -3586,7 +3586,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return true; 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("#")) { if (ref.startsWith("#")) {
// work back through the parent list. // work back through the parent list.
// really, there should only be one level for this (contained resources cannot contain // 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(); stack = stack.getParent();
} }
// we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity. // we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity.
if (rootResource != null && BUNDLE.equals(rootResource.fhirType())) { if (groupingResource != null && BUNDLE.equals(groupingResource.fhirType())) { // it could also be a Parameters resource - that case isn't handled yet
String type = rootResource.getChildValue(TYPE); String type = groupingResource.getChildValue(TYPE);
Element entry = getEntryForSource(rootResource, source); Element entry = getEntryForSource(groupingResource, source);
fullUrl = entry.getChildValue(FULL_URL); 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) { if (res == null) {
return null; return null;
} else { } 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 { 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) if (local != null)
return local; return local;
if (fetcher == null) if (fetcher == null)
@ -4600,7 +4600,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ValidatorHostContext hc = null; ValidatorHostContext hc = null;
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) { if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
resource = element; 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 { } else {
hc = hostContext.forContained(element); hc = hostContext.forContained(element);
} }

View File

@ -16,6 +16,7 @@ public class ValidatorHostContext {
private Element resource; 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. // 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 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 StructureDefinition profile; // the profile that contains the content being validated
private boolean checkSpecials = true; private boolean checkSpecials = true;
@ -29,7 +30,7 @@ public class ValidatorHostContext {
this.appContext = appContext; this.appContext = appContext;
this.resource = element; this.resource = element;
this.rootResource = element; this.rootResource = element;
// no container // no groupingResource (Bundle or Parameters)
dump("creating"); dump("creating");
} }
@ -37,7 +38,15 @@ public class ValidatorHostContext {
this.appContext = appContext; this.appContext = appContext;
this.resource = element; this.resource = element;
this.rootResource = root; 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"); dump("creating");
} }
@ -65,6 +74,10 @@ public class ValidatorHostContext {
return this; return this;
} }
public Element getGroupingResource() {
return groupingResource;
}
public StructureDefinition getProfile() { public StructureDefinition getProfile() {
return profile; return profile;
} }
@ -106,15 +119,17 @@ public class ValidatorHostContext {
res.rootResource = resource; res.rootResource = resource;
res.resource = element; res.resource = element;
res.profile = profile; res.profile = profile;
res.groupingResource = groupingResource;
res.dump("forContained"); res.dump("forContained");
return res; return res;
} }
public ValidatorHostContext forEntry(Element element) { public ValidatorHostContext forEntry(Element element, Element groupingResource) {
ValidatorHostContext res = new ValidatorHostContext(appContext); ValidatorHostContext res = new ValidatorHostContext(appContext);
res.rootResource = element; res.rootResource = element;
res.resource = element; res.resource = element;
res.profile = profile; res.profile = profile;
res.groupingResource = groupingResource;
res.dump("forEntry"); res.dump("forEntry");
return res; return res;
} }
@ -124,6 +139,7 @@ public class ValidatorHostContext {
res.resource = resource; res.resource = resource;
res.rootResource = rootResource; res.rootResource = rootResource;
res.profile = profile; res.profile = profile;
res.groupingResource = groupingResource;
res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>(); res.sliceRecords = sliceRecords != null ? sliceRecords : new HashMap<String, List<ValidationMessage>>();
res.dump("forProfile "+profile.getUrl()); res.dump("forProfile "+profile.getUrl());
return res; return res;
@ -134,6 +150,7 @@ public class ValidatorHostContext {
res.resource = resource; res.resource = resource;
res.rootResource = resource; res.rootResource = resource;
res.profile = profile; res.profile = profile;
res.groupingResource = groupingResource;
res.checkSpecials = false; res.checkSpecials = false;
res.dump("forLocalReference "+profile.getUrl()); res.dump("forLocalReference "+profile.getUrl());
return res; return res;
@ -151,6 +168,7 @@ public class ValidatorHostContext {
res.resource = resource; res.resource = resource;
res.rootResource = resource; res.rootResource = resource;
res.profile = profile; res.profile = profile;
res.groupingResource = null;
res.checkSpecials = false; res.checkSpecials = false;
res.dump("forRemoteReference "+profile.getUrl()); res.dump("forRemoteReference "+profile.getUrl());
return res; return res;
@ -160,6 +178,7 @@ public class ValidatorHostContext {
ValidatorHostContext res = new ValidatorHostContext(appContext); ValidatorHostContext res = new ValidatorHostContext(appContext);
res.resource = resource; res.resource = resource;
res.rootResource = resource; res.rootResource = resource;
res.groupingResource = groupingResource;
res.profile = profile; res.profile = profile;
res.checkSpecials = false; res.checkSpecials = false;
res.sliceRecords = new HashMap<String, List<ValidationMessage>>(); res.sliceRecords = new HashMap<String, List<ValidationMessage>>();