change constraints on Reference targets for logical models

This commit is contained in:
Grahame Grieve 2023-05-17 10:32:43 +10:00
parent 6d2e3ee388
commit 52db200d8b
1 changed files with 28 additions and 10 deletions

View File

@ -19,6 +19,8 @@ import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.extensions.ExtensionConstants;
import org.hl7.fhir.r5.extensions.Extensions;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Coding;
@ -125,11 +127,12 @@ public class StructureDefinitionValidator extends BaseValidator {
}
List<Element> differentials = src.getChildrenByName("differential");
List<Element> snapshots = src.getChildrenByName("snapshot");
boolean logical = "logical".equals(src.getNamedChildValue("kind"));
for (Element differential : differentials) {
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName) && ok;
ok = validateElementList(errors, differential, stack.push(differential, -1, null, null), false, snapshots.size() > 0, sd, typeName, logical) && ok;
}
for (Element snapshot : snapshots) {
ok = validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true, sd, typeName) && ok;
ok = validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true, sd, typeName, logical) && ok;
}
return ok;
}
@ -169,18 +172,18 @@ public class StructureDefinitionValidator extends BaseValidator {
}
}
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName) {
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical) {
boolean ok = true;
List<Element> elements = elementList.getChildrenByName("element");
int cc = 0;
for (Element element : elements) {
ok = validateElementDefinition(errors, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName) && ok;
ok = validateElementDefinition(errors, element, stack.push(element, cc, null, null), snapshot, hasSnapshot, sd, typeName, logical) && ok;
cc++;
}
return ok;
}
private boolean validateElementDefinition(List<ValidationMessage> errors, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName) {
private boolean validateElementDefinition(List<ValidationMessage> errors, Element element, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName, boolean logical) {
boolean ok = true;
boolean typeMustSupport = false;
String path = element.getNamedChildValue("path");
@ -231,7 +234,7 @@ public class StructureDefinitionValidator extends BaseValidator {
}
// check the stated profile - must be a constraint on the type
if (snapshot || sd != null) {
ok = validateElementType(errors, type, stack.push(type, -1, null, null), sd, path) && ok;
ok = validateElementType(errors, type, stack.push(type, -1, null, null), sd, path, logical) && ok;
}
}
}
@ -479,7 +482,7 @@ public class StructureDefinitionValidator extends BaseValidator {
return vr.getErrorClass() == null;
}
private boolean validateElementType(List<ValidationMessage> errors, Element type, NodeStack stack, StructureDefinition sd, String path) {
private boolean validateElementType(List<ValidationMessage> errors, Element type, NodeStack stack, StructureDefinition sd, String path, boolean logical) {
boolean ok = true;
String code = type.getNamedChildValue("code");
if (code == null && path != null) {
@ -498,7 +501,7 @@ public class StructureDefinitionValidator extends BaseValidator {
}
profiles = type.getChildrenByName("targetProfile");
for (Element profile : profiles) {
ok = validateTargetProfile(errors, profile, code, stack.push(profile, -1, null, null), path) && ok;
ok = validateTargetProfile(errors, profile, code, stack.push(profile, -1, null, null), path, logical) && ok;
}
}
}
@ -589,7 +592,7 @@ public class StructureDefinitionValidator extends BaseValidator {
return t.getSnapshot().getElementFirstRep().getIsModifier();
}
private boolean validateTargetProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path) {
private boolean validateTargetProfile(List<ValidationMessage> errors, Element profile, String code, NodeStack stack, String path, boolean logical) {
boolean ok = true;
String p = profile.primitiveValue();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
@ -599,7 +602,7 @@ public class StructureDefinitionValidator extends BaseValidator {
if (t == null) {
ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else {
ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Resource") && ok;
ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), (sd.getKind() == StructureDefinitionKind.RESOURCE) || (logical && isReferenceableTarget(t)), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Resource") && ok;
}
}
} else if (code.equals("canonical")) {
@ -619,6 +622,21 @@ public class StructureDefinitionValidator extends BaseValidator {
return ok;
}
private boolean isReferenceableTarget(StructureDefinition t) {
for (Extension ext : t.getExtensionsByUrl(ExtensionConstants.EXT_SDTYPE_CHARACTERISTICS)) {
if (ext.hasValue()) {
String c = ext.getValue().primitiveValue();
if ("can-be-target".equals(c)) {
return true;
}
}
}
if (ToolingExtensions.readBoolExtension(t, "http://hl7.org/fhir/tools/StructureDefinition/logical-target")) {
return true;
}
return false;
}
private boolean isInstanceOf(StructureDefinition sd, String code) {
while (sd != null) {
if (sd.getType().equals(code)) {