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 fcbed22af..c386925e3 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 @@ -121,7 +121,6 @@ public class ToolingExtensions { public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name"; public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-style"; public static final String EXT_EXPLICIT_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"; - public static final String EXT_TIME_FORMAT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-timeformat"; public static final String EXT_IGP_RESOURCES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-resource"; public static final String EXT_IGP_PAGES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-pages"; @@ -210,6 +209,7 @@ public class ToolingExtensions { public static final String EXT_XML_NO_ORDER = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order"; public static final String EXT_DEF_TYPE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype"; public static final String EXT_TYPE_SPEC = "http://hl7.org/fhir/tools/StructureDefinition/type-specifier"; + public static final String EXT_TYPE_CHARACTERISTICS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics"; // in the tooling IG public static final String EXT_PRIVATE_BASE = "http://hl7.org/fhir/tools/"; @@ -217,6 +217,7 @@ public class ToolingExtensions { public static final String EXT_JSON_PROP_KEY = "http://hl7.org/fhir/tools/StructureDefinition/json-property-key"; public static final String EXT_JSON_EMPTY = "http://hl7.org/fhir/tools/StructureDefinition/json-empty-behavior"; public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix"; + public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format"; // unregistered? - don't know what these are used for 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 e9222c8f6..705e2bf5a 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 @@ -357,7 +357,8 @@ public class I18nConstants { public static final String REFERENCE_TO__CANNOT_BE_RESOLVED = "reference_to__cannot_be_resolved"; public static final String REFERENCE__REFERS_TO_A__NOT_A_VALUESET = "Reference__refers_to_a__not_a_ValueSet"; public static final String RESOURCE_RESOLUTION_SERVICES_NOT_PROVIDED = "Resource_resolution_services_not_provided"; - public static final String RESOURCE_RES_ID_MALFORMED = "Resource_RES_ID_Malformed"; + public static final String RESOURCE_RES_ID_MALFORMED_CHARS = "Resource_RES_ID_Malformed_Chars"; + public static final String RESOURCE_RES_ID_MALFORMED_LENGTH = "Resource_RES_ID_Malformed_Length"; public static final String RESOURCE_RES_ID_MISSING = "Resource_RES_ID_Missing"; public static final String RESOURCE_RES_ID_PROHIBITED = "Resource_RES_ID_Prohibited"; public static final String RESOURCE_TYPE_MISMATCH_FOR___ = "Resource_type_mismatch_for___"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 114af80fb..2609b86ab 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -123,7 +123,8 @@ Reference_REF_NotFound_Bundle = Bundled or contained reference not found within Reference_REF_ResourceType = Matching reference for reference {0} has resourceType {1} Reference_REF_WrongTarget = The type ''{0}'' is not a valid Target for this element (must be one of {1}) REFERENCE_REF_WRONGTARGET_LOAD = The type ''{2}'' is not a valid Target for the element {0} (must be {1}) -Resource_RES_ID_Malformed = Invalid Resource id +Resource_RES_ID_Malformed_Length = Invalid Resource id: Too long +Resource_RES_ID_Malformed_Chars = Invalid Resource id: Invalid Characters Resource_RES_ID_Missing = Resource requires an id, but none is present Resource_RES_ID_Prohibited = Resource has an id, but none is allowed Terminology_PassThrough_TX_Message = {0} for ''{1}#{2}'' @@ -728,7 +729,7 @@ 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 {1} to do not make this kind of constraint relevant +SD_ILLEGAL_CHARACTERISTICS = This element has a {0} but the types {1} 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 VALUESET_SHAREABLE_MISSING = The ShareableValueSet profile says that the {0} element is mandatory, but it is not present. Published value sets SHOULD conform to the ShareableValueSet profile VALUESET_SHAREABLE_EXTRA_MISSING = The ShareableValueSet profile recommends that the {0} element is populated, but it is not present. Published value sets SHOULD conform to the ShareableValueSet profile 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 ba7355590..c5071610b 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 @@ -5866,7 +5866,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat Element eid = element.getNamedChild(ID); if (eid.getProperty() != null && eid.getProperty().getDefinition() != null && eid.getProperty().getDefinition().getBase().getPath().equals("Resource.id")) { NodeStack ns = stack.push(eid, -1, eid.getProperty().getDefinition(), null); - rule(errors, IssueType.INVALID, eid.line(), eid.col(), ns.getLiteralPath(), FormatUtilities.isValidId(eid.primitiveValue()), I18nConstants.RESOURCE_RES_ID_MALFORMED); + if (eid.primitiveValue() != null && eid.primitiveValue().length() > 64) { + rule(errors, IssueType.INVALID, eid.line(), eid.col(), ns.getLiteralPath(), false, I18nConstants.RESOURCE_RES_ID_MALFORMED_LENGTH); + } else { + rule(errors, IssueType.INVALID, eid.line(), eid.col(), ns.getLiteralPath(), FormatUtilities.isValidId(eid.primitiveValue()), I18nConstants.RESOURCE_RES_ID_MALFORMED_CHARS); + } } } // validate diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java index 73cf6ed13..042e8a2f9 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureDefinitionValidator.java @@ -23,6 +23,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ExpressionNode; +import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; @@ -149,7 +150,15 @@ public class StructureDefinitionValidator extends BaseValidator { } typeCodes.add(tc); Set tcharacteristics = new HashSet<>(); - addCharacteristics(tcharacteristics, tc); + StructureDefinition tsd = context.fetchTypeDefinition(tc); + if (tsd != null && tsd.hasExtension(ToolingExtensions.EXT_TYPE_CHARACTERISTICS)) { + for (Extension ext : tsd.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_CHARACTERISTICS)) { + tcharacteristics.add(ext.getValue().primitiveValue()); + } + } else { + // nothing specified, so infer from known types + addCharacteristics(tcharacteristics, tc); + } characteristics.addAll(tcharacteristics); if (type.hasChildren("targetProfile")) { rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), tcharacteristics.contains("has-target") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "targetProfile", tc); @@ -345,6 +354,11 @@ public class StructureDefinitionValidator extends BaseValidator { if (sd.hasExtension(ToolingExtensions.EXT_BINDING_STYLE)) { return tc; } + for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_CHARACTERISTICS)) { + if ("can-bind".equals(ext.getValue().primitiveValue())) { + return tc; + } + } } } return null; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/profile/ProfileValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/profile/ProfileValidator.java index c09a5cdbc..5ea1bbf23 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/profile/ProfileValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/profile/ProfileValidator.java @@ -39,6 +39,7 @@ 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.StructureDefinition; +import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.utilities.Utilities; @@ -83,8 +84,9 @@ public class ProfileValidator extends BaseValidator { List errors = new ArrayList(); // must have a FHIR version- GF#3160 - warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), "Profiles SHOULD state the FHIR Version on which they are based"); - warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), "Profiles SHOULD state their own version"); + String s = (profile.getKind() == StructureDefinitionKind.LOGICAL) ? "Logical Models" : "Profiles"; + warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), s+" SHOULD state the FHIR Version on which they are based"); + warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), s+" SHOULD state their own version"); // extensions must be defined for (ElementDefinition ec : profile.getDifferential().getElement())