Fix to get context variables right when running invariants + fix for parent not always being populated + check type in derived profiles
This commit is contained in:
parent
6c2c1b21f9
commit
ced714305d
|
@ -975,3 +975,5 @@ ED_INVARIANT_EXPRESSION_ERROR = Error in invariant ''{0}'' with expression ''{1}
|
||||||
SNAPSHOT_IS_EMPTY = The snapshot for the profile ''{0}'' is empty (which should not happen)
|
SNAPSHOT_IS_EMPTY = The snapshot for the profile ''{0}'' is empty (which should not happen)
|
||||||
TERMINOLOGY_TX_HINT = {1}
|
TERMINOLOGY_TX_HINT = {1}
|
||||||
TERMINOLOGY_TX_WARNING = {1}
|
TERMINOLOGY_TX_WARNING = {1}
|
||||||
|
SD_ED_TYPE_WRONG_TYPE_one = The element has a type {0} which is different to the type {1} on the base profile {2}
|
||||||
|
SD_ED_TYPE_WRONG_TYPE_other = The element has a type {0} which is not in the types {1} on the base profile {2}
|
||||||
|
|
|
@ -368,10 +368,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
if (externalHostServices != null) {
|
if (externalHostServices != null) {
|
||||||
return externalHostServices.resolveReference(c.getAppContext(), url, refContext);
|
return setParentsBase(externalHostServices.resolveReference(c.getAppContext(), url, refContext));
|
||||||
} else if (fetcher != null) {
|
} else if (fetcher != null) {
|
||||||
try {
|
try {
|
||||||
return fetcher.fetch(InstanceValidator.this, c.getAppContext(), url);
|
return setParents(fetcher.fetch(InstanceValidator.this, c.getAppContext(), url));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FHIRException(e);
|
throw new FHIRException(e);
|
||||||
}
|
}
|
||||||
|
@ -5620,11 +5620,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
boolean checkDisplay = true;
|
boolean checkDisplay = true;
|
||||||
|
|
||||||
SpecialElement special = ei.getElement().getSpecial();
|
SpecialElement special = ei.getElement().getSpecial();
|
||||||
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.BUNDLE_ISSUES || special == SpecialElement.PARAMETER) {
|
// this used to say
|
||||||
ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, ei.getElement(), ei.getElement(), localStack, false) && ok;
|
// if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.BUNDLE_ISSUES || special == SpecialElement.PARAMETER) {
|
||||||
} else {
|
// ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, ei.getElement(), ei.getElement(), localStack, false) && ok;
|
||||||
|
// but this isn't correct - when the invariant is on the element, the invariant is in the context of the resource that contains the element.
|
||||||
|
// changed 18-Jul 2023 - see https://chat.fhir.org/#narrow/stream/179266-fhirpath/topic/FHIRPath.20.25resource.20variable
|
||||||
ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, resource, ei.getElement(), localStack, false) && ok;
|
ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, resource, ei.getElement(), localStack, false) && ok;
|
||||||
}
|
|
||||||
|
|
||||||
ei.getElement().markValidation(profile, checkDefn);
|
ei.getElement().markValidation(profile, checkDefn);
|
||||||
boolean elementValidated = false;
|
boolean elementValidated = false;
|
||||||
|
@ -5770,10 +5771,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
int index = profile.getSnapshot().getElement().indexOf(checkDefn);
|
int index = profile.getSnapshot().getElement().indexOf(checkDefn);
|
||||||
if (index < profile.getSnapshot().getElement().size() - 1) {
|
if (index < profile.getSnapshot().getElement().size() - 1) {
|
||||||
String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath();
|
String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath();
|
||||||
if (!nextPath.equals(checkDefn.getPath()) && nextPath.startsWith(checkDefn.getPath()))
|
if (!nextPath.equals(checkDefn.getPath()) && nextPath.startsWith(checkDefn.getPath())) {
|
||||||
|
if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER) {
|
||||||
|
ok = validateElement(hostContext.forEntry(ei.getElement(), null), errors, profile, checkDefn, null, null, ei.getElement(), ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension, pct, mode) && ok;
|
||||||
|
} else if (ei.getElement().getSpecial() == SpecialElement.CONTAINED) {
|
||||||
|
ok = validateElement(hostContext.forContained(ei.getElement()), errors, profile, checkDefn, null, null, ei.getElement(), ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension, pct, mode) && ok;
|
||||||
|
} else {
|
||||||
ok = validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension, pct, mode) && ok;
|
ok = validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension, pct, mode) && ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6560,11 +6568,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath;
|
this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setParents(Element element) {
|
public static Element setParents(Element element) {
|
||||||
if (element != null && !element.hasParentForValidator()) {
|
if (element != null && !element.hasParentForValidator()) {
|
||||||
element.setParentForValidator(null);
|
element.setParentForValidator(null);
|
||||||
setParentsInner(element);
|
setParentsInner(element);
|
||||||
}
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Base setParentsBase(Base element) {
|
||||||
|
if (element instanceof Element) {
|
||||||
|
setParents((Element) element);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setParentsInner(Element element) {
|
public static void setParentsInner(Element element) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
|
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||||
import org.hl7.fhir.r5.model.ExpressionNode;
|
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
|
@ -760,6 +761,9 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
String code = type.getNamedChildValue("code");
|
String code = type.getNamedChildValue("code");
|
||||||
if (code == null && path != null) {
|
if (code == null && path != null) {
|
||||||
code = getTypeCodeFromSD(sd, path);
|
code = getTypeCodeFromSD(sd, path);
|
||||||
|
} else {
|
||||||
|
Set<String> types = getTypeCodesFromSD(sd, path);
|
||||||
|
ok = rulePlural(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), types.isEmpty() || types.contains(code), types.size(), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TYPE, code, types.toString(), sd.getVersionedUrl());
|
||||||
}
|
}
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
List<Element> profiles = type.getChildrenByName("profile");
|
List<Element> profiles = type.getChildrenByName("profile");
|
||||||
|
@ -778,7 +782,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateProfileTypeOrTarget(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
private boolean validateProfileTypeOrTarget(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
||||||
|
@ -833,6 +837,18 @@ public class StructureDefinitionValidator extends BaseValidator {
|
||||||
return ed != null && ed.getType().size() == 1 ? ed.getTypeFirstRep().getCode() : null;
|
return ed != null && ed.getType().size() == 1 ? ed.getTypeFirstRep().getCode() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<String> getTypeCodesFromSD(StructureDefinition sd, String path) {
|
||||||
|
Set<String> codes = new HashSet<>();
|
||||||
|
for (ElementDefinition t : sd.getSnapshot().getElement()) {
|
||||||
|
if (t.hasPath() && t.getPath().equals(path)) {
|
||||||
|
for (TypeRefComponent tr : t.getType()) {
|
||||||
|
codes.add(tr.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codes;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean validateTypeProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
private boolean validateTypeProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
String p = profile.primitiveValue();
|
String p = profile.primitiveValue();
|
||||||
|
|
|
@ -30,14 +30,23 @@ public class ValidatorHostContext {
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.resource = element;
|
this.resource = element;
|
||||||
this.rootResource = element;
|
this.rootResource = element;
|
||||||
|
check();
|
||||||
|
|
||||||
// no groupingResource (Bundle or Parameters)
|
// no groupingResource (Bundle or Parameters)
|
||||||
dump("creating");
|
dump("creating");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void check() {
|
||||||
|
if (!rootResource.hasParentForValidator()) {
|
||||||
|
throw new Error("No parent on root resource");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ValidatorHostContext(Object appContext, Element element, Element root) {
|
public ValidatorHostContext(Object appContext, Element element, Element root) {
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.resource = element;
|
this.resource = element;
|
||||||
this.rootResource = root;
|
this.rootResource = root;
|
||||||
|
check();
|
||||||
// no groupingResource (Bundle or Parameters)
|
// no groupingResource (Bundle or Parameters)
|
||||||
dump("creating");
|
dump("creating");
|
||||||
}
|
}
|
||||||
|
@ -47,6 +56,7 @@ public class ValidatorHostContext {
|
||||||
this.resource = element;
|
this.resource = element;
|
||||||
this.rootResource = root;
|
this.rootResource = root;
|
||||||
this.groupingResource = groupingResource;
|
this.groupingResource = groupingResource;
|
||||||
|
check();
|
||||||
dump("creating");
|
dump("creating");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue