check StructureDefinition derivation consistency

This commit is contained in:
Grahame Grieve 2021-12-17 12:09:29 +11:00
parent 3118cdc132
commit a13a43ffdf
5 changed files with 24 additions and 9 deletions

View File

@ -0,0 +1,5 @@
Validator:
* check StructureDefinition derivation consistency
Other code changes:
* Add support for new FHIR releases

View File

@ -361,6 +361,7 @@ public class I18nConstants {
public static final String SD_MUST_HAVE_DERIVATION = "SD_MUST_HAVE_DERIVATION";
public static final String SD_NESTED_MUST_SUPPORT_DIFF = "SD_NESTED_MUST_SUPPORT_DIFF";
public static final String SD_NESTED_MUST_SUPPORT_SNAPSHOT = "SD_NESTED_MUST_SUPPORT_SNAPSHOT";
public static final String SD_DERIVATION_KIND_MISMATCH = "SD_DERIVATION_KIND_MISMATCH";
public static final String SD_ED_TYPE_PROFILE_UNKNOWN = "SD_ED_TYPE_PROFILE_UNKNOWN";
public static final String SD_ED_TYPE_PROFILE_NOTYPE = "SD_ED_TYPE_PROFILE_NOTYPE";
public static final String SD_ED_TYPE_PROFILE_WRONG = "SD_ED_TYPE_PROFILE_WRONG";

View File

@ -701,4 +701,4 @@ TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG = The value in the instance ({2}) is
TYPE_SPECIFIC_CHECKS_DT_QTY_MAX_VALUE_WRONG_UCUM = The value in the instance ({0} {1}) is greater than the specified maxValue ({2} {3}) after UCUM conversion
TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_ERROR = Base64 encoded values are not allowed to contain any whitespace (per RFC 4648). Note that non-validating readers are encouraged to accept whitespace anyway
TYPE_SPECIFIC_CHECKS_DT_BASE64_NO_WS_WARNING = Base64 encoded values SHOULD not contain any whitespace (per RFC 4648). Note that non-validating readers are encouraged to accept whitespace anyway
SD_DERIVATION_KIND_MISMATCH = The structure definition constrains a kind of {0}, but has a different kind ({1})

View File

@ -1312,7 +1312,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String system = c.getSystem();
String display = c.getDisplay();
String version = c.getVersion();
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isCodeSystemReferenceValid(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
if (system != null && code != null && !noTerminologyChecks) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
@ -1568,7 +1568,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private void checkCodedElement(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay, NodeStack stack,
String theCode, String theSystem, String theVersion, String theDisplay) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isCodeSystemReferenceValid(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_RELATIVE);
warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, Utilities.noString(theCode) || !Utilities.noString(theSystem), I18nConstants.TERMINOLOGY_TX_SYSTEM_NO_CODE);
if (theSystem != null && theCode != null && !noTerminologyChecks) {
@ -2023,7 +2023,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private void checkIdentifier(List<ValidationMessage> errors, String path, Element element, ElementDefinition context) {
String system = element.getNamedChildValue("system");
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM);
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isIdentifierSystemReferenceValid(system), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_SYSTEM);
if ("urn:ietf:rfc:3986".equals(system)) {
String value = element.getNamedChildValue("value");
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, isAbsolute(value), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_IDENTIFIER_IETF_SYSTEM_VALUE);
@ -3488,13 +3488,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return fmt.length() > 10 && (fmt.substring(10).contains("-") || fmt.substring(10).contains("+") || fmt.substring(10).contains("Z"));
}
private boolean isAbsolute(String uri) {
return Utilities.noString(uri) || uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:uuid:") || uri.startsWith("urn:oid:") || uri.startsWith("urn:ietf:")
|| uri.startsWith("urn:iso:") || uri.startsWith("urn:iso-astm:") || uri.startsWith("mailto:")|| isValidFHIRUrn(uri);
private boolean isAbsolute(String uri, String... protocols) {
return Utilities.noString(uri) || uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:");
}
private boolean isValidFHIRUrn(String uri) {
return (uri.equals("urn:x-fhir:uk:id:nhs-number")) || uri.startsWith("urn:"); // Anyone can invent a URN, so why should we complain?
private boolean isCodeSystemReferenceValid(String uri) {
return isSystemReferenceValid(uri);
}
private boolean isIdentifierSystemReferenceValid(String uri) {
return isSystemReferenceValid(uri) || uri.startsWith("ldap:");
}
private boolean isSystemReferenceValid(String uri) {
return uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("urn:");
}
public boolean isAnyExtensionsAllowed() {

View File

@ -97,6 +97,8 @@ public class StructureDefinitionValidator extends BaseValidator {
}
}
}
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")),
I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind"));
}
} catch (FHIRException | IOException e) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());