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

Refactor Measure logic into a service #648

Merged
merged 1 commit into from
Oct 27, 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
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