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)
|
||||
TERMINOLOGY_TX_HINT = {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) {
|
||||
return externalHostServices.resolveReference(c.getAppContext(), url, refContext);
|
||||
return setParentsBase(externalHostServices.resolveReference(c.getAppContext(), url, refContext));
|
||||
} else if (fetcher != null) {
|
||||
try {
|
||||
return fetcher.fetch(InstanceValidator.this, c.getAppContext(), url);
|
||||
return setParents(fetcher.fetch(InstanceValidator.this, c.getAppContext(), url));
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
|
@ -5620,11 +5620,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
boolean checkDisplay = true;
|
||||
|
||||
SpecialElement special = ei.getElement().getSpecial();
|
||||
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.BUNDLE_ISSUES || special == SpecialElement.PARAMETER) {
|
||||
ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, ei.getElement(), ei.getElement(), localStack, false) && ok;
|
||||
} else {
|
||||
ok = checkInvariants(hostContext, errors, profile, typeDefn != null ? typeDefn : checkDefn, resource, ei.getElement(), localStack, false) && ok;
|
||||
}
|
||||
// this used to say
|
||||
// if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.BUNDLE_ISSUES || special == SpecialElement.PARAMETER) {
|
||||
// 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;
|
||||
|
||||
ei.getElement().markValidation(profile, checkDefn);
|
||||
boolean elementValidated = false;
|
||||
|
@ -5770,8 +5771,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
int index = profile.getSnapshot().getElement().indexOf(checkDefn);
|
||||
if (index < profile.getSnapshot().getElement().size() - 1) {
|
||||
String nextPath = profile.getSnapshot().getElement().get(index + 1).getPath();
|
||||
if (!nextPath.equals(checkDefn.getPath()) && nextPath.startsWith(checkDefn.getPath()))
|
||||
ok = validateElement(hostContext, errors, profile, checkDefn, null, null, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension, pct, mode) && ok;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
|
@ -6560,11 +6568,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
this.allowDoubleQuotesInFHIRPath = allowDoubleQuotesInFHIRPath;
|
||||
}
|
||||
|
||||
public static void setParents(Element element) {
|
||||
public static Element setParents(Element element) {
|
||||
if (element != null && !element.hasParentForValidator()) {
|
||||
element.setParentForValidator(null);
|
||||
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) {
|
||||
|
|
|
@ -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.Coding;
|
||||
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.Extension;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
|
@ -760,6 +761,9 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
String code = type.getNamedChildValue("code");
|
||||
if (code == null && path != null) {
|
||||
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) {
|
||||
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) {
|
||||
|
@ -833,6 +837,18 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
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) {
|
||||
boolean ok = true;
|
||||
String p = profile.primitiveValue();
|
||||
|
|
|
@ -30,14 +30,23 @@ public class ValidatorHostContext {
|
|||
this.appContext = appContext;
|
||||
this.resource = element;
|
||||
this.rootResource = element;
|
||||
check();
|
||||
|
||||
// no groupingResource (Bundle or Parameters)
|
||||
dump("creating");
|
||||
}
|
||||
|
||||
private void check() {
|
||||
if (!rootResource.hasParentForValidator()) {
|
||||
throw new Error("No parent on root resource");
|
||||
}
|
||||
}
|
||||
|
||||
public ValidatorHostContext(Object appContext, Element element, Element root) {
|
||||
this.appContext = appContext;
|
||||
this.resource = element;
|
||||
this.rootResource = root;
|
||||
check();
|
||||
// no groupingResource (Bundle or Parameters)
|
||||
dump("creating");
|
||||
}
|
||||
|
@ -47,6 +56,7 @@ public class ValidatorHostContext {
|
|||
this.resource = element;
|
||||
this.rootResource = root;
|
||||
this.groupingResource = groupingResource;
|
||||
check();
|
||||
dump("creating");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue