Closed almostchristian closed 1 month ago
I decided to make the Parameters resource the %rootResource here because of this:
https://www.hl7.org/fhir/fhirpath.html#variables
FHIR defines two specific variables that are always in scope when FHIRPath is used in any of the contexts above:
%resource // the resource that contains the original node that is in %context %rootResource // the container resource for the resource identified by %resource
This does not tell us much, but the text under it says:
When a DomainResource contains another resource, and that contained resource is the focus (%resource) then %rootResource refers to the container resource. Note that in most cases, the resource is not contained by another resource, and then %rootResource is the same as %resource.
Clearly, the contained resource (Patient) is the focus here, as we are validating the reference in Patient.identifier. The text says "then %rootResource refers to the container resource", which clearly is the Parameters resource here.
Now, the only interesting bit is that the spec says: "When a DomainResource contains another resource" - and Parameters is not a DomainResource. Will that be the difference? Maybe the %rootResource
is to be read in the context of containment, and non-domain resources do not have a contained
. This might be because the definition of %rootResource
says "the container resource for the resource(...)". And non-domain resources cannot be container resources. Well, actually, I have interpreted they can be, since Bundles and Parameters are containers of other resources, just not through contained
....
Found this interesting discussion https://chat.fhir.org/#narrow/stream/179166-implementers/topic/Contained.20resources/near/398280761
DomainResource.contained isn't a boundary that resets rootResource, but resources in Bundle and Parameters do reset rootResource
Also solve #FirelyTeam/firely-net-sdk#2177
The latest version of the the validator (2.5.0) fixes ref-1
for R5 but seems to fail for R4/R4B. I think it's because of the difference of the expression. I got it to work in R4B by modifying the Expression to be the same as the one in R5. It's a bit of a hack for now.
[System.Runtime.CompilerServices.UnsafeAccessor(System.Runtime.CompilerServices.UnsafeAccessorKind.Field, Name = "<Expression>k__BackingField")]
private static extern ref string GetExpression(FhirPathValidator counter);
// ...
validationSettings.ExcludeFilters.Add(x =>
{
if (x is FhirPathValidator fpv && fpv.Key == "ref-1")
{
GetExpression(fpv) = "reference.exists() implies (reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource))";
}
return false;
});
The following input fails for both the legacy validator and the new validator. We do profile validation on Parameters resources as inputs to custom operations using the profile set in
OperationDefinition.inputProfile
.Validation response:
The FhirPath expression is
reference.exists() implies (reference.startsWith('#').not() or (reference.substring(1).trace('url') in %rootResource.contained.id.trace('ids')) or (reference='#' and %rootResource!=%resource))
which means the%rootResource
in this context is the Parameters resource which would be impossible since Parameters does not have contained resources. The resource validates successfully in https://validator.fhir.org/, which I think means it doesn't use the Parameters as the rootResource.For now, we just disable the ref-1 rule.