From c918f724eef527a369f6b320358e1b68ddf66deb Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 26 Feb 2022 06:22:42 +1100 Subject: [PATCH] fix problem missing profiles on references in discriminators --- .../org/hl7/fhir/r5/utils/FHIRPathEngine.java | 24 +++++++++++++++---- .../instance/InstanceValidator.java | 10 +++++--- .../test/resources/txCache/3.0.2/snomed.cache | 9 +++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java index 1239685a8..7bbee529c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -235,6 +235,13 @@ public class FHIRPathEngine { } return res; } + public boolean hasType(String tn) { + if (type != null) { + return tn.equals(type); + } else { + return element.hasType(tn); + } + } } private IWorkerContext worker; private IEvaluationContext hostServices; @@ -5472,7 +5479,7 @@ public class FHIRPathEngine { * @throws PathEngineException * @throws DefinitionException */ - public TypedElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, TypedElementDefinition element, StructureDefinition source) throws DefinitionException { + public TypedElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, TypedElementDefinition element, StructureDefinition source, boolean dontWalkIntoReferences) throws DefinitionException { StructureDefinition sd = profile; TypedElementDefinition focus = null; boolean okToNotResolve = false; @@ -5584,10 +5591,19 @@ public class FHIRPathEngine { } else { throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_CANT_FIND, expr.toString(), source.getUrl(), element.getElement().getId(), profile.getUrl()); } - } else if (expr.getInner() == null) { - return focus; } else { - return evaluateDefinition(expr.getInner(), sd, focus, profile); + // gdg 26-02-2022. If we're walking towards a resolve() and we're on a reference, and we try to walk into the reference + // then we don't do that. .resolve() is allowed on the Reference.reference, but the target of the reference will be defined + // on the Reference, not the reference.reference. + ExpressionNode next = expr.getInner(); + if (dontWalkIntoReferences && focus.hasType("Reference") && next != null && next.getKind() == Kind.Name && next.getName().equals("reference")) { + next = next.getInner(); + } + if (next == null) { + return focus; + } else { + return evaluateDefinition(next, sd, focus, profile, dontWalkIntoReferences); + } } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index fdc6782d5..54c748c7a 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -3405,13 +3405,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return elements; } + boolean dontFollowReference = false; + if (removeResolve) { // if we're doing profile slicing, we don't want to walk into the last resolve.. we need the profile on the source not the target if (discriminator.equals("resolve()")) { elements.add(element); return elements; } - if (discriminator.endsWith(".resolve()")) + if (discriminator.endsWith(".resolve()")) { discriminator = discriminator.substring(0, discriminator.length() - 10); + dontFollowReference = true; + } } TypedElementDefinition ted = null; @@ -3424,7 +3428,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat throw new FHIRException(context.formatMessage(I18nConstants.DISCRIMINATOR_BAD_PATH, e.getMessage(), fp), e); } long t2 = System.nanoTime(); - ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile); + ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile, dontFollowReference); timeTracker.sd(t2); if (ted != null) elements.add(ted.getElement()); @@ -3449,7 +3453,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } expr = fpe.parse(fp); t2 = System.nanoTime(); - ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile); + ted = fpe.evaluateDefinition(expr, profile, new TypedElementDefinition(element), srcProfile, dontFollowReference); timeTracker.sd(t2); if (ted != null) elements.add(ted.getElement()); diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/3.0.2/snomed.cache b/org.hl7.fhir.validation/src/test/resources/txCache/3.0.2/snomed.cache index 054313479..4d4ad75b9 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/3.0.2/snomed.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/3.0.2/snomed.cache @@ -343,3 +343,12 @@ v: { "system" : "http://snomed.info/sct" } ------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://snomed.info/sct", + "code" : "11181000146103" +}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}#### +v: { + "severity" : "error", + "error" : "Unable to find code 11181000146103 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20210731); The code \"11181000146103\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#11181000146103) is not valid in the value set 'All codes known to the system' (from http://tx.fhir.org/r3)" +} +-------------------------------------------------------------------------------------