fix issues in MeasureReport validation

This commit is contained in:
Grahame Grieve 2020-07-15 16:45:21 +10:00
parent fe29c3022f
commit 9ccb37a0ba
3 changed files with 26 additions and 5 deletions

View File

@ -42,6 +42,7 @@ import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.file.Paths; 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) { public static boolean charInSet(char value, char... array) {
for (int i : array) for (int i : array)
if (value == i) if (value == i)
@ -1299,6 +1308,7 @@ public class Utilities {
return false; return false;
} }
} }

View File

@ -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_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_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_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_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_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} MEASURE_MR_SCORE_UNIT_REQUIRED = A unit should be present when the scoring type is {0}

View File

@ -279,14 +279,19 @@ public class MeasureValidator extends BaseValidator {
} }
i++; i++;
} }
boolean dataCollection = isDataCollection(mr);
for (MeasureGroupComponent mg : m.groups()) { for (MeasureGroupComponent mg : m.groups()) {
if (!groups.contains(mg)) { 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<ValidationMessage> errors, Element mrg, NodeStack ns, boolean inProgress) { private void validateMeasureReportGroup(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mrg, NodeStack ns, boolean inProgress) {
validateMeasureReportGroupPopulations(hostContext, m, mg, errors, mrg, ns, inProgress); validateMeasureReportGroupPopulations(hostContext, m, mg, errors, mrg, ns, inProgress);
validateScore(hostContext, m, 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())) { 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()); NodeStack ns = stack.push(ms, -1, ms.getProperty().getDefinition(), ms.getProperty().getDefinition());
Element v = ms.getNamedChild("value"); 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())) { if ("proportion".equals(m.scoring())) {
// proportion - score is a unitless number from 0 ... 1 // 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, "unit", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion");
banned(errors, ns, ms, "system", 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"); 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 { try {
BigDecimal dec = new BigDecimal(v.primitiveValue()); BigDecimal dec = new BigDecimal(v.primitiveValue());
NodeStack nsv = ns.push(v, -1, v.getProperty().getDefinition(), v.getProperty().getDefinition()); 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())) { } else if ("ratio".equals(m.scoring())) {
// ratio - score is a number with no value constraints, and maybe with a unit (perhaps constrained by extension) // 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"); 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; 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) { if (unit != null) {
@ -344,7 +355,7 @@ public class MeasureValidator extends BaseValidator {
} }
} else if ("continuous-variable".equals(m.scoring())) { } else if ("continuous-variable".equals(m.scoring())) {
// continuous-variable - score is a quantity with a unit per the extension // 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"); 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; 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) { if (unit != null) {