diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index a0e4c17a9..7edc5903b 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -42,6 +42,7 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.channels.FileChannel; import java.nio.file.Paths; @@ -834,6 +835,14 @@ public class Utilities { } + public static String URLDecode(String ref) { + try { + return URLDecoder.decode(ref, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new Error(e.getMessage()); + } + } + public static boolean charInSet(char value, char... array) { for (int i : array) if (value == i) @@ -1299,6 +1308,7 @@ public class Utilities { return false; } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index f78bd128f..820194d27 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -468,7 +468,7 @@ MEASURE_MR_SCORE_PROHIBITED_MS = No measureScore when the scoring of the mesage MEASURE_MR_SCORE_REQUIRED = A measureScore is required when the Measure.scoring={0} MEASURE_MR_M_SCORING_UNK = The scoring system in this measure is unknown, so the measureScore values cannot be checked MEASURE_MR_SCORE_UNIT_PROHIBITED = A measureScore for this Measure Scoring ({0}) should not have units -MEASURE_MR_SCORE_VALUE_REQUIRED = A value is required when the Measure.scoring={0} +MEASURE_MR_SCORE_VALUE_REQUIRED = A value is required when the Measure.scoring = {0} MEASURE_MR_SCORE_VALUE_INVALID_01 = The value is invalid - it must be between 0 and 1 MEASURE_MR_SCORE_FIXED = This value is fixed by the Measure to ''{0]'' MEASURE_MR_SCORE_UNIT_REQUIRED = A unit should be present when the scoring type is {0} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/MeasureValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/MeasureValidator.java index e424decf6..ebcbbc00b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/MeasureValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/MeasureValidator.java @@ -279,14 +279,19 @@ public class MeasureValidator extends BaseValidator { } i++; } + boolean dataCollection = isDataCollection(mr); for (MeasureGroupComponent mg : m.groups()) { if (!groups.contains(mg)) { - rule(errors, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mg.getCode())); + rule(errors, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg) || dataCollection, I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mg.getCode())); } } } } + private boolean isDataCollection(Element mr) { + return "data-collection".equals(mr.getChildValue("type")); + } + private void validateMeasureReportGroup(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupComponent mg, List errors, Element mrg, NodeStack ns, boolean inProgress) { validateMeasureReportGroupPopulations(hostContext, m, mg, errors, mrg, ns, inProgress); validateScore(hostContext, m, errors, mrg, ns, inProgress); @@ -305,12 +310,18 @@ public class MeasureValidator extends BaseValidator { if (rule(errors, IssueType.REQUIRED, mrg.line(), mrg.col(), stack.getLiteralPath(), ms != null, I18nConstants.MEASURE_MR_SCORE_REQUIRED, m.scoring())) { NodeStack ns = stack.push(ms, -1, ms.getProperty().getDefinition(), ms.getProperty().getDefinition()); Element v = ms.getNamedChild("value"); + // TODO: this is a DEQM special and should be handled differently + if (v == null) { + if (ms.hasExtension("http://hl7.org/fhir/us/davinci-deqm/StructureDefinition/extension-alternateScoreType")) { + v = ms.getExtension("http://hl7.org/fhir/us/davinci-deqm/StructureDefinition/extension-alternateScoreType").getNamedChild("value"); + } + } if ("proportion".equals(m.scoring())) { // proportion - score is a unitless number from 0 ... 1 banned(errors, ns, ms, "unit", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); banned(errors, ns, ms, "system", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); banned(errors, ns, ms, "code", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); - if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED)) { + if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "proportion")) { try { BigDecimal dec = new BigDecimal(v.primitiveValue()); NodeStack nsv = ns.push(v, -1, v.getProperty().getDefinition(), v.getProperty().getDefinition()); @@ -321,7 +332,7 @@ public class MeasureValidator extends BaseValidator { } } else if ("ratio".equals(m.scoring())) { // ratio - score is a number with no value constraints, and maybe with a unit (perhaps constrained by extension) - if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED)) { + if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "ratio")) { Element unit = ms.getNamedChild("code"); Coding c = m.measure().hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-unit") ? (Coding) m.measure().getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-unit").getValue() : null; if (unit != null) { @@ -344,7 +355,7 @@ public class MeasureValidator extends BaseValidator { } } else if ("continuous-variable".equals(m.scoring())) { // continuous-variable - score is a quantity with a unit per the extension - if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED)) { + if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "continuous-variable")) { Element unit = ms.getNamedChild("code"); Coding c = m.measure().hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-unit") ? (Coding) m.measure().getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-unit").getValue() : null; if (unit != null) {