From fba2145a9c2c8249db0f53279c88adcb9ea6b31f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 23 Aug 2022 22:32:40 +1000 Subject: [PATCH] Fix bug where instance validator doesn't check type of sub-extensions, and check type characteristics --- .../hl7/fhir/r5/conformance/ProfileUtilities.java | 3 ++- .../org/hl7/fhir/r5/utils/ToolingExtensions.java | 3 +++ .../hl7/fhir/utilities/i18n/I18nConstants.java | 2 ++ .../src/main/resources/Messages.properties | 2 ++ .../validation/instance/InstanceValidator.java | 15 ++++++++++++--- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index fa80788e9..73a7e4765 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -3614,6 +3614,7 @@ public class ProfileUtilities extends TranslatingUtilities { private static final int AGG_IND = 1; private static final int AGG_GR = 2; private static final boolean TABLE_FORMAT_FOR_FIXED_VALUES = false; + public static final String CONSTRAINT_CHAR = "C"; private Cell genTypes(HierarchicalTableGenerator gen, Row r, ElementDefinition e, String profileBaseFileName, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean mustSupportMode) { Cell c = gen.new Cell(); @@ -4365,7 +4366,7 @@ public class ProfileUtilities extends TranslatingUtilities { checkForNoChange(element.getIsSummaryElement(), gc.addStyledText(translate("sd.table", "This element is included in summaries"), "\u03A3", null, null, null, false)); } if (element != null && (hasNonBaseConstraints(element.getConstraint()) || hasNonBaseConditions(element.getCondition()))) { - Piece p = gc.addText("I"); + Piece p = gc.addText(ProfileUtilities.CONSTRAINT_CHAR); p.setHint(translate("sd.table", "This element has or is affected by some invariants ("+listConstraintsAndConditions(element)+")")); p.addStyle(CONSTRAINT_STYLE); p.setReference(context.getSpecUrl()+"conformance-rules.html#constraints"); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java index c6903ad5d..c0dd89535 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java @@ -207,6 +207,9 @@ public class ToolingExtensions { public static final String EXT_EXPAND_RULES = "http://hl7.org/fhir/StructureDefinition/valueset-expand-rules"; public static final String EXT_EXPAND_GROUP = "http://hl7.org/fhir/StructureDefinition/valueset-expand-group"; public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding"; + public static final String EXT_MIN_LENGTH = "http://hl7.org/fhir/StructureDefinition/minLength"; + public static final String EXT_MAX_DECIMALS = "http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces"; + public static final String EXT_MAX_SIZE = "http://hl7.org/fhir/StructureDefinition/maxSize"; // specific extension helpers diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index 439d65e6a..47e2db330 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -381,8 +381,10 @@ public class I18nConstants { public static final String SD_ED_BIND_MULTIPLE_TYPES = "SD_ED_BIND_MULTIPLE_TYPES"; public static final String SD_VALUE_TYPE_IILEGAL = "SD_VALUE_TYPE_IILEGAL"; public static final String SD_VALUE_TYPE_REPEAT_HINT = "SD_VALUE_TYPE_REPEAT_HINT"; + public static final String SD_VALUE_COMPLEX_FIXED = "SD_VALUE_COMPLEX_FIXED"; public static final String SD_VALUE_TYPE_REPEAT_WARNING_DOTNET = "SD_VALUE_TYPE_REPEAT_WARNING_DOTNET"; public static final String SD_NO_TYPES_OR_CONTENTREF = "SD_NO_TYPES_OR_CONTENTREF"; + public static final String SD_ILLEGAL_CHARACTERISTICS = "SD_ILLEGAL_CHARACTERISTICS"; public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG"; public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG"; public static final String SEARCHPARAMETER_NOTFOUND = "SEARCHPARAMETER_NOTFOUND"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index fb1b82c2b..ca032b05c 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -720,3 +720,5 @@ TX_SERVER_NO_BATCH_RESPONSE = The server return null from a batch validation req BUNDLE_POSSSIBLE_MATCHES = The bundle contains no match for {1} by the rules of Bundle reference resolution, but it has multiple resources that match {0} by resource type and id BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU = Entry {0} matches the reference {1} by type and id but it does not match the full target URL {2} by Bundle resolution rules BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU = Entry {0} matches the reference {1} by type and id but it''s fullUrl {2} does not match the full target URL {3} by Bundle resolution rules +SD_ILLEGAL_CHARACTERISTICS = This element has a {0} but the types to do not make this kind of constraint relevant +SD_VALUE_COMPLEX_FIXED = For the complex type {0}, consider using a pattern rather than a fixed value to avoid over-constraining the instance diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 4188ebdd7..018fb7ea7 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -4994,11 +4994,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat type = checkDefn.getType().get(0).getWorkingCode(); String stype = ei.getElement().fhirType(); if (checkDefn.isChoice() && !stype.equals(type)) { - if ("Extension".equals(profile.getType())) { - // error will be raised elsewhere - } else { + if (extensionUrl != null && !isAbsolute(extensionUrl)) { rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype); + } else if (!isAbstractType(type) && !"Extension".equals(profile.getType())) { + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type), I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype); } + } else if (!isAbstractType(type)) { + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type) || + (Utilities.existsInList(type, "string", "id") && Utilities.existsInList(stype, "string", "id")), // work around a r4 problem with id/string + I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype); } // Excluding reference is a kludge to get around versioning issues @@ -5231,6 +5235,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } + private boolean isAbstractType(String type) { + StructureDefinition sd = context.fetchTypeDefinition(type); + return sd != null && sd.getAbstract(); + } + private boolean isResourceAndTypes(ElementDefinition ed) { if (!Utilities.existsInList(ed.getBase().getPath(), "Bundle.entry.resource", "Bundle.entry.response.outcome", "DomainResource.contained", "Parameters.parameter.resource", "Parameters.parameter.part.resource")) { return false;