Improved invariant checking
This commit is contained in:
parent
bd3d718256
commit
c58703c63f
|
@ -946,6 +946,7 @@ public class I18nConstants {
|
|||
public static final String ED_INVARIANT_DIFF_NO_SOURCE = "ED_INVARIANT_DIFF_NO_SOURCE";
|
||||
public static final String FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT = "FHIRPATH_COLLECTION_STATUS_OPERATION_LEFT";
|
||||
public static final String FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT = "FHIRPATH_COLLECTION_STATUS_OPERATION_RIGHT";
|
||||
public static final String ED_INVARIANT_KEY_ALREADY_USED = "ED_INVARIANT_KEY_ALREADY_USED";
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -970,10 +970,11 @@ QUESTIONNAIRE_Q_ITEM_DERIVED_ANSWER_OPTIONS_NEW = The item with linkId ''{1}'' f
|
|||
PRIMITIVE_MUSTHAVEVALUE_MESSAGE = The element definition ``{0}`` in the profile ''{1}'' requires that a value be present in this element
|
||||
PRIMITIVE_VALUE_ALTERNATIVES_MESSAGE_one = The element definition ``{0}`` in the profile ''{1}'' requires that if a value is not present, the extension ''{2}'' must be present
|
||||
PRIMITIVE_VALUE_ALTERNATIVES_MESSAGE_other = The element definition ``{0}`` in the profile ''{1}'' requires that if a value is not present, one of the extensions ''{2}'' must be present
|
||||
ED_INVARIANT_NO_KEY = The invariant has no key, so the content cannot be validated
|
||||
ED_INVARIANT_NO_EXPRESSION = The invariant ''{0}'' has no computable expression, so validators will not be able to check it
|
||||
ED_INVARIANT_EXPRESSION_CONFLICT = The invariant ''{0}'' has an expression ''{1}'', which differs from the earlier expression provided of ''{2}'' (invariants are allowed to repeat, but cannot differ)
|
||||
ED_INVARIANT_EXPRESSION_ERROR = Error in invariant ''{0}'' with expression ''{1}'': {2}
|
||||
ED_INVARIANT_NO_KEY = The constraint has no key, so the content cannot be validated
|
||||
ED_INVARIANT_KEY_ALREADY_USED = The constraint key ''{0}'' already exists in the base profile ''{1}''
|
||||
ED_INVARIANT_NO_EXPRESSION = The constraint ''{0}'' has no computable expression, so validators will not be able to check it
|
||||
ED_INVARIANT_EXPRESSION_CONFLICT = The constraint ''{0}'' has an expression ''{1}'', which differs from the earlier expression provided of ''{2}'' (invariants are allowed to repeat, but cannot differ)
|
||||
ED_INVARIANT_EXPRESSION_ERROR = Error in constraint ''{0}'' with expression ''{1}'': {2}
|
||||
SNAPSHOT_IS_EMPTY = The snapshot for the profile ''{0}'' is empty (which should not happen)
|
||||
TERMINOLOGY_TX_HINT = {1}
|
||||
TERMINOLOGY_TX_WARNING = {1}
|
||||
|
|
|
@ -26,6 +26,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.ElementDefinitionConstraintComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
|
@ -131,10 +132,10 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
boolean logical = "logical".equals(src.getNamedChildValue("kind"));
|
||||
boolean constraint = "constraint".equals(src.getNamedChildValue("derivation"));
|
||||
for (Element differential : differentials) {
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url")) && ok;
|
||||
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url"), base) && ok;
|
||||
}
|
||||
for (Element snapshotE : snapshots) {
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url")) && ok;
|
||||
ok = validateElementList(errors, snapshotE, stack.push(snapshotE, -1, null, null), true, true, sd, typeName, logical, constraint, src.getNamedChildValue("type"), src.getNamedChildValue("url"), base) && ok;
|
||||
}
|
||||
|
||||
// obligation profile support
|
||||
|
@ -217,7 +218,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
NodeStack stack = push.push(child, c, null, null);
|
||||
if (child.getName().equals("extension")) {
|
||||
String url = child.getNamedChildValue("url");
|
||||
if ("http://hl7.org/fhir/tools/StructureDefinition/obligation".equals(url)) {
|
||||
if (Utilities.existsInList(url, ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) {
|
||||
// this is ok, and it doesn't matter what's in the obligation
|
||||
} else {
|
||||
ok = false;
|
||||
|
@ -332,19 +333,19 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl) {
|
||||
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, String rootPath, String profileUrl, StructureDefinition base) {
|
||||
Map<String, String> invariantMap = new HashMap<>();
|
||||
boolean ok = true;
|
||||
List<Element> elements = elementList.getChildrenByName("element");
|
||||
int cc = 0;
|
||||
for (Element element : elements) {
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl) && ok;
|
||||
ok = validateElementDefinition(errors, elements, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical, constraint, invariantMap, rootPath, profileUrl, base) && ok;
|
||||
cc++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl) {
|
||||
private boolean validateElementDefinition(List<ValidationMessage> errors, List<Element> elements, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical, boolean constraint, Map<String, String> invariantMap, String rootPath, String profileUrl, StructureDefinition base) {
|
||||
boolean ok = true;
|
||||
boolean typeMustSupport = false;
|
||||
String path = element.getNamedChildValue("path");
|
||||
|
@ -472,13 +473,14 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
List<Element> constraints = element.getChildrenByName("constraint");
|
||||
int cc = 0;
|
||||
for (Element invariant : constraints) {
|
||||
ok = validateElementDefinitionInvariant(errors, invariant, stack.push(invariant, cc, null, null), invariantMap, elements, element, element.getNamedChildValue("path"), rootPath, profileUrl, snapshot) && ok;
|
||||
ok = validateElementDefinitionInvariant(errors, invariant, stack.push(invariant, cc, null, null), invariantMap, elements, element, element.getNamedChildValue("path"), rootPath, profileUrl, snapshot, base) && ok;
|
||||
cc++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateElementDefinitionInvariant(List<ValidationMessage> errors, Element invariant, NodeStack stack, Map<String, String> invariantMap, List<Element> elements, Element element, String path, String rootPath, String profileUrl, boolean snapshot) {
|
||||
private boolean validateElementDefinitionInvariant(List<ValidationMessage> errors, Element invariant, NodeStack stack, Map<String, String> invariantMap, List<Element> elements, Element element,
|
||||
String path, String rootPath, String profileUrl, boolean snapshot, StructureDefinition base) {
|
||||
boolean ok = true;
|
||||
String key = invariant.getNamedChildValue("key");
|
||||
String expression = invariant.getNamedChildValue("expression");
|
||||
|
@ -525,13 +527,26 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ok = rule(errors, "2023-07-27", IssueType.INVALID, stack, source == null || source.equals(profileUrl), I18nConstants.ED_INVARIANT_DIFF_NO_SOURCE, key, source);
|
||||
ok = rule(errors, "2023-07-27", IssueType.INVALID, stack, source == null || source.equals(profileUrl), I18nConstants.ED_INVARIANT_DIFF_NO_SOURCE, key, source) &&
|
||||
rule(errors, "2023-07-27", IssueType.INVALID, stack, !haseHasInvariant(base, key), I18nConstants.ED_INVARIANT_KEY_ALREADY_USED, key, base.getVersionedUrl());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean haseHasInvariant(StructureDefinition base, String key) {
|
||||
for (ElementDefinition ed : base.getSnapshot().getElement()) {
|
||||
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
|
||||
if (key.equals(inv.getKey())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String tail(Element te, Element newte) {
|
||||
String p = te.getNamedChildValue("path");
|
||||
String pn = newte.getNamedChildValue("path");
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -20,7 +20,7 @@
|
|||
<properties>
|
||||
<guava_version>32.0.1-jre</guava_version>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.3.18</validator_test_case_version>
|
||||
<validator_test_case_version>1.3.19-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.15.2</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue