more work on Measure/MeasureReport validation

This commit is contained in:
Grahame Grieve 2020-04-03 12:16:33 +11:00
parent 8d695bb4c1
commit 101fbe3126
5 changed files with 179 additions and 37 deletions

View File

@ -461,5 +461,13 @@ public class I18nConstants {
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_LIB_UNKNOWN = "MEASURE_M_LIB_UNKNOWN"; public static final String MEASURE_M_LIB_UNKNOWN = "MEASURE_M_LIB_UNKNOWN";
public static final String TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = "TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE"; public static final String TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = "TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE";
public static final String MEASURE_MR_SCORE_PROHIBITED_RT = "MEASURE_MR_SCORE_PROHIBITED_RT";
public static final String MEASURE_MR_SCORE_PROHIBITED_MS = "MEASURE_MR_SCORE_PROHIBITED_MS";
public static final String MEASURE_MR_SCORE_REQUIRED = "MEASURE_MR_SCORE_REQUIRED";
public static final String MEASURE_MR_M_SCORING_UNK = "MEASURE_MR_M_SCORING_UNK";
public static final String MEASURE_MR_SCORE_UNIT_PROHIBITED = "MEASURE_MR_SCORE_UNIT_PROHIBITED";
public static final String MEASURE_MR_SCORE_VALUE_REQUIRED = "MEASURE_MR_SCORE_VALUE_REQUIRED";
public static final String MEASURE_MR_SCORE_VALUE_INVALID_01 = "MEASURE_MR_SCORE_VALUE_INVALID_01";
public static final String MEASURE_MR_SCORE_FIXED = "MEASURE_MR_SCORE_FIXED";
public static final String MEASURE_MR_SCORE_UNIT_REQUIRED = "MEASURE_MR_SCORE_UNIT_REQUIRED";
} }

View File

@ -461,3 +461,12 @@ MEASURE_M_GROUP_STRATA_NO_CODE = A measure group stratifier should have a code w
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_LIB_UNKNOWN = The Library {0} could not be resolved, so expression validation may not be correct MEASURE_M_LIB_UNKNOWN = The Library {0} could not be resolved, so expression validation may not be correct
TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = Canonical URLs must be absolute URLs if they are not fragment references ({0}) TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE = Canonical URLs must be absolute URLs if they are not fragment references ({0})
MEASURE_MR_SCORE_PROHIBITED_RT = No measureScore when the type of the report is ''data-collection''
MEASURE_MR_SCORE_PROHIBITED_MS = No measureScore when the scoring of the mesage is ''cohort''
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_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}

View File

@ -0,0 +1,46 @@
package org.hl7.fhir.validation.instance.type;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Library;
import org.hl7.fhir.r5.model.Measure;
import org.hl7.fhir.r5.model.Measure.MeasureGroupComponent;
public class MeasureContext {
private List<Library> libs = new ArrayList<>();
private Measure measure;
private Element report;
public MeasureContext() {
}
public MeasureContext(Measure measure, Element report) {
this.measure = measure;
this.report = report;
}
public void seeLibrary(Library l) {
libs.add(l);
}
public List<MeasureGroupComponent> groups() {
return measure.getGroup();
}
public Measure measure() {
return measure;
}
public String reportType() {
return report.getChildValue("type");
}
public String scoring() {
return measure.getScoring().getCodingFirstRep().getCode();
}
}

View File

@ -4,6 +4,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,9 +35,10 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import org.hl7.fhir.validation.instance.utils.NodeStack; import org.hl7.fhir.validation.instance.utils.NodeStack;
import org.hl7.fhir.validation.BaseValidator; import org.hl7.fhir.validation.BaseValidator;
import org.hl7.fhir.validation.TimeTracker; import org.hl7.fhir.validation.TimeTracker;
import org.hl7.fhir.validation.instance.utils.MeasureContext;
import org.hl7.fhir.validation.instance.utils.ValidatorHostContext; import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
import net.sf.saxon.tree.tiny.LargeStringBuffer;
public class MeasureValidator extends BaseValidator { public class MeasureValidator extends BaseValidator {
public MeasureValidator(IWorkerContext context, TimeTracker timeTracker) { public MeasureValidator(IWorkerContext context, TimeTracker timeTracker) {
@ -71,7 +74,6 @@ public class MeasureValidator extends BaseValidator {
warning(errors, IssueType.REQUIRED, p.line(), p.col(), ns2.getLiteralPath(), pl.size() == 1 || p.hasChild("code"), I18nConstants.MEASURE_M_GROUP_POP_NO_CODE); warning(errors, IssueType.REQUIRED, p.line(), p.col(), ns2.getLiteralPath(), pl.size() == 1 || p.hasChild("code"), I18nConstants.MEASURE_M_GROUP_POP_NO_CODE);
c1++; c1++;
} }
warning(errors, IssueType.REQUIRED, group.line(), group.col(), ns.getLiteralPath(), group.hasChildren("stratifier"), I18nConstants.MEASURE_M_GROUP_STRATA);
c1 = 0; c1 = 0;
List<Element> stl = group.getChildrenByName("stratifier"); List<Element> stl = group.getChildrenByName("stratifier");
for (Element st : stl) { for (Element st : stl) {
@ -127,9 +129,13 @@ public class MeasureValidator extends BaseValidator {
if (hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), measure != null, I18nConstants.MEASURE_MR_M_NONE)) { if (hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), measure != null, I18nConstants.MEASURE_MR_M_NONE)) {
long t = System.nanoTime(); long t = System.nanoTime();
Measure msrc = measure.startsWith("#") ? loadMeasure(element, measure.substring(1)) : context.fetchResource(Measure.class, measure); Measure msrc = measure.startsWith("#") ? loadMeasure(element, measure.substring(1)) : context.fetchResource(Measure.class, measure);
timeTracker.sd(t, System.nanoTime());
if (warning(errors, IssueType.REQUIRED, m.line(), m.col(), stack.getLiteralPath(), msrc != null, I18nConstants.MEASURE_MR_M_NOTFOUND, measure)) { if (warning(errors, IssueType.REQUIRED, m.line(), m.col(), stack.getLiteralPath(), msrc != null, I18nConstants.MEASURE_MR_M_NOTFOUND, measure)) {
boolean inComplete = !"complete".equals(element.getNamedChildValue("status")); boolean inComplete = !"complete".equals(element.getNamedChildValue("status"));
validateMeasureReportGroups(hostContext, msrc, errors, element, stack, inComplete); MeasureContext mc = new MeasureContext(msrc, element);
NodeStack ns = stack.push(m, -1, m.getProperty().getDefinition(), m.getProperty().getDefinition());
hint(errors, IssueType.BUSINESSRULE, m.line(), m.col(), ns.getLiteralPath(), Utilities.existsInList(mc.scoring(), "proportion", "ratio", "continuous-variable", "cohort"), I18nConstants.MEASURE_MR_M_SCORING_UNK);
validateMeasureReportGroups(hostContext, mc, errors, element, stack, inComplete);
} }
} }
} }
@ -178,41 +184,41 @@ public class MeasureValidator extends BaseValidator {
} }
} }
private void validateMeasureReportGroups(ValidatorHostContext hostContext, Measure m, List<ValidationMessage> errors, Element mr, NodeStack stack, boolean inProgress) { private void validateMeasureReportGroups(ValidatorHostContext hostContext, MeasureContext m, List<ValidationMessage> errors, Element mr, NodeStack stack, boolean inProgress) {
NarrativeGenerator gen = new NarrativeGenerator(null, null, context); NarrativeGenerator gen = new NarrativeGenerator(null, null, context);
List<MeasureGroupComponent> groups = new ArrayList<MeasureGroupComponent>(); List<MeasureGroupComponent> groups = new ArrayList<MeasureGroupComponent>();
List<Element> glist = mr.getChildrenByName("group"); List<Element> glist = mr.getChildrenByName("group");
if (glist.size() == 1 && m.getGroup().size() == 1) { if (glist.size() == 1 && m.groups().size() == 1) {
// if there's only one group, it can be ((and usually is) anonymous) // if there's only one group, it can be ((and usually is) anonymous)
// but we still check that the code, if both have one, is consistent. // but we still check that the code, if both have one, is consistent.
Element mrg = glist.get(0); Element mrg = glist.get(0);
NodeStack ns = stack.push(mrg, 0, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition()); NodeStack ns = stack.push(mrg, 0, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
if (m.getGroupFirstRep().hasCode() && mrg.hasChild("code")) { if (m.groups().get(0).hasCode() && mrg.hasChild("code")) {
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), hasUseableCode(cc), I18nConstants.MEASURE_MR_GRP_NO_USABLE_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), hasUseableCode(cc), I18nConstants.MEASURE_MR_GRP_NO_USABLE_CODE)) {
rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc.matches(m.getGroupFirstRep().getCode()), I18nConstants.MEASURE_MR_GRP_NO_WRONG_CODE, gen.gen(cc), gen.gen(m.getGroupFirstRep().getCode())); rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc.matches(m.groups().get(0).getCode()), I18nConstants.MEASURE_MR_GRP_NO_WRONG_CODE, gen.gen(cc), gen.gen(m.groups().get(0).getCode()));
} }
} }
validateMeasureReportGroup(hostContext, m.getGroupFirstRep(), errors, mr, mrg, ns, inProgress, gen); validateMeasureReportGroup(hostContext, m, m.groups().get(0), errors, mrg, ns, inProgress, gen);
} else { } else {
int i = 0; int i = 0;
for (Element mrg : glist) { for (Element mrg : glist) {
NodeStack ns = stack.push(mrg, i, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition()); NodeStack ns = stack.push(mrg, i, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_NO_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_NO_CODE)) {
MeasureGroupComponent mg = getGroupForCode(cc, m); MeasureGroupComponent mg = getGroupForCode(cc, m.measure());
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mg != null, I18nConstants.MEASURE_MR_GRP_UNK_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mg != null, I18nConstants.MEASURE_MR_GRP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !groups.contains(mg), I18nConstants.MEASURE_MR_GRP_DUPL_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !groups.contains(mg), I18nConstants.MEASURE_MR_GRP_DUPL_CODE)) {
groups.add(mg); groups.add(mg);
validateMeasureReportGroup(hostContext, mg, errors, mr, mrg, ns, inProgress, gen); validateMeasureReportGroup(hostContext, m, mg, errors, mrg, ns, inProgress, gen);
} }
} }
} }
i++; i++;
} }
for (MeasureGroupComponent mg : m.getGroup()) { 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, gen.gen(mg.getCode())); rule(errors, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, gen.gen(mg.getCode()));
} }
@ -220,14 +226,99 @@ public class MeasureValidator extends BaseValidator {
} }
} }
private void validateMeasureReportGroup(ValidatorHostContext hostContext, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mr, Element mrg, NodeStack ns, boolean inProgress, NarrativeGenerator gen) { private void validateMeasureReportGroup(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mrg, NodeStack ns, boolean inProgress, NarrativeGenerator gen) {
validateMeasureReportGroupPopulations(hostContext, mg, errors, mr, mrg, ns, inProgress, gen); validateMeasureReportGroupPopulations(hostContext, m, mg, errors, mrg, ns, inProgress, gen);
// validate the score validateScore(hostContext, m, errors, mrg, ns, inProgress, gen);
validateMeasureReportGroupStratifiers(hostContext, mg, errors, mr, mrg, ns, inProgress, gen); validateMeasureReportGroupStratifiers(hostContext, m, mg, errors, mrg, ns, inProgress, gen);
// validate the stratifiers
} }
private void validateMeasureReportGroupPopulations(ValidatorHostContext hostContext, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mr, Element mrg, NodeStack stack, boolean inProgress, NarrativeGenerator gen) { private void validateScore(ValidatorHostContext hostContext, MeasureContext m, List<ValidationMessage> errors, Element mrg, NodeStack stack, boolean inProgress, NarrativeGenerator gen) {
Element ms = mrg.getNamedChild("measureScore");
// first, we check MeasureReport.type
if ("data-collection".equals(m.reportType())) {
banned(errors, stack, ms, I18nConstants.MEASURE_MR_SCORE_PROHIBITED_RT);
} else if ("cohort".equals(m.scoring())) {
// cohort - there is no measure score
banned(errors, stack, ms, I18nConstants.MEASURE_MR_SCORE_PROHIBITED_MS);
} else if (Utilities.existsInList(m.scoring(), "proportion", "ratio", "continuous-variable")) {
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");
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)) {
try {
BigDecimal dec = new BigDecimal(v.primitiveValue());
NodeStack nsv = ns.push(v, -1, v.getProperty().getDefinition(), v.getProperty().getDefinition());
rule(errors, IssueType.REQUIRED, v.line(), v.col(), nsv.getLiteralPath(), dec.compareTo(new BigDecimal(0)) >= 0 && dec.compareTo(new BigDecimal(1)) <= 0, I18nConstants.MEASURE_MR_SCORE_VALUE_INVALID_01);
} catch (Exception e) {
// nothing - will have caused an error elsewhere
}
}
} 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)) {
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) {
if (c != null) {
NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition());
rule(errors, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode());
Element system = ms.getNamedChild("system");
if (system == null) {
NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition());
rule(errors, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem());
} else {
rule(errors, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem());
}
}
} else if (c != null) {
rule(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, gen.gen(c));
} else {
warning(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_UNIT_REQUIRED, "ratio");
}
}
} 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)) {
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) {
if (c != null) {
NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition());
rule(errors, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode());
Element system = ms.getNamedChild("system");
if (system == null) {
NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition());
rule(errors, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem());
} else {
rule(errors, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem());
}
}
} else if (c != null) {
rule(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, gen.gen(c));
}
}
}
} // else do nothing - there's a hint elsewhere
}
}
private void banned(List<ValidationMessage> errors, NodeStack stack, Element parent, String childName, String msgId, Object... params) {
Element child = parent.getNamedChild(childName);
banned(errors, stack, child, msgId, params);
}
private void banned(List<ValidationMessage> errors, NodeStack stack, Element e, String msgId, Object... params) {
if (e != null) {
NodeStack ns = stack.push(e, -1, e.getProperty().getDefinition(), e.getProperty().getDefinition());
rule(errors, IssueType.BUSINESSRULE, e.line(), e.col(), ns.getLiteralPath(), false, msgId, params);
}
}
private void validateMeasureReportGroupPopulations(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mrg, NodeStack stack, boolean inProgress, NarrativeGenerator gen) {
// there must be a population for each population defined in the measure, and no 4others. // there must be a population for each population defined in the measure, and no 4others.
List<MeasureGroupPopulationComponent> pops = new ArrayList<MeasureGroupPopulationComponent>(); List<MeasureGroupPopulationComponent> pops = new ArrayList<MeasureGroupPopulationComponent>();
List<Element> plist = mrg.getChildrenByName("population"); List<Element> plist = mrg.getChildrenByName("population");
@ -241,7 +332,7 @@ public class MeasureValidator extends BaseValidator {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgp != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgp != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !pops.contains(mgp), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !pops.contains(mgp), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) {
pops.add(mgp); pops.add(mgp);
validateMeasureReportGroupPopulation(hostContext, mgp, errors, mr, mrgp, ns, inProgress); validateMeasureReportGroupPopulation(hostContext, m, mgp, errors, mrgp, ns, inProgress);
} }
} }
} }
@ -254,9 +345,9 @@ public class MeasureValidator extends BaseValidator {
} }
} }
private void validateMeasureReportGroupPopulation(ValidatorHostContext hostContext, MeasureGroupPopulationComponent mgp, List<ValidationMessage> errors, Element mr, Element mrgp, NodeStack ns, boolean inProgress) { private void validateMeasureReportGroupPopulation(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupPopulationComponent mgp, List<ValidationMessage> errors, Element mrgp, NodeStack ns, boolean inProgress) {
List<Element> sr = mrgp.getChildrenByName("subjectResults"); List<Element> sr = mrgp.getChildrenByName("subjectResults");
if ("subject-list".equals(mr.getChildValue("type"))) { if ("subject-list".equals(m.reportType())) {
try { try {
int c = Integer.parseInt(mrgp.getChildValue("count")); int c = Integer.parseInt(mrgp.getChildValue("count"));
rule(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == sr.size(), I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, sr.size()); rule(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == sr.size(), I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, sr.size());
@ -269,7 +360,7 @@ public class MeasureValidator extends BaseValidator {
} }
} }
private void validateMeasureReportGroupStratifiers(ValidatorHostContext hostContext, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mr, Element mrg, NodeStack stack, boolean inProgress, NarrativeGenerator gen) { private void validateMeasureReportGroupStratifiers(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupComponent mg, List<ValidationMessage> errors, Element mrg, NodeStack stack, boolean inProgress, NarrativeGenerator gen) {
// there must be a population for each population defined in the measure, and no 4others. // there must be a population for each population defined in the measure, and no 4others.
List<MeasureGroupStratifierComponent> strats = new ArrayList<>(); List<MeasureGroupStratifierComponent> strats = new ArrayList<>();
List<Element> slist = mrg.getChildrenByName("stratifier"); List<Element> slist = mrg.getChildrenByName("stratifier");
@ -283,7 +374,7 @@ public class MeasureValidator extends BaseValidator {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgs != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgs != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !strats.contains(mgs), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) { if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !strats.contains(mgs), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) {
strats.add(mgs); strats.add(mgs);
validateMeasureReportGroupStratifier(hostContext, mgs, errors, mr, mrgs, ns, inProgress); validateMeasureReportGroupStratifier(hostContext, m, mgs, errors, mrgs, ns, inProgress);
} }
} }
} }
@ -296,7 +387,7 @@ public class MeasureValidator extends BaseValidator {
} }
} }
private void validateMeasureReportGroupStratifier(ValidatorHostContext hostContext, MeasureGroupStratifierComponent mgs, List<ValidationMessage> errors, Element mr, Element mrgs, NodeStack ns, boolean inProgress) { private void validateMeasureReportGroupStratifier(ValidatorHostContext hostContext, MeasureContext m, MeasureGroupStratifierComponent mgs, List<ValidationMessage> errors, Element mrgs, NodeStack ns, boolean inProgress) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }

View File

@ -1,12 +0,0 @@
package org.hl7.fhir.validation.instance.utils;
import org.hl7.fhir.r5.model.Library;
public class MeasureContext {
public void seeLibrary(Library l) {
// TODO Auto-generated method stub
}
}