add partition support to $evaluate-measure (#2736)
* Finished adding partition support to $evaluate-measure * review feedback
This commit is contained in:
parent
5d246bcca8
commit
097a2f70b3
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2735
|
||||
title: "The $evaluate-measure now works on a partitioned server."
|
|
@ -345,8 +345,8 @@ public class RequestPartitionHelperSvc implements IRequestPartitionHelperSvc {
|
|||
|
||||
}
|
||||
|
||||
private void validateRequestPartitionNotNull(RequestPartitionId theTheRequestPartitionId, Pointcut theThePointcut) {
|
||||
if (theTheRequestPartitionId == null) {
|
||||
private void validateRequestPartitionNotNull(RequestPartitionId theRequestPartitionId, Pointcut theThePointcut) {
|
||||
if (theRequestPartitionId == null) {
|
||||
throw new InternalErrorException("No interceptor provided a value for pointcut: " + theThePointcut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,18 +20,19 @@ package ca.uhn.fhir.cql.common.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.opencds.cqf.cql.engine.data.DataProvider;
|
||||
import org.opencds.cqf.cql.engine.terminology.TerminologyProvider;
|
||||
|
||||
// TODO: This interface is a partial duplicate of the provider factory interface
|
||||
// in the cql service layer. We need another round of refactoring to consolidate that.
|
||||
public interface EvaluationProviderFactory {
|
||||
public DataProvider createDataProvider(String model, String version);
|
||||
DataProvider createDataProvider(String model, String version, RequestDetails theRequestDetails);
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, String url, String user, String pass);
|
||||
DataProvider createDataProvider(String model, String version, String url, String user, String pass, RequestDetails theRequestDetails);
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider);
|
||||
DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider, RequestDetails theRequestDetails);
|
||||
|
||||
public TerminologyProvider createTerminologyProvider(String model, String version, String url, String user,
|
||||
String pass);
|
||||
TerminologyProvider createTerminologyProvider(String model, String version, String url, String user,
|
||||
String pass);
|
||||
}
|
||||
|
|
|
@ -20,51 +20,12 @@ package ca.uhn.fhir.cql.common.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface LibraryResolutionProvider<LibraryType> {
|
||||
public LibraryType resolveLibraryById(String libraryId);
|
||||
|
||||
public LibraryType resolveLibraryByName(String libraryName, String libraryVersion);
|
||||
|
||||
public LibraryType resolveLibraryByCanonicalUrl(String libraryUrl);
|
||||
|
||||
|
||||
// Hmmm... Probably need to think through this use case a bit more.
|
||||
// Should we throw an exception? Should this be a different interface?
|
||||
public void update(LibraryType library);
|
||||
|
||||
|
||||
// This function assumes that you're selecting from a set of libraries with the same name.
|
||||
// It returns the closest matching version, or the max version if no version is specified.
|
||||
static <LibraryType> LibraryType selectFromList(Iterable<LibraryType> libraries, String libraryVersion, Function<LibraryType, String> getVersion) {
|
||||
LibraryType library = null;
|
||||
LibraryType maxVersion = null;
|
||||
for (LibraryType l : libraries) {
|
||||
String currentVersion = getVersion.apply(l);
|
||||
if ((libraryVersion != null && currentVersion.equals(libraryVersion)) ||
|
||||
(libraryVersion == null && currentVersion == null))
|
||||
{
|
||||
library = l;
|
||||
}
|
||||
|
||||
if (maxVersion == null || compareVersions(
|
||||
getVersion.apply(maxVersion),
|
||||
getVersion.apply(l) ) < 0){
|
||||
maxVersion = l;
|
||||
}
|
||||
}
|
||||
|
||||
// If we were not given a version, return the highest found
|
||||
if (libraryVersion == null && maxVersion != null) {
|
||||
return maxVersion;
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
public static int compareVersions(String version1, String version2)
|
||||
{
|
||||
static int compareVersions(String version1, String version2) {
|
||||
// Treat null as MAX VERSION
|
||||
if (version1 == null && version2 == null) {
|
||||
return 0;
|
||||
|
@ -94,8 +55,7 @@ public interface LibraryResolutionProvider<LibraryType> {
|
|||
return 1;
|
||||
}
|
||||
//Making sure Version1 smaller than version2
|
||||
else if(v1 < v2)
|
||||
{
|
||||
else if (v1 < v2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -103,4 +63,42 @@ public interface LibraryResolutionProvider<LibraryType> {
|
|||
//Both are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
LibraryType resolveLibraryById(String libraryId, RequestDetails theRequestDetails);
|
||||
|
||||
LibraryType resolveLibraryByName(String libraryName, String libraryVersion);
|
||||
|
||||
LibraryType resolveLibraryByCanonicalUrl(String libraryUrl, RequestDetails theRequestDetails);
|
||||
|
||||
|
||||
// This function assumes that you're selecting from a set of libraries with the same name.
|
||||
// It returns the closest matching version, or the max version if no version is specified.
|
||||
static <LibraryType> LibraryType selectFromList(Iterable<LibraryType> libraries, String libraryVersion, Function<LibraryType, String> getVersion) {
|
||||
LibraryType library = null;
|
||||
LibraryType maxVersion = null;
|
||||
for (LibraryType l : libraries) {
|
||||
String currentVersion = getVersion.apply(l);
|
||||
if ((libraryVersion != null && currentVersion.equals(libraryVersion)) ||
|
||||
(libraryVersion == null && currentVersion == null)) {
|
||||
library = l;
|
||||
}
|
||||
|
||||
if (maxVersion == null || compareVersions(
|
||||
getVersion.apply(maxVersion),
|
||||
getVersion.apply(l)) < 0) {
|
||||
maxVersion = l;
|
||||
}
|
||||
}
|
||||
|
||||
// If we were not given a version, return the highest found
|
||||
if (libraryVersion == null && maxVersion != null) {
|
||||
return maxVersion;
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
// Hmmm... Probably need to think through this use case a bit more.
|
||||
// Should we throw an exception? Should this be a different interface?
|
||||
void update(LibraryType library);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.opencds.cqf.cql.engine.fhir.retrieve.SearchParamFhirRetrieveProvider;
|
||||
import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterMap;
|
||||
|
@ -45,21 +46,23 @@ import java.util.stream.Collectors;
|
|||
@Component
|
||||
public class JpaFhirRetrieveProvider extends SearchParamFhirRetrieveProvider {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JpaFhirRetrieveProvider.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(JpaFhirRetrieveProvider.class);
|
||||
|
||||
DaoRegistry registry;
|
||||
private final DaoRegistry registry;
|
||||
private final RequestDetails myRequestDetails;
|
||||
|
||||
@Autowired
|
||||
public JpaFhirRetrieveProvider(DaoRegistry registry, SearchParameterResolver searchParameterResolver) {
|
||||
super(searchParameterResolver);
|
||||
this.registry = registry;
|
||||
}
|
||||
@Autowired
|
||||
public JpaFhirRetrieveProvider(DaoRegistry registry, SearchParameterResolver searchParameterResolver, RequestDetails theRequestDetails) {
|
||||
super(searchParameterResolver);
|
||||
this.registry = registry;
|
||||
myRequestDetails = theRequestDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Object> executeQueries(String dataType, List<SearchParameterMap> queries) {
|
||||
if (queries == null || queries.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
protected Iterable<Object> executeQueries(String dataType, List<SearchParameterMap> queries) {
|
||||
if (queries == null || queries.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Object> objects = new ArrayList<>();
|
||||
for (SearchParameterMap map : queries) {
|
||||
|
@ -91,7 +94,7 @@ public class JpaFhirRetrieveProvider extends SearchParamFhirRetrieveProvider {
|
|||
|
||||
IFhirResourceDao<?> dao = this.registry.getResourceDao(dataType);
|
||||
|
||||
IBundleProvider bundleProvider = dao.search(hapiMap);
|
||||
IBundleProvider bundleProvider = dao.search(hapiMap, myRequestDetails);
|
||||
if (bundleProvider.size() == null) {
|
||||
return resolveResourceList(bundleProvider.getResources(0, 10000));
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import ca.uhn.fhir.cql.dstu3.builder.MeasureReportBuilder;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import org.cqframework.cql.elm.execution.ExpressionDef;
|
||||
import org.cqframework.cql.elm.execution.FunctionDef;
|
||||
|
@ -74,17 +75,17 @@ public class MeasureEvaluation {
|
|||
this.measurementPeriod = measurementPeriod;
|
||||
}
|
||||
|
||||
public MeasureReport evaluatePatientMeasure(Measure measure, Context context, String patientId) {
|
||||
public MeasureReport evaluatePatientMeasure(Measure measure, Context context, String patientId, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating individual report");
|
||||
|
||||
if (patientId == null) {
|
||||
return evaluatePopulationMeasure(measure, context);
|
||||
}
|
||||
return evaluatePopulationMeasure(measure, context, theRequestDetails);
|
||||
}
|
||||
|
||||
Patient patient = registry.getResourceDao(Patient.class).read(new IdType(patientId));
|
||||
// Iterable<Object> patientRetrieve = provider.retrieve("Patient", "id",
|
||||
// patientId, "Patient", null, null, null, null, null, null, null, null);
|
||||
// Patient patient = null;
|
||||
Patient patient = registry.getResourceDao(Patient.class).read(new IdType(patientId), theRequestDetails);
|
||||
// Iterable<Object> patientRetrieve = provider.retrieve("Patient", "id",
|
||||
// patientId, "Patient", null, null, null, null, null, null, null, null);
|
||||
// Patient patient = null;
|
||||
// if (patientRetrieve.iterator().hasNext()) {
|
||||
// patient = (Patient) patientRetrieve.iterator().next();
|
||||
// }
|
||||
|
@ -92,45 +93,47 @@ public class MeasureEvaluation {
|
|||
|
||||
|
||||
boolean isSingle = true;
|
||||
return evaluate(measure, context,
|
||||
|
||||
|
||||
return evaluate(measure, context,
|
||||
patient == null ? Collections.emptyList() : Collections.singletonList(patient),
|
||||
MeasureReport.MeasureReportType.INDIVIDUAL, isSingle);
|
||||
}
|
||||
|
||||
public MeasureReport evaluatePatientListMeasure(Measure measure, Context context, String practitionerRef) {
|
||||
logger.info("Generating patient-list report");
|
||||
public MeasureReport evaluatePatientListMeasure(Measure measure, Context context, String practitionerRef, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating patient-list report");
|
||||
|
||||
List<Patient> patients = practitionerRef == null ? getAllPatients() : getPractitionerPatients(practitionerRef);
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, patients, MeasureReport.MeasureReportType.PATIENTLIST, isSingle);
|
||||
}
|
||||
List<Patient> patients = practitionerRef == null ? getAllPatients(theRequestDetails) : getPractitionerPatients(practitionerRef, theRequestDetails);
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, patients, MeasureReport.MeasureReportType.PATIENTLIST, isSingle);
|
||||
}
|
||||
|
||||
private List<Patient> getPractitionerPatients(String practitionerRef) {
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add("general-practitioner", new ReferenceParam(
|
||||
practitionerRef.startsWith("Practitioner/") ? practitionerRef : "Practitioner/" + practitionerRef));
|
||||
private List<Patient> getPractitionerPatients(String practitionerRef, RequestDetails theRequestDetails) {
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add("general-practitioner", new ReferenceParam(
|
||||
practitionerRef.startsWith("Practitioner/") ? practitionerRef : "Practitioner/" + practitionerRef));
|
||||
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(map);
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(map, theRequestDetails);
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
|
||||
private List<Patient> getAllPatients() {
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(SearchParameterMap.newSynchronous());
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
private List<Patient> getAllPatients(RequestDetails theRequestDetails) {
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(SearchParameterMap.newSynchronous(), theRequestDetails);
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
|
||||
public MeasureReport evaluatePopulationMeasure(Measure measure, Context context) {
|
||||
logger.info("Generating summary report");
|
||||
public MeasureReport evaluatePopulationMeasure(Measure measure, Context context, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating summary report");
|
||||
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, getAllPatients(), MeasureReport.MeasureReportType.SUMMARY, isSingle);
|
||||
}
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, getAllPatients(theRequestDetails), MeasureReport.MeasureReportType.SUMMARY, isSingle);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void clearExpressionCache(Context context) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.cql.common.helper.UsingHelper;
|
|||
import ca.uhn.fhir.cql.common.provider.EvaluationProviderFactory;
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.cql.dstu3.helper.LibraryHelper;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.cqframework.cql.elm.execution.Library;
|
||||
import org.hl7.fhir.dstu3.model.Measure;
|
||||
|
@ -74,13 +75,13 @@ public class MeasureEvaluationSeed {
|
|||
}
|
||||
|
||||
public void setup(Measure measure, String periodStart, String periodEnd, String productLine, String source,
|
||||
String user, String pass) {
|
||||
String user, String pass, RequestDetails theRequestDetails) {
|
||||
this.measure = measure;
|
||||
|
||||
this.libraryHelper.loadLibraries(measure, this.libraryLoader, this.libraryResourceProvider);
|
||||
this.libraryHelper.loadLibraries(measure, this.libraryLoader, this.libraryResourceProvider, theRequestDetails);
|
||||
|
||||
// resolve primary library
|
||||
Library library = this.libraryHelper.resolvePrimaryLibrary(measure, libraryLoader, this.libraryResourceProvider);
|
||||
Library library = this.libraryHelper.resolvePrimaryLibrary(measure, libraryLoader, this.libraryResourceProvider, theRequestDetails);
|
||||
|
||||
// resolve execution context
|
||||
context = new Context(library);
|
||||
|
@ -90,7 +91,7 @@ public class MeasureEvaluationSeed {
|
|||
|
||||
if (usingDefs.size() > 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Evaluation of Measure using multiple Models is not supported at this time.");
|
||||
"Evaluation of Measure using multiple Models is not supported at this time.");
|
||||
}
|
||||
|
||||
// If there are no Usings, there is probably not any place the Terminology
|
||||
|
@ -108,7 +109,7 @@ public class MeasureEvaluationSeed {
|
|||
|
||||
for (Triple<String, String, String> def : usingDefs) {
|
||||
this.dataProvider = this.providerFactory.createDataProvider(def.getLeft(), def.getMiddle(),
|
||||
terminologyProvider);
|
||||
terminologyProvider, theRequestDetails);
|
||||
context.registerDataProvider(def.getRight(), dataProvider);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.cql.common.provider.EvaluationProviderFactory;
|
||||
import ca.uhn.fhir.cql.common.retrieve.JpaFhirRetrieveProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.opencds.cqf.cql.engine.data.CompositeDataProvider;
|
||||
import org.opencds.cqf.cql.engine.data.DataProvider;
|
||||
import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver;
|
||||
|
@ -38,40 +39,40 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class ProviderFactory implements EvaluationProviderFactory {
|
||||
|
||||
DaoRegistry registry;
|
||||
TerminologyProvider defaultTerminologyProvider;
|
||||
FhirContext fhirContext;
|
||||
ModelResolver fhirModelResolver;
|
||||
private final DaoRegistry registry;
|
||||
private final TerminologyProvider defaultTerminologyProvider;
|
||||
private final FhirContext fhirContext;
|
||||
private final ModelResolver fhirModelResolver;
|
||||
|
||||
@Autowired
|
||||
public ProviderFactory(FhirContext fhirContext, DaoRegistry registry,
|
||||
TerminologyProvider defaultTerminologyProvider, ModelResolver fhirModelResolver) {
|
||||
this.defaultTerminologyProvider = defaultTerminologyProvider;
|
||||
this.registry = registry;
|
||||
this.fhirContext = fhirContext;
|
||||
this.fhirModelResolver = fhirModelResolver;
|
||||
TerminologyProvider defaultTerminologyProvider, ModelResolver fhirModelResolver) {
|
||||
this.defaultTerminologyProvider = defaultTerminologyProvider;
|
||||
this.registry = registry;
|
||||
this.fhirContext = fhirContext;
|
||||
this.fhirModelResolver = fhirModelResolver;
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version) {
|
||||
return this.createDataProvider(model, version, null, null, null);
|
||||
}
|
||||
public DataProvider createDataProvider(String model, String version, RequestDetails theRequestDetails) {
|
||||
return this.createDataProvider(model, version, null, null, null, theRequestDetails);
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, String url, String user, String pass) {
|
||||
TerminologyProvider terminologyProvider = this.createTerminologyProvider(model, version, url, user, pass);
|
||||
return this.createDataProvider(model, version, terminologyProvider);
|
||||
}
|
||||
public DataProvider createDataProvider(String model, String version, String url, String user, String pass, RequestDetails theRequestDetails) {
|
||||
TerminologyProvider terminologyProvider = this.createTerminologyProvider(model, version, url, user, pass);
|
||||
return this.createDataProvider(model, version, terminologyProvider, theRequestDetails);
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider) {
|
||||
if (model.equals("FHIR") && version.startsWith("3")) {
|
||||
JpaFhirRetrieveProvider retrieveProvider = new JpaFhirRetrieveProvider(this.registry,
|
||||
new SearchParameterResolver(this.fhirContext));
|
||||
retrieveProvider.setTerminologyProvider(terminologyProvider);
|
||||
retrieveProvider.setExpandValueSets(true);
|
||||
public DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider, RequestDetails theRequestDetails) {
|
||||
if (model.equals("FHIR") && version.startsWith("3")) {
|
||||
JpaFhirRetrieveProvider retrieveProvider = new JpaFhirRetrieveProvider(this.registry,
|
||||
new SearchParameterResolver(this.fhirContext), theRequestDetails);
|
||||
retrieveProvider.setTerminologyProvider(terminologyProvider);
|
||||
retrieveProvider.setExpandValueSets(true);
|
||||
|
||||
return new CompositeDataProvider(this.fhirModelResolver, retrieveProvider);
|
||||
}
|
||||
return new CompositeDataProvider(this.fhirModelResolver, retrieveProvider);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Can't construct a data provider for model %s version %s", model, version));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,10 @@ package ca.uhn.fhir.cql.dstu3.helper;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cqframework.cql.cql2elm.LibraryManager;
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryContentProvider;
|
||||
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cqframework.cql.cql2elm.CqlTranslatorOptions;
|
||||
import org.cqframework.cql.cql2elm.ModelManager;
|
||||
import org.cqframework.cql.cql2elm.model.Model;
|
||||
|
@ -36,11 +35,12 @@ import org.hl7.fhir.dstu3.model.Measure;
|
|||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.hl7.fhir.dstu3.model.RelatedArtifact;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.opencds.cqf.cql.engine.execution.LibraryLoader;
|
||||
import org.opencds.cqf.cql.evaluator.cql2elm.model.CacheAwareModelManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.opencds.cqf.cql.evaluator.engine.execution.CacheAwareLibraryLoaderDecorator;
|
||||
import org.opencds.cqf.cql.evaluator.engine.execution.TranslatingLibraryLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -51,8 +51,8 @@ public class LibraryHelper {
|
|||
private static final Logger ourLog = LoggerFactory.getLogger(LibraryHelper.class);
|
||||
|
||||
private final Map<org.hl7.elm.r1.VersionedIdentifier, Model> modelCache;
|
||||
private Map<VersionedIdentifier, Library> libraryCache;
|
||||
private CqlTranslatorOptions translatorOptions;
|
||||
private final Map<VersionedIdentifier, Library> libraryCache;
|
||||
private final CqlTranslatorOptions translatorOptions;
|
||||
|
||||
|
||||
public LibraryHelper(Map<org.hl7.elm.r1.VersionedIdentifier, Model> modelCache, Map<VersionedIdentifier, Library> libraryCache, CqlTranslatorOptions translatorOptions) {
|
||||
|
@ -72,8 +72,8 @@ public class LibraryHelper {
|
|||
}
|
||||
|
||||
public List<Library> loadLibraries(Measure measure,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
List<org.cqframework.cql.elm.execution.Library> libraries = new ArrayList<Library>();
|
||||
List<String> messages = new ArrayList<>();
|
||||
|
||||
|
@ -96,7 +96,7 @@ public class LibraryHelper {
|
|||
id = id.substring(1);
|
||||
}
|
||||
|
||||
org.hl7.fhir.dstu3.model.Library library = libraryResourceProvider.resolveLibraryById(id);
|
||||
org.hl7.fhir.dstu3.model.Library library = libraryResourceProvider.resolveLibraryById(id, theRequestDetails);
|
||||
if (library != null) {
|
||||
if (isLogicLibrary(library)) {
|
||||
libraries.add(libraryLoader
|
||||
|
@ -119,11 +119,11 @@ public class LibraryHelper {
|
|||
for (RelatedArtifact artifact : primaryLibrary.getRelatedArtifact()) {
|
||||
if (artifact.hasType() && artifact.getType().equals(RelatedArtifact.RelatedArtifactType.DEPENDSON) && artifact.hasResource() && artifact.getResource().hasReference()) {
|
||||
if (artifact.getResource().getReferenceElement().getResourceType().equals("Library")) {
|
||||
org.hl7.fhir.dstu3.model.Library library = libraryResourceProvider.resolveLibraryById(artifact.getResource().getReferenceElement().getIdPart());
|
||||
org.hl7.fhir.dstu3.model.Library library = libraryResourceProvider.resolveLibraryById(artifact.getResource().getReferenceElement().getIdPart(), theRequestDetails);
|
||||
if (library != null) {
|
||||
if (isLogicLibrary(library)) {
|
||||
libraries.add(libraryLoader
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
} else {
|
||||
ourLog.warn("Library {} not included as part of evaluation context. Only Libraries with the 'logic-library' type are included.", library.getId());
|
||||
}
|
||||
|
@ -169,22 +169,22 @@ public class LibraryHelper {
|
|||
}
|
||||
|
||||
public Library resolveLibraryById(String libraryId,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
// Library library = null;
|
||||
|
||||
org.hl7.fhir.dstu3.model.Library fhirLibrary = libraryResourceProvider.resolveLibraryById(libraryId);
|
||||
org.hl7.fhir.dstu3.model.Library fhirLibrary = libraryResourceProvider.resolveLibraryById(libraryId, theRequestDetails);
|
||||
return libraryLoader
|
||||
.load(new VersionedIdentifier().withId(fhirLibrary.getName()).withVersion(fhirLibrary.getVersion()));
|
||||
}
|
||||
|
||||
public Library resolvePrimaryLibrary(Measure measure,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.dstu3.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
// default is the first library reference
|
||||
String id = measure.getLibraryFirstRep().getReferenceElement().getIdPart();
|
||||
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider);
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider, theRequestDetails);
|
||||
|
||||
if (library == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve primary library for Measure/%s.",
|
||||
|
|
|
@ -22,7 +22,9 @@ package ca.uhn.fhir.cql.dstu3.provider;
|
|||
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
|
@ -48,16 +50,16 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
}
|
||||
|
||||
@Override
|
||||
public Library resolveLibraryById(String libraryId) {
|
||||
public Library resolveLibraryById(String libraryId, RequestDetails theRequestDetails) {
|
||||
try {
|
||||
return myLibraryDao.read(new IdType(libraryId));
|
||||
return myLibraryDao.read(new IdType(libraryId), theRequestDetails);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve library id %s", libraryId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Library resolveLibraryByCanonicalUrl(String url) {
|
||||
public Library resolveLibraryByCanonicalUrl(String url, RequestDetails theRequestDetails) {
|
||||
Objects.requireNonNull(url, "url must not be null");
|
||||
|
||||
String[] parts = url.split("\\|");
|
||||
|
@ -73,7 +75,7 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
map.add("version", new TokenParam(version));
|
||||
}
|
||||
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map);
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map, theRequestDetails);
|
||||
|
||||
if (bundleProvider.size() == null || bundleProvider.size() == 0) {
|
||||
return null;
|
||||
|
@ -99,7 +101,7 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
// Search for libraries by name
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add("name", new StringParam(name, true));
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map);
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map, new SystemRequestDetails());
|
||||
|
||||
if (bundleProvider.size() == null || bundleProvider.size() == 0) {
|
||||
return new ArrayList<>();
|
||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
|||
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.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
|
@ -81,17 +82,18 @@ public class MeasureOperationsProvider {
|
|||
@OperationParam(name = "lastReceivedOn") String lastReceivedOn,
|
||||
@OperationParam(name = "source") String source,
|
||||
@OperationParam(name = "user") String user,
|
||||
@OperationParam(name = "pass") String pass) throws InternalErrorException, FHIRException {
|
||||
@OperationParam(name = "pass") String pass,
|
||||
RequestDetails theRequestDetails) throws InternalErrorException, FHIRException {
|
||||
LibraryLoader libraryLoader = this.libraryHelper.createLibraryLoader(this.libraryResolutionProvider);
|
||||
MeasureEvaluationSeed seed = new MeasureEvaluationSeed(this.factory, libraryLoader,
|
||||
this.libraryResolutionProvider, this.libraryHelper);
|
||||
Measure measure = myMeasureDao.read(theId);
|
||||
Measure measure = myMeasureDao.read(theId, theRequestDetails);
|
||||
|
||||
if (measure == null) {
|
||||
throw new RuntimeException("Could not find Measure/" + theId.getIdPart());
|
||||
}
|
||||
|
||||
seed.setup(measure, periodStart, periodEnd, productLine, source, user, pass);
|
||||
seed.setup(measure, periodStart, periodEnd, productLine, source, user, pass, theRequestDetails);
|
||||
|
||||
// resolve report type
|
||||
MeasureEvaluation evaluator = new MeasureEvaluation(this.registry,
|
||||
|
@ -99,18 +101,18 @@ public class MeasureOperationsProvider {
|
|||
if (reportType != null) {
|
||||
switch (reportType) {
|
||||
case "patient":
|
||||
return evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef);
|
||||
return evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef, theRequestDetails);
|
||||
case "patient-list":
|
||||
return evaluator.evaluatePatientListMeasure(seed.getMeasure(), seed.getContext(), practitionerRef);
|
||||
return evaluator.evaluatePatientListMeasure(seed.getMeasure(), seed.getContext(), practitionerRef, theRequestDetails);
|
||||
case "population":
|
||||
return evaluator.evaluatePopulationMeasure(seed.getMeasure(), seed.getContext());
|
||||
return evaluator.evaluatePopulationMeasure(seed.getMeasure(), seed.getContext(), theRequestDetails);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid report type: " + reportType);
|
||||
}
|
||||
}
|
||||
|
||||
// default report type is patient
|
||||
MeasureReport report = evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef);
|
||||
MeasureReport report = evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef, theRequestDetails);
|
||||
if (productLine != null) {
|
||||
Extension ext = new Extension();
|
||||
ext.setUrl("http://hl7.org/fhir/us/cqframework/cqfmeasures/StructureDefinition/cqfm-productLine");
|
||||
|
|
|
@ -26,6 +26,7 @@ import ca.uhn.fhir.cql.r4.builder.MeasureReportBuilder;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import org.cqframework.cql.elm.execution.ExpressionDef;
|
||||
import org.cqframework.cql.elm.execution.FunctionDef;
|
||||
|
@ -77,15 +78,15 @@ public class MeasureEvaluation {
|
|||
this.measurementPeriod = measurementPeriod;
|
||||
}
|
||||
|
||||
public MeasureReport evaluatePatientMeasure(Measure measure, Context context, String patientId) {
|
||||
public MeasureReport evaluatePatientMeasure(Measure measure, Context context, String patientId, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating individual report");
|
||||
|
||||
if (patientId == null) {
|
||||
return evaluatePopulationMeasure(measure, context);
|
||||
return evaluatePopulationMeasure(measure, context, theRequestDetails);
|
||||
}
|
||||
|
||||
Iterable<Object> patientRetrieve = provider.retrieve("Patient", "id", patientId, "Patient", null, null, null,
|
||||
null, null, null, null, null);
|
||||
null, null, null, null, null);
|
||||
Patient patient = null;
|
||||
if (patientRetrieve.iterator().hasNext()) {
|
||||
patient = (Patient) patientRetrieve.iterator().next();
|
||||
|
@ -93,42 +94,42 @@ public class MeasureEvaluation {
|
|||
|
||||
boolean isSingle = true;
|
||||
return evaluate(measure, context, patient == null ? Collections.emptyList() : Collections.singletonList(patient),
|
||||
MeasureReport.MeasureReportType.INDIVIDUAL, isSingle);
|
||||
MeasureReport.MeasureReportType.INDIVIDUAL, isSingle);
|
||||
}
|
||||
|
||||
public MeasureReport evaluateSubjectListMeasure(Measure measure, Context context, String practitionerRef) {
|
||||
public MeasureReport evaluateSubjectListMeasure(Measure measure, Context context, String practitionerRef, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating patient-list report");
|
||||
|
||||
List<Patient> patients = practitionerRef == null ? getAllPatients() : getPractitionerPatients(practitionerRef);
|
||||
List<Patient> patients = practitionerRef == null ? getAllPatients(theRequestDetails) : getPractitionerPatients(practitionerRef, theRequestDetails);
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, patients, MeasureReport.MeasureReportType.SUBJECTLIST, isSingle);
|
||||
}
|
||||
|
||||
private List<Patient> getPractitionerPatients(String practitionerRef) {
|
||||
private List<Patient> getPractitionerPatients(String practitionerRef, RequestDetails theRequestDetails) {
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add("general-practitioner", new ReferenceParam(
|
||||
practitionerRef.startsWith("Practitioner/") ? practitionerRef : "Practitioner/" + practitionerRef));
|
||||
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(map);
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(map, theRequestDetails);
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
|
||||
private List<Patient> getAllPatients() {
|
||||
private List<Patient> getAllPatients(RequestDetails theRequestDetails) {
|
||||
List<Patient> patients = new ArrayList<>();
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(SearchParameterMap.newSynchronous());
|
||||
IBundleProvider patientProvider = registry.getResourceDao("Patient").search(SearchParameterMap.newSynchronous(), theRequestDetails);
|
||||
List<IBaseResource> patientList = patientProvider.getAllResources();
|
||||
patientList.forEach(x -> patients.add((Patient) x));
|
||||
return patients;
|
||||
}
|
||||
|
||||
public MeasureReport evaluatePopulationMeasure(Measure measure, Context context) {
|
||||
public MeasureReport evaluatePopulationMeasure(Measure measure, Context context, RequestDetails theRequestDetails) {
|
||||
logger.info("Generating summary report");
|
||||
|
||||
boolean isSingle = false;
|
||||
return evaluate(measure, context, getAllPatients(), MeasureReport.MeasureReportType.SUMMARY, isSingle);
|
||||
return evaluate(measure, context, getAllPatients(theRequestDetails), MeasureReport.MeasureReportType.SUMMARY, isSingle);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.cql.common.helper.UsingHelper;
|
|||
import ca.uhn.fhir.cql.common.provider.EvaluationProviderFactory;
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.cql.r4.helper.LibraryHelper;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.cqframework.cql.elm.execution.Library;
|
||||
import org.hl7.fhir.r4.model.Measure;
|
||||
|
@ -74,13 +75,13 @@ public class MeasureEvaluationSeed {
|
|||
}
|
||||
|
||||
public void setup(Measure measure, String periodStart, String periodEnd, String productLine, String source,
|
||||
String user, String pass) {
|
||||
String user, String pass, RequestDetails theRequestDetails) {
|
||||
this.measure = measure;
|
||||
|
||||
this.libraryHelper.loadLibraries(measure, this.libraryLoader, this.libraryResourceProvider);
|
||||
this.libraryHelper.loadLibraries(measure, this.libraryLoader, this.libraryResourceProvider, theRequestDetails);
|
||||
|
||||
// resolve primary library
|
||||
Library library = this.libraryHelper.resolvePrimaryLibrary(measure, libraryLoader, this.libraryResourceProvider);
|
||||
Library library = this.libraryHelper.resolvePrimaryLibrary(measure, libraryLoader, this.libraryResourceProvider, theRequestDetails);
|
||||
|
||||
|
||||
// resolve execution context
|
||||
|
@ -109,7 +110,7 @@ public class MeasureEvaluationSeed {
|
|||
|
||||
for (Triple<String, String, String> def : usingDefs) {
|
||||
this.dataProvider = this.providerFactory.createDataProvider(def.getLeft(), def.getMiddle(),
|
||||
terminologyProvider);
|
||||
terminologyProvider, theRequestDetails);
|
||||
context.registerDataProvider(def.getRight(), dataProvider);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.cql.common.provider.EvaluationProviderFactory;
|
||||
import ca.uhn.fhir.cql.common.retrieve.JpaFhirRetrieveProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.opencds.cqf.cql.engine.data.CompositeDataProvider;
|
||||
import org.opencds.cqf.cql.engine.data.DataProvider;
|
||||
import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver;
|
||||
|
@ -51,19 +52,19 @@ public class ProviderFactory implements EvaluationProviderFactory {
|
|||
myModelResolver = theFhirModelResolver;
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version) {
|
||||
return this.createDataProvider(model, version, null, null, null);
|
||||
public DataProvider createDataProvider(String model, String version, RequestDetails theRequestDetails) {
|
||||
return this.createDataProvider(model, version, null, null, null, theRequestDetails);
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, String url, String user, String pass) {
|
||||
public DataProvider createDataProvider(String model, String version, String url, String user, String pass, RequestDetails theRequestDetails) {
|
||||
TerminologyProvider terminologyProvider = this.createTerminologyProvider(model, version, url, user, pass);
|
||||
return this.createDataProvider(model, version, terminologyProvider);
|
||||
return this.createDataProvider(model, version, terminologyProvider, theRequestDetails);
|
||||
}
|
||||
|
||||
public DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider) {
|
||||
public DataProvider createDataProvider(String model, String version, TerminologyProvider terminologyProvider, RequestDetails theRequestDetails) {
|
||||
if (model.equals("FHIR") && version.startsWith("4")) {
|
||||
JpaFhirRetrieveProvider retrieveProvider = new JpaFhirRetrieveProvider(myDaoRegistry,
|
||||
new SearchParameterResolver(myFhirContext));
|
||||
new SearchParameterResolver(myFhirContext), theRequestDetails);
|
||||
retrieveProvider.setTerminologyProvider(terminologyProvider);
|
||||
retrieveProvider.setExpandValueSets(true);
|
||||
|
||||
|
|
|
@ -20,10 +20,9 @@ package ca.uhn.fhir.cql.r4.helper;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryContentProvider;
|
||||
|
||||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.cqframework.cql.cql2elm.CqlTranslatorOptions;
|
||||
import org.cqframework.cql.cql2elm.LibraryManager;
|
||||
import org.cqframework.cql.cql2elm.ModelManager;
|
||||
|
@ -37,11 +36,13 @@ import org.hl7.fhir.r4.model.Measure;
|
|||
import org.hl7.fhir.r4.model.PlanDefinition;
|
||||
import org.hl7.fhir.r4.model.RelatedArtifact;
|
||||
import org.hl7.fhir.r4.model.Resource;
|
||||
import org.opencds.cqf.cql.engine.execution.LibraryLoader;
|
||||
import org.opencds.cqf.cql.evaluator.cql2elm.model.CacheAwareModelManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.opencds.cqf.cql.evaluator.engine.execution.CacheAwareLibraryLoaderDecorator;
|
||||
import org.opencds.cqf.cql.evaluator.engine.execution.TranslatingLibraryLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -54,18 +55,18 @@ public class LibraryHelper {
|
|||
private static final Logger ourLog = LoggerFactory.getLogger(LibraryHelper.class);
|
||||
|
||||
private final Map<org.hl7.elm.r1.VersionedIdentifier, Model> modelCache;
|
||||
private Map<VersionedIdentifier, Library> libraryCache;
|
||||
private CqlTranslatorOptions translatorOptions;
|
||||
private final Map<VersionedIdentifier, Library> libraryCache;
|
||||
private final CqlTranslatorOptions translatorOptions;
|
||||
|
||||
public LibraryHelper(Map<org.hl7.elm.r1.VersionedIdentifier, Model> modelCache,
|
||||
Map<VersionedIdentifier, Library> libraryCache, CqlTranslatorOptions translatorOptions) {
|
||||
Map<VersionedIdentifier, Library> libraryCache, CqlTranslatorOptions translatorOptions) {
|
||||
this.modelCache = modelCache;
|
||||
this.libraryCache = libraryCache;
|
||||
this.translatorOptions = translatorOptions;
|
||||
}
|
||||
|
||||
public org.opencds.cqf.cql.engine.execution.LibraryLoader createLibraryLoader(
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> provider) {
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> provider) {
|
||||
ModelManager modelManager = new CacheAwareModelManager(this.modelCache);
|
||||
LibraryManager libraryManager = new LibraryManager(modelManager);
|
||||
libraryManager.getLibrarySourceLoader().clearProviders();
|
||||
|
@ -90,22 +91,22 @@ public class LibraryHelper {
|
|||
}
|
||||
|
||||
public org.hl7.fhir.r4.model.Library resolveLibraryReference(
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, String reference) {
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, String reference, RequestDetails theRequestDetails) {
|
||||
// Raw references to Library/libraryId or libraryId
|
||||
if (reference.startsWith("Library/") || !reference.contains("/")) {
|
||||
return libraryResourceProvider.resolveLibraryById(reference.replace("Library/", ""));
|
||||
return libraryResourceProvider.resolveLibraryById(reference.replace("Library/", ""), theRequestDetails);
|
||||
}
|
||||
// Full url (e.g. http://hl7.org/fhir/us/Library/FHIRHelpers)
|
||||
else if (reference.contains(("/Library/"))) {
|
||||
return libraryResourceProvider.resolveLibraryByCanonicalUrl(reference);
|
||||
return libraryResourceProvider.resolveLibraryByCanonicalUrl(reference, theRequestDetails);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<org.cqframework.cql.elm.execution.Library> loadLibraries(Measure measure,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
List<org.cqframework.cql.elm.execution.Library> libraries = new ArrayList<org.cqframework.cql.elm.execution.Library>();
|
||||
|
||||
// load libraries
|
||||
|
@ -118,21 +119,21 @@ public class LibraryHelper {
|
|||
id = id.substring(1);
|
||||
for (Resource resource : measure.getContained()) {
|
||||
if (resource instanceof org.hl7.fhir.r4.model.Library
|
||||
&& resource.getIdElement().getIdPart().equals(id)) {
|
||||
&& resource.getIdElement().getIdPart().equals(id)) {
|
||||
libraryResourceProvider.update((org.hl7.fhir.r4.model.Library) resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We just loaded it into the server so we can access it by Id
|
||||
org.hl7.fhir.r4.model.Library library = resolveLibraryReference(libraryResourceProvider, id);
|
||||
org.hl7.fhir.r4.model.Library library = resolveLibraryReference(libraryResourceProvider, id, theRequestDetails);
|
||||
if (primaryLibrary == null) {
|
||||
primaryLibrary = library;
|
||||
}
|
||||
|
||||
if (library != null && isLogicLibrary(library)) {
|
||||
libraries.add(libraryLoader
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,12 +146,12 @@ public class LibraryHelper {
|
|||
if (artifact.hasType() && artifact.getType().equals(RelatedArtifact.RelatedArtifactType.DEPENDSON)
|
||||
&& artifact.hasResource()) {
|
||||
org.hl7.fhir.r4.model.Library library = null;
|
||||
library = resolveLibraryReference(libraryResourceProvider, artifact.getResource());
|
||||
library = resolveLibraryReference(libraryResourceProvider, artifact.getResource(), theRequestDetails);
|
||||
|
||||
if (library != null) {
|
||||
if (isLogicLibrary(library)) {
|
||||
libraries.add(libraryLoader
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion())));
|
||||
} else {
|
||||
ourLog.warn("Library {} not included as part of evaluation context. Only Libraries with the 'logic-library' type are included.", library.getId());
|
||||
}
|
||||
|
@ -187,7 +188,7 @@ public class LibraryHelper {
|
|||
|
||||
for (Coding c : library.getType().getCoding()) {
|
||||
if (c.hasSystem() && c.getSystem().equals("http://terminology.hl7.org/CodeSystem/library-type") && c.hasCode()
|
||||
&& c.getCode().equals("logic-library")) {
|
||||
&& c.getCode().equals("logic-library")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -195,40 +196,40 @@ public class LibraryHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Library resolveLibraryById(String libraryId, org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider) {
|
||||
public Library resolveLibraryById(String libraryId, LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
|
||||
org.hl7.fhir.r4.model.Library fhirLibrary = libraryResourceProvider.resolveLibraryById(libraryId);
|
||||
org.hl7.fhir.r4.model.Library fhirLibrary = libraryResourceProvider.resolveLibraryById(libraryId, theRequestDetails);
|
||||
return libraryLoader
|
||||
.load(new VersionedIdentifier().withId(fhirLibrary.getName()).withVersion(fhirLibrary.getVersion()));
|
||||
.load(new VersionedIdentifier().withId(fhirLibrary.getName()).withVersion(fhirLibrary.getVersion()));
|
||||
}
|
||||
|
||||
public Library resolvePrimaryLibrary(Measure measure,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
// default is the first library reference
|
||||
String id = CanonicalHelper.getId(measure.getLibrary().get(0));
|
||||
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider);
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider, theRequestDetails);
|
||||
|
||||
if (library == null) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Could not resolve primary library for Measure/%s.", measure.getIdElement().getIdPart()));
|
||||
String.format("Could not resolve primary library for Measure/%s.", measure.getIdElement().getIdPart()));
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
public Library resolvePrimaryLibrary(PlanDefinition planDefinition,
|
||||
org.opencds.cqf.cql.engine.execution.LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider) {
|
||||
LibraryLoader libraryLoader,
|
||||
LibraryResolutionProvider<org.hl7.fhir.r4.model.Library> libraryResourceProvider, RequestDetails theRequestDetails) {
|
||||
String id = CanonicalHelper.getId(planDefinition.getLibrary().get(0));
|
||||
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider);
|
||||
Library library = resolveLibraryById(id, libraryLoader, libraryResourceProvider, theRequestDetails);
|
||||
|
||||
if (library == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve primary library for PlanDefinition/%s",
|
||||
planDefinition.getIdElement().getIdPart()));
|
||||
planDefinition.getIdElement().getIdPart()));
|
||||
}
|
||||
|
||||
return library;
|
||||
|
|
|
@ -23,7 +23,9 @@ package ca.uhn.fhir.cql.r4.provider;
|
|||
import ca.uhn.fhir.cql.common.provider.LibraryResolutionProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
|
@ -54,9 +56,9 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
}
|
||||
|
||||
@Override
|
||||
public Library resolveLibraryById(String libraryId) {
|
||||
public Library resolveLibraryById(String libraryId, RequestDetails theRequestDetails) {
|
||||
try {
|
||||
return myLibraryDao.read(new IdType(libraryId));
|
||||
return myLibraryDao.read(new IdType(libraryId), theRequestDetails);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve library id %s", libraryId));
|
||||
}
|
||||
|
@ -64,7 +66,7 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
|
||||
@Override
|
||||
public Library resolveLibraryByName(String libraryName, String libraryVersion) {
|
||||
Iterable<org.hl7.fhir.r4.model.Library> libraries = getLibrariesByName(libraryName);
|
||||
Iterable<org.hl7.fhir.r4.model.Library> libraries = getLibrariesByName(libraryName, new SystemRequestDetails());
|
||||
org.hl7.fhir.r4.model.Library library = LibraryResolutionProvider.selectFromList(libraries, libraryVersion,
|
||||
x -> x.getVersion());
|
||||
|
||||
|
@ -76,7 +78,7 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
}
|
||||
|
||||
@Override
|
||||
public Library resolveLibraryByCanonicalUrl(String url) {
|
||||
public Library resolveLibraryByCanonicalUrl(String url, RequestDetails theRequestDetails) {
|
||||
Objects.requireNonNull(url, "url must not be null");
|
||||
|
||||
String[] parts = url.split("\\|");
|
||||
|
@ -92,7 +94,7 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
map.add("version", new TokenParam(version));
|
||||
}
|
||||
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map);
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map, theRequestDetails);
|
||||
|
||||
if (bundleProvider.size() == null || bundleProvider.size() == 0) {
|
||||
return null;
|
||||
|
@ -101,11 +103,11 @@ public class LibraryResolutionProviderImpl implements LibraryResolutionProvider<
|
|||
return LibraryResolutionProvider.selectFromList(resolveLibraries(resourceList), version, x -> x.getVersion());
|
||||
}
|
||||
|
||||
private Iterable<org.hl7.fhir.r4.model.Library> getLibrariesByName(String name) {
|
||||
private Iterable<org.hl7.fhir.r4.model.Library> getLibrariesByName(String name, RequestDetails theRequestDetails) {
|
||||
// Search for libraries by name
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add("name", new StringParam(name, true));
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map);
|
||||
ca.uhn.fhir.rest.api.server.IBundleProvider bundleProvider = myLibraryDao.search(map, theRequestDetails);
|
||||
|
||||
if (bundleProvider.size() == null || bundleProvider.size() == 0) {
|
||||
return new ArrayList<>();
|
||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
|||
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.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -82,36 +83,38 @@ public class MeasureOperationsProvider {
|
|||
@OperationParam(name = "lastReceivedOn") String lastReceivedOn,
|
||||
@OperationParam(name = "source") String source,
|
||||
@OperationParam(name = "user") String user,
|
||||
@OperationParam(name = "pass") String pass) throws InternalErrorException, FHIRException {
|
||||
@OperationParam(name = "pass") String pass,
|
||||
RequestDetails theRequestDetails) throws InternalErrorException, FHIRException {
|
||||
LibraryLoader libraryLoader = this.libraryHelper.createLibraryLoader(this.libraryResolutionProvider);
|
||||
|
||||
MeasureEvaluationSeed seed = new MeasureEvaluationSeed(this.factory, libraryLoader,
|
||||
this.libraryResolutionProvider, this.libraryHelper);
|
||||
Measure measure = myMeasureDao.read(theId);
|
||||
this.libraryResolutionProvider, this.libraryHelper);
|
||||
Measure measure = myMeasureDao.read(theId, theRequestDetails);
|
||||
|
||||
if (measure == null) {
|
||||
throw new RuntimeException("Could not find Measure/" + theId.getIdPart());
|
||||
}
|
||||
|
||||
seed.setup(measure, periodStart, periodEnd, productLine, source, user, pass);
|
||||
seed.setup(measure, periodStart, periodEnd, productLine, source, user, pass, theRequestDetails);
|
||||
|
||||
// resolve report type
|
||||
MeasureEvaluation evaluator = new MeasureEvaluation(seed.getDataProvider(), this.registry,
|
||||
seed.getMeasurementPeriod());
|
||||
seed.getMeasurementPeriod());
|
||||
if (reportType != null) {
|
||||
switch (reportType) {
|
||||
case "patient":
|
||||
return evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef);
|
||||
return evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef, theRequestDetails);
|
||||
case "patient-list":
|
||||
return evaluator.evaluateSubjectListMeasure(seed.getMeasure(), seed.getContext(), practitionerRef);
|
||||
return evaluator.evaluateSubjectListMeasure(seed.getMeasure(), seed.getContext(), practitionerRef, theRequestDetails);
|
||||
case "population":
|
||||
return evaluator.evaluatePopulationMeasure(seed.getMeasure(), seed.getContext());
|
||||
return evaluator.evaluatePopulationMeasure(seed.getMeasure(), seed.getContext(), theRequestDetails);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid report type: " + reportType);
|
||||
}
|
||||
}
|
||||
|
||||
// default report type is patient
|
||||
MeasureReport report = evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef);
|
||||
MeasureReport report = evaluator.evaluatePatientMeasure(seed.getMeasure(), seed.getContext(), patientRef, theRequestDetails);
|
||||
if (productLine != null) {
|
||||
Extension ext = new Extension();
|
||||
ext.setUrl("http://hl7.org/fhir/us/cqframework/cqfmeasures/StructureDefinition/cqfm-productLine");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.cql;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.cql.common.helper.PartitionHelper;
|
||||
import ca.uhn.fhir.cql.common.provider.CqlProviderTestBase;
|
||||
import ca.uhn.fhir.cql.config.CqlDstu3Config;
|
||||
import ca.uhn.fhir.cql.config.TestCqlConfig;
|
||||
|
@ -8,12 +9,17 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaDstu3Test;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.test.utilities.RequestDetailsHelper;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
@ -23,10 +29,11 @@ import java.io.IOException;
|
|||
import java.util.Collection;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {TestCqlConfig.class, SubscriptionProcessorConfig.class, CqlDstu3Config.class})
|
||||
@ContextConfiguration(classes = {TestCqlConfig.class, SubscriptionProcessorConfig.class, CqlDstu3Config.class, BaseCqlDstu3Test.Config.class})
|
||||
public class BaseCqlDstu3Test extends BaseJpaDstu3Test implements CqlProviderTestBase {
|
||||
Logger ourLog = LoggerFactory.getLogger(BaseCqlDstu3Test.class);
|
||||
public static Logger ourLog = LoggerFactory.getLogger(BaseCqlDstu3Test.class);
|
||||
|
||||
protected final RequestDetails myRequestDetails = RequestDetailsHelper.newServletRequestDetails();
|
||||
@Autowired
|
||||
protected
|
||||
DaoRegistry myDaoRegistry;
|
||||
|
@ -35,17 +42,9 @@ public class BaseCqlDstu3Test extends BaseJpaDstu3Test implements CqlProviderTes
|
|||
FhirContext myFhirContext;
|
||||
@Autowired
|
||||
IFhirSystemDao mySystemDao;
|
||||
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@RegisterExtension
|
||||
protected PartitionHelper myPartitionHelper;
|
||||
|
||||
protected int loadDataFromDirectory(String theDirectoryName) throws IOException {
|
||||
int count = 0;
|
||||
|
@ -63,7 +62,7 @@ public class BaseCqlDstu3Test extends BaseJpaDstu3Test implements CqlProviderTes
|
|||
if (filename.contains("bundle")) {
|
||||
loadBundle(filename);
|
||||
} else {
|
||||
loadResource(filename);
|
||||
loadResource(filename, myRequestDetails);
|
||||
}
|
||||
count++;
|
||||
} else {
|
||||
|
@ -73,18 +72,38 @@ public class BaseCqlDstu3Test extends BaseJpaDstu3Test implements CqlProviderTes
|
|||
return count;
|
||||
}
|
||||
|
||||
protected Bundle parseBundle(String theLocation) throws IOException {
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
protected Bundle loadBundle(Bundle bundle) {
|
||||
return (Bundle) mySystemDao.transaction(myRequestDetails, bundle);
|
||||
}
|
||||
|
||||
protected Bundle parseBundle(String theLocation) throws IOException {
|
||||
String json = stringFromResource(theLocation);
|
||||
Bundle bundle = (Bundle) myFhirContext.newJsonParser().parseResource(json);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
protected Bundle loadBundle(Bundle bundle) {
|
||||
return (Bundle) mySystemDao.transaction(null, bundle);
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public PartitionHelper myPartitionHelper() {
|
||||
return new PartitionHelper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Bundle loadBundle(String theLocation) throws IOException {
|
||||
Bundle bundle = parseBundle(theLocation);
|
||||
return loadBundle(bundle);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.cql;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.cql.common.helper.PartitionHelper;
|
||||
import ca.uhn.fhir.cql.common.provider.CqlProviderTestBase;
|
||||
import ca.uhn.fhir.cql.config.CqlR4Config;
|
||||
import ca.uhn.fhir.cql.config.TestCqlConfig;
|
||||
|
@ -8,15 +9,17 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.test.utilities.RequestDetailsHelper;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.MeasureReport;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
@ -24,12 +27,16 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {CqlR4Config.class, TestCqlConfig.class, SubscriptionProcessorConfig.class})
|
||||
@ContextConfiguration(classes = {CqlR4Config.class, TestCqlConfig.class, SubscriptionProcessorConfig.class, BaseCqlR4Test.Config.class})
|
||||
public class BaseCqlR4Test extends BaseJpaR4Test implements CqlProviderTestBase {
|
||||
Logger ourLog = LoggerFactory.getLogger(BaseCqlR4Test.class);
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseCqlR4Test.class);
|
||||
|
||||
protected final RequestDetails myRequestDetails = RequestDetailsHelper.newServletRequestDetails();
|
||||
@Autowired
|
||||
@RegisterExtension
|
||||
protected PartitionHelper myPartitionHelper;
|
||||
|
||||
@Autowired
|
||||
protected
|
||||
|
@ -40,16 +47,6 @@ public class BaseCqlR4Test extends BaseJpaR4Test implements CqlProviderTestBase
|
|||
@Autowired
|
||||
IFhirSystemDao mySystemDao;
|
||||
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
protected int loadDataFromDirectory(String theDirectoryName) throws IOException {
|
||||
int count = 0;
|
||||
ourLog.info("Reading files in directory: {}", theDirectoryName);
|
||||
|
@ -66,7 +63,7 @@ public class BaseCqlR4Test extends BaseJpaR4Test implements CqlProviderTestBase
|
|||
if (filename.contains("bundle")) {
|
||||
loadBundle(filename);
|
||||
} else {
|
||||
loadResource(filename);
|
||||
loadResource(filename, myRequestDetails);
|
||||
}
|
||||
count++;
|
||||
} else {
|
||||
|
@ -76,18 +73,36 @@ public class BaseCqlR4Test extends BaseJpaR4Test implements CqlProviderTestBase
|
|||
return count;
|
||||
}
|
||||
|
||||
protected Bundle parseBundle(String theLocation) throws IOException {
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myFhirContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoRegistry getDaoRegistry() {
|
||||
return myDaoRegistry;
|
||||
}
|
||||
|
||||
protected Bundle loadBundle(String theLocation) throws IOException {
|
||||
Bundle bundle = parseBundle(theLocation);
|
||||
return loadBundle(bundle, myRequestDetails);
|
||||
}
|
||||
|
||||
protected Bundle parseBundle(String theLocation) throws IOException {
|
||||
String json = stringFromResource(theLocation);
|
||||
Bundle bundle = (Bundle) myFhirContext.newJsonParser().parseResource(json);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
protected Bundle loadBundle(Bundle bundle) {
|
||||
return (Bundle) mySystemDao.transaction(null, bundle);
|
||||
protected Bundle loadBundle(Bundle bundle, RequestDetails theRequestDetails) {
|
||||
return (Bundle) mySystemDao.transaction(theRequestDetails, bundle);
|
||||
}
|
||||
|
||||
protected Bundle loadBundle(String theLocation) throws IOException {
|
||||
Bundle bundle = parseBundle(theLocation);
|
||||
return loadBundle(bundle);
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public PartitionHelper myPartitionHelper() {
|
||||
return new PartitionHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package ca.uhn.fhir.cql.common.helper;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class PartitionHelper implements BeforeEachCallback, AfterEachCallback {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(PartitionHelper.class);
|
||||
protected final MyTestInterceptor myInterceptor = new MyTestInterceptor();
|
||||
|
||||
@Autowired
|
||||
IInterceptorService myIInterceptorService;
|
||||
@Autowired
|
||||
PartitionSettings myPartitionSettings;
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) throws Exception {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myIInterceptorService.registerInterceptor(myInterceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) throws Exception {
|
||||
myIInterceptorService.unregisterInterceptor(myInterceptor);
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myInterceptor.clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myInterceptor.clear();
|
||||
}
|
||||
|
||||
public boolean wasCalled() {
|
||||
return myInterceptor.wasCalled();
|
||||
}
|
||||
|
||||
public static class MyTestInterceptor {
|
||||
private boolean myCalled = false;
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
|
||||
RequestPartitionId partitionIdentifyRead(ServletRequestDetails theRequestDetails) {
|
||||
myCalled = true;
|
||||
if (theRequestDetails == null) {
|
||||
ourLog.info("useful breakpoint :-)");
|
||||
}
|
||||
assertNotNull(theRequestDetails);
|
||||
return RequestPartitionId.defaultPartition();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myCalled = false;
|
||||
}
|
||||
|
||||
public boolean wasCalled() {
|
||||
return myCalled;
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_CREATE)
|
||||
RequestPartitionId partitionIdentifyCreate(ServletRequestDetails theRequestDetails) {
|
||||
return RequestPartitionId.defaultPartition();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.cql.common.provider;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -20,14 +21,14 @@ public interface CqlProviderTestBase {
|
|||
|
||||
DaoRegistry getDaoRegistry();
|
||||
|
||||
default IBaseResource loadResource(String theLocation) throws IOException {
|
||||
default IBaseResource loadResource(String theLocation, RequestDetails theRequestDetails) throws IOException {
|
||||
String json = stringFromResource(theLocation);
|
||||
IBaseResource resource = getFhirContext().newJsonParser().parseResource(json);
|
||||
IFhirResourceDao<IBaseResource> dao = getDaoRegistry().getResourceDao(resource.getIdElement().getResourceType());
|
||||
if (dao == null) {
|
||||
return null;
|
||||
} else {
|
||||
dao.update(resource);
|
||||
dao.update(resource, theRequestDetails);
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
package ca.uhn.fhir.cql.dstu3;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
||||
import ca.uhn.fhir.cql.dstu3.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||
|
@ -24,15 +16,24 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
||||
import ca.uhn.fhir.cql.dstu3.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class CqlMeasureEvaluationDstu3Test extends BaseCqlDstu3Test {
|
||||
Logger ourLog = LoggerFactory.getLogger(CqlMeasureEvaluationDstu3Test.class);
|
||||
|
||||
@Autowired
|
||||
MeasureOperationsProvider myMeasureOperationsProvider;
|
||||
private final SystemRequestDetails mySrd = new SystemRequestDetails();
|
||||
|
||||
protected void testMeasureBundle(String theLocation) throws IOException {
|
||||
Bundle bundle = parseBundle(theLocation);
|
||||
|
@ -62,11 +63,11 @@ public class CqlMeasureEvaluationDstu3Test extends BaseCqlDstu3Test {
|
|||
this.ourLog.info("Measure: %s, Patient: %s, Start: %s, End: %s", measureId, patientId, periodStart, periodEnd);
|
||||
|
||||
MeasureReport actual = this.myMeasureOperationsProvider.evaluateMeasure(new IdType("Measure", measureId),
|
||||
periodStart, periodEnd, null,
|
||||
// TODO: These are all individual reports
|
||||
"patient", patientId,
|
||||
// TODO: Generalize these parameters into a Parameters resource
|
||||
null, null, null, null, null, null);
|
||||
periodStart, periodEnd, null,
|
||||
// TODO: These are all individual reports
|
||||
"patient", patientId,
|
||||
// TODO: Generalize these parameters into a Parameters resource
|
||||
null, null, null, null, null, null, mySrd);
|
||||
|
||||
compareMeasureReport(expected, actual);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,6 @@ import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
|||
import ca.uhn.fhir.cql.common.provider.CqlProviderFactory;
|
||||
import ca.uhn.fhir.cql.dstu3.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.rp.dstu3.LibraryResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu3.MeasureResourceProvider;
|
||||
import ca.uhn.fhir.jpa.rp.dstu3.ValueSetResourceProvider;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
|
@ -26,6 +23,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(CqlProviderDstu3Test.class);
|
||||
|
@ -37,12 +35,6 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
@Autowired
|
||||
CqlProviderFactory myCqlProviderFactory;
|
||||
@Autowired
|
||||
private LibraryResourceProvider myLibraryResourceProvider;
|
||||
@Autowired
|
||||
private MeasureResourceProvider myMeasureResourceProvider;
|
||||
@Autowired
|
||||
private ValueSetResourceProvider myValueSetResourceProvider;
|
||||
@Autowired
|
||||
private MeasureOperationsProvider myMeasureOperationsProvider;
|
||||
|
||||
@BeforeEach
|
||||
|
@ -51,8 +43,8 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
loadBundle("dstu3/hedis-ig/hedis-valuesets-bundle.json");
|
||||
|
||||
// Load libraries
|
||||
loadResource("dstu3/hedis-ig/library/library-fhir-model-definition.json");
|
||||
loadResource("dstu3/hedis-ig/library/library-fhir-helpers.json");
|
||||
loadResource("dstu3/hedis-ig/library/library-fhir-model-definition.json", myRequestDetails);
|
||||
loadResource("dstu3/hedis-ig/library/library-fhir-helpers.json", myRequestDetails);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -80,9 +72,9 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
*/
|
||||
@Test
|
||||
public void testHedisIGEvaluatePatientMeasure() throws IOException {
|
||||
loadResource("dstu3/hedis-ig/library/library-asf-logic.json");
|
||||
loadResource("dstu3/hedis-ig/library/library-asf-logic.json", myRequestDetails);
|
||||
// Load the measure for ASF: Unhealthy Alcohol Use Screening and Follow-up (ASF)
|
||||
loadResource("dstu3/hedis-ig/measure-asf.json");
|
||||
loadResource("dstu3/hedis-ig/measure-asf.json", myRequestDetails);
|
||||
Bundle result = loadBundle("dstu3/hedis-ig/test-patient-6529-data.json");
|
||||
assertNotNull(result);
|
||||
List<Bundle.BundleEntryComponent> entries = result.getEntry();
|
||||
|
@ -96,8 +88,9 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
String periodEnd = "2003-12-31";
|
||||
|
||||
// First run to absorb startup costs
|
||||
myPartitionHelper.clear();
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, null,
|
||||
patient, null, null, null, null, null, null);
|
||||
patient, null, null, null, null, null, null, myRequestDetails);
|
||||
// Assert it worked
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertThat(report.getGroup().get(0).getPopulation(), hasSize(3));
|
||||
|
@ -108,17 +101,18 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
StopWatch sw = new StopWatch();
|
||||
for (int i = 0; i < runCount; ++i) {
|
||||
myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, null,
|
||||
patient, null, null, null, null, null, null);
|
||||
patient, null, null, null, null, null, null, myRequestDetails);
|
||||
}
|
||||
|
||||
ourLog.info("Called evaluateMeasure() {} times: average time per call: {}", runCount, sw.formatMillisPerOperation(runCount));
|
||||
assertTrue(myPartitionHelper.wasCalled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHedisIGEvaluatePopulationMeasure() throws IOException {
|
||||
loadResource("dstu3/hedis-ig/library/library-asf-logic.json");
|
||||
loadResource("dstu3/hedis-ig/library/library-asf-logic.json", myRequestDetails);
|
||||
// Load the measure for ASF: Unhealthy Alcohol Use Screening and Follow-up (ASF)
|
||||
loadResource("dstu3/hedis-ig/measure-asf.json");
|
||||
loadResource("dstu3/hedis-ig/measure-asf.json", myRequestDetails);
|
||||
loadBundle("dstu3/hedis-ig/test-patient-6529-data.json");
|
||||
// Add a second patient with the same data
|
||||
loadBundle("dstu3/hedis-ig/test-patient-9999-x-data.json");
|
||||
|
@ -129,7 +123,7 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
|
||||
// First run to absorb startup costs
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, "population",
|
||||
null, null, null, null, null, null, null);
|
||||
null, null, null, null, null, null, null, myRequestDetails);
|
||||
// Assert it worked
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertThat(report.getGroup().get(0).getPopulation(), hasSize(3));
|
||||
|
@ -140,7 +134,7 @@ public class CqlProviderDstu3Test extends BaseCqlDstu3Test {
|
|||
StopWatch sw = new StopWatch();
|
||||
for (int i = 0; i < runCount; ++i) {
|
||||
myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, null, "population",
|
||||
null, null, null, null, null, null, null);
|
||||
null, null, null, null, null, null, null, myRequestDetails);
|
||||
}
|
||||
|
||||
ourLog.info("Called evaluateMeasure() {} times: average time per call: {}", runCount, sw.formatMillisPerOperation(runCount));
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
package ca.uhn.fhir.cql.dstu3.provider;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opencds.cqf.cql.engine.runtime.Code;
|
||||
|
@ -17,8 +11,13 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlDstu3Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class JpaTerminologyProviderTest extends BaseCqlDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaTerminologyProviderTest.class);
|
||||
|
@ -32,7 +31,7 @@ public class JpaTerminologyProviderTest extends BaseCqlDstu3Test {
|
|||
@BeforeEach
|
||||
public void before() throws IOException {
|
||||
// Load executable (i.e. "pre-expanded") value set
|
||||
loadResource("dstu3/provider/test-executable-value-set.json");
|
||||
loadResource("dstu3/provider/test-executable-value-set.json", myRequestDetails);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
package ca.uhn.fhir.cql.r4;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.cql.r4.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
|
@ -24,9 +16,16 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.cql.r4.provider.MeasureOperationsProvider;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class CqlMeasureEvaluationR4Test extends BaseCqlR4Test {
|
||||
Logger ourLog = LoggerFactory.getLogger(CqlMeasureEvaluationR4Test.class);
|
||||
|
@ -36,7 +35,7 @@ public class CqlMeasureEvaluationR4Test extends BaseCqlR4Test {
|
|||
|
||||
protected void testMeasureBundle(String theLocation) throws IOException {
|
||||
Bundle bundle = parseBundle(theLocation);
|
||||
loadBundle(bundle);
|
||||
loadBundle(bundle, myRequestDetails);
|
||||
|
||||
List<Measure> measures = BundleUtil.toListOfResourcesOfType(myFhirContext, bundle, Measure.class);
|
||||
if (measures == null || measures.isEmpty()) {
|
||||
|
@ -62,11 +61,11 @@ public class CqlMeasureEvaluationR4Test extends BaseCqlR4Test {
|
|||
this.ourLog.info("Measure: %s, Patient: %s, Start: %s, End: %s", measureId, patientId, periodStart, periodEnd);
|
||||
|
||||
MeasureReport actual = this.myMeasureOperationsProvider.evaluateMeasure(new IdType("Measure", measureId),
|
||||
periodStart, periodEnd, null,
|
||||
// TODO: These are all individual reports
|
||||
"patient", patientId,
|
||||
// TODO: Generalize these parameters into a Parameters resource
|
||||
null, null, null, null, null, null);
|
||||
periodStart, periodEnd, null,
|
||||
// TODO: These are all individual reports
|
||||
"patient", patientId,
|
||||
// TODO: Generalize these parameters into a Parameters resource
|
||||
null, null, null, null, null, null, myRequestDetails);
|
||||
|
||||
compareMeasureReport(expected, actual);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.io.IOException;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class CqlProviderR4Test extends BaseCqlR4Test implements CqlProviderTestBase {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(CqlProviderR4Test.class);
|
||||
|
@ -47,11 +48,15 @@ public class CqlProviderR4Test extends BaseCqlR4Test implements CqlProviderTestB
|
|||
@Test
|
||||
public void testHedisIGEvaluateMeasureWithTimeframe() throws IOException {
|
||||
loadBundles();
|
||||
loadResource("r4/hedis-ig/library-asf-logic.json");
|
||||
loadResource("r4/hedis-ig/measure-asf.json");
|
||||
loadResource("r4/hedis-ig/library-asf-logic.json", myRequestDetails);
|
||||
loadResource("r4/hedis-ig/measure-asf.json", myRequestDetails);
|
||||
|
||||
myPartitionHelper.clear();
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, periodStart, periodEnd, measure, "patient",
|
||||
patient, null, null, null, null, null, null);
|
||||
patient, null, null, null, null, null, null, myRequestDetails);
|
||||
|
||||
// Assert it worked
|
||||
assertTrue(myPartitionHelper.wasCalled());
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertThat(report.getGroup().get(0).getPopulation(), hasSize(3));
|
||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(report));
|
||||
|
@ -60,11 +65,15 @@ public class CqlProviderR4Test extends BaseCqlR4Test implements CqlProviderTestB
|
|||
@Test
|
||||
public void testHedisIGEvaluateMeasureNoTimeframe() throws IOException {
|
||||
loadBundles();
|
||||
loadResource("r4/hedis-ig/library-asf-logic.json");
|
||||
loadResource("r4/hedis-ig/measure-asf.json");
|
||||
loadResource("r4/hedis-ig/library-asf-logic.json", myRequestDetails);
|
||||
loadResource("r4/hedis-ig/measure-asf.json", myRequestDetails);
|
||||
|
||||
myPartitionHelper.clear();
|
||||
MeasureReport report = myMeasureOperationsProvider.evaluateMeasure(measureId, null, null, measure, "patient",
|
||||
patient, null, null, null, null, null, null);
|
||||
patient, null, null, null, null, null, null, myRequestDetails);
|
||||
|
||||
// Assert it worked
|
||||
assertTrue(myPartitionHelper.wasCalled());
|
||||
assertThat(report.getGroup(), hasSize(1));
|
||||
assertThat(report.getGroup().get(0).getPopulation(), hasSize(3));
|
||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(report));
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
package ca.uhn.fhir.cql.r4.provider;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opencds.cqf.cql.engine.runtime.Code;
|
||||
|
@ -17,8 +11,13 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.cql.BaseCqlR4Test;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class JpaTerminologyProviderTest extends BaseCqlR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(JpaTerminologyProviderTest.class);
|
||||
|
@ -32,7 +31,7 @@ public class JpaTerminologyProviderTest extends BaseCqlR4Test {
|
|||
@BeforeEach
|
||||
public void before() throws IOException {
|
||||
// Load executable (i.e. "pre-expanded") value set
|
||||
loadResource("r4/provider/test-executable-value-set.json");
|
||||
loadResource("r4/provider/test-executable-value-set.json", myRequestDetails);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>TRACE</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator" additivity="false"
|
||||
level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.jpa.dao.FhirResourceDaoSubscriptionDstu2" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.eclipse.jetty.websocket" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
<!-- TODO GGG HS can probably eventually disable this. -->
|
||||
<logger name="org.hibernate.search.backend.lucene.infostream" additivity="true" level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
<logger name="org.hibernate.search.query" additivity="true" level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
j
|
||||
<logger name="org.hibernate.event.internal.DefaultPersistEventListener" additivity="true" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.elasticsearch.client" additivity="true" level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.eclipse" additivity="false" level="error">
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.jpa.dao" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- set to debug to enable term expansion logs -->
|
||||
<logger name="ca.uhn.fhir.jpa.term" additivity="false" level="debug">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- Set to 'trace' to enable SQL logging -->
|
||||
<logger name="org.hibernate.SQL" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
<!-- Set to 'trace' to enable SQL Value logging -->
|
||||
<logger name="org.hibernate.type" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.hibernate.search.elasticsearch.request" additivity="false" level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.test.context.cache" additivity="false" level="debug">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</logger>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -59,6 +59,11 @@
|
|||
<artifactId>spring-context</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.batch</groupId>
|
||||
<artifactId>spring-batch-core</artifactId>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package ca.uhn.fhir.test.utilities;
|
||||
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
public class RequestDetailsHelper {
|
||||
public static RequestDetails newServletRequestDetails() {
|
||||
ServletRequestDetails retval = new ServletRequestDetails();
|
||||
retval.setServletRequest(new MockHttpServletRequest());
|
||||
retval.setServer(new RestfulServer());
|
||||
return retval;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue