Improve MeasureReport validation for checking subject count

This commit is contained in:
Grahame Grieve 2024-07-16 06:16:47 +08:00
parent 37006946cd
commit 512f70aa18
5 changed files with 177 additions and 32 deletions

View File

@ -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";
}

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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"]
}]
}
}
-------------------------------------------------------------------------------------