Improve MeasureReport validation for checking subject count
This commit is contained in:
parent
37006946cd
commit
512f70aa18
|
@ -1093,4 +1093,9 @@ public class I18nConstants {
|
|||
public static final String IG_DEPENDENCY_EXCEPTION = "IG_DEPENDENCY_EXCEPTION";
|
||||
public static final String IG_DEPENDENCY_PACKAGE_UNKNOWN = "IG_DEPENDENCY_PACKAGE_UNKNOWN";
|
||||
public static final String NDJSON_EMPTY_LINE_WARNING = "NDJSON_EMPTY_LINE_WARNING";
|
||||
public static final String MEASURE_MR_GRP_POP_COUNT_CANT_CHECK = "MEASURE_MR_GRP_POP_COUNT_CANT_CHECK";
|
||||
public static final String MEASURE_MR_GRP_POP_COUNT_NO_REF = "MEASURE_MR_GRP_POP_COUNT_NO_REF";
|
||||
public static final String MEASURE_MR_GRP_POP_COUNT_UNRESOLVED = "MEASURE_MR_GRP_POP_COUNT_UNRESOLVED";
|
||||
public static final String MEASURE_MR_GRP_POP_COUNT_NO_REF_RES = "MEASURE_MR_GRP_POP_COUNT_NO_REF_RES";
|
||||
public static final String MEASURE_MR_GRP_POP_COUNT_REF_UNPROCESSIBLE = "MEASURE_MR_GRP_POP_COUNT_REF_UNPROCESSIBLE";
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE_FRAGMENT = Found {0} matches for fragment {2}
|
|||
BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED = Except for transactions and batches, each entry in a Bundle must have a fullUrl which is the identity of the resource in the entry
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_MULTIPLE_MATCHES = The {1} resource matched more than one of the allowed profiles ({3})
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH = The {1} resource did not match any of the allowed profiles (Type {2}: {3})
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH_REASON = The {1} resource did not match the profile {2} because: {3}
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH_REASON = The {1} resource did not match the profile {2} because: {3}
|
||||
BUNDLE_BUNDLE_ENTRY_NOTFOUND_APPARENT_one = Can''t find ''{1}'' in the bundle ({2}). Note that there is a resource in the bundle with the same type and id, but it does not match because of the fullUrl based rules around matching relative references (must be ``{3}``)
|
||||
BUNDLE_BUNDLE_ENTRY_NOTFOUND_APPARENT_other = Can''t find ''{1}'' in the bundle ({2}). Note that there are {0} resources in the bundle with the same type and id, but they do not match because of the fullUrl based rules around matching relative references (one of ``{3}``)
|
||||
BUNDLE_BUNDLE_ENTRY_NOTFOUND_FRAGMENT = Can''t find ''{0}'' in the bundle ({1})
|
||||
|
@ -102,7 +102,7 @@ CODESYSTEM_CS_SUPP_INVALID_CODE = The code ''{1}'' is not declared in the base C
|
|||
CODESYSTEM_CS_SUPP_NO_SUPP = The code system is marked as a supplement, but it does not define what code system it supplements
|
||||
CODESYSTEM_CS_UNK_EXPANSION = The code provided ({2}) is not in the expansion in the value set {0}, and a code is required from this value set. The system {1} could not be found.
|
||||
CODESYSTEM_CS_VS_EXP_MISMATCH = CodeSystem {0} has an ''all system'' value set of {1}, but it is an expansion with the wrong number of concepts (found {2}, expected {3})
|
||||
CODESYSTEM_DESIGNATION_DISP_CLASH_LANG = The designation ''{0}'' has no use and is in the same language (''{2}''), so is not differentiated from the base display (''{1}'')
|
||||
CODESYSTEM_DESIGNATION_DISP_CLASH_LANG = The designation ''{0}'' has no use and is in the same language (''{2}''), so is not differentiated from the base display (''{1}'')
|
||||
CODESYSTEM_DESIGNATION_DISP_CLASH_NO_LANG = The designation ''{0}'' has no use and no language, so is not differentiated from the base display (''{1}'')
|
||||
CODESYSTEM_NOT_CONTAINED = CodeSystems are referred to directly from Coding.system, so it''s generally best for them not to be contained resources
|
||||
CODESYSTEM_PROPERTY_BAD_HL7_URI = Unknown CodeSystem Property ''{0}''. If you are creating your own property, do not create it in the HL7 namespace
|
||||
|
@ -110,7 +110,7 @@ CODESYSTEM_PROPERTY_CODE_TYPE_MISMATCH = Wrong type ''{2}'': The code ''{0}'' id
|
|||
CODESYSTEM_PROPERTY_CODE_WARNING = If the type is ''code'', then the valueSet property should be provided to clarify what kind of code will be found in the element
|
||||
CODESYSTEM_PROPERTY_DUPLICATE_CODE = A property is already defined with the code ''{0}''
|
||||
CODESYSTEM_PROPERTY_DUPLICATE_URI = A property is already defined with the URI ''{0}''
|
||||
CODESYSTEM_PROPERTY_KNOWN_CODE_SUGGESTIVE = This property has only the standard code (''{0}'') but not the standard URI ''{1}'', so it has no clearly defined meaning in the terminology ecosystem
|
||||
CODESYSTEM_PROPERTY_KNOWN_CODE_SUGGESTIVE = This property has only the standard code (''{0}'') but not the standard URI ''{1}'', so it has no clearly defined meaning in the terminology ecosystem
|
||||
CODESYSTEM_PROPERTY_NO_VALUE = The property ''{0}'' has no value, and cannot be understood
|
||||
CODESYSTEM_PROPERTY_SYNONYM_CHECK = The synonym ''{0}'' is not also defined in the code system. The Synonym property should only used to declare equivalence to other existing codes
|
||||
CODESYSTEM_PROPERTY_UNDEFINED = The property ''{0}'' has no definition in CodeSystem.property. Many terminology tools won''t know what to do with it
|
||||
|
@ -174,7 +174,7 @@ Derived_profile__has_no_type = Derived profile {0} has no type
|
|||
Details_for__matching_against_Profile_ = Details for {0} matching against profile {1}
|
||||
Did_not_find_single_slice_ = Did not find single slice: {0}
|
||||
Did_not_find_type_root_ = Did not find type root: {0}
|
||||
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})
|
||||
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})
|
||||
Differential_walks_into____but_the_base_does_not_and_there_is_not_a_single_fixed_type_The_type_is__This_is_not_handled_yet = Differential walks into ''{0} (@ {1})'', but the base does not, and there is not a single fixed type. The type is {2}. This is not handled yet
|
||||
Discriminator__is_based_on_element_existence_but_slice__neither_sets_min1_or_max0 = Discriminator ({0}) is based on element existence, but slice {1} neither sets min>=1 or max=0
|
||||
Discriminator__is_based_on_type_but_slice__in__has_multiple_types_one =
|
||||
|
@ -336,7 +336,7 @@ Illegal_path__in_differential_in__name_portion_exceeds_64_chars_in_length = Inva
|
|||
Illegal_path__in_differential_in__name_portion_mising_ = Invalid path ''{0}'' in differential in {1}: name portion missing (''..'')
|
||||
Illegal_path__in_differential_in__no_unicode_whitespace = Invalid path ''{0}'' in differential in {1}: no unicode whitespace
|
||||
Internal_INT_Bad_Type = Unhandled fixed value type {0}
|
||||
Internal_error___type_not_known_ = Internal error - type not known {0}
|
||||
Internal_error___type_not_known_ = Internal error - type not known {0}
|
||||
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 {0}, but one of them ({1}) has min = 1, so the other slices cannot exist
|
||||
JSON_COMMA_EXTRA = There is an extra comma at the end of the {0} in the JSON
|
||||
JSON_COMMA_MISSING = A Comma is missing in the JSON
|
||||
|
@ -371,6 +371,11 @@ MEASURE_MR_GRP_NO_CODE = Group should have a code that matches the group definit
|
|||
MEASURE_MR_GRP_NO_USABLE_CODE = None of the codes provided are usable for comparison - need both system and code on at least one code
|
||||
MEASURE_MR_GRP_NO_WRONG_CODE = The code provided ({0}) does not match the code specified in the measure report ({1})
|
||||
MEASURE_MR_GRP_POP_COUNT_MISMATCH = Mismatch between count {0} and number of subjects {1}
|
||||
MEASURE_MR_GRP_POP_COUNT_CANT_CHECK = Unable to check the stated count {0} because the subject list cannot be fully processed ({1})
|
||||
MEASURE_MR_GRP_POP_COUNT_NO_REF = Subject reference has no actual reference
|
||||
MEASURE_MR_GRP_POP_COUNT_UNRESOLVED = Subject reference {0} could not be resolved, and the apparent type is {1} which could not be processed
|
||||
MEASURE_MR_GRP_POP_COUNT_NO_REF_RES = Subject reference {0} could not be resolved, and so could not be processed
|
||||
MEASURE_MR_GRP_POP_COUNT_REF_UNPROCESSIBLE = Subject reference {0} resolved to a {1}, which could not be processed
|
||||
MEASURE_MR_GRP_POP_DUPL_CODE = The code for this group population is duplicated with another group
|
||||
MEASURE_MR_GRP_POP_NO_CODE = Group should have a code that matches the group population definition in the measure
|
||||
MEASURE_MR_GRP_POP_NO_COUNT = Count should be present for reports where type is not ''subject-list''
|
||||
|
@ -398,7 +403,7 @@ MEASURE_M_CRITERIA_UNKNOWN = The expression language {0} is not supported, so ca
|
|||
MEASURE_M_GROUP_CODE = Groups should have codes when there is more than one group
|
||||
MEASURE_M_GROUP_POP = Measure Groups should have at least one population
|
||||
MEASURE_M_GROUP_POP_NO_CODE = A measure group population should have a code when there is more than one population
|
||||
MEASURE_M_GROUP_STRATA_COMP_NO_CODE = A measure group stratifier component should have a code when there is more than one population
|
||||
MEASURE_M_GROUP_STRATA_COMP_NO_CODE = A measure group stratifier component should have a code when there is more than one population
|
||||
MEASURE_M_GROUP_STRATA_NO_CODE = A measure group stratifier should have a code when there is more than one population
|
||||
MEASURE_M_LIB_UNKNOWN = The Library {0} could not be resolved, so expression validation may not be correct
|
||||
MEASURE_M_NO_GROUPS = A measure should contain at least one group
|
||||
|
@ -547,8 +552,8 @@ Reference_REF_CantMatchChoice = Unable to find a match for profile {0} among cho
|
|||
Reference_REF_CantMatchType = Unable to find a match for profile {0} (by type) among choices: {1}
|
||||
Reference_REF_CantResolve = Unable to resolve resource with reference ''{0}''
|
||||
Reference_REF_CantResolveProfile = Unable to resolve the profile reference ''{0}''
|
||||
Reference_REF_Format1 = Relative URLs must be of the format [ResourceName]/[id], or a search URL is allowed ([type]?parameters. Encountered {0})
|
||||
Reference_REF_Format2 = Relative URLs must be of the format [ResourceName]/[id]. Encountered {0}
|
||||
Reference_REF_Format1 = Relative URLs must be of the format [ResourceName]/[id], or a search URL is allowed ([type]?parameters. Encountered {0})
|
||||
Reference_REF_Format2 = Relative URLs must be of the format [ResourceName]/[id]. Encountered {0}
|
||||
Reference_REF_MultipleMatches = Found multiple matching profiles for {0} among choices: {1}
|
||||
Reference_REF_NoDisplay = A Reference without an actual reference or identifier should have a display
|
||||
Reference_REF_NoType = Unable to determine type of target resource
|
||||
|
@ -631,8 +636,8 @@ SECURITY_STRING_CONTENT_ERROR = The string value contains text that looks like e
|
|||
SECURITY_STRING_CONTENT_WARNING = The string value contains text that looks like embedded HTML tags. If this content is rendered to HTML without appropriate post-processing, it may be a security risk
|
||||
SLICING_CANNOT_BE_EVALUATED = Slicing cannot be evaluated: {0}
|
||||
SM_DEPENDENT_PARAM_MODE_MISMATCH = The parameter {0} refers to the variable {1} but it''s mode is {2} which is not the same as the mode required for the group {3}
|
||||
SM_DEPENDENT_PARAM_NOT_FOUND = The {1} parameter ''{0}'' was not found
|
||||
SM_DEPENDENT_PARAM_TYPE_MISMATCH = The parameter ''{0}'' refers to the variable ''{1}'' but it''s type is ''{2}'' which is not compatible with the type required for the group ''{3}'', which is ''{4}'' (from map ''{5}'')
|
||||
SM_DEPENDENT_PARAM_NOT_FOUND = The {1} parameter ''{0}'' was not found
|
||||
SM_DEPENDENT_PARAM_TYPE_MISMATCH = The parameter ''{0}'' refers to the variable ''{1}'' but it''s type is ''{2}'' which is not compatible with the type required for the group ''{3}'', which is ''{4}'' (from map ''{5}'')
|
||||
SM_DEPENDENT_PARAM_TYPE_MISMATCH_DUPLICATE = The group {0} has already been used with different parameters, so the type checking may be incorrect (other = [{1}]; this = [{2}])
|
||||
SM_GROUP_INPUT_DUPLICATE = The name {0} is already used
|
||||
SM_GROUP_INPUT_MODE_INVALID = The group parameter {0} mode {1} isn''t valid
|
||||
|
@ -646,7 +651,7 @@ SM_IMPORT_NOT_FOUND = No maps were found to match {0} - validation may be wrong
|
|||
SM_LIST_RULE_ID_ONLY_WHEN_SHARE = A ruleId should only be provided when the rule mode is ''share''
|
||||
SM_MATCHING_RULEGROUP_NOT_FOUND = Unable to find a default rule for the type pair source={0} and target={1}
|
||||
SM_NAME_INVALID = The name {0} is not valid
|
||||
SM_NO_LIST_MODE_NEEDED = A list mode should not be provided since this is a rule that can only be executed once
|
||||
SM_NO_LIST_MODE_NEEDED = A list mode should not be provided since this is a rule that can only be executed once
|
||||
SM_NO_LIST_RULE_ID_NEEDED = A list ruleId should not be provided since this is a rule that can only be executed once
|
||||
SM_ORPHAN_GROUP = The group {0} is not called successfully from within this mapping script, and does not have types on it''s inputs, so type verification is not possible
|
||||
SM_RULEGROUP_NOT_FOUND = The group {0} could not be resolved
|
||||
|
@ -679,7 +684,7 @@ SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE = The value of the type parameter for {0}
|
|||
SM_TARGET_TRANSLATE_BINDING_SOURCE = The source variable does not have a required binding, so this concept map can''t be checked
|
||||
SM_TARGET_TRANSLATE_BINDING_SOURCE_UNMAPPED = The source value set includes one or more codes that the map does not translate: {0}
|
||||
SM_TARGET_TRANSLATE_BINDING_TARGET = The target variable does not have a required binding, so this concept map can''t be checked
|
||||
SM_TARGET_TRANSLATE_BINDING_TARGET_WRONG = The map produces one or more codes that the target value set does not include: {0}
|
||||
SM_TARGET_TRANSLATE_BINDING_TARGET_WRONG = The map produces one or more codes that the target value set does not include: {0}
|
||||
SM_TARGET_TRANSLATE_BINDING_VSE_SOURCE = There was an error expanding the source value set, so this concept map can''t be checked: ''{0}''
|
||||
SM_TARGET_TRANSLATE_BINDING_VSE_TARGET = There was an error expanding the target value set, so this concept map can''t be checked: ''{0}''
|
||||
SM_TARGET_TRANSLATE_BINDING_VS_SOURCE = The source variable refers to an unknown value set ''{0}'', so this concept map can''t be checked
|
||||
|
@ -767,7 +772,7 @@ TYPE_SPECIFIC_CHECKS_DT_QTY_UCUM_ANNOTATIONS_NOT_IN_UNIT = UCUM Codes that conta
|
|||
TYPE_SPECIFIC_CHECKS_DT_QTY_UCUM_ANNOTATIONS_NO_UNIT = UCUM Codes that contain human readable annotations like {0} can be misleading (e.g. they are ignored when comparing units). Best Practice is not to depend on annotations in the UCUM code, so this usage should be checked, and the Quantity.unit SHOULD contain the annotation
|
||||
TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE = Example URLs are not allowed in this context ({0})
|
||||
TYPE_SPECIFIC_CHECKS_DT_XHTML_MULTIPLE_MATCHES = Hyperlink ''{0}'' at ''{1}'' for ''{2}'' resolves to multiple targets ({3})
|
||||
TYPE_SPECIFIER_ABSTRACT_TYPE = The Type specifier {1} specified an abstract type {0}
|
||||
TYPE_SPECIFIER_ABSTRACT_TYPE = The Type specifier {1} specified an abstract type {0}
|
||||
TYPE_SPECIFIER_ILLEGAL_TYPE = The Type specifier {1} specified an invalid type {0}
|
||||
TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract
|
||||
TYPE_SPECIFIER_NM_ILLEGAL_TYPE = No Type specifier matched, and the underlying type {0} is not valid
|
||||
|
@ -830,7 +835,7 @@ This_element_does_not_match_any_known_slice_ = This element does not match any k
|
|||
This_property_must_be__not_ = The property {2} must be {0}, not {1} (at {3})
|
||||
This_property_must_be_a_Literal_not_ = This property must be a Literal, not {0}
|
||||
This_property_must_be_a_URI_or_bnode_not_ = This property must be a URI or bnode, not {0}
|
||||
This_property_must_be_an_Array_not_ = The property {1} must be a JSON Array, not {0} (at {2})
|
||||
This_property_must_be_an_Array_not_ = The property {1} must be a JSON Array, not {0} (at {2})
|
||||
This_property_must_be_an_object_not_ = This property must be an object, not {0} ({1} at {2})
|
||||
This_property_must_be_an_simple_value_not_ = This property must be a simple value, not {0} ({1} at {2})
|
||||
Type_Specific_Checks_DT_Base64_Valid = The value ''{0}'' is not a valid Base64 value
|
||||
|
@ -919,9 +924,9 @@ Unable_to_resolve_slice_matching__slice_matching_by_value_set_not_done = Unable
|
|||
Unable_to_resolve_system__no_value_set = Unable to resolve system - no value set
|
||||
Unable_to_resolve_system__value_set_expansion_has_multiple_systems = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': value set expansion has multiple systems
|
||||
Unable_to_resolve_system__value_set_has_imports = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': value set has imports
|
||||
Unable_to_resolve_system__value_set_has_include_with_filter = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': include #{2} has a filter on system {3}: {4}
|
||||
Unable_to_resolve_system__value_set_has_include_with_filter = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': include #{2} has a filter on system {3}: {4}
|
||||
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 = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': include #{2} has system {3} which could not be found, and the server returned error {4}
|
||||
Unable_to_resolve_system__value_set_has_include_with_unknown_system = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': include #{2} has system {3} which could not be found, and the server returned error {4}
|
||||
Unable_to_resolve_system__value_set_has_multiple_matches = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': value set expansion has multiple matches: {2}
|
||||
Unable_to_resolve_system__value_set_has_no_includes_or_expansion = The System URI could not be determined for the code ''{0}'' in the ValueSet ''{1}'': value set has no includes or expansion
|
||||
Unable_to_resolve_value_Set_ = A definition for the value Set ''{0}'' could not be found
|
||||
|
@ -991,7 +996,7 @@ VALUESET_BAD_FILTER_VALUE_VALID_REGEX = The value for a filter based on property
|
|||
VALUESET_BAD_PROPERTY_NO_REGEX = Cannot apply a regex filter to the property ''{0}'' (usually regex filters are applied to the codes, or a named property of the code system)
|
||||
VALUESET_CIRCULAR_REFERENCE = Found a circularity pointing to {0} processing ValueSet with pathway {1}
|
||||
VALUESET_CONCEPT_DISPLAY_PRESENCE_MIXED = This include has some concepts with displays and some without - check that this is what is intended
|
||||
VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED = This SNOMED-CT based include has some concepts with semantic tags (FSN terms) and some without (preferred terms) - check that this is what is intended (examples for FSN: {0} and examples for no FSN: {1})
|
||||
VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED = This SNOMED-CT based include has some concepts with semantic tags (FSN terms) and some without (preferred terms) - check that this is what is intended (examples for FSN: {0} and examples for no FSN: {1})
|
||||
VALUESET_EXAMPLE_SYSTEM_ERROR = Example System ''{0}'' specified, which is illegal. Concepts and Filters can''t be checked
|
||||
VALUESET_EXAMPLE_SYSTEM_HINT = Example System ''{0}'' specified, so Concepts and Filters can''t be checked
|
||||
VALUESET_IMPORT_UNION_INTERSECTION = This value set has a single include with multiple imported value sets. Per issue https://jira.hl7.org/browse/FHIR-25179, there has been confusion in the past whether these value sets are unioned or intersectioned. If this value set is contained in a package published prior to March 31 2022, it will be treated as a union, otherwise it will be treated as an intersection. If want a union, split the value set imports across multiple includes
|
||||
|
|
|
@ -4564,7 +4564,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return true;
|
||||
}
|
||||
|
||||
private ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element groupingResource, Element source, BooleanHolder bh) {
|
||||
public ResolvedReference localResolve(String ref, NodeStack stack, List<ValidationMessage> errors, String path, Element rootResource, Element groupingResource, Element source, BooleanHolder bh) {
|
||||
if (ref.startsWith("#")) {
|
||||
// work back through the parent list, tracking the stack as we go
|
||||
// really, there should only be one level for this (contained resources cannot contain
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hl7.fhir.r5.model.Measure.MeasureGroupStratifierComponent;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.DataRenderer;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
|
@ -32,7 +33,10 @@ import org.hl7.fhir.utilities.validation.ValidationMessage;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.BaseValidator.BooleanHolder;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
import org.hl7.fhir.validation.instance.utils.ResolvedReference;
|
||||
import org.hl7.fhir.validation.instance.utils.ValidationContext;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
|
@ -493,19 +497,93 @@ public class MeasureValidator extends BaseValidator {
|
|||
|
||||
private boolean validateMeasureReportGroupPopulation(ValidationContext hostContext, MeasureContext m, MeasureGroupPopulationComponent mgp, List<ValidationMessage> errors, Element mrgp, NodeStack ns, boolean inProgress) {
|
||||
boolean ok = true;
|
||||
List<Element> sr = mrgp.getChildrenByName("subjectResults");
|
||||
List<Element> srl = mrgp.getChildrenByName("subjectResults");
|
||||
if ("subject-list".equals(m.reportType())) {
|
||||
try {
|
||||
int c = Integer.parseInt(mrgp.getChildValue("count"));
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == sr.size(), I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, sr.size()) && ok;
|
||||
int subCount = 0;
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("; ");
|
||||
for (Element sr : srl) {
|
||||
subCount = addToSubjectCount(subCount, hostContext, sr, m, ns, b);
|
||||
}
|
||||
if (mrgp.hasChild("count")) {
|
||||
int c = Integer.parseInt(mrgp.getChildValue("count"));
|
||||
if (subCount > -1) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == subCount, I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, subCount) && ok;
|
||||
} else {
|
||||
hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_GRP_POP_COUNT_CANT_CHECK, c, b.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// nothing; that'll be because count is not valid, and that's a different error or its missing and we don't care
|
||||
}
|
||||
} else {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), sr.size() == 0, I18nConstants.MEASURE_MR_GRP_POP_NO_SUBJECTS) && ok;
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), srl.size() == 0, I18nConstants.MEASURE_MR_GRP_POP_NO_SUBJECTS) && ok;
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), mrgp.hasChild("count", false), I18nConstants.MEASURE_MR_GRP_POP_NO_COUNT);
|
||||
}
|
||||
return ok;
|
||||
return ok;
|
||||
}
|
||||
|
||||
private int addToSubjectCount(int subCount, ValidationContext valContext, Element sr, MeasureContext m, NodeStack ns, CommaSeparatedStringBuilder b) throws FHIRException, IOException {
|
||||
if (subCount < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
String ref = sr.getNamedChildValue("reference");
|
||||
if (ref == null) {
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_NO_REF));
|
||||
return -1;
|
||||
}
|
||||
BooleanHolder bh = new BooleanHolder();
|
||||
ResolvedReference rr = ((InstanceValidator) parent).localResolve(ref, ns, new ArrayList<>(), ns.getLiteralPath(), valContext.getRootResource(), valContext.getGroupingResource(), sr, bh);
|
||||
Element tgt;
|
||||
if (rr != null) {
|
||||
tgt = rr.getResource();
|
||||
} else {
|
||||
tgt = fetcher.fetch(((InstanceValidator) parent), valContext.getAppContext(), ref);
|
||||
}
|
||||
if (tgt == null) {
|
||||
// we couldn't resolve it, but we'll draw our own conclusion from the literal URL if we can.
|
||||
String[] parts = ref.split("\\/");
|
||||
if (parts.length == 2 && context.getResourceNamesAsSet().contains(parts[0])) {
|
||||
switch (parts[0]) {
|
||||
case "Patient":
|
||||
case "Practitioner":
|
||||
case "Person":
|
||||
case "PractitionerRole":
|
||||
case "RelatedPerson":
|
||||
return subCount + 1;
|
||||
case "List":
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_UNRESOLVED, "List", ref));
|
||||
return -1; // for now
|
||||
case "Group":
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_UNRESOLVED, "Group", ref));
|
||||
return -1; // for now
|
||||
default:
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_UNRESOLVED, parts[0], ref));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// add information / hint?
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_NO_REF_RES, ref));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (tgt.fhirType()) {
|
||||
case "Patient":
|
||||
case "Practitioner":
|
||||
case "Person":
|
||||
case "PractitionerRole":
|
||||
case "RelatedPerson":
|
||||
return subCount + 1;
|
||||
case "List":
|
||||
return subCount + tgt.getChildren("entry").size();
|
||||
case "Group":
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_REF_UNPROCESSIBLE, "Group", ref));
|
||||
return -1; // for now
|
||||
default:
|
||||
b.append(context.formatMessage(I18nConstants.MEASURE_MR_GRP_POP_COUNT_REF_UNPROCESSIBLE, tgt.fhirType(), ref));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateMeasureReportGroupStratifiers(ValidationContext hostContext, MeasureContext m, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mrg, NodeStack stack, boolean inProgress) {
|
||||
|
|
|
@ -3587,10 +3587,67 @@ v: {
|
|||
"code" : "en-AU",
|
||||
"system" : "urn:ietf:bcp:47",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome"
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260",
|
||||
"code" : "1",
|
||||
"display" : "Surgery Case"
|
||||
}, "url": "http://terminology.hl7.org/ValueSet/v3-ActEncounterCode", "version": "3.0.0", "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"code" : "1",
|
||||
"severity" : "error",
|
||||
"error" : "A definition for CodeSystem 'urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260' could not be found, so the code cannot be validated; The provided code 'urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260#1 ('Surgery Case')' was not found in the value set 'http://terminology.hl7.org/ValueSet/v3-ActEncounterCode|3.0.0'",
|
||||
"class" : "UNKNOWN",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "not-found",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-found"
|
||||
}],
|
||||
"text" : "A definition for CodeSystem 'urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260' could not be found, so the code cannot be validated"
|
||||
},
|
||||
"location" : ["Coding.system"],
|
||||
"expression" : ["Coding.system"]
|
||||
},
|
||||
{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "code-invalid",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-in-vs"
|
||||
}],
|
||||
"text" : "The provided code 'urn:oid:1.2.840.114350.1.72.1.7.7.10.696784.13260#1 ('Surgery Case')' was not found in the value set 'http://terminology.hl7.org/ValueSet/v3-ActEncounterCode|3.0.0'"
|
||||
},
|
||||
"location" : ["Coding.code"],
|
||||
"expression" : ["Coding.code"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue