From a56e26936624111e4a75796ea79c5ce68f45b6cc Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 3 Mar 2021 13:14:12 +1100 Subject: [PATCH 1/4] fix R5 --> R4 conversion for ConceptMap equivalence default value --- .../fhir/convertors/conv40_50/ConceptMap40_50.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/ConceptMap40_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/ConceptMap40_50.java index 1c131f8da..60b631320 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/ConceptMap40_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/ConceptMap40_50.java @@ -167,11 +167,14 @@ public class ConceptMap40_50 extends VersionConvertor_40_50 { if (src.hasCode()) tgt.setCodeElement(convertCode(src.getCodeElement())); if (src.hasDisplay()) - tgt.setDisplayElement(convertString(src.getDisplayElement())); - for (org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent t : src.getTarget()) if (t.getEquivalence() == org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence.UNMATCHED) { + tgt.setDisplayElement(convertString(src.getDisplayElement())); + for (org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent t : src.getTarget()) { + if (t.getEquivalence() == org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence.UNMATCHED) { tgt.setNoMap(true); - } else { + } + else { tgt.addTarget(convertTargetElementComponent(t)); + } } return tgt; } @@ -222,6 +225,8 @@ public class ConceptMap40_50 extends VersionConvertor_40_50 { tgt.setDisplayElement(convertString(src.getDisplayElement())); if (src.hasRelationship()) tgt.setEquivalenceElement(convertConceptMapEquivalence(src.getRelationshipElement())); + else + tgt.setEquivalence(ConceptMapEquivalence.RELATEDTO); if (src.hasComment()) tgt.setCommentElement(convertString(src.getCommentElement())); for (org.hl7.fhir.r5.model.ConceptMap.OtherElementComponent t : src.getDependsOn()) tgt.addDependsOn(convertOtherElementComponent(t)); From a51a8c003d24c4fba775303a97c8764c32f7af2b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 3 Mar 2021 13:18:44 +1100 Subject: [PATCH 2/4] fix issue with snapshot generation for logical models (CCDA) --- .../fhir/r5/conformance/ProfileUtilities.java | 7 +++++-- .../src/main/resources/Messages.properties | 20 ++++++++++--------- .../src/main/resources/Messages_de.properties | 12 +++++------ 3 files changed, 22 insertions(+), 17 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 cf7ba9ef7..6eb607534 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 @@ -636,6 +636,9 @@ public class ProfileUtilities extends TranslatingUtilities { } baseSnapshot = cloneSnapshot(baseSnapshot, base.getType(), derivedType); } +// if (derived.getId().equals("2.16.840.1.113883.10.20.22.2.1.1")) { +// debug = true; +// } processPaths("", derived.getSnapshot(), baseSnapshot, diff, baseCursor, diffCursor, baseSnapshot.getElement().size()-1, derived.getDifferential().hasElement() ? derived.getDifferential().getElement().size()-1 : -1, url, webUrl, derived.present(), null, null, false, base.getUrl(), null, false, null, null, new ArrayList(), base); checkGroupConstraints(derived); @@ -1388,7 +1391,7 @@ public class ProfileUtilities extends TranslatingUtilities { // (but you might do that in order to split up constraints by type) throw new DefinitionException(context.formatMessage(I18nConstants.ATTEMPT_TO_A_SLICE_AN_ELEMENT_THAT_DOES_NOT_REPEAT__FROM__IN_, currentBase.getPath(), currentBase.getPath(), contextName, url, diffMatches.get(0).getId(), sliceNames(diffMatches))); if (!diffMatches.get(0).hasSlicing() && !isExtension(currentBase)) // well, the diff has set up a slice, but hasn't defined it. this is an error - throw new DefinitionException(context.formatMessage(I18nConstants.DIFFERENTIAL_DOES_NOT_HAVE_A_SLICE__B_OF_____IN_PROFILE_, currentBase.getPath(), baseCursor, baseLimit, diffCursor, diffLimit, url)); + throw new DefinitionException(context.formatMessage(I18nConstants.DIFFERENTIAL_DOES_NOT_HAVE_A_SLICE__B_OF_____IN_PROFILE_, currentBase.getPath(), baseCursor, baseLimit, diffCursor, diffLimit, url, cpath)); // well, if it passed those preconditions then we slice the dest. int start = 0; @@ -1792,7 +1795,7 @@ public class ProfileUtilities extends TranslatingUtilities { removeStatusExtensions(outcome); // --- LM Added this diffCursor = differential.getElement().indexOf(diffItem)+1; - if (!outcome.getType().isEmpty() && (/*outcome.getType().get(0).getCode().equals("Extension") || */differential.getElement().size() > diffCursor) && outcome.getPath().contains(".") && isDataType(outcome.getType())) { // don't want to do this for the root, since that's base, and we're already processing it + if (!outcome.getType().isEmpty() && (/*outcome.getType().get(0).getCode().equals("Extension") || */differential.getElement().size() > diffCursor) && outcome.getPath().contains(".")/* && isDataType(outcome.getType())*/) { // don't want to do this for the root, since that's base, and we're already processing it if (!baseWalksInto(base.getElement(), baseCursor)) { if (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".")) { if (outcome.getType().size() > 1) diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index d8b40f7af..a5b49377c 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -133,9 +133,9 @@ Terminology_TX_Code_ValueSet = No code provided, and a code is required from the Terminology_TX_Code_ValueSetMax = No code provided, and a code must be provided from the value set {0} (max value set {1}) Terminology_TX_Code_ValueSet_Ext = No code provided, and a code should be provided from the value set {0} ({1}) Terminology_TX_Coding_Count = Expected {0} but found {1} coding elements -Terminology_TX_Confirm_1 = Could not confirm that the codes provided are in the value set {0} and a code from this value set is required (class = {1}) -Terminology_TX_Confirm_2 = Could not confirm that the codes provided are in the value set {0} and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) (class = {1}) -Terminology_TX_Confirm_3 = Could not confirm that the codes provided are in the value set {0} and a code is recommended to come from this value set (class = {1}) +Terminology_TX_Confirm_1_CC = Could not confirm that the codings provided are in the value set {0} and a coding from this value set is required (class = {1}) +Terminology_TX_Confirm_2_CC = Could not confirm that the codings provided are in the value set {0} and a coding should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) (class = {1}) +Terminology_TX_Confirm_3_CC = Could not confirm that the codings provided are in the value set {0} and a coding is recommended to come from this value set (class = {1}) Terminology_TX_Confirm_4a = The code provided ({2}) is not in the value set {0}, and a code from this value set is required: {1} Terminology_TX_Confirm_4b = The codes provided ({2}) are not in the value set {0}, and a code from this value set is required: {1} Terminology_TX_Confirm_5 = Could not confirm that the codes provided are in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) @@ -145,18 +145,18 @@ Terminology_TX_Error_CodeableConcept = Error {0} validating CodeableConcept Terminology_TX_Error_CodeableConcept_Max = Error {0} validating CodeableConcept using maxValueSet Terminology_TX_Error_Coding1 = Error {0} validating Coding Terminology_TX_Error_Coding2 = Error {0} validating Coding: {1} -Terminology_TX_NoValid_1 = None of the codes provided are in the value set {0} ({1}), and a code from this value set is required) (codes = {2}) +Terminology_TX_NoValid_1_CC = None of the codings provided are in the value set {0} ({1}), and a coding from this value set is required) (codes = {2}) Terminology_TX_NoValid_10 = The code provided is not in the maximum value set {0} ({1}), and a code from this value set is required) (code = {2}#{3}) Terminology_TX_NoValid_11 = The code provided is not in the maximum value set {0} ({1}{2}) Terminology_TX_NoValid_12 = The Coding provided ({2}) is not in the value set {0}, and a code is required from this value set. {1} -Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable). {1} +Terminology_TX_NoValid_13 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable). {1} Terminology_TX_NoValid_14 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set. {1} Terminology_TX_NoValid_15 = The value provided (''{0}'') could not be validated in the absence of a terminology server Terminology_TX_NoValid_16 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code is required from this value set){3} -Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code should come from this value set unless it has no suitable code and the validator cannot judge what is suitable) {3} +Terminology_TX_NoValid_17 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) {3} Terminology_TX_NoValid_18 = The value provided (''{0}'') is not in the value set {1} ({2}), and a code is recommended to come from this value set){3} -Terminology_TX_NoValid_2 = None of the codes provided are in the value set {0} ({1}), and a code should come from this value set unless it has no suitable code and the validator cannot judge what is suitable) (codes = {2}) -Terminology_TX_NoValid_3 = None of the codes provided are in the value set {0} ({1}), and a code is recommended to come from this value set) (codes = {2}) +Terminology_TX_NoValid_2_CC = None of the codings provided are in the value set {0} ({1}), and a coding should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) (codes = {2}) +Terminology_TX_NoValid_3_CC = None of the codings provided are in the value set {0} ({1}), and a coding is recommended to come from this value set) (codes = {2}) Terminology_TX_NoValid_4 = The Coding provided ({2}) is not in the value set {0}, and a code is required from this value set {1} Terminology_TX_NoValid_5 = The Coding provided ({2}) is not in the value set {0}, and a code should come from this value set unless it has no suitable code (the validator cannot judge what is suitable) {1} Terminology_TX_NoValid_6 = The Coding provided ({2}) is not in the value set {0}, and a code is recommended to come from this value set {1} @@ -325,7 +325,7 @@ Adding_wrong_path_in_profile___vs_ = Adding wrong path in profile {0}: {1} vs {2 _has_no_children__and_no_types_in_profile_ = {0} has no children ({1}) and no types in profile {2} not_done_yet = not done yet Did_not_find_single_slice_ = Did not find single slice: {0} -Differential_does_not_have_a_slice__b_of_____in_profile_ = Differential does not have a slice: {0}/ (b:{1} of {2} / {3}/ {4}) in profile {5} +Differential_does_not_have_a_slice__b_of_____in_profile_ = Differential in profile {5} does not have a slice at {6} (on {0}, position {1} of {2} / {3} / {4}) Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_ = Attempt to a slice an element that does not repeat: {0}/{1} from {2} in {3}, at element {4} (slice = {5}) Unable_to_resolve_reference_to_ = Unable to resolve reference to {0} Unable_to_find_element__in_ = Unable to find element {0} in {1} @@ -639,3 +639,5 @@ TYPE_SPECIFIC_CHECKS_DT_CANONICAL_TYPE = Canonical URL ''{0}'' refers to a resou CODESYSTEM_CS_NO_SUPPLEMENT = CodeSystem {0} is a supplement, so can't be used as a value in Coding.system CODESYSTEM_CS_SUPP_CANT_CHECK = CodeSystem {0} cannot be found, so can't check if concepts are valid CODESYSTEM_CS_SUPP_INVALID_CODE = The code ''{1}'' is not declared in the base CodeSystem {0} so is not valid in the supplement +SD_VALUE_TYPE_IILEGAL = The element {0} has a {1} of type {2}, which is not in the list of allowed types ({3}) +SD_NO_TYPES = The element {0} has no assigned types diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages_de.properties b/org.hl7.fhir.utilities/src/main/resources/Messages_de.properties index a8f2fe28b..057429ebd 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages_de.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages_de.properties @@ -128,9 +128,9 @@ Terminology_TX_Code_ValueSet=Es wird kein Code gesetzt, und es ist ein Code aus Terminology_TX_Code_ValueSetMax=Kein Code gesetzt, und es muss ein Code aus ValueSet {0} (max. Wertemenge {1}) gesetzt werden Terminology_TX_Code_ValueSet_Ext=Kein Code gesetzt, und es sollte ein Code aus ValueSet{0} ({1}) gesetzt werden Terminology_TX_Coding_Count=Erwartete {0}, aber gefundene {1} coding elements -Terminology_TX_Confirm_1=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind und ein Code aus diesem ValueSet ist erforderlich (class = {1}) -Terminology_TX_Confirm_2=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind und ein Code aus diesem ValueSet stammen sollte. Es sei denn, es enthält keinen geeigneten Code (class = {1}) -Terminology_TX_Confirm_3=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind, und es wird empfohlen einen Code aus diesem ValueSet zu verwenden (Klasse = {1}) +Terminology_TX_Confirm_1_CC=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind und ein Code aus diesem ValueSet ist erforderlich (class = {1}) +Terminology_TX_Confirm_2_CC=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind und ein Code aus diesem ValueSet stammen sollte. Es sei denn, es enthält keinen geeigneten Code (class = {1}) +Terminology_TX_Confirm_3_CC=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind, und es wird empfohlen einen Code aus diesem ValueSet zu verwenden (Klasse = {1}) Terminology_TX_Confirm_4=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind, und ein Code aus diesem ValueSet ist erforderlich Terminology_TX_Confirm_5=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind, und ein Code sollte aus diesem ValueSet stammen. Es sei denn, er hat enthält keinen geeigneten Code Terminology_TX_Confirm_6=Konnte nicht bestätigen, dass die angegebenen Codes im ValueSet {0} enthalten sind, und es wird empfohlen, einen Code aus diesem ValueSet zu verwenden. @@ -139,7 +139,7 @@ Terminology_TX_Error_CodeableConcept=Fehler {0} bei der Validierung des Codeable Terminology_TX_Error_CodeableConcept_Max=Fehler {0} bei der Validierung des CodeableConcepts mit maxValueSet Terminology_TX_Error_Coding1=Fehler {0} bei der Validierung des Coding Terminology_TX_Error_Coding2=Fehler {0} bei der Validierung des Coding: {1} -Terminology_TX_NoValid_1=Keiner der bereitgestellten Codes ist im ValueSet {0} ({1}, und ein Code aus diesem ValueSet ist erforderlich) (Codes = {2}) +Terminology_TX_NoValid_1_CC=Keiner der bereitgestellten Codes ist im ValueSet {0} ({1}, und ein Code aus diesem ValueSet ist erforderlich) (Codes = {2}) Terminology_TX_NoValid_10=Der bereitgestellte Code ist nicht im maximum ValueSet {0} ({1}, und ein Code aus diesem ValueSet ist erforderlich) (Code = {2}#{3}) Terminology_TX_NoValid_11=Der bereitgestellte Code ist nicht im maximum value set {0} ({1}{2} Terminology_TX_NoValid_12=Die angegebene Codierung ist nicht im ValueSet {0} enthalten, und es wird ein Code aus diesem ValueSet benötigt. {1} @@ -149,8 +149,8 @@ Terminology_TX_NoValid_15=Der angegebene Wert ("{0}") konnte in Ermangelung eine Terminology_TX_NoValid_16=Der angegebene Wert ("{0}") ist nicht im ValueSet {1} ({2}, und ein Code aus diesem Valueset ist erforderlich){3} Terminology_TX_NoValid_17=Der angegebene Wert ("{0}") ist nicht im Valueset {1} ({2}, und ein Code sollte aus diesem Valueset stammen, es sei denn, er hat enthält geeigneten Code){3} Terminology_TX_NoValid_18=Der angegebene Wert ("{0}") ist nicht im Valueset {1} ({2}, und es wird empfohlen, einen Code aus diesem Valueset zu verwenden){3} -Terminology_TX_NoValid_2=Keiner der angegebenen Codes ist im Valueset {0} ({1}, und ein Code sollte aus diesem Valueset stammen, es sei denn, er enthält keinen geeigneten Code) (Codes = {2}) -Terminology_TX_NoValid_3=Keiner der angegebenen Codes ist im Valueset {0} ({1}, und es wird empfohlen, einen Code aus dieserm Valueset zu verwenden) (Codes = {2}) +Terminology_TX_NoValid_2_CC=Keiner der angegebenen Codes ist im Valueset {0} ({1}, und ein Code sollte aus diesem Valueset stammen, es sei denn, er enthält keinen geeigneten Code) (Codes = {2}) +Terminology_TX_NoValid_3_CC=Keiner der angegebenen Codes ist im Valueset {0} ({1}, und es wird empfohlen, einen Code aus dieserm Valueset zu verwenden) (Codes = {2}) Terminology_TX_NoValid_4=Die bereitgestellte Codierung ist nicht im Valueset {0}, und es wird ein Code aus diesem Valueset benötigt{1} Terminology_TX_NoValid_5=Die angegebene Codierung ist nicht im Valueset {0}, und ein Code sollte aus diesem Valueset stammen, es sei denn, er enthält keinen geeigneten Code{1} Terminology_TX_NoValid_6=Die bereitgestellte Codierung ist nicht im Valueset {0} enthalten, und es wird empfohlen, einen Code aus diesem Valueset zu verwenden{1} From a25f17a916fa996eafb7d17a289d442cd748210d Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 3 Mar 2021 13:24:39 +1100 Subject: [PATCH 3/4] Define binding method extension --- .../src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java | 1 + 1 file changed, 1 insertion(+) 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 4af353d13..7b23d2990 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 @@ -183,6 +183,7 @@ public class ToolingExtensions { public static final String EXT_MUST_SUPPORT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support"; public static final String EXT_TRANSLATABLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable"; public static final String EXT_PATTERN = "http://hl7.org/fhir/StructureDefinition/elementdefinition-pattern"; + public static final String EXT_BINDING_METHOD = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-method"; // specific extension helpers From cd7a8d39e7376eb6ac3eeddb0d1cd716027f45dd Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 3 Mar 2021 13:30:58 +1100 Subject: [PATCH 4/4] * Improve terminology validation error messages * add additional validation on profiles around types (for logical models) --- RELEASE_NOTES.md | 5 +++ .../fhir/utilities/i18n/I18nConstants.java | 14 ++++--- .../instance/InstanceValidator.java | 38 +++++++++++-------- .../type/StructureDefinitionValidator.java | 23 +++++++++++ 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index be272a686..593dd4d45 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1 +1,6 @@ * adding session ids to validator service +* fix R5 --> R4 conversion for ConceptMap equivalence default value +* fix issue with snapshot generation for logical models (CCDA) +* Define binding method extension +* Improve terminology validation error messages +* add additional validation on profiles around types (for logical models) 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 fb6690293..ed86cdee4 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 @@ -361,6 +361,8 @@ public class I18nConstants { public static final String SD_ED_BIND_UNKNOWN_VS = "SD_ED_BIND_UNKNOWN_VS"; public static final String SD_ED_BIND_NOT_VS = "SD_ED_BIND_NOT_VS"; public static final String SD_ED_BIND_NO_BINDABLE = "SD_ED_BIND_NO_BINDABLE"; + public static final String SD_VALUE_TYPE_IILEGAL = "SD_VALUE_TYPE_IILEGAL"; + public static final String SD_NO_TYPES = "SD_NO_TYPES"; 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"; @@ -386,9 +388,9 @@ public class I18nConstants { public static final String TERMINOLOGY_TX_CODE_VALUESETMAX = "Terminology_TX_Code_ValueSetMax"; public static final String TERMINOLOGY_TX_CODE_VALUESET_EXT = "Terminology_TX_Code_ValueSet_Ext"; public static final String TERMINOLOGY_TX_CODING_COUNT = "Terminology_TX_Coding_Count"; - public static final String TERMINOLOGY_TX_CONFIRM_1 = "Terminology_TX_Confirm_1"; - public static final String TERMINOLOGY_TX_CONFIRM_2 = "Terminology_TX_Confirm_2"; - public static final String TERMINOLOGY_TX_CONFIRM_3 = "Terminology_TX_Confirm_3"; + public static final String TERMINOLOGY_TX_CONFIRM_1_CC = "Terminology_TX_Confirm_1_CC"; + public static final String TERMINOLOGY_TX_CONFIRM_2_CC = "Terminology_TX_Confirm_2_CC"; + public static final String TERMINOLOGY_TX_CONFIRM_3_CC = "Terminology_TX_Confirm_3_CC"; public static final String TERMINOLOGY_TX_CONFIRM_4a = "Terminology_TX_Confirm_4a"; public static final String TERMINOLOGY_TX_CONFIRM_4b = "Terminology_TX_Confirm_4b"; public static final String TERMINOLOGY_TX_CONFIRM_5 = "Terminology_TX_Confirm_5"; @@ -398,7 +400,7 @@ public class I18nConstants { public static final String TERMINOLOGY_TX_ERROR_CODEABLECONCEPT_MAX = "Terminology_TX_Error_CodeableConcept_Max"; public static final String TERMINOLOGY_TX_ERROR_CODING1 = "Terminology_TX_Error_Coding1"; public static final String TERMINOLOGY_TX_ERROR_CODING2 = "Terminology_TX_Error_Coding2"; - public static final String TERMINOLOGY_TX_NOVALID_1 = "Terminology_TX_NoValid_1"; + public static final String TERMINOLOGY_TX_NOVALID_1_CC = "Terminology_TX_NoValid_1_CC"; public static final String TERMINOLOGY_TX_NOVALID_10 = "Terminology_TX_NoValid_10"; public static final String TERMINOLOGY_TX_NOVALID_11 = "Terminology_TX_NoValid_11"; public static final String TERMINOLOGY_TX_NOVALID_12 = "Terminology_TX_NoValid_12"; @@ -408,8 +410,8 @@ public class I18nConstants { public static final String TERMINOLOGY_TX_NOVALID_16 = "Terminology_TX_NoValid_16"; public static final String TERMINOLOGY_TX_NOVALID_17 = "Terminology_TX_NoValid_17"; public static final String TERMINOLOGY_TX_NOVALID_18 = "Terminology_TX_NoValid_18"; - public static final String TERMINOLOGY_TX_NOVALID_2 = "Terminology_TX_NoValid_2"; - public static final String TERMINOLOGY_TX_NOVALID_3 = "Terminology_TX_NoValid_3"; + public static final String TERMINOLOGY_TX_NOVALID_2_CC = "Terminology_TX_NoValid_2_CC"; + public static final String TERMINOLOGY_TX_NOVALID_3_CC = "Terminology_TX_NoValid_3_CC"; public static final String TERMINOLOGY_TX_NOVALID_4 = "Terminology_TX_NoValid_4"; public static final String TERMINOLOGY_TX_NOVALID_5 = "Terminology_TX_NoValid_5"; public static final String TERMINOLOGY_TX_NOVALID_6 = "Terminology_TX_NoValid_6"; 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 0a5d6217d..95688103f 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 @@ -1023,28 +1023,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } else if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) { if (binding.getStrength() == BindingStrength.REQUIRED) - txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet")) checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); else if (!noExtensibleWarnings) - txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_2, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_2_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); } else if (binding.getStrength() == BindingStrength.PREFERRED) { if (baseOnly) { - txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_3, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_3_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); } } } else { - if (binding.getStrength() == BindingStrength.REQUIRED) - txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); - else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { + if (binding.getStrength() == BindingStrength.REQUIRED) { + txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + } else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet")) checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); if (!noExtensibleWarnings) - txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); } else if (binding.getStrength() == BindingStrength.PREFERRED) { if (baseOnly) { - txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); } } } @@ -1137,28 +1137,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat bindingsOk = false; if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) { if (binding.getStrength() == BindingStrength.REQUIRED) - txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_1_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet")) checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); else if (!noExtensibleWarnings) - txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_2, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_2_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); } else if (binding.getStrength() == BindingStrength.PREFERRED) { if (baseOnly) { - txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_3, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); + txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_3_CC, describeReference(binding.getValueSet()), vr.getErrorClass().toString()); } } } else { if (binding.getStrength() == BindingStrength.REQUIRED) - txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + txRule(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); else if (binding.getStrength() == BindingStrength.EXTENSIBLE) { if (binding.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet")) checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"), cc, stack); if (!noExtensibleWarnings) - txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + txWarningForLaterRemoval(element, errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); } else if (binding.getStrength() == BindingStrength.PREFERRED) { if (baseOnly) { - txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); + txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(binding.getValueSet()), valueset.getUrl(), ccSummary(cc)); } } } @@ -2220,6 +2220,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat * 2. This code doesn't actually decode, which is much easier on memory use for big payloads */ private boolean isValidBase64(String theEncoded) { + if (theEncoded == null) { + return false; + } int charCount = 0; boolean ok = true; for (int i = 0; i < theEncoded.length(); i++) { @@ -4678,8 +4681,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat if (ed.getMin() > 0) { if (problematicPaths.contains(ed.getPath())) hint(errors, IssueType.NOTSUPPORTED, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_NOCHECKMIN, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), Integer.toString(ed.getMin())); - else - rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), count >= ed.getMin(), I18nConstants.VALIDATION_VAL_PROFILE_MINIMUM, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), Integer.toString(ed.getMin()), Integer.toString(count)); + else { + if (count < ed.getMin()) { + rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_MINIMUM, profile.getUrl(), ed.getPath(), ed.getId(), ed.getSliceName(),ed.getLabel(), stack.getLiteralPath(), Integer.toString(ed.getMin()), Integer.toString(count)); + } + } } if (ed.hasMax() && !ed.getMax().equals("*")) { if (problematicPaths.contains(ed.getPath())) 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 b40f6b82c..9873985b7 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 @@ -146,6 +146,23 @@ public class StructureDefinitionValidator extends BaseValidator { // String bt = boundType(typeCodes); // hint(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || bt == null, I18nConstants.SD_ED_SHOULD_BIND, element.getNamedChildValue("path"), bt); } + // in a snapshot, we validate that fixedValue, pattern, and defaultValue, if present, are all of the right type + if (snapshot && element.getIdBase().contains(".")) { + if (rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !typeCodes.isEmpty(), I18nConstants.SD_NO_TYPES, element.getIdBase())) { + Element v = element.getNamedChild("defaultValue"); + if (v != null) { + rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "defaultValue", v.fhirType(), typeCodes); + } + v = element.getNamedChild("fixed"); + if (v != null) { + rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes); + } + v = element.getNamedChild("pattern"); + if (v != null) { + rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes); + } + } + } } private String boundType(Set typeCodes) { @@ -166,6 +183,12 @@ public class StructureDefinitionValidator extends BaseValidator { if (Utilities.existsInList(tc, "string", "uri", "CodeableConcept", "Quantity", "CodeableReference")) { return tc; } + StructureDefinition sd = context.fetchTypeDefinition(tc); + if (sd != null) { + if (sd.hasExtension(ToolingExtensions.EXT_BINDING_METHOD)) { + return tc; + } + } } return null; }