diff --git a/docker-compose.yml b/docker-compose.yml index 48e72dc09..990d475b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,23 +1,37 @@ +version: "2.4" services: - # dqm: - # depends_on: - # - postgres - # image: alphora/cqf-ruler:testy - # ports: - # - 8080:8080 - # environment: - # - "spring.datasource.url=jdbc:postgresql://postgres:5432/postgres" - # - "spring.datasource.username=postgres" - # - "spring.datasource.password=" - # - "spring.datasource.driverClassName=org.postgresql.Driver" - # - "spring.jpa.properties.hibernate.dialect=ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect" - # - "spring.jpa.database-platform=ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect" - # - "hapi.fhir.bulk_export_enabled=false" - # - "spring.batch.job.enabled=false" - postgres: - image: postgres + image: "postgres" ports: - 5432:5432 environment: - - "POSTGRES_HOST_AUTH_METHOD=trust" + POSTGRES_HOST_AUTH_METHOD: trust + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres" ] + interval: 10s + timeout: 5s + retries: 5 + ruler: + image: "alphora/cqf-ruler:0.7.1" + depends_on: + - postgres + ports: + - "8080:8080" + healthcheck: + test: + [ + "CMD", + "curl", + "-f", + "http://localhost:8080/fhir/metadata" + ] + interval: 90s + timeout: 5s + retries: 3 + start_period: 90s + environment: + - "spring.datasource.url=jdbc:postgresql://postgres:5432/postgres" + - "spring.datasource.username=postgres" + - "spring.datasource.password=" + - "spring.datasource.driverClassName=org.postgresql.Driver" + - "spring.jpa.properties.hibernate.dialect=ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect" diff --git a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/CrConfig.java b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/CrConfig.java index 7a22ddfaa..2b5dbd02f 100644 --- a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/CrConfig.java +++ b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/CrConfig.java @@ -1,5 +1,7 @@ package org.opencds.cqf.ruler.cr; +import java.util.function.Function; + import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver; import org.opencds.cqf.cql.evaluator.measure.MeasureEvaluationOptions; import org.opencds.cqf.external.annotations.OnDSTU3Condition; @@ -10,8 +12,10 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Scope; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.api.server.RequestDetails; @Configuration @ConditionalOnProperty(prefix = "hapi.fhir.cr", name = "enabled", havingValue = "true", matchIfMissing = true) @@ -74,12 +78,46 @@ public org.opencds.cqf.ruler.cr.dstu3.provider.MeasureEvaluateProvider dstu3Meas return new org.opencds.cqf.ruler.cr.dstu3.provider.MeasureEvaluateProvider(); } + @Bean + @Conditional(OnDSTU3Condition.class) + public Function dstu3MeasureServiceFactory() { + return r -> { + var ms = dstu3measureService(); + ms.setRequestDetails(r); + return ms; + }; + } + + @Bean + @Scope("prototype") + @Conditional(OnDSTU3Condition.class) + public org.opencds.cqf.ruler.cr.dstu3.service.MeasureService dstu3measureService() { + return new org.opencds.cqf.ruler.cr.dstu3.service.MeasureService(); + } + @Bean @Conditional(OnR4Condition.class) public org.opencds.cqf.ruler.cr.r4.provider.MeasureEvaluateProvider r4MeasureEvaluateProvider() { return new org.opencds.cqf.ruler.cr.r4.provider.MeasureEvaluateProvider(); } + @Bean + @Conditional(OnR4Condition.class) + public Function r4MeasureServiceFactory() { + return r -> { + var ms = r4measureService(); + ms.setRequestDetails(r); + return ms; + }; + } + + @Bean + @Scope("prototype") + @Conditional(OnR4Condition.class) + public org.opencds.cqf.ruler.cr.r4.service.MeasureService r4measureService() { + return new org.opencds.cqf.ruler.cr.r4.service.MeasureService(); + } + @Bean @Conditional(OnDSTU3Condition.class) public org.opencds.cqf.ruler.cr.dstu3.provider.SubmitDataProvider dstu3SubmitDataProvider() { diff --git a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/dstu3/provider/MeasureEvaluateProvider.java b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/dstu3/provider/MeasureEvaluateProvider.java index 361aa835f..13f68fffc 100644 --- a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/dstu3/provider/MeasureEvaluateProvider.java +++ b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/dstu3/provider/MeasureEvaluateProvider.java @@ -1,28 +1,14 @@ package org.opencds.cqf.ruler.cr.dstu3.provider; -import java.util.Map; +import java.util.function.Function; -import org.cqframework.cql.cql2elm.LibrarySourceProvider; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Endpoint; -import org.hl7.fhir.dstu3.model.Extension; import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.Measure; import org.hl7.fhir.dstu3.model.MeasureReport; -import org.hl7.fhir.dstu3.model.StringType; -import org.opencds.cqf.cql.engine.data.DataProvider; -import org.opencds.cqf.cql.engine.fhir.terminology.Dstu3FhirTerminologyProvider; -import org.opencds.cqf.cql.engine.terminology.TerminologyProvider; -import org.opencds.cqf.cql.evaluator.CqlOptions; -import org.opencds.cqf.cql.evaluator.builder.DataProviderFactory; -import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal; -import org.opencds.cqf.cql.evaluator.measure.MeasureEvaluationOptions; -import org.opencds.cqf.ruler.cql.JpaDataProviderFactory; -import org.opencds.cqf.ruler.cql.JpaFhirDalFactory; -import org.opencds.cqf.ruler.cql.JpaLibrarySourceProviderFactory; -import org.opencds.cqf.ruler.cql.JpaTerminologyProviderFactory; -import org.opencds.cqf.ruler.provider.DaoRegistryOperationProvider; -import org.opencds.cqf.ruler.utility.Clients; +import org.opencds.cqf.ruler.api.OperationProvider; +import org.opencds.cqf.ruler.cr.dstu3.service.MeasureService; import org.springframework.beans.factory.annotation.Autowired; import ca.uhn.fhir.model.api.annotation.Description; @@ -30,32 +16,11 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.client.api.IGenericClient; -public class MeasureEvaluateProvider extends DaoRegistryOperationProvider { - @Autowired - private JpaTerminologyProviderFactory jpaTerminologyProviderFactory; - - @Autowired - private JpaDataProviderFactory jpaDataProviderFactory; - - @Autowired - private DataProviderFactory dataProviderFactory; - - @Autowired - private JpaLibrarySourceProviderFactory libraryContentProviderFactory; - - @Autowired - private JpaFhirDalFactory fhirDalFactory; - - @Autowired - private Map globalLibraryCache; - - @Autowired - private CqlOptions cqlOptions; +public class MeasureEvaluateProvider implements OperationProvider { @Autowired - private MeasureEvaluationOptions measureEvaluationOptions; + Function dstu3MeasureServiceFactory; /** * Implements the globalLibraryCache; + + @Autowired + private CqlOptions cqlOptions; + + @Autowired + private MeasureEvaluationOptions measureEvaluationOptions; + + @Autowired + private DaoRegistry daoRegistry; + + private RequestDetails requestDetails; + + public void setRequestDetails(RequestDetails requestDetails) { + this.requestDetails = requestDetails; + } + + public MeasureReport evaluateMeasure(IdType theId, + String periodStart, + String periodEnd, + String reportType, + String patient, + String practitioner, + String lastReceivedOn, + String productLine, + Bundle additionalData, + Endpoint terminologyEndpoint) { + + Measure measure = read(theId, requestDetails); + + TerminologyProvider terminologyProvider; + + if (terminologyEndpoint != null) { + IGenericClient client = Clients.forEndpoint(getFhirContext(), terminologyEndpoint); + terminologyProvider = new Dstu3FhirTerminologyProvider(client); + } else { + terminologyProvider = this.jpaTerminologyProviderFactory.create(requestDetails); + } + + DataProvider dataProvider = this.jpaDataProviderFactory.create(requestDetails, terminologyProvider); + LibrarySourceProvider 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, dataProviderFactory, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, + fhirDal, measureEvaluationOptions, cqlOptions, globalLibraryCache); + + MeasureReport report = measureProcessor.evaluateMeasure(measure.getUrl(), periodStart, periodEnd, reportType, + patient, null, lastReceivedOn, null, null, null, additionalData); + + if (productLine != null) { + Extension ext = new Extension(); + ext.setUrl("http://hl7.org/fhir/us/cqframework/cqfmeasures/StructureDefinition/cqfm-productLine"); + ext.setValue(new StringType(productLine)); + report.addExtension(ext); + } + + return report; + } + + @Override + public DaoRegistry getDaoRegistry() { + return this.daoRegistry; + } +} diff --git a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/r4/provider/MeasureEvaluateProvider.java b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/r4/provider/MeasureEvaluateProvider.java index 462e689fd..7240b258f 100644 --- a/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/r4/provider/MeasureEvaluateProvider.java +++ b/plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/r4/provider/MeasureEvaluateProvider.java @@ -1,29 +1,15 @@ package org.opencds.cqf.ruler.cr.r4.provider; -import java.util.Map; +import java.util.function.Function; -import org.cqframework.cql.cql2elm.LibrarySourceProvider; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Endpoint; -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.fhir.terminology.R4FhirTerminologyProvider; -import org.opencds.cqf.cql.engine.terminology.TerminologyProvider; -import org.opencds.cqf.cql.evaluator.CqlOptions; -import org.opencds.cqf.cql.evaluator.builder.DataProviderFactory; -import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal; -import org.opencds.cqf.cql.evaluator.measure.MeasureEvaluationOptions; import org.opencds.cqf.ruler.behavior.r4.MeasureReportUser; -import org.opencds.cqf.ruler.cql.JpaDataProviderFactory; -import org.opencds.cqf.ruler.cql.JpaFhirDalFactory; -import org.opencds.cqf.ruler.cql.JpaLibrarySourceProviderFactory; -import org.opencds.cqf.ruler.cql.JpaTerminologyProviderFactory; +import org.opencds.cqf.ruler.cr.r4.service.MeasureService; import org.opencds.cqf.ruler.provider.DaoRegistryOperationProvider; -import org.opencds.cqf.ruler.utility.Clients; import org.springframework.beans.factory.annotation.Autowired; import ca.uhn.fhir.model.api.annotation.Description; @@ -31,33 +17,12 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.client.api.IGenericClient; public class MeasureEvaluateProvider extends DaoRegistryOperationProvider implements MeasureReportUser { - @Autowired - private JpaTerminologyProviderFactory jpaTerminologyProviderFactory; - - @Autowired - private JpaDataProviderFactory jpaDataProviderFactory; - - @Autowired - private DataProviderFactory dataProviderFactory; - - @Autowired - private JpaLibrarySourceProviderFactory libraryContentProviderFactory; - - @Autowired - private JpaFhirDalFactory fhirDalFactory; - - @Autowired - private Map globalLibraryCache; - - @Autowired - private CqlOptions cqlOptions; @Autowired - private MeasureEvaluationOptions measureEvaluationOptions; + Function r4MeasureServiceFactory; /** * Implements the globalLibraryCache; + + @Autowired + private CqlOptions cqlOptions; + + @Autowired + private MeasureEvaluationOptions measureEvaluationOptions; + + @Autowired + private DaoRegistry daoRegistry; + + private RequestDetails requestDetails; + + public void setRequestDetails(RequestDetails requestDetails) { + this.requestDetails = requestDetails; + } + + public MeasureReport evaluateMeasure(IdType theId, + String periodStart, + String periodEnd, + String reportType, + String subject, + String practitioner, + String lastReceivedOn, + String productLine, + Bundle additionalData, + Endpoint terminologyEndpoint) { + + ensureSupplementalDataElementSearchParameter(requestDetails); + + Measure measure = read(theId); + + TerminologyProvider terminologyProvider; + + if (terminologyEndpoint != null) { + IGenericClient client = Clients.forEndpoint(getFhirContext(), terminologyEndpoint); + terminologyProvider = new R4FhirTerminologyProvider(client); + } else { + terminologyProvider = this.jpaTerminologyProviderFactory.create(requestDetails); + } + + DataProvider dataProvider = this.jpaDataProviderFactory.create(requestDetails, terminologyProvider); + LibrarySourceProvider 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, this.dataProviderFactory, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, + fhirDal, measureEvaluationOptions, cqlOptions, + this.globalLibraryCache); + + MeasureReport report = measureProcessor.evaluateMeasure(measure.getUrl(), periodStart, periodEnd, reportType, + subject, null, lastReceivedOn, null, null, null, additionalData); + + if (productLine != null) { + Extension ext = new Extension(); + ext.setUrl("http://hl7.org/fhir/us/cqframework/cqfmeasures/StructureDefinition/cqfm-productLine"); + ext.setValue(new StringType(productLine)); + report.addExtension(ext); + } + + return report; + } + + @Override + public DaoRegistry getDaoRegistry() { + return this.daoRegistry; + } + +}