Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature additional measure bundle #459

Merged
merged 8 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions plugin/cql/src/main/java/org/opencds/cqf/ruler/cql/CqlConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.tuple.Triple;
import org.cqframework.cql.cql2elm.CqlTranslatorOptions;
import org.cqframework.cql.cql2elm.LibraryManager;
import org.cqframework.cql.cql2elm.ModelManager;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.opencds.cqf.cql.engine.data.CompositeDataProvider;
import org.opencds.cqf.cql.engine.fhir.model.Dstu2FhirModelResolver;
import org.opencds.cqf.cql.engine.fhir.model.Dstu3FhirModelResolver;
import org.opencds.cqf.cql.engine.fhir.model.R4FhirModelResolver;
import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver;
import org.opencds.cqf.cql.engine.model.ModelResolver;
import org.opencds.cqf.cql.engine.retrieve.RetrieveProvider;
import org.opencds.cqf.cql.evaluator.builder.Constants;
import org.opencds.cqf.cql.evaluator.builder.DataProviderFactory;
import org.opencds.cqf.cql.evaluator.builder.EndpointInfo;
import org.opencds.cqf.cql.evaluator.cql2elm.content.LibraryContentProvider;
import org.opencds.cqf.cql.evaluator.cql2elm.content.fhir.EmbeddedFhirLibraryContentProvider;
import org.opencds.cqf.cql.evaluator.cql2elm.model.CacheAwareModelManager;
import org.opencds.cqf.cql.evaluator.cql2elm.util.LibraryVersionSelector;
import org.opencds.cqf.cql.evaluator.engine.execution.CacheAwareLibraryLoaderDecorator;
import org.opencds.cqf.cql.evaluator.engine.execution.TranslatingLibraryLoader;
import org.opencds.cqf.cql.evaluator.engine.model.CachingModelResolverDecorator;
import org.opencds.cqf.cql.evaluator.engine.retrieve.BundleRetrieveProvider;
import org.opencds.cqf.cql.evaluator.fhir.adapter.AdapterFactory;
import org.opencds.cqf.cql.evaluator.spring.fhir.adapter.AdapterConfiguration;
import org.opencds.cqf.ruler.external.annotations.OnDSTU2Condition;
Expand Down Expand Up @@ -111,6 +118,24 @@ JpaDataProviderFactory jpaDataProviderFactory(ModelResolver modelResolver, DaoRe
};
}

@Bean
DataProviderFactory dataProviderFactory(FhirContext fhirContext, ModelResolver modelResolver) {
return new DataProviderFactory() {
@Override
public Triple<String, ModelResolver, RetrieveProvider> create(EndpointInfo endpointInfo) {
// to do implement endpoint
return null;
}

@Override
public Triple<String, ModelResolver, RetrieveProvider> create(IBaseBundle dataBundle) {
return Triple.of(Constants.FHIR_MODEL_URI, modelResolver,
new BundleRetrieveProvider(fhirContext, dataBundle));
}
};

}

@Bean
public JpaFhirRetrieveProvider jpaFhirRetrieveProvider(DaoRegistry daoRegistry,
SearchParameterResolver searchParameterResolver) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public Parameters collectData(RequestDetails theRequestDetails, @IdParam IdType
@OperationParam(name = "lastReceivedOn") String lastReceivedOn) {

MeasureReport report = measureEvaluateProvider.evaluateMeasure(theRequestDetails, theId, periodStart, periodEnd,
"subject", subject, practitioner, lastReceivedOn, null);
"subject", subject, practitioner, lastReceivedOn, null, null);

// TODO: Data collection doesn't exist?
report.setType(MeasureReportType.SUMMARY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import org.hl7.fhir.dstu3.model.Measure;
import org.hl7.fhir.dstu3.model.MeasureReport;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.Bundle;
import org.opencds.cqf.cql.engine.data.DataProvider;
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
import org.opencds.cqf.cql.evaluator.cql2elm.content.LibraryContentProvider;
import org.opencds.cqf.cql.evaluator.builder.DataProviderFactory;
import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal;
import org.opencds.cqf.ruler.cql.JpaDataProviderFactory;
import org.opencds.cqf.ruler.cql.JpaFhirDalFactory;
Expand All @@ -27,7 +29,10 @@ public class MeasureEvaluateProvider extends DaoRegistryOperationProvider {
private JpaTerminologyProviderFactory jpaTerminologyProviderFactory;

@Autowired
private JpaDataProviderFactory dataProviderFactory;
private JpaDataProviderFactory jpaDataProviderFactory;

@Autowired
private DataProviderFactory dataProviderFactory;

@Autowired
private JpaLibraryContentProviderFactory libraryContentProviderFactory;
Expand Down Expand Up @@ -56,6 +61,7 @@ public class MeasureEvaluateProvider extends DaoRegistryOperationProvider {
* received.
* @param productLine the productLine (e.g. Medicare, Medicaid, etc) to use
* for the evaluation. This is a non-standard parameter.
* @param additionalData the data bundle containing additional data
* @return the calculated MeasureReport
*/
@Description(shortDefinition = "$evaluate-measure", value = "Implements the <a href=\"https://www.hl7.org/fhir/operation-measure-evaluate-measure.html\">$evaluate-measure</a> operation found in the <a href=\"http://www.hl7.org/fhir/clinicalreasoning-module.html\">FHIR Clinical Reasoning Module</a>. This implementation aims to be compatible with the CQF IG.", example = "Measure/example/$evaluate-measure?subject=Patient/123&periodStart=2019&periodEnd=2020")
Expand All @@ -67,20 +73,21 @@ public MeasureReport evaluateMeasure(RequestDetails requestDetails, @IdParam IdT
@OperationParam(name = "patient") String patient,
@OperationParam(name = "practitioner") String practitioner,
@OperationParam(name = "lastReceivedOn") String lastReceivedOn,
@OperationParam(name = "productLine") String productLine) {
@OperationParam(name = "productLine") String productLine,
@OperationParam(name = "additionalData") Bundle additionalData) {

Measure measure = read(theId);
TerminologyProvider terminologyProvider = this.jpaTerminologyProviderFactory.create(requestDetails);
DataProvider dataProvider = this.dataProviderFactory.create(requestDetails, terminologyProvider);
DataProvider dataProvider = this.jpaDataProviderFactory.create(requestDetails, terminologyProvider);
LibraryContentProvider libraryContentProvider = this.libraryContentProviderFactory.create(requestDetails);
FhirDal fhirDal = this.fhirDalFactory.create(requestDetails);

org.opencds.cqf.cql.evaluator.measure.dstu3.Dstu3MeasureProcessor measureProcessor = new org.opencds.cqf.cql.evaluator.measure.dstu3.Dstu3MeasureProcessor(
null, null, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, fhirDal, null,
null, dataProviderFactory, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, fhirDal, null,
null);

MeasureReport report = measureProcessor.evaluateMeasure(measure.getUrl(), periodStart, periodEnd, reportType,
patient, null, lastReceivedOn, null, null, null, null);
patient, null, lastReceivedOn, null, null, null, additionalData);

if (productLine != null) {
Extension ext = new Extension();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public Parameters collectData(RequestDetails theRequestDetails, @IdParam IdType
@OperationParam(name = "lastReceivedOn") String lastReceivedOn) {

MeasureReport report = measureEvaluateProvider.evaluateMeasure(theRequestDetails, theId, periodStart, periodEnd,
"subject", subject, practitioner, lastReceivedOn, null);
"subject", subject, practitioner, lastReceivedOn, null, null);
report.setType(MeasureReport.MeasureReportType.DATACOLLECTION);
report.setGroup(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import java.util.Map;

import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Measure;
import org.hl7.fhir.r4.model.MeasureReport;
import org.hl7.fhir.r4.model.StringType;
import org.opencds.cqf.cql.engine.data.DataProvider;
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
import org.opencds.cqf.cql.evaluator.builder.DataProviderFactory;
import org.opencds.cqf.cql.evaluator.cql2elm.content.LibraryContentProvider;
import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal;
import org.opencds.cqf.ruler.cql.JpaDataProviderFactory;
Expand All @@ -29,7 +31,10 @@ public class MeasureEvaluateProvider extends DaoRegistryOperationProvider {
private JpaTerminologyProviderFactory jpaTerminologyProviderFactory;

@Autowired
private JpaDataProviderFactory dataProviderFactory;
private JpaDataProviderFactory jpaDataProviderFactory;

@Autowired
private DataProviderFactory dataProviderFactory;

@Autowired
private JpaLibraryContentProviderFactory libraryContentProviderFactory;
Expand Down Expand Up @@ -60,6 +65,7 @@ public class MeasureEvaluateProvider extends DaoRegistryOperationProvider {
* received.
* @param productLine the productLine (e.g. Medicare, Medicaid, etc) to use
* for the evaluation. This is a non-standard parameter.
* @param additionalData the data bundle containing additional data
* @return the calculated MeasureReport
*/
@SuppressWarnings("squid:S00107") // warning for greater than 7 parameters
Expand All @@ -72,20 +78,21 @@ public MeasureReport evaluateMeasure(RequestDetails requestDetails, @IdParam IdT
@OperationParam(name = "subject") String subject,
@OperationParam(name = "practitioner") String practitioner,
@OperationParam(name = "lastReceivedOn") String lastReceivedOn,
@OperationParam(name = "productLine") String productLine) {
@OperationParam(name = "productLine") String productLine,
@OperationParam(name = "additionalData") Bundle additionalData) {

Measure measure = read(theId);
TerminologyProvider terminologyProvider = this.jpaTerminologyProviderFactory.create(requestDetails);
DataProvider dataProvider = this.dataProviderFactory.create(requestDetails, terminologyProvider);
DataProvider dataProvider = this.jpaDataProviderFactory.create(requestDetails, terminologyProvider);
LibraryContentProvider libraryContentProvider = this.libraryContentProviderFactory.create(requestDetails);
FhirDal fhirDal = this.fhirDalFactory.create(requestDetails);

org.opencds.cqf.cql.evaluator.measure.r4.R4MeasureProcessor measureProcessor = new org.opencds.cqf.cql.evaluator.measure.r4.R4MeasureProcessor(
null, null, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, fhirDal, null,
this.globalLibraryCache);
null, this.dataProviderFactory, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, fhirDal, null,
this.globalLibraryCache);

MeasureReport report = measureProcessor.evaluateMeasure(measure.getUrl(), periodStart, periodEnd, reportType,
subject, null, lastReceivedOn, null, null, null, null);
subject, null, lastReceivedOn, null, null, null, additionalData);

if (productLine != null) {
Extension ext = new Extension();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,21 @@
import org.hl7.fhir.dstu3.model.Library;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.StringType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.opencds.cqf.ruler.cr.CrConfig;
import org.opencds.cqf.ruler.test.RestIntegrationTest;
import org.springframework.boot.test.context.SpringBootTest;

import ca.uhn.fhir.context.FhirContext;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { DataOperationProviderIT.class,
CrConfig.class }, properties = { "hapi.fhir.fhir_version=dstu3" })
public class DataOperationProviderIT extends RestIntegrationTest {

@Disabled("Erroring because the DataRequirementsLibraryTransactionBundle.json is missing")
@Test
public void testDstu3DataRequirementsOperation() throws IOException {
String bundleTextValueSets = stringFromResource( "DataRequirementsLibraryTransactionBundle.json");
FhirContext fhirContext = FhirContext.forDstu3();
Bundle bundleValueSet = (Bundle)fhirContext.newJsonParser().parseResource(bundleTextValueSets);
getClient().transaction().withBundle(bundleValueSet).execute();
String bundleAsText = stringFromResource( "DataRequirementsTransactionBundle.json");
Bundle bundle = (Bundle)getFhirContext().newJsonParser().parseResource(bundleAsText);
getClient().transaction().withBundle(bundle).execute();

Parameters params = new Parameters();
params.addParameter().setName("target").setValue(new StringType("dummy"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,72 @@
package org.opencds.cqf.ruler.cr.dstu3.provider;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.MeasureReport;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.StringType;
import org.junit.jupiter.api.Test;
import org.opencds.cqf.ruler.cql.CqlConfig;
import org.opencds.cqf.ruler.cr.CrConfig;
import org.opencds.cqf.ruler.devtools.DevToolsConfig;
import org.opencds.cqf.ruler.devtools.dstu3.CodeSystemUpdateProvider;
import org.opencds.cqf.ruler.test.RestIntegrationTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { MeasureEvaluateProviderIT.class,
CrConfig.class, CqlConfig.class, DevToolsConfig.class }, properties = {
"hapi.fhir.fhir_version=dstu3",
})
public class MeasureEvaluateProviderIT extends RestIntegrationTest {

// @Autowired
// private MeasureEvaluateProvider measureEvaluateProvider;
@Test
public void testMeasureEvaluate() throws Exception {
String bundleAsText = stringFromResource( "Exm105Fhir3Measure.json");
Bundle bundle = (Bundle)getFhirContext().newJsonParser().parseResource(bundleAsText);
getClient().transaction().withBundle(bundle).execute();

@Autowired
private CodeSystemUpdateProvider codeSystemUpdateProvider;
Parameters params = new Parameters();
params.addParameter().setName("periodStart").setValue(new StringType("2019-01-01"));
params.addParameter().setName("periodEnd").setValue(new StringType("2020-01-01"));
params.addParameter().setName("reportType").setValue(new StringType("individual"));
params.addParameter().setName("subject").setValue(new StringType("Patient/denom-EXM105-FHIR3"));
params.addParameter().setName("lastReceivedOn").setValue(new StringType("2019-12-12"));

@BeforeEach
public void setup() throws Exception {
uploadTests("valueset");
codeSystemUpdateProvider.updateCodeSystems();
uploadTests("library");
MeasureReport returnMeasureReport = getClient().operation().onInstance(new IdType("Measure", "measure-EXM105-FHIR3-8.0.000"))
.named("$evaluate-measure")
.withParameters(params)
.returnResourceType(MeasureReport.class)
.execute();

assertNotNull(returnMeasureReport);
// System.out.println("Resource:"+this.getFhirContext().newJsonParser().setPrettyPrint(true).encodeResourceToString(returnMeasureReport));
}

@Disabled("uncommented line is throwing a null pointer exception")
@Test
public void testMeasureEvaluate() throws Exception {
// Patient First
uploadTests("test/plandefinition/LungCancerScreening/Former-Smoker/Patient");
// Map<String, IBaseResource> resources =
// uploadTests("test/plandefinition/LungCancerScreening/Former-Smoker", ourCtx,
// myDaoRegistry);
// IBaseResource patient = resources.get("Former-Smoker");
// MeasureReport report =
// measureEvaluateProvider.evaluateMeasure(requestDetails, theId, periodStart,
// periodEnd, reportType, subject, practitioner, lastReceivedOn, productLine);
public void testMeasureEvaluateWithAdditionalData() throws Exception {
String mainBundleAsText = stringFromResource( "Exm105FhirR3MeasurePartBundle.json");
Bundle bundle = (Bundle)getFhirContext().newJsonParser().parseResource(mainBundleAsText);
getClient().transaction().withBundle(bundle).execute();

String additionalBundleAsText = stringFromResource( "Exm105FhirR3MeasureAdditionalData.json");
Bundle additionalData = (Bundle)getFhirContext().newJsonParser().parseResource(additionalBundleAsText);


Parameters params = new Parameters();
params.addParameter().setName("periodStart").setValue(new StringType("2019-01-01"));
params.addParameter().setName("periodEnd").setValue(new StringType("2020-01-01"));
params.addParameter().setName("reportType").setValue(new StringType("individual"));
params.addParameter().setName("subject").setValue(new StringType("Patient/denom-EXM105-FHIR3"));
params.addParameter().setName("lastReceivedOn").setValue(new StringType("2019-12-12"));
params.addParameter().setName("additionalData").setResource(additionalData);

MeasureReport returnMeasureReport = getClient().operation().onInstance(new IdType("Measure", "measure-EXM105-FHIR3-8.0.000"))
.named("$evaluate-measure")
.withParameters(params)
.returnResourceType(MeasureReport.class)
.execute();

assertNotNull(returnMeasureReport);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,21 @@
import org.hl7.fhir.r4.model.Library;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.opencds.cqf.ruler.cr.CrConfig;
import org.opencds.cqf.ruler.test.RestIntegrationTest;
import org.springframework.boot.test.context.SpringBootTest;

import ca.uhn.fhir.context.FhirContext;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { DataOperationProviderIT.class,
CrConfig.class }, properties = { "hapi.fhir.fhir_version=r4" })
public class DataOperationProviderIT extends RestIntegrationTest {

@Test
public void testR4LibraryDataRequirementsOperation() throws IOException {
String bundleTextValueSets = stringFromResource( "DataRequirementsTransactionBundle.json");
FhirContext fhirContext = FhirContext.forR4();
Bundle bundleValueSet = (Bundle)fhirContext.newJsonParser().parseResource(bundleTextValueSets);
getClient().transaction().withBundle(bundleValueSet).execute();
String bundleAsText = stringFromResource( "DataRequirementsTransactionBundle.json");
Bundle bundle = (Bundle)getFhirContext().newJsonParser().parseResource(bundleAsText);
getClient().transaction().withBundle(bundle).execute();

Parameters params = new Parameters();
params.addParameter().setName("target").setValue(new StringType("dummy"));
Expand All @@ -40,13 +37,11 @@ public void testR4LibraryDataRequirementsOperation() throws IOException {
assertNotNull(returnLibrary);
}

@Disabled("Erroring for could not load measure library")
@Test
public void testR4MeasureDataRequirementsOperation() throws IOException {
String bundleTextValueSets = stringFromResource( "Exm104Bundle.json");
FhirContext fhirContext = FhirContext.forR4();
Bundle bundleValueSet = (Bundle)fhirContext.newJsonParser().parseResource(bundleTextValueSets);
getClient().transaction().withBundle(bundleValueSet).execute();
String bundleAsText = stringFromResource( "Exm104FhirR4MeasureBundle.json");
Bundle bundle = (Bundle)getFhirContext().newJsonParser().parseResource(bundleAsText);
getClient().transaction().withBundle(bundle).execute();

Parameters params = new Parameters();
params.addParameter().setName("startPeriod").setValue(new StringType("2019-01-01"));
Expand Down
Loading