diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceSorters.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceSorters.java index fa9608a6b..c1bf091f3 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceSorters.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceSorters.java @@ -10,10 +10,12 @@ public class ResourceSorters { @Override public int compare(CanonicalResource arg0, CanonicalResource arg1) { - if (arg0.getUrl() != null) { + if (arg0.getUrl() != null && arg1.getUrl() != null) { return arg0.getUrl().compareTo(arg1.getUrl()); } else if (arg1.getUrl() != null) { - return -arg1.getUrl().compareTo(arg0.getUrl()); + return -1; + } else if (arg0.getUrl() != null) { + return 1; } else { return 0; } 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 c9d685ede..4eba72976 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 @@ -278,6 +278,8 @@ public class ToolingExtensions { public static final String EXT_ALTERNATE_CANONICAL = "http://hl7.org/fhir/StructureDefinition/alternate-canonical"; public static final String EXT_SUPPRESSED = "http://hl7.org/fhir/StructureDefinition/elementdefinition-suppress"; public static final String EXT_SUPPRESS_RESOURCE_TYPE = "http://hl7.org/fhir/tools/StructureDefinition/json-suppress-resourcetype"; + public static final String EXT_PROFILE_VIEW_HINT = "http://hl7.org/fhir/tools/StructureDefinition/view-hint"; + public static final String EXT_SNAPSHOT_BEHAVIOR = "http://hl7.org/fhir/tools/StructureDefinition/snapshot-behavior"; // specific extension helpers @@ -474,6 +476,7 @@ public class ToolingExtensions { } return null; } + public static String readStringExtension(DomainResource c, String uri) { Extension ex = getExtension(c, uri); if (ex == null) @@ -495,6 +498,30 @@ public class ToolingExtensions { return null; } + public static String readStringSubExtension(DomainResource c, String uri, String name) { + Extension ex = getExtension(c, uri); + if (ex == null) + return null; + ex = getExtension(ex, name); + if (ex == null) + return null; + if ((ex.getValue() instanceof StringType)) + return ((StringType) ex.getValue()).getValue(); + if ((ex.getValue() instanceof UriType)) + return ((UriType) ex.getValue()).getValue(); + if (ex.getValue() instanceof CodeType) + return ((CodeType) ex.getValue()).getValue(); + if (ex.getValue() instanceof IntegerType) + return ((IntegerType) ex.getValue()).asStringValue(); + if (ex.getValue() instanceof Integer64Type) + return ((Integer64Type) ex.getValue()).asStringValue(); + if (ex.getValue() instanceof DecimalType) + return ((DecimalType) ex.getValue()).asStringValue(); + if ((ex.getValue() instanceof MarkdownType)) + return ((MarkdownType) ex.getValue()).getValue(); + return null; + } + @SuppressWarnings("unchecked") public static PrimitiveType readPrimitiveExtension(DomainResource c, String uri) { Extension ex = getExtension(c, uri); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/UserDataNames.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/UserDataNames.java index 0f33c2419..ff9dbe062 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/UserDataNames.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/UserDataNames.java @@ -17,6 +17,7 @@ public class UserDataNames { public static final String SNAPSHOT_DERIVATION_POINTER = "derived.pointer"; public static final String SNAPSHOT_IS_DERIVED = "derived.fact"; public static final String SNAPSHOT_GENERATED_IN_SNAPSHOT = "profileutilities.snapshot.processed"; + public static final String SNAPSHOT_DERIVATION_DIFF = "profileutilities.snapshot.diffsource"; public static final String SNAPSHOT_GENERATING = "profileutils.snapshot.generating"; public static final String SNAPSHOT_GENERATED = "profileutils.snapshot.generated"; public static final String SNAPSHOT_GENERATED_MESSAGES = "profileutils.snapshot.generated.messages"; 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 e44ddd998..894a4638c 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 @@ -1163,4 +1163,6 @@ public class I18nConstants { public static final String VS_EXP_IMPORT_FAIL_X = "VS_EXP_IMPORT_FAIL_X"; public static final String VS_EXP_FILTER_UNK = "VS_EXP_FILTER_UNK"; public static final String NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR = "NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR"; + public static final String CONCEPTMAP_VS_NOT_A_VS = "CONCEPTMAP_VS_NOT_A_VS"; + public static final String SD_DERIVATION_NO_CONCRETE = "SD_DERIVATION_NO_CONCRETE"; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java index 39e5c3221..5f41a3f37 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java @@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode; +import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; @@ -144,8 +145,10 @@ public class ConceptMapValidator extends BaseValidator { } } } - VSReference sourceScope = readVSReference(cm, "sourceScope", "source"); - VSReference targetScope = readVSReference(cm, "targetScope", "target"); + BooleanHolder bh = new BooleanHolder(); + VSReference sourceScope = readVSReference(errors, stack, bh, cm, "sourceScope", "source"); + VSReference targetScope = readVSReference(errors, stack, bh, cm, "targetScope", "target"); + ok = ok && bh.ok(); List groups = cm.getChildrenByName("group"); int ci = 0; @@ -191,7 +194,7 @@ public class ConceptMapValidator extends BaseValidator { } - private VSReference readVSReference(Element cm, String... names) { + private VSReference readVSReference(List errors, NodeStack stack,BooleanHolder bok, Element cm, String... names) { for (String n : names) { if (cm.hasChild(n, false)) { Element e = cm.getNamedChild(n, false); @@ -206,10 +209,32 @@ public class ConceptMapValidator extends BaseValidator { if (ref.contains("|")) { res.url = ref.substring(0, ref.indexOf("|")); res.version = ref.substring(ref.indexOf("|")+1); - res.vs = context.findTxResource(ValueSet.class, res.url, res.version); + Resource r = context.fetchResource(Resource.class, res.url, res.version); + if (r != null) { + if (r instanceof ValueSet) { + res.vs = (ValueSet) r; + } else { + bok.fail(); + rule(errors, "2025-12-31", IssueType.INVALID, stack.getLiteralPath()+"."+n, false, I18nConstants.CONCEPTMAP_VS_NOT_A_VS, r.fhirType()); + } + } + if (res.vs == null) { + res.vs = context.findTxResource(ValueSet.class, res.url, res.version); + } } else { res.url = ref; - res.vs = context.findTxResource(ValueSet.class, res.url); + Resource r = context.fetchResource(Resource.class, res.url); + if (r != null) { + if (r instanceof ValueSet) { + res.vs = (ValueSet) r; + } else { + bok.fail(); + rule(errors, "2025-12-31", IssueType.INVALID, stack.getLiteralPath()+"."+n, false, I18nConstants.CONCEPTMAP_VS_NOT_A_VS, r.fhirType()); + } + } + if (res.vs == null) { + res.vs = context.findTxResource(ValueSet.class, res.url); + } } return res; } 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 9da107df1..13c44d27a 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 @@ -162,6 +162,19 @@ public class StructureDefinitionValidator extends BaseValidator { warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !base.getExperimental() || experimental, I18nConstants.SD_BASE_EXPERIMENTAL, sd.getBaseDefinition()); } + String abstractV = src.getNamedChildValue("abstract"); + if ("true".equals(abstractV)) { + String burl = src.getNamedChildValue("url"); + if (burl != null) { + boolean bok = false; + for (StructureDefinition sdb : context.fetchResourcesByType(StructureDefinition.class)) { + if (burl.equals(sdb.getBaseDefinition())) { + bok = true; + } + } + warning(errors, "2024-12-31", IssueType.NOTFOUND, stack.getLiteralPath(), bok, I18nConstants.SD_DERIVATION_NO_CONCRETE, typeName); + } + } List differentials = src.getChildrenByName("differential"); List snapshots = src.getChildrenByName("snapshot"); boolean logical = "logical".equals(src.getNamedChildValue("kind", false)); @@ -684,33 +697,37 @@ public class StructureDefinitionValidator extends BaseValidator { boolean found = false; for (Element e : extensions) { if (ToolingExtensions.EXT_TYPE_PARAMETER.equals(e.getNamedChildValue("url"))) { - String ename = e.getExtensionValue("name").primitiveValue(); - if (name.equals(ename)) { - found = true; - String etype = e.getExtensionValue("type").primitiveValue(); - for (Extension ex : sd.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_PARAMETER)) { - String tn = ex.getExtensionString("name"); - if (tn != null && tn.equals(etype)) { - etype = ex.getExtensionString("type"); - break; - } - } - StructureDefinition esd = context.fetchTypeDefinition(etype); - if (rule(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), esd != null, I18nConstants.SD_TYPE_PARAMETER_UNKNOWN, tc, etype)) { - StructureDefinition t = esd; - while (t != null && t != psd) { - t = context.fetchResource(StructureDefinition.class, t.getBaseDefinition()); - } - ok = rule(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), t != null, I18nConstants.SD_TYPE_PARAMETER_INVALID_REF, tc, etype, tsd.getVersionedUrl(), name, type) & ok; - if (t != null) { - if (!sd.getAbstract() && esd.getAbstract()) { - warning(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), t != null, I18nConstants.SD_TYPE_PARAMETER_ABSTRACT_WARNING, tc, etype, tsd.getVersionedUrl(), name, type); + if (!e.hasExtension("name")) { + rule(errors, "2024-12-31", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.SD_TYPE_PARAMETER_UNKNOWN, tc, "no name"); + } else { + String ename = e.getExtensionValue("name").primitiveValue(); + if (name.equals(ename)) { + found = true; + String etype = e.getExtensionValue("type").primitiveValue(); + for (Extension ex : sd.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_PARAMETER)) { + String tn = ex.getExtensionString("name"); + if (tn != null && tn.equals(etype)) { + etype = ex.getExtensionString("type"); + break; } } - } else { - ok = false; - } - } + StructureDefinition esd = context.fetchTypeDefinition(etype); + if (rule(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), esd != null, I18nConstants.SD_TYPE_PARAMETER_UNKNOWN, tc, etype)) { + StructureDefinition t = esd; + while (t != null && t != psd) { + t = context.fetchResource(StructureDefinition.class, t.getBaseDefinition()); + } + ok = rule(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), t != null, I18nConstants.SD_TYPE_PARAMETER_INVALID_REF, tc, etype, tsd.getVersionedUrl(), name, type) & ok; + if (t != null) { + if (!sd.getAbstract() && esd.getAbstract()) { + warning(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), t != null, I18nConstants.SD_TYPE_PARAMETER_ABSTRACT_WARNING, tc, etype, tsd.getVersionedUrl(), name, type); + } + } + } else { + ok = false; + } + } + } } } ok = rule(errors, "2024-05-29", IssueType.BUSINESSRULE, stack.getLiteralPath(), found, I18nConstants.SD_TYPE_PARAM_NOT_SPECIFIED, tc, tsd.getVersionedUrl(), name, path) && ok;