Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,6 @@ public When evaluate() {
null,
null,
null,
null,
additionalData,
null,
null,
null);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public class CrDstu3Config {
@Bean
IMeasureServiceFactory dstu3MeasureServiceFactory(
IRepositoryFactory repositoryFactory, MeasureEvaluationOptions evaluationOptions) {
return rd -> new Dstu3MeasureService(repositoryFactory.create(rd), evaluationOptions);
return (requestDetails, environment) -> new Dstu3MeasureService(
environment.resolve(repositoryFactory.create(requestDetails)), evaluationOptions);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ R4MeasureEvaluatorSingleFactory r4MeasureServiceFactory(
MeasureEvaluationOptions evaluationOptions,
MeasurePeriodValidator measurePeriodValidator) {
// We are effectively returning an R4MeasureEvaluatorSingle her
return requestDetails -> new R4MultiMeasureService(
repositoryFactory.create(requestDetails),
return (requestDetails, environment) -> new R4MultiMeasureService(
environment.resolve(repositoryFactory.create(requestDetails)),
evaluationOptions,
requestDetails.getFhirServerBase(),
measurePeriodValidator);
Expand All @@ -87,8 +87,11 @@ R4MeasureEvaluatorMultipleFactory r4MeasureEvaluatorMultipleFactory(
IRepositoryFactory repositoryFactory,
MeasureEvaluationOptions evaluationOptions,
MeasurePeriodValidator measurePeriodValidator) {
return rd -> new R4MultiMeasureService(
repositoryFactory.create(rd), evaluationOptions, rd.getFhirServerBase(), measurePeriodValidator);
return (requestDetails, environment) -> new R4MultiMeasureService(
environment.resolve(repositoryFactory.create(requestDetails)),
evaluationOptions,
requestDetails.getFhirServerBase(),
measurePeriodValidator);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.opencds.cqf.fhir.cr.hapi.dstu3;

import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.opencds.cqf.fhir.cr.measure.common.MeasureEnvironment;
import org.opencds.cqf.fhir.cr.measure.dstu3.Dstu3MeasureService;

@FunctionalInterface
public interface IMeasureServiceFactory {
Dstu3MeasureService create(RequestDetails requestDetails);
Dstu3MeasureService create(RequestDetails requestDetails, MeasureEnvironment environment);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.exceptions.FHIRException;
import org.opencds.cqf.fhir.cr.hapi.dstu3.IMeasureServiceFactory;
import org.opencds.cqf.fhir.cr.measure.common.MeasureEnvironment;
import org.springframework.stereotype.Component;

@Component
Expand Down Expand Up @@ -72,8 +73,9 @@ public MeasureReport evaluateMeasure(
RequestDetails requestDetails)
throws InternalErrorException, FHIRException {
var terminologyEndpointParam = (Endpoint) getEndpoint(fhirVersion, terminologyEndpoint);
var environment = new MeasureEnvironment(null, terminologyEndpointParam, null, additionalData);
return dstu3MeasureProcessorFactory
.create(requestDetails)
.create(requestDetails, environment)
.evaluateMeasure(
id,
periodStart,
Expand All @@ -83,8 +85,6 @@ public MeasureReport evaluateMeasure(
practitioner,
lastReceivedOn,
productLine,
additionalData,
parameters,
terminologyEndpointParam);
parameters);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.opencds.cqf.fhir.cr.hapi.r4;

import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.opencds.cqf.fhir.cr.measure.common.MeasureEnvironment;
import org.opencds.cqf.fhir.cr.measure.r4.R4MeasureEvaluatorMultiple;

@FunctionalInterface
public interface R4MeasureEvaluatorMultipleFactory {
R4MeasureEvaluatorMultiple create(RequestDetails requestDetails);
R4MeasureEvaluatorMultiple create(RequestDetails requestDetails, MeasureEnvironment environment);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.opencds.cqf.fhir.cr.hapi.r4;

import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.opencds.cqf.fhir.cr.measure.common.MeasureEnvironment;
import org.opencds.cqf.fhir.cr.measure.r4.R4MeasureEvaluatorSingle;

@FunctionalInterface
public interface R4MeasureEvaluatorSingleFactory {
R4MeasureEvaluatorSingle create(RequestDetails requestDetails);
R4MeasureEvaluatorSingle create(RequestDetails requestDetails, MeasureEnvironment environment);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.opencds.cqf.fhir.cr.hapi.common.StringTimePeriodHandler;
import org.opencds.cqf.fhir.cr.hapi.r4.R4MeasureEvaluatorMultipleFactory;
import org.opencds.cqf.fhir.cr.hapi.r4.R4MeasureEvaluatorSingleFactory;
import org.opencds.cqf.fhir.cr.measure.common.MeasureEnvironment;
import org.opencds.cqf.fhir.cr.measure.common.MeasureReference;

@SuppressWarnings("java:S107")
Expand Down Expand Up @@ -87,19 +88,17 @@ public MeasureReport evaluateMeasure(
var contentEndpointParam = (Endpoint) getEndpoint(fhirVersion, contentEndpoint);
var terminologyEndpointParam = (Endpoint) getEndpoint(fhirVersion, terminologyEndpoint);
var dataEndpointParam = (Endpoint) getEndpoint(fhirVersion, dataEndpoint);
var environment = new MeasureEnvironment(
contentEndpointParam, terminologyEndpointParam, dataEndpointParam, additionalData);
return r4MeasureServiceFactory
.create(requestDetails)
.create(requestDetails, environment)
.evaluate(
new MeasureReference.ById(id),
stringTimePeriodHandler.getStartZonedDateTime(periodStart, requestDetails),
stringTimePeriodHandler.getEndZonedDateTime(periodEnd, requestDetails),
reportType,
subject,
lastReceivedOn,
contentEndpointParam,
terminologyEndpointParam,
dataEndpointParam,
additionalData,
parameters,
productLine,
practitioner);
Expand Down Expand Up @@ -157,18 +156,16 @@ public Parameters evaluate(
var terminologyEndpointParam = (Endpoint) getEndpoint(fhirVersion, terminologyEndpoint);
var dataEndpointParam = (Endpoint) getEndpoint(fhirVersion, dataEndpoint);
var measureRefs = MeasureReference.fromOperationParams(measureId, measureIdentifier, measureUrl);
var environment = new MeasureEnvironment(
contentEndpointParam, terminologyEndpointParam, dataEndpointParam, additionalData);
return r4MultiMeasureServiceFactory
.create(requestDetails)
.create(requestDetails, environment)
.evaluate(
measureRefs,
stringTimePeriodHandler.getStartZonedDateTime(periodStart, requestDetails),
stringTimePeriodHandler.getEndZonedDateTime(periodEnd, requestDetails),
reportType,
subject,
contentEndpointParam,
terminologyEndpointParam,
dataEndpointParam,
additionalData,
parameters,
productLine,
reporter);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.opencds.cqf.fhir.cr.measure.common;

import ca.uhn.fhir.repository.IRepository;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.opencds.cqf.fhir.utility.repository.FederatedRepository;
import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository;
import org.opencds.cqf.fhir.utility.repository.Repositories;

/**
* Version-agnostic environment configuration for measure evaluation.
*
* <p>Separates the <em>infrastructure inputs</em> (where data, content, and terminology come from)
* from the <em>operation parameters</em> (what to evaluate). Per the pipeline architecture,
* environment resolution happens before domain logic: the service layer composes a
* {@code ProxyRepository} from these endpoints and passes it to the evaluator.
*
* <p>Endpoint resources are typed as {@link IBaseResource} so both R4 and DSTU3
* {@code Endpoint} instances can be carried without version coupling.
* {@code Repositories.proxy()} already accepts {@code IBaseResource} endpoints directly.
*
* @param contentEndpoint endpoint for library/content resolution (nullable)
* @param terminologyEndpoint endpoint for terminology resolution (nullable)
* @param dataEndpoint endpoint for clinical data retrieval (nullable)
* @param additionalData supplemental data bundle for repository federation and CQL engine
* configuration (nullable)
*/
public record MeasureEnvironment(
@Nullable IBaseResource contentEndpoint,
@Nullable IBaseResource terminologyEndpoint,
@Nullable IBaseResource dataEndpoint,
@Nullable IBaseBundle additionalData) {

/** Empty environment — no endpoints, no additional data. */
public static final MeasureEnvironment EMPTY = new MeasureEnvironment(null, null, null, null);

/**
* Resolves this environment against a base repository.
*
* <p>If any endpoint is present, wraps {@code base} in a {@code ProxyRepository}; null
* endpoints fall back to {@code base}. If {@code additionalData} is present, federates
* the result with an in-memory repository seeded from that bundle.
*
* @param base the base repository to build on top of
* @return the resolved repository, possibly wrapped
*/
public IRepository resolve(IRepository base) {
Comment thread
JPercival marked this conversation as resolved.
IRepository repo = base;
if (dataEndpoint() != null || contentEndpoint() != null || terminologyEndpoint() != null) {
repo = Repositories.proxy(repo, true, dataEndpoint(), contentEndpoint(), terminologyEndpoint());
}
if (additionalData() != null) {
repo = new FederatedRepository(repo, new InMemoryFhirRepository(repo.fhirContext(), additionalData()));
}
return repo;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.opencds.cqf.fhir.cr.measure.dstu3;

import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Endpoint;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.MeasureReport;
import org.hl7.fhir.dstu3.model.Parameters;
Expand All @@ -21,7 +19,5 @@ MeasureReport evaluateMeasure(
String practitioner,
String lastReceivedOn,
String productLine,
Bundle additionalData,
Parameters parameters,
Endpoint terminologyEndpoint);
Parameters parameters);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
import ca.uhn.fhir.util.BundleBuilder;
import java.util.Collections;
import java.util.List;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.ContactDetail;
import org.hl7.fhir.dstu3.model.ContactPoint;
import org.hl7.fhir.dstu3.model.Endpoint;
import org.hl7.fhir.dstu3.model.Enumerations;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.IdType;
Expand Down Expand Up @@ -89,8 +87,7 @@ public Dstu3MeasureService(IRepository repository, MeasureEvaluationOptions meas
* received.
* @param productLine the productLine (e.g. Medicare, Medicaid, etc) to use
* for the evaluation. This is a non-standard parameter.
* @param additionalData the data bundle containing additional data
* @param terminologyEndpoint the endpoint of terminology services for your measure valuesets
* @param environment endpoint and supplemental data configuration
* @return the calculated MeasureReport
*/
@Override
Expand All @@ -103,16 +100,14 @@ public MeasureReport evaluateMeasure(
String practitioner,
String lastReceivedOn,
String productLine,
Bundle additionalData,
Parameters parameters,
Endpoint terminologyEndpoint) {
Parameters parameters) {

ensureSupplementalDataElementSearchParameter();

var dstu3MeasureProcessor = new Dstu3MeasureProcessor(repository, measureEvaluationOptions);

MeasureReport report = dstu3MeasureProcessor.evaluateMeasure(
id, periodStart, periodEnd, reportType, Collections.singletonList(subject), additionalData, parameters);
id, periodStart, periodEnd, reportType, Collections.singletonList(subject), null, parameters);

if (productLine != null) {
Extension ext = new Extension();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ public List<Parameters.ParametersParameterComponent> makePatientBundles(
subject,
null,
null,
null,
null,
null,
null,
reporter);

var entries = result.getParameter().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import jakarta.annotation.Nullable;
import java.time.ZonedDateTime;
import java.util.List;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Endpoint;
import org.hl7.fhir.r4.model.Parameters;
import org.opencds.cqf.fhir.cr.measure.common.MeasureReference;

Expand All @@ -20,10 +18,6 @@ Parameters evaluate(
@Nullable ZonedDateTime periodEnd,
String reportType,
String subject, // practitioner passed in here
Endpoint contentEndpoint,
Endpoint terminologyEndpoint,
Endpoint dataEndpoint,
Bundle additionalData,
Parameters parameters,
String productLine,
String reporter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import jakarta.annotation.Nullable;
import java.time.ZonedDateTime;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Endpoint;
import org.hl7.fhir.r4.model.MeasureReport;
import org.hl7.fhir.r4.model.Parameters;
import org.opencds.cqf.fhir.cr.measure.common.MeasureReference;
Expand All @@ -20,10 +18,6 @@ MeasureReport evaluate(
String reportType,
String subjectId,
String lastReceivedOn,
Endpoint contentEndpoint,
Endpoint terminologyEndpoint,
Endpoint dataEndpoint,
Bundle additionalData,
Parameters parameters,
String productLine,
String practitioner);
Expand Down
Loading
Loading