Skip to content

Commit

Permalink
Refactor Measure logic into a service (#648)
Browse files Browse the repository at this point in the history
  • Loading branch information
JPercival authored Oct 27, 2022
1 parent 2a2069f commit b241601
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 158 deletions.
50 changes: 32 additions & 18 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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"
38 changes: 38 additions & 0 deletions plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/CrConfig.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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<RequestDetails, org.opencds.cqf.ruler.cr.dstu3.service.MeasureService> 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<RequestDetails, org.opencds.cqf.ruler.cr.r4.service.MeasureService> 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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,26 @@
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;
import ca.uhn.fhir.rest.annotation.IdParam;
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<org.cqframework.cql.elm.execution.VersionedIdentifier, org.cqframework.cql.elm.execution.Library> globalLibraryCache;

@Autowired
private CqlOptions cqlOptions;
public class MeasureEvaluateProvider implements OperationProvider {

@Autowired
private MeasureEvaluationOptions measureEvaluationOptions;
Function<RequestDetails, MeasureService> dstu3MeasureServiceFactory;

/**
* Implements the <a href=
Expand Down Expand Up @@ -94,36 +59,19 @@ public MeasureReport evaluateMeasure(RequestDetails requestDetails, @IdParam IdT
@OperationParam(name = "additionalData") Bundle additionalData,
@OperationParam(name = "terminologyEndpoint") Endpoint terminologyEndpoint) {

Measure measure = read(theId);

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;
return this.dstu3MeasureServiceFactory
.apply(requestDetails)
.evaluateMeasure(
theId,
periodStart,
periodEnd,
reportType,
patient,
practitioner,
lastReceivedOn,
productLine,
additionalData,
terminologyEndpoint);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.opencds.cqf.ruler.cr.dstu3.service;

import java.util.Map;

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.behavior.DaoRegistryUser;
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.utility.Clients;
import org.springframework.beans.factory.annotation.Autowired;

import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.client.api.IGenericClient;

public class MeasureService implements DaoRegistryUser {

@Autowired
private JpaTerminologyProviderFactory jpaTerminologyProviderFactory;

@Autowired
private JpaDataProviderFactory jpaDataProviderFactory;

@Autowired
private DataProviderFactory dataProviderFactory;

@Autowired
private JpaLibrarySourceProviderFactory libraryContentProviderFactory;

@Autowired
private JpaFhirDalFactory fhirDalFactory;

@Autowired
private Map<org.cqframework.cql.elm.execution.VersionedIdentifier, org.cqframework.cql.elm.execution.Library> 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;
}
}
Loading

0 comments on commit b241601

Please sign in to comment.