From a1a27b359d873cd266c35415260262151d0777c7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 27 Oct 2022 07:39:30 +1100 Subject: [PATCH 01/10] json fix --- .../main/java/org/hl7/fhir/utilities/json/JsonUtilities.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonUtilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonUtilities.java index 47f8674a7..c66df9667 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonUtilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonUtilities.java @@ -179,4 +179,8 @@ public class JsonUtilities { return odt.toInstant(); } } + + public static void setProperty(JsonObject json, String name, String value) { + json.addProperty(name, value); + } } \ No newline at end of file From 3e8dea22c87b0f6389a6c766bce48c3d4baef349 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 27 Oct 2022 11:49:44 +1100 Subject: [PATCH 02/10] fix build --- .../org.hl7.fhir.validation/5.0.0/v2-0360|2.7.cache | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/v2-0360|2.7.cache diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/v2-0360|2.7.cache b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/v2-0360|2.7.cache deleted file mode 100644 index a54af93b9..000000000 --- a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/5.0.0/v2-0360|2.7.cache +++ /dev/null @@ -1,12 +0,0 @@ -------------------------------------------------------------------------------------- -{"code" : { - "system" : "http://terminology.hl7.org/CodeSystem/v2-0360|2.7", - "code" : "BS", - "display" : "Bachelor of Science" -}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"true"}#### -v: { - "display" : "Bachelor of Science", - "code" : "BS", - "system" : "http://terminology.hl7.org/CodeSystem/v2-0360|2.7" -} -------------------------------------------------------------------------------------- From 83dfcd398c2a82317a747df03cdb76311d7af648 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 09:09:48 +1100 Subject: [PATCH 03/10] Fix problem with determining implied code system --- .../terminologies/ValueSetCheckerSimple.java | 86 +++++++++---------- .../fhir/utilities/i18n/I18nConstants.java | 28 +++--- .../src/main/resources/Messages.properties | 9 +- 3 files changed, 61 insertions(+), 62 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java index db188b615..c8bccf21a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java @@ -63,6 +63,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.terminologies.ValueSetChecker.ValidationProcessInfo; import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass; +import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier; import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy; @@ -207,7 +208,17 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe String system = code.hasSystem() ? code.getSystem() : getValueSetSystemOrNull(); if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) { if (system == null && !code.hasDisplay()) { // dealing with just a plain code (enum) - system = systemForCodeInValueSet(code.getCode()); + List problems = new ArrayList<>(); + system = systemForCodeInValueSet(code.getCode(), problems); + if (system == null) { + if (problems.size() == 0) { + throw new Error("Unable to resolve systems but no reason why"); // this is an error in the java code + } else if (problems.size() == 1) { + return new ValidationResult(IssueSeverity.ERROR, problems.get(0)); + } else { + return new ValidationResult(IssueSeverity.ERROR, problems.toString()); + } + } } if (!code.hasSystem()) { if (options.isGuessSystem() && system == null && Utilities.isAbsoluteUrl(code.getCode())) { @@ -453,36 +464,6 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe } } - private String getValueSetSystem() throws FHIRException { - if (valueset == null) { - throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__NO_VALUE_SET)); - } - if (valueset.getCompose().getInclude().size() == 0) { - if (!valueset.hasExpansion() || valueset.getExpansion().getContains().size() == 0) { - throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_NO_INCLUDES_OR_EXPANSION)); - } else { - String cs = valueset.getExpansion().getContains().get(0).getSystem(); - if (cs != null && checkSystem(valueset.getExpansion().getContains(), cs)) { - return cs; - } else { - throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_EXPANSION_HAS_MULTIPLE_SYSTEMS)); - } - } - } - for (ConceptSetComponent inc : valueset.getCompose().getInclude()) { - if (inc.hasValueSet()) { - throw new FHIRException(context.formatMessagePL(inc.getValueSet().size(), I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_IMPORTS)); - } - if (!inc.hasSystem()) { - throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_NO_SYSTEM)); - } - } - if (valueset.getCompose().getInclude().size() == 1) { - return valueset.getCompose().getInclude().get(0).getSystem(); - } - - return null; - } private String getValueSetSystemOrNull() throws FHIRException { if (valueset == null) { @@ -561,36 +542,41 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe } - private String systemForCodeInValueSet(String code) { + private String systemForCodeInValueSet(String code, List problems) { Set sys = new HashSet<>(); - if (!scanForCodeInValueSet(code, sys)) { + if (!scanForCodeInValueSet(code, sys, problems)) { return null; } if (sys.size() != 1) { + problems.add(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_MULTIPLE_MATCHES, sys.toString())); return null; } else { return sys.iterator().next(); } } - private boolean scanForCodeInValueSet(String code, Set sys) { + private boolean scanForCodeInValueSet(String code, Set sys, List problems) { if (valueset.hasCompose()) { - // not sure what to do with the -// if (valueset.getCompose().hasExclude()) { -// return false; -// } + // ignore excludes - they can't make any difference + if (!valueset.getCompose().hasInclude() && !valueset.getExpansion().hasContains()) { + problems.add(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_NO_INCLUDES_OR_EXPANSION, valueset.getVersionedUrl())); + } + + int i = 0; for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) { if (vsi.hasValueSet()) { for (CanonicalType u : vsi.getValueSet()) { - if (!checkForCodeInValueSet(code, u.getValue(), sys)) { + if (!checkForCodeInValueSet(code, u.getValue(), sys, problems)) { return false; } } } else if (!vsi.hasSystem()) { + problems.add(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_NO_SYSTEM, valueset.getVersionedUrl(), i)); return false; } if (vsi.hasSystem()) { if (vsi.hasFilter()) { + problems.add(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_NO_SYSTEM, valueset.getVersionedUrl(), i, vsi.getSystem())); return false; } CodeSystem cs = resolveCodeSystem(vsi.getSystem(), vsi.getVersion()); @@ -617,35 +603,45 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe } } } else { - return false; + // we'll try to expand this one then + ValueSetExpansionOutcome vse = context.expandVS(vsi, false, false); + if (vse.isOk()) { + if (!checkSystems(vse.getValueset().getExpansion().getContains(), code, sys, problems)) { + return false; + } + } else { + problems.add(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_UNKNOWN_SYSTEM, valueset.getVersionedUrl(), i, vsi.getSystem(), vse.getAllErrors().toString())); + return false; + } } } + i++; } } else if (valueset.hasExpansion()) { // Retrieve a list of all systems associated with this code in the expansion - if (!checkSystems(valueset.getExpansion().getContains(), code, sys)) { + if (!checkSystems(valueset.getExpansion().getContains(), code, sys, problems)) { return false; } } return true; } - private boolean checkForCodeInValueSet(String code, String uri, Set sys) { + private boolean checkForCodeInValueSet(String code, String uri, Set sys, List problems) { ValueSetCheckerSimple vs = getVs(uri); - return vs.scanForCodeInValueSet(code, sys); + return vs.scanForCodeInValueSet(code, sys, problems); } /* * Recursively go through all codes in the expansion and for any coding that matches the specified code, add the system for that coding * to the passed list. */ - private boolean checkSystems(List contains, String code, Set systems) { + private boolean checkSystems(List contains, String code, Set systems, List problems) { for (ValueSetExpansionContainsComponent c: contains) { if (c.getCode().equals(code)) { systems.add(c.getSystem()); } if (c.hasContains()) - checkSystems(c.getContains(), code, systems); + checkSystems(c.getContains(), code, systems, problems); } return true; } 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 8b8f5be54..58ebadc72 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 @@ -79,7 +79,7 @@ public class I18nConstants { public static final String DOES_NOT_MATCH_SLICE_ = "Does_not_match_slice_"; public static final String DUPLICATE_ID = "DUPLICATE_ID"; public static final String DUPLICATE_RESOURCE_ = "Duplicate_Resource_"; - public static final String DUPLICATE_RESOURCE_VERSION = "DUPLICATE_RESOURCE_VERSION"; +// public static final String DUPLICATE_RESOURCE_VERSION = "DUPLICATE_RESOURCE_VERSION"; public static final String ELEMENT_CANNOT_BE_NULL = "ELEMENT_CANNOT_BE_NULL"; public static final String ELEMENT_ID__NULL__ON_ = "element_id__null__on_"; public static final String ELEMENT_MUST_HAVE_SOME_CONTENT = "Element_must_have_some_content"; @@ -132,7 +132,7 @@ public class I18nConstants { public static final String EXTENSION_EXT_VERSION_NOCHANGE = "Extension_EXT_Version_NoChange"; public static final String EXTENSION_PROF_TYPE = "Extension_PROF_Type"; public static final String FHIRPATH_ALIAS_COLLECTION = "FHIRPATH_ALIAS_COLLECTION"; - public static final String FHIRPATH_BAD_DATE = "FHIRPATH_BAD_DATE"; +// public static final String FHIRPATH_BAD_DATE = "FHIRPATH_BAD_DATE"; public static final String FHIRPATH_CANNOT_USE = "FHIRPATH_CANNOT_USE"; public static final String FHIRPATH_CANT_COMPARE = "FHIRPATH_CANT_COMPARE"; public static final String FHIRPATH_CHECK_FAILED = "FHIRPATH_CHECK_FAILED"; @@ -153,7 +153,7 @@ public class I18nConstants { public static final String FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE = "FHIRPATH_DISCRIMINATOR_RESOLVE_NOT_REFERENCE"; public static final String FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE = "FHIRPATH_DISCRIMINATOR_RESOLVE_NO_TYPE"; public static final String FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND = "FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND"; - public static final String FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE = "FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE"; +// public static final String FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE = "FHIRPATH_DISCRIMINATOR_TYPE_MULTIPLE"; public static final String FHIRPATH_DISCRIMINATOR_TYPE_NONE = "FHIRPATH_DISCRIMINATOR_TYPE_NONE"; public static final String FHIRPATH_FOCUS_PLURAL = "FHIRPATH_FOCUS_PLURAL"; public static final String FHIRPATH_HO_HOST_SERVICES = "FHIRPATH_HO_HOST_SERVICES"; @@ -196,7 +196,7 @@ public class I18nConstants { public static final String ILLEGAL_PATH__IN_DIFFERENTIAL_IN__NO_UNICODE_WHITESPACE = "Illegal_path__in_differential_in__no_unicode_whitespace"; public static final String INTERNAL_ERROR___TYPE_NOT_KNOWN_ = "Internal_error___type_not_known_"; public static final String INTERNAL_INT_BAD_TYPE = "Internal_INT_Bad_Type"; - public static final String INTERNAL_RECURSION_DETECTION_FIND_LOOP_PATH_RECURSION____CHECK_PATHS_ARE_VALID_FOR_PATH_ = "Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_"; +// public static final String INTERNAL_RECURSION_DETECTION_FIND_LOOP_PATH_RECURSION____CHECK_PATHS_ARE_VALID_FOR_PATH_ = "Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_"; public static final String INV_FAILED = "INV_FAILED"; public static final String INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST = "Invalid_slicing__there_is_more_than_one_type_slice_at__but_one_of_them__has_min__1_so_the_other_slices_cannot_exist"; public static final String LANGUAGE_XHTML_LANG_DIFFERENT1 = "Language_XHTML_Lang_Different1"; @@ -211,7 +211,7 @@ public class I18nConstants { public static final String MEASURE_MR_GRP_NO_WRONG_CODE = "MEASURE_MR_GRP_NO_WRONG_CODE"; public static final String MEASURE_MR_GRP_POP_COUNT_MISMATCH = "MEASURE_MR_GRP_POP_COUNT_MISMATCH"; public static final String MEASURE_MR_GRP_POP_DUPL_CODE = "MEASURE_MR_GRP_POP_DUPL_CODE"; - public static final String MEASURE_MR_GRP_POP_MISSING_BY_CODE = "MEASURE_MR_GRP_POP_MISSING_BY_CODE"; +// public static final String MEASURE_MR_GRP_POP_MISSING_BY_CODE = "MEASURE_MR_GRP_POP_MISSING_BY_CODE"; public static final String MEASURE_MR_GRP_POP_NO_CODE = "MEASURE_MR_GRP_POP_NO_CODE"; public static final String MEASURE_MR_GRP_POP_NO_COUNT = "MEASURE_MR_GRP_POP_NO_COUNT"; public static final String MEASURE_MR_GRP_POP_NO_SUBJECTS = "MEASURE_MR_GRP_POP_NO_SUBJECTS"; @@ -228,7 +228,7 @@ public class I18nConstants { public static final String MEASURE_MR_SCORE_UNIT_REQUIRED = "MEASURE_MR_SCORE_UNIT_REQUIRED"; public static final String MEASURE_MR_SCORE_VALUE_INVALID_01 = "MEASURE_MR_SCORE_VALUE_INVALID_01"; public static final String MEASURE_MR_SCORE_VALUE_REQUIRED = "MEASURE_MR_SCORE_VALUE_REQUIRED"; - public static final String MEASURE_M_CQL_NOT_FOUND = "MEASURE_M_CQL_NOT_FOUND"; +// public static final String MEASURE_M_CQL_NOT_FOUND = "MEASURE_M_CQL_NOT_FOUND"; public static final String MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID = "MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID"; public static final String MEASURE_M_CRITERIA_CQL_ERROR = "MEASURE_M_CRITERIA_CQL_ERROR"; public static final String MEASURE_M_CRITERIA_CQL_LIB_DUPL = "MEASURE_M_CRITERIA_CQL_LIB_DUPL"; @@ -241,7 +241,7 @@ public class I18nConstants { public static final String MEASURE_M_GROUP_CODE = "MEASURE_M_GROUP_CODE"; public static final String MEASURE_M_GROUP_POP = "MEASURE_M_GROUP_POP"; public static final String MEASURE_M_GROUP_POP_NO_CODE = "MEASURE_M_GROUP_POP_NO_CODE"; - public static final String MEASURE_M_GROUP_STRATA = "MEASURE_M_GROUP_STRATA"; +// public static final String MEASURE_M_GROUP_STRATA = "MEASURE_M_GROUP_STRATA"; public static final String MEASURE_M_GROUP_STRATA_COMP_NO_CODE = "MEASURE_M_GROUP_STRATA_COMP_NO_CODE"; public static final String MEASURE_M_GROUP_STRATA_NO_CODE = "MEASURE_M_GROUP_STRATA_NO_CODE"; public static final String MEASURE_M_LIB_UNKNOWN = "MEASURE_M_LIB_UNKNOWN"; @@ -262,7 +262,7 @@ public class I18nConstants { public static final String NOT_DONE_YET_VALIDATORHOSTSERVICESRESOLVEFUNCTION_ = "Not_done_yet_ValidatorHostServicesresolveFunction_"; public static final String NOT_DONE_YET__RESOLVE__LOCALLY_2 = "Not_done_yet__resolve__locally_2"; public static final String NOT_HANDLED_YET_SORTELEMENTS_ = "Not_handled_yet_sortElements_"; - public static final String NOT_SUPPORTED_YET = "Not_supported_yet"; +// public static final String NOT_SUPPORTED_YET = "Not_supported_yet"; public static final String NOT_THE_RIGHT_KIND_OF_STRUCTURE_TO_GENERATE_SCHEMATRONS_FOR = "not_the_right_kind_of_structure_to_generate_schematrons_for"; public static final String NO_BASE_PROFILE_PROVIDED = "no_base_profile_provided"; public static final String NO_DERIVED_STRUCTURE_PROVIDED = "no_derived_structure_provided"; @@ -317,7 +317,7 @@ public class I18nConstants { public static final String QUESTIONNAIRE_QR_ITEM_NOOPTIONSSTRING = "Questionnaire_QR_Item_NoOptionsString"; public static final String QUESTIONNAIRE_QR_ITEM_NOOPTIONSTIME = "Questionnaire_QR_Item_NoOptionsTime"; public static final String QUESTIONNAIRE_QR_ITEM_NOSTRING = "Questionnaire_QR_Item_NoString"; - public static final String QUESTIONNAIRE_QR_ITEM_NOTENABLED = "Questionnaire_QR_Item_NotEnabled"; +// public static final String QUESTIONNAIRE_QR_ITEM_NOTENABLED = "Questionnaire_QR_Item_NotEnabled"; public static final String QUESTIONNAIRE_QR_ITEM_NOTENABLED2 = "Questionnaire_QR_Item_NotEnabled2"; public static final String QUESTIONNAIRE_QR_ITEM_NOTFOUND = "Questionnaire_QR_Item_NotFound"; public static final String QUESTIONNAIRE_QR_ITEM_NOTIME = "Questionnaire_QR_Item_NoTime"; @@ -374,7 +374,7 @@ public class I18nConstants { public static final String SD_ED_TYPE_PROFILE_NOT_MODIFIER = "SD_ED_TYPE_PROFILE_NOT_MODIFIER"; public static final String SD_ED_TYPE_PROFILE_WRONG_TARGET = "SD_ED_TYPE_PROFILE_WRONG_TARGET"; public static final String SD_ED_TYPE_NO_TARGET_PROFILE = "SD_ED_TYPE_NO_TARGET_PROFILE"; - public static final String SD_ED_SHOULD_BIND = "SD_ED_SHOULD_BIND"; +// public static final String SD_ED_SHOULD_BIND = "SD_ED_SHOULD_BIND"; public static final String SD_ED_SHOULD_BIND_WITH_VS = "SD_ED_SHOULD_BIND_WITH_VS"; 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"; @@ -416,7 +416,7 @@ public class I18nConstants { 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_4b = "Terminology_TX_Confirm_4b"; public static final String TERMINOLOGY_TX_CONFIRM_5 = "Terminology_TX_Confirm_5"; public static final String TERMINOLOGY_TX_CONFIRM_6 = "Terminology_TX_Confirm_6"; public static final String TERMINOLOGY_TX_DISPLAY_WRONG = "Terminology_TX_Display_Wrong"; @@ -562,9 +562,11 @@ public class I18nConstants { public static final String UNABLE_TO_RESOLVE_SLICE_MATCHING__SLICE_MATCHING_BY_VALUE_SET_NOT_DONE = "Unable_to_resolve_slice_matching__slice_matching_by_value_set_not_done"; public static final String UNABLE_TO_RESOLVE_SYSTEM__NO_VALUE_SET = "Unable_to_resolve_system__no_value_set"; public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_EXPANSION_HAS_MULTIPLE_SYSTEMS = "Unable_to_resolve_system__value_set_expansion_has_multiple_systems"; - public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_EXCLUDES = "Unable_to_resolve_system__value_set_has_excludes"; public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_IMPORTS = "Unable_to_resolve_system__value_set_has_imports"; + public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_MULTIPLE_MATCHES = "Unable_to_resolve_system__value_set_has_multiple_matches"; public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_NO_SYSTEM = "Unable_to_resolve_system__value_set_has_include_with_no_system"; + public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_UNKNOWN_SYSTEM = "Unable_to_resolve_system__value_set_has_include_with_unknown_system"; +// public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_INCLUDE_WITH_FILTER = "Unable_to_resolve_system__value_set_has_include_with_filter"; public static final String UNABLE_TO_RESOLVE_SYSTEM__VALUE_SET_HAS_NO_INCLUDES_OR_EXPANSION = "Unable_to_resolve_system__value_set_has_no_includes_or_expansion"; public static final String UNABLE_TO_RESOLVE_VALUE_SET_ = "Unable_to_resolve_value_Set_"; public static final String UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER = "Unable_to_validate_code_without_using_server"; @@ -671,7 +673,7 @@ public class I18nConstants { public static final String XHTML_XHTML_NS_INVALID = "XHTML_XHTML_NS_InValid"; public static final String XML_ATTR_VALUE_INVALID = "xml_attr_value_invalid"; public static final String XML_ENCODING_INVALID = "xml_encoding_invalid"; - public static final String XML_STATED_ENCODING_INVALID = "xml_stated_encoding_invalid"; +// public static final String XML_STATED_ENCODING_INVALID = "xml_stated_encoding_invalid"; public static final String _DT_FIXED_WRONG = "_DT_Fixed_Wrong"; public static final String _HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_ = "_has_children__and_multiple_types__in_profile_"; public static final String _HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE = "_has_children__for_type__in_profile__but_cant_find_type"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 280c486f5..5c8b11048 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -449,11 +449,12 @@ None_of_the_provided_codes_are_in_the_value_set_ = None of the provided codes ar Coding_has_no_system__cannot_validate = Coding has no system - cannot validate Unable_to_handle_system__concept_filter_with_op__ = Unable to handle system {0} concept filter with op = {1} Unable_to_handle_system__filter_with_property__ = Unable to handle system {0} filter with property = {1} -Unable_to_resolve_system__value_set_has_include_with_no_system = Unable to resolve system - value set has include with no system +Unable_to_resolve_system__value_set_has_include_with_no_system = Unable to resolve system - value set {0} include #{1} has no system +Unable_to_resolve_system__value_set_has_include_with_unknown_system = Unable to resolve system - value set {0} include #{1} has system {2} which is unknown, and the server return error {3} +Unable_to_resolve_system__value_set_has_include_with_filter = Unable to resolve system - value set {0} include #{1} has a filter on system {2} Unable_to_resolve_system__value_set_has_imports = Unable to resolve system - value set has imports -Unable_to_resolve_system__value_set_expansion_has_multiple_systems = Unable to resolve system - value set expansion has multiple systems -Unable_to_resolve_system__value_set_has_no_includes_or_expansion = Unable to resolve system - value set has no includes or expansion -Unable_to_resolve_system__value_set_has_excludes = Unable to resolve system - value set has excludes +Unable_to_resolve_system__value_set_has_multiple_matches = Unable to resolve system - value set expansion has multiple matches: {0} +Unable_to_resolve_system__value_set_has_no_includes_or_expansion = Unable to resolve system - value set {0} has no includes or expansion Unable_to_resolve_system__no_value_set = Unable to resolve system - no value set This_base_property_must_be_an_Array_not_ = This base property must be an Array, not {0} This_property_must_be_an_Array_not_ = This property must be an Array, not {0} From 9352b6e441a8a31e2241476d7130045fc7d7e17a Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 17:48:27 +1100 Subject: [PATCH 04/10] Fix problem generating snapshots for specializations where inherited types have properties --- .../loaders/loaderR5/R5ToR5Loader.java | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/R5ToR5Loader.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/R5ToR5Loader.java index 0cdbca665..9518ab1c3 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/R5ToR5Loader.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/R5ToR5Loader.java @@ -138,44 +138,9 @@ public class R5ToR5Loader extends BaseLoaderR5 { patchUrl(ed); } } - // hack errors in R5 ballot - if (r5 instanceof StructureDefinition) { - StructureDefinition sd = (StructureDefinition) r5; - if ("5.0.0-ballot".equals(sd.getVersion()) && "ElementDefinition".equals(sd.getType())) { - for (ElementDefinition ed : sd.getDifferential().getElement()) { - hackEDR5BallotError(ed); - } - for (ElementDefinition ed : sd.getSnapshot().getElement()) { - hackEDR5BallotError(ed); - } - } - if ("5.0.0-ballot".equals(sd.getVersion()) && "Bundle".equals(sd.getType())) { - for (ElementDefinition ed : sd.getDifferential().getElement()) { - hackBundleR5BallotError(ed); - } - for (ElementDefinition ed : sd.getSnapshot().getElement()) { - hackBundleR5BallotError(ed); - } - } - if ("5.0.0-ballot".equals(sd.getVersion()) && "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype".equals(sd.getUrl())) { - sd.getContextFirstRep().setExpression("ElementDefinition"); - } - } return r5; } - private void hackBundleR5BallotError(ElementDefinition ed) { - if (ed.getPath().equals("Bundle.link.relation")) { - ToolingExtensions.removeExtension(ed.getBinding(), ToolingExtensions.EXT_BINDING_NAME); - } - } - - private void hackEDR5BallotError(ElementDefinition ed) { - if (ed.getPath().equals("ElementDefinition.type.code")) { - ed.getBinding().setStrength(BindingStrength.EXTENSIBLE); - } - } - private void patchUrl(ElementDefinition ed) { for (TypeRefComponent tr : ed.getType()) { for (CanonicalType s : tr.getTargetProfile()) { From 63767a78c3a9dfacae27bc2ecac2e39ad309ffbf Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 17:49:22 +1100 Subject: [PATCH 05/10] more work in CDS Hooks extensions --- .../fhir/r5/conformance/ProfileUtilities.java | 56 ++++++++++++++ .../fhir/r5/context/SimpleWorkerContext.java | 5 +- .../fhir/r5/renderers/CodeSystemRenderer.java | 3 +- .../OperationDefinitionRenderer.java | 3 +- .../r5/renderers/QuestionnaireRenderer.java | 23 +++--- .../QuestionnaireResponseRenderer.java | 15 ++-- .../r5/renderers/SearchParameterRenderer.java | 3 +- .../StructureDefinitionRenderer.java | 3 +- .../r5/renderers/utils/RenderingContext.java | 43 ++++++----- .../fhir/r5/test/utils/TestingUtilities.java | 2 + .../java/org/hl7/fhir/r5/utils/R5Hacker.java | 74 +++++++++++++++++++ .../hl7/fhir/r5/utils/ToolingExtensions.java | 27 ++++++- 12 files changed, 213 insertions(+), 44 deletions(-) create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/R5Hacker.java 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 88a4da1ec..fb192456a 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 @@ -117,6 +117,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.renderers.TerminologyRenderer; import org.hl7.fhir.r5.renderers.spreadsheets.SpreadsheetGenerator; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.utils.FHIRLexer; import org.hl7.fhir.r5.utils.FHIRPathEngine; @@ -723,6 +724,13 @@ public class ProfileUtilities extends TranslatingUtilities { ElementDefinition outcome = updateURLs(url, webUrl, e.copy()); e.setUserData(GENERATED_IN_SNAPSHOT, outcome); derived.getSnapshot().addElement(outcome); + if (walksInto(diff.getElement(), e)) { + if (e.getType().size() > 1) { + throw new DefinitionException("Unsupported scenario: specialization walks into multiple types at "+e.getId()); + } else { + addInheritedElementsForSpecialization(derived.getSnapshot(), outcome, outcome.getTypeFirstRep().getWorkingCode(), outcome.getPath(), url, webUrl); + } + } } } } @@ -851,6 +859,28 @@ public class ProfileUtilities extends TranslatingUtilities { } } + + private void addInheritedElementsForSpecialization(StructureDefinitionSnapshotComponent snapshot, ElementDefinition focus, String type, String path, String url, String weburl) { + StructureDefinition sd = context.fetchTypeDefinition(type); + if (sd != null) { + addInheritedElementsForSpecialization(snapshot, focus, sd.getBaseDefinition(), path, url, weburl); + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + if (ed.getPath().contains(".")) { + ElementDefinition outcome = updateURLs(url, weburl, ed.copy()); + outcome.setPath(outcome.getPath().replace(sd.getType(), path)); + snapshot.getElement().add(outcome); + } else { + focus.getConstraint().addAll(ed.getConstraint()); + } + } + } + } + + private boolean walksInto(List list, ElementDefinition ed) { + int i = list.indexOf(ed); + return (i < list.size() - 1) && list.get(i + 1).getPath().startsWith(ed.getPath()+"."); + } + private void fixTypeOfResourceId(StructureDefinition base) { if (base.getKind() == StructureDefinitionKind.RESOURCE && (base.getFhirVersion() == null || VersionUtilities.isR4Plus(base.getFhirVersion().toCode()))) { fixTypeOfResourceId(base.getSnapshot().getElement()); @@ -4901,6 +4931,18 @@ public class ProfileUtilities extends TranslatingUtilities { c.getPieces().add(piece); c.getPieces().add(gen.new Piece(null, " is prefixed to the value before validation", null)); } + + if (definition.hasExtension(ToolingExtensions.EXT_EXTENSION_STYLE)) { + if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } + String es = definition.getExtensionString(ToolingExtensions.EXT_EXTENSION_STYLE); + if ("named-elements".equals(es)) { + if (rc.hasLink(KnownLinkType.JSON_NAMES)) { + c.getPieces().add(gen.new Piece(rc.getLink(KnownLinkType.JSON_NAMES), "This element can be extended by named JSON elements", null)); + } else { + c.getPieces().add(gen.new Piece(ToolingExtensions.WEB_EXTENSION_STYLE, "This element can be extended by named JSON elements", null)); + } + } + } if (definition.hasExtension(ToolingExtensions.EXT_ID_EXPECTATION)) { String ide = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_ID_EXPECTATION); if (ide.equals("optional")) { @@ -4940,6 +4982,20 @@ public class ProfileUtilities extends TranslatingUtilities { c.getPieces().add(gen.new Piece(null, "This element may be present as a JSON Array even when there are no items in the instance", null)); } } + String jn = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_NAME); + if (!Utilities.noString(jn)) { + if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } + if (definition.getPath().contains(".")) { + c.getPieces().add(gen.new Piece(null, translate("sd.table", "JSON Property Name")+": ", null).addStyle("font-weight:bold")); + c.getPieces().add(gen.new Piece(null, jn, null)); + } else { + c.getPieces().add(gen.new Piece(null, translate("sd.table", "JSON Property Name for Type")+": ", null).addStyle("font-weight:bold")); + Piece piece = gen.new Piece("code"); + piece.addHtml(new XhtmlNode(NodeType.Text).setContent(jn)); + c.getPieces().add(piece); + } + } + if (ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_NULLABLE)) { if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } c.getPieces().add(gen.new Piece(null, "This object can be represented as null in the JSON structure (which counts as 'present' for cardinality purposes)", null)); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index bc3996390..0efac0a70 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -71,6 +71,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.JurisdictionUtilities; import org.hl7.fhir.r5.terminologies.TerminologyClient; import org.hl7.fhir.r5.utils.validation.IResourceValidator; +import org.hl7.fhir.r5.utils.R5Hacker; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.utilities.CSFileInputStream; import org.hl7.fhir.utilities.TextFile; @@ -112,9 +113,9 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon FileInputStream f = new FileInputStream(filename); try { if (loader != null) { - return (CanonicalResource) loader.loadResource(f, true); + return R5Hacker.fixR5BrokenResource((CanonicalResource) loader.loadResource(f, true)); } else { - return (CanonicalResource) new JsonParser().parse(f); + return R5Hacker.fixR5BrokenResource((CanonicalResource) new JsonParser().parse(f)); } } finally { f.close(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java index d31982eaf..9d99a600c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java @@ -20,6 +20,7 @@ import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator; @@ -468,7 +469,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { first = false; XhtmlNode span = td.span(null, mapping.comp.hasRelationship() ? mapping.comp.getRelationship().toCode() : ""); span.addText(getCharForRelationship(mapping.comp)); - a = td.ah(getContext().getSpecificationLink()+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode())); + a = td.ah(getContext().getLink(KnownLinkType.SPEC)+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode())); a.addText(mapping.comp.getCode()); if (!Utilities.noString(mapping.comp.getComment())) td.i().tx("("+mapping.comp.getComment()+")"); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java index 5cd96699c..644aee8c9 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java @@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterCom import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; @@ -123,7 +124,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (p.hasSearchType()) { td.br(); td.tx("("); - td.ah( context.getSpecificationLink() == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getSpecificationLink(), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode()); + td.ah( context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode()); td.tx(")"); } td = tr.td(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java index bfbbeed75..ce696f24a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java @@ -24,6 +24,7 @@ import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; @@ -68,8 +69,8 @@ public class QuestionnaireRenderer extends TerminologyRenderer { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+q.getId(), !forResource); model.setAlternating(true); - model.setDocoImg(context.getSpecificationLink() +"help16.png"); - model.setDocoRef(context.getSpecificationLink()+"formats.html#table"); + model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); + model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Cardinality"), translate("sd.hint", "Minimum and Maximum # of times the the itemcan appear in the instance"), null, 0)); @@ -131,7 +132,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { li.tx(opt.getValue().primitiveValue()); } else if (opt.getValue() instanceof Coding) { Coding c = (Coding) opt.getValue(); - String link = c.hasSystem() ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getSpecificationLink(), c.getSystem()) : null; + String link = c.hasSystem() ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), c.getSystem()) : null; if (link == null) { li.tx(c.getSystem()+"#"+c.getCode()); } else { @@ -213,7 +214,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { } private String getSpecLink(String path) { - return Utilities.pathURL(context.getSpecificationLink(), path); + return Utilities.pathURL(context.getLink(KnownLinkType.SPEC), path); } private String getSDCLink(String path) { @@ -234,9 +235,9 @@ public class QuestionnaireRenderer extends TerminologyRenderer { r.getCells().add(gen.new Cell(null, null, (i.getRequired() ? "1" : "0")+".."+(i.getRepeats() ? "*" : "1"), null, null)); if (i.getTypeElement().hasExtension(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) { String t = i.getTypeElement().getExtensionString(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL); - r.getCells().add(gen.new Cell(null, context.getSpecificationLink()+"codesystem-item-type.html#item-type-"+t, t, null, null)); + r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+t, t, null, null)); } else { - r.getCells().add(gen.new Cell(null, context.getSpecificationLink()+"codesystem-item-type.html#item-type-"+i.getType().toCode(), i.getType().toCode(), null, null)); + r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+i.getType().toCode(), i.getType().toCode(), null, null)); } if (hasFlags) { @@ -244,7 +245,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { Cell flags = gen.new Cell(); r.getCells().add(flags); if (i.getReadOnly()) { - flags.addPiece(gen.new Piece(Utilities.pathURL(context.getSpecificationLink(), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, "Is Readonly").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-readonly.png")))); + flags.addPiece(gen.new Piece(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, "Is Readonly").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-readonly.png")))); } if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) { flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-isSubject.html"), null, "Can change the subject of the questionnaire").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png")))); @@ -433,8 +434,8 @@ public class QuestionnaireRenderer extends TerminologyRenderer { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+q.getId(), true); model.setAlternating(true); - model.setDocoImg(context.getSpecificationLink() +"help16.png"); - model.setDocoRef(context.getSpecificationLink()+"formats.html#table"); + model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); + model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Description & Constraints"), translate("sd.hint", "Additional information about the item"), null, 0)); @@ -683,7 +684,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { } if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_HIDDEN)) { hasFlag = true; - flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"), "icon"); + flags.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"), "icon"); d.style("background-color: #eeeeee"); } if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_OTP_DISP)) { @@ -836,7 +837,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer { private boolean renderLinks(XhtmlNode x, Questionnaire q) { x.para().tx("Try this questionnaire out:"); XhtmlNode ul = x.ul(); - ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getSelfLink(), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); + ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); return false; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java index b5c679323..7c9c7f001 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java @@ -15,6 +15,7 @@ import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; @@ -62,8 +63,8 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+qr.getId(), false); model.setAlternating(true); - model.setDocoImg(context.getSpecificationLink() +"help16.png"); - model.setDocoRef(context.getSpecificationLink()+"formats.html#table"); + model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); + model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Definition"), translate("sd.hint", "Minimum and Maximum # of times the the itemcan appear in the instance"), null, 0)); @@ -85,8 +86,8 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+q.getId(), true); model.setAlternating(true); - model.setDocoImg(context.getSpecificationLink() +"help16.png"); - model.setDocoRef(context.getSpecificationLink()+"formats.html#table"); + model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); + model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Definition"), translate("sd.hint", "Minimum and Maximum # of times the the itemcan appear in the instance"), null, 0)); @@ -432,7 +433,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { // } // if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-hidden")) { // hasFlag = true; -// flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-QuestionnaireResponse-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png")); +// flags.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "extension-QuestionnaireResponse-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png")); // d.style("background-color: #eeeeee"); // } // if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-optionalDisplay")) { @@ -584,14 +585,14 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { private boolean renderLinks(XhtmlNode x, QuestionnaireResponse q) { x.para().tx("Try this QuestionnaireResponse out:"); XhtmlNode ul = x.ul(); - ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getSelfLink(), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); + ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); return false; } private boolean renderLinks(XhtmlNode x, ResourceWrapper q) { x.para().tx("Try this QuestionnaireResponse out:"); XhtmlNode ul = x.ul(); - ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getSelfLink(), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); + ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); return false; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java index 4d98241a6..446a1c1af 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java @@ -16,6 +16,7 @@ import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; @@ -73,7 +74,7 @@ public class SearchParameterRenderer extends TerminologyRenderer { tr.td().tx(Utilities.pluralize("Target Resources", spd.getTarget().size())); td = tr.td(); if (isAllConcreteResources(spd.getTarget())) { - td.ah(Utilities.pathURL(context.getSpecificationLink(), "resourcelist.html")).tx("All Resources"); + td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "resourcelist.html")).tx("All Resources"); } else { for (CodeType t : spd.getTarget()) { StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.toString()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index 97b3a63c8..dfdfba03f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -10,6 +10,7 @@ import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.utilities.xhtml.XhtmlNode; @@ -28,7 +29,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } public boolean render(XhtmlNode x, StructureDefinition sd) throws FHIRFormatError, DefinitionException, IOException { - x.getChildNodes().add(context.getProfileUtilities().generateTable(context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, context.getSpecificationLink(), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, false, context, "")); + x.getChildNodes().add(context.getProfileUtilities().generateTable(context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, false, context, "")); return true; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java index ab59b006d..8384312d8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java @@ -6,8 +6,10 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; import org.hl7.fhir.exceptions.FHIRException; @@ -91,6 +93,12 @@ public class RenderingContext { LINKS } + public enum KnownLinkType { + SELF, // absolute link to where the content is to be found (only used in a few circumstances when making external references to tools) + SPEC, // version specific link to core specification + JSON_NAMES + + } private IWorkerContext worker; private MarkDownProcessor markdown; private ResourceRendererMode mode; @@ -101,8 +109,6 @@ public class RenderingContext { private String lang; private String localPrefix; // relative link within local context - private String specificationLink; - private String selfLink; // absolute link to where the content is to be found (only used in a few circumstances when making external references to tools) private int headerLevelContext; private boolean canonicalUrlsAsLinks; private boolean pretty; @@ -136,6 +142,7 @@ public class RenderingContext { private boolean copyButton; private ProfileKnowledgeProvider pkp; + private Map links = new HashMap<>(); /** * * @param context - access to all related resources that might be needed @@ -149,7 +156,7 @@ public class RenderingContext { this.worker = worker; this.markdown = markdown; this.lang = lang; - this.specificationLink = specLink; + this.links.put(KnownLinkType.SPEC, specLink); this.localPrefix = localPrefix; this.mode = mode; if (terminologyServiceOptions != null) { @@ -159,7 +166,7 @@ public class RenderingContext { this.locale = new Locale.Builder().setLanguageTag("en-US").build(); } public RenderingContext copy() { - RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, specificationLink, localPrefix, lang, mode); + RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, getLink(KnownLinkType.SPEC), localPrefix, lang, mode); res.resolver = resolver; res.templateProvider = templateProvider; @@ -184,7 +191,7 @@ public class RenderingContext { res.addGeneratedNarrativeHeader = addGeneratedNarrativeHeader; res.questionnaireMode = questionnaireMode; res.header = header; - res.selfLink = selfLink; + res.links.putAll(links); res.inlineGraphics = inlineGraphics; res.timeZoneId = timeZoneId; res.dateTimeFormat = dateTimeFormat; @@ -241,10 +248,6 @@ public class RenderingContext { return lang; } - public String getSpecificationLink() { - return specificationLink; - } - public String getLocalPrefix() { return localPrefix; } @@ -419,21 +422,12 @@ public class RenderingContext { return this; } - public String getSelfLink() { - return selfLink; - } - - public RenderingContext setSelfLink(String selfLink) { - this.selfLink = selfLink; - return this; - } - public String fixReference(String ref) { if (!Utilities.isAbsoluteUrl(ref)) { return (localPrefix == null ? "" : localPrefix)+ref; } if (ref.startsWith("http://hl7.org/fhir") && !ref.substring(20).contains("/")) { - return specificationLink+ref.substring(20); + return getLink(KnownLinkType.SPEC)+ref.substring(20); } return ref; } @@ -617,5 +611,16 @@ public class RenderingContext { return pkp; } + public boolean hasLink(KnownLinkType link) { + return links.containsKey(link); + } + public String getLink(KnownLinkType link) { + return links.get(link); + } + public void addLink(KnownLinkType self, String targetOutput) { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java index 8e034338d..08b3ead30 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java @@ -19,6 +19,7 @@ import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.context.TerminologyCache; import org.hl7.fhir.r5.model.Parameters; +import org.hl7.fhir.r5.utils.R5Hacker; import org.hl7.fhir.utilities.CSFile; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.ToolGlobalSettings; @@ -117,6 +118,7 @@ public class TestingUtilities extends BaseTestingUtilities { System.out.println("Loading THO: "+utg.name()+"#"+utg.version()); fcontext.loadFromPackage(utg, new TestPackageLoader(new String[]{"CodeSystem", "ValueSet"})); } + R5Hacker.fixR5BrokenResources(fcontext); return fcontext; } catch (Exception e) { e.printStackTrace(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/R5Hacker.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/R5Hacker.java new file mode 100644 index 000000000..7db230057 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/R5Hacker.java @@ -0,0 +1,74 @@ +package org.hl7.fhir.r5.utils; + +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.Enumerations.BindingStrength; + +public class R5Hacker { + + public static void fixR5BrokenResources(IWorkerContext context) { + for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { + fixSD(sd); + } + } + + + private static void fixSD(StructureDefinition sd) { + if ("5.0.0-ballot".equals(sd.getVersion()) && "ElementDefinition".equals(sd.getType())) { + for (ElementDefinition ed : sd.getDifferential().getElement()) { + hackEDR5BallotError(ed); + } + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + hackEDR5BallotError(ed); + } + } + if ("5.0.0-ballot".equals(sd.getVersion()) && "Base".equals(sd.getType())) { + for (ElementDefinition ed : sd.getDifferential().getElement()) { + hackBaseR5BallotError(ed); + } + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + hackBaseR5BallotError(ed); + } + } + if ("5.0.0-ballot".equals(sd.getVersion()) && "Bundle".equals(sd.getType())) { + for (ElementDefinition ed : sd.getDifferential().getElement()) { + hackBundleR5BallotError(ed); + } + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + hackBundleR5BallotError(ed); + } + } + if ("5.0.0-ballot".equals(sd.getVersion()) && "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype".equals(sd.getUrl())) { + sd.getContextFirstRep().setExpression("ElementDefinition"); + } + } + + + private static void hackBaseR5BallotError(ElementDefinition ed) { + ed.getConstraint().clear(); + } + + private static void hackBundleR5BallotError(ElementDefinition ed) { + if (ed.getPath().equals("Bundle.link.relation")) { + ToolingExtensions.removeExtension(ed.getBinding(), ToolingExtensions.EXT_BINDING_NAME); + } + } + + private static void hackEDR5BallotError(ElementDefinition ed) { + if (ed.getPath().equals("ElementDefinition.type.code")) { + ed.getBinding().setStrength(BindingStrength.EXTENSIBLE); + } + } + + + public static CanonicalResource fixR5BrokenResource(CanonicalResource cr) { + if (cr instanceof StructureDefinition) { + StructureDefinition sd = (StructureDefinition) cr; + fixSD(sd); + } + return cr; + } + +} 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 71de59075..c9c44a34a 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 @@ -119,7 +119,6 @@ public class ToolingExtensions { public static final String EXT_RESOURCE_IMPLEMENTS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-implements"; public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type"; 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_IGP_RESOURCES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-resource"; @@ -138,6 +137,9 @@ public class ToolingExtensions { public static final String EXT_IGP_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/resource-information"; public static final String EXT_IGP_LOADVERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-loadversion"; public static final String EXT_LIST_PACKAGE = "http://hl7.org/fhir/StructureDefinition/list-packageId"; + public static final String EXT_JSON_NAME = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-json-name"; + public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-binding-style"; + public static final String EXT_EXTENSION_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style"; // validated // private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid"; @@ -233,6 +235,11 @@ public class ToolingExtensions { public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type"; public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality"; + + + public static final String WEB_EXTENSION_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/branches/master/format-extensions.html#extension-related-extensions"; + ; + // specific extension helpers public static Extension makeIssueSource(Source source) { @@ -989,5 +996,23 @@ public class ToolingExtensions { } + public static boolean hasExtensions(ElementDefinition d, String... urls) { + for (String url : urls) { + if (d.hasExtension(url)) { + return true; + } + } + return false; + } + + public static int countExtensions(ElementDefinition d, String... urls) { + int res = 0; + for (String url : urls) { + if (d.hasExtension(url)) { + res++; + } + } + return res; + } } \ No newline at end of file From 27febc03effe57a1c98f227a756f47815e8c86a3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 21:58:59 +1100 Subject: [PATCH 06/10] inherited type URLs --- .../fhir/r5/conformance/ProfileUtilities.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) 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 fb192456a..a5e73ccb5 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 @@ -40,6 +40,7 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -174,6 +175,10 @@ import org.hl7.fhir.utilities.xml.SchematronWriter.Section; */ public class ProfileUtilities extends TranslatingUtilities { + private static final List INHERITED_ED_URLS = Arrays.asList( + "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-binding-style", + "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style"); + public static class SourcedChildDefinitions { private StructureDefinition source; private List list; @@ -689,6 +694,7 @@ public class ProfileUtilities extends TranslatingUtilities { checkDifferential(derived.getDifferential().getElement(), typeName(derived.getType()), derived.getUrl()); checkDifferentialBaseType(derived); + copyInheritedExtensions(base, derived); // so we have two lists - the base list, and the differential list // the differential list is only allowed to include things that are in the base list, but // is allowed to include them multiple times - thereby slicing them @@ -860,6 +866,15 @@ public class ProfileUtilities extends TranslatingUtilities { } + private void copyInheritedExtensions(StructureDefinition base, StructureDefinition derived) { + for (Extension ext : base.getExtension()) { + if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !derived.hasExtension(ext.getUrl())) { + derived.getExtension().add(ext.copy()); + } + } + + } + private void addInheritedElementsForSpecialization(StructureDefinitionSnapshotComponent snapshot, ElementDefinition focus, String type, String path, String url, String weburl) { StructureDefinition sd = context.fetchTypeDefinition(type); if (sd != null) { @@ -871,6 +886,11 @@ public class ProfileUtilities extends TranslatingUtilities { snapshot.getElement().add(outcome); } else { focus.getConstraint().addAll(ed.getConstraint()); + for (Extension ext : ed.getExtension()) { + if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !focus.hasExtension(ext.getUrl())) { + focus.getExtension().add(ext.copy()); + } + } } } } @@ -2965,6 +2985,11 @@ public class ProfileUtilities extends TranslatingUtilities { boolean isExtension = checkExtensionDoco(base); + for (Extension ext : source.getExtension()) { + if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) { + dest.getExtension().add(ext.copy()); + } + } // Before applying changes, apply them to what's in the profile StructureDefinition profile = null; if (base.hasSliceName()) From 1e046a0d0099e59346b83af0dcd579311b9e34c3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 21:59:08 +1100 Subject: [PATCH 07/10] fix for NPE rendering patient photo --- .../main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java index 9098f3e9d..49133f06e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java @@ -795,7 +795,7 @@ public class PatientRenderer extends ResourceRenderer { PropertyWrapper a = r.getChildByName("photo"); for (BaseWrapper v : a.getValues()) { Attachment att = (Attachment) v.getBase(); - if (att.getContentType().startsWith("image/") && + if (att.hasContentType() && att.getContentType().startsWith("image/") && att.getData() != null && (!context.isInlineGraphics() || (att.getData().length > 0 && att.getData().length < MAX_IMAGE_LENGTH))) { return true; } From a3281ea69b9d6512ac227700bc14a30e0ee72cab Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 28 Oct 2022 22:01:54 +1100 Subject: [PATCH 08/10] set up release --- RELEASE_NOTES.md | 8 ++++++-- pom.xml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..b28d22011 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,11 @@ ## Validator Changes -* no changes +* Fix problem determining implicit code system when code system only known to tx.fhir.org ## Other code changes -* no changes \ No newline at end of file +* Fix bugs generating CDSHooks snapshots +* Fix for NPE rendering Patient Photo +* Fix problem generating snapshots for specializations where inherited types have properties +* Work on i18n framework + diff --git a/pom.xml b/pom.xml index 395dc99c4..12b4d5e0e 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 5.4.0 - 1.1.121-SNAPSHOT + 1.1.121 5.7.1 1.8.2 3.0.0-M5 From a285132f5b46c3b454dc1894bc9ecf53f80aae8e Mon Sep 17 00:00:00 2001 From: markiantorno Date: Fri, 28 Oct 2022 11:38:37 +0000 Subject: [PATCH 09/10] Release: v5.6.75 ## Validator Changes * Fix problem determining implicit code system when code system only known to tx.fhir.org ## Other code changes * Fix bugs generating CDSHooks snapshots * Fix for NPE rendering Patient Photo * Fix problem generating snapshots for specializations where inherited types have properties * Work on i18n framework ***NO_CI*** --- org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r4b/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.report/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index 3a501104a..ab9320b8d 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index def8546a2..ab71d83a4 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 53413c4d2..6d26e4898 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index bc527a127..92fbd3903 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index e580f01c0..d1f6e285a 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 40ef7e5ae..898f35c22 100644 --- a/org.hl7.fhir.r4b/pom.xml +++ b/org.hl7.fhir.r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 8f0c6730d..7f3651e8f 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index 2c6edb58c..b100beca6 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index d7ad5b9ec..f4602777d 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index cb566ea25..50a3b0666 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index 2276bc2e4..ad04274ec 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 ../pom.xml diff --git a/pom.xml b/pom.xml index 12b4d5e0e..2d5fc94cf 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 5.6.75-SNAPSHOT + 5.6.75 pom From f0c53bd7a9968a410671e706ab322551485fbdd0 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Fri, 28 Oct 2022 11:57:13 +0000 Subject: [PATCH 10/10] Updating version to: 5.6.76-SNAPSHOT and incrementing test cases dependency. --- RELEASE_NOTES.md | 8 ++------ org.hl7.fhir.convertors/pom.xml | 2 +- org.hl7.fhir.dstu2/pom.xml | 2 +- org.hl7.fhir.dstu2016may/pom.xml | 2 +- org.hl7.fhir.dstu3/pom.xml | 2 +- org.hl7.fhir.r4/pom.xml | 2 +- org.hl7.fhir.r4b/pom.xml | 2 +- org.hl7.fhir.r5/pom.xml | 2 +- org.hl7.fhir.report/pom.xml | 2 +- org.hl7.fhir.utilities/pom.xml | 2 +- org.hl7.fhir.validation.cli/pom.xml | 2 +- org.hl7.fhir.validation/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 14 insertions(+), 18 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b28d22011..7b06c6ab5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,11 +1,7 @@ ## Validator Changes -* Fix problem determining implicit code system when code system only known to tx.fhir.org +* no changes ## Other code changes -* Fix bugs generating CDSHooks snapshots -* Fix for NPE rendering Patient Photo -* Fix problem generating snapshots for specializations where inherited types have properties -* Work on i18n framework - +* no changes \ No newline at end of file diff --git a/org.hl7.fhir.convertors/pom.xml b/org.hl7.fhir.convertors/pom.xml index ab9320b8d..b4d749c75 100644 --- a/org.hl7.fhir.convertors/pom.xml +++ b/org.hl7.fhir.convertors/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2/pom.xml b/org.hl7.fhir.dstu2/pom.xml index ab71d83a4..434687572 100644 --- a/org.hl7.fhir.dstu2/pom.xml +++ b/org.hl7.fhir.dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu2016may/pom.xml b/org.hl7.fhir.dstu2016may/pom.xml index 6d26e4898..63021afb1 100644 --- a/org.hl7.fhir.dstu2016may/pom.xml +++ b/org.hl7.fhir.dstu2016may/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.dstu3/pom.xml b/org.hl7.fhir.dstu3/pom.xml index 92fbd3903..7fd29c1f8 100644 --- a/org.hl7.fhir.dstu3/pom.xml +++ b/org.hl7.fhir.dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4/pom.xml b/org.hl7.fhir.r4/pom.xml index d1f6e285a..74b827351 100644 --- a/org.hl7.fhir.r4/pom.xml +++ b/org.hl7.fhir.r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r4b/pom.xml b/org.hl7.fhir.r4b/pom.xml index 898f35c22..9587e989c 100644 --- a/org.hl7.fhir.r4b/pom.xml +++ b/org.hl7.fhir.r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.r5/pom.xml b/org.hl7.fhir.r5/pom.xml index 7f3651e8f..2e6563f12 100644 --- a/org.hl7.fhir.r5/pom.xml +++ b/org.hl7.fhir.r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.report/pom.xml b/org.hl7.fhir.report/pom.xml index b100beca6..b79e64824 100644 --- a/org.hl7.fhir.report/pom.xml +++ b/org.hl7.fhir.report/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.utilities/pom.xml b/org.hl7.fhir.utilities/pom.xml index f4602777d..56c552ccb 100644 --- a/org.hl7.fhir.utilities/pom.xml +++ b/org.hl7.fhir.utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation.cli/pom.xml b/org.hl7.fhir.validation.cli/pom.xml index 50a3b0666..8c4b2028a 100644 --- a/org.hl7.fhir.validation.cli/pom.xml +++ b/org.hl7.fhir.validation.cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/org.hl7.fhir.validation/pom.xml b/org.hl7.fhir.validation/pom.xml index ad04274ec..e288a2e3c 100644 --- a/org.hl7.fhir.validation/pom.xml +++ b/org.hl7.fhir.validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2d5fc94cf..0e55c6493 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ HAPI FHIR --> org.hl7.fhir.core - 5.6.75 + 5.6.76-SNAPSHOT pom