Search in sources :

Example 6 with Subject

use of org.hl7.fhir.r4.utils.formats.Turtle.Subject in project cqf-ruler by DBCG.

the class CqlExecutionProvider method evaluate.

/**
 * Evaluates a CQL expression and returns the results as a Parameters resource.
 *
 * @param theRequestDetails   the {@link RequestDetails RequestDetails}
 * @param subject             Subject for which the expression will be
 *                            evaluated. This corresponds to the context in
 *                            which the expression will be evaluated and is
 *                            represented as a relative FHIR id (e.g.
 *                            Patient/123), which establishes both the context
 *                            and context value for the evaluation
 * @param expression          Expression to be evaluated. Note that this is an
 *                            expression of CQL, not the text of a library with
 *                            definition statements.
 * @param parameters          Any input parameters for the expression.
 *                            {@link Parameters} Parameters defined in this
 *                            input will be made available by name to the CQL
 *                            expression. Parameter types are mapped to CQL as
 *                            specified in the Using CQL section of the CPG
 *                            Implementation guide. If a parameter appears more
 *                            than once in the input Parameters resource, it is
 *                            represented with a List in the input CQL. If a
 *                            parameter has parts, it is represented as a Tuple
 *                            in the input CQL.
 * @param library             A library to be included. The {@link Library}
 *                            library is resolved by url and made available by
 *                            name within the expression to be evaluated.
 * @param useServerData       Whether to use data from the server performing the
 *                            evaluation. If this parameter is true (the
 *                            default), then the operation will use data first
 *                            from any bundles provided as parameters (through
 *                            the data and prefetch parameters), second data
 *                            from the server performing the operation, and
 *                            third, data from the dataEndpoint parameter (if
 *                            provided). If this parameter is false, the
 *                            operation will use data first from the bundles
 *                            provided in the data or prefetch parameters, and
 *                            second from the dataEndpoint parameter (if
 *                            provided).
 * @param data                Data to be made available to the library
 *                            evaluation. This parameter is exclusive with the
 *                            prefetchData parameter (i.e. either provide all
 *                            data as a single bundle, or provide data using
 *                            multiple bundles with prefetch descriptions).
 * @param prefetchData        ***Not Yet Implemented***
 * @param dataEndpoint        An {@link Endpoint} endpoint to use to access data
 *                            referenced by retrieve operations in the library.
 *                            If provided, this endpoint is used after the data
 *                            or prefetchData bundles, and the server, if the
 *                            useServerData parameter is true.
 * @param contentEndpoint     An {@link Endpoint} endpoint to use to access
 *                            content (i.e. libraries) referenced by the
 *                            library. If no content endpoint is supplied, the
 *                            evaluation will attempt to retrieve content from
 *                            the server on which the operation is being
 *                            performed.
 * @param terminologyEndpoint An {@link Endpoint} endpoint to use to access
 *                            terminology (i.e. valuesets, codesystems, and
 *                            membership testing) referenced by the library. If
 *                            no terminology endpoint is supplied, the
 *                            evaluation will attempt to use the server on which
 *                            the operation is being performed as the
 *                            terminology server.
 * @return The result of evaluating the given expression, returned as a FHIR
 *         type, either a {@link Resource} resource, or a FHIR-defined type
 *         corresponding to the CQL return type, as defined in the Using CQL
 *         section of the CPG Implementation guide. If the result is a List of
 *         resources, the result will be a {@link Bundle} Bundle . If the result
 *         is a CQL system-defined or FHIR-defined type, the result is returned
 *         as a {@link Parameters} Parameters resource
 */
@Operation(name = "$cql")
@Description(shortDefinition = "$cql", value = "Evaluates a CQL expression and returns the results as a Parameters resource. Defined: http://build.fhir.org/ig/HL7/cqf-recommendations/OperationDefinition-cpg-cql.html", example = "$cql?expression=5*5")
public Parameters evaluate(RequestDetails theRequestDetails, @OperationParam(name = "subject", max = 1) String subject, @OperationParam(name = "expression", min = 1, max = 1) String expression, @OperationParam(name = "parameters", max = 1) Parameters parameters, @OperationParam(name = "library") List<Parameters> library, @OperationParam(name = "useServerData", max = 1) BooleanType useServerData, @OperationParam(name = "data", max = 1) Bundle data, @OperationParam(name = "prefetchData") List<Parameters> prefetchData, @OperationParam(name = "dataEndpoint", max = 1) Endpoint dataEndpoint, @OperationParam(name = "contentEndpoint", max = 1) Endpoint contentEndpoint, @OperationParam(name = "terminologyEndpoint", max = 1) Endpoint terminologyEndpoint) {
    if (prefetchData != null) {
        throw new NotImplementedException("prefetchData is not yet supported.");
    }
    if (useServerData == null) {
        useServerData = new BooleanType(true);
    }
    List<LibraryParameter> libraryParameters = new ArrayList<>();
    if (library != null) {
        for (Parameters libraryParameter : library) {
            CanonicalType url = null;
            String name = null;
            for (ParametersParameterComponent param : libraryParameter.getParameter()) {
                switch(param.getName()) {
                    case "url":
                        url = ((CanonicalType) param.getValue());
                        break;
                    case "name":
                        name = ((StringType) param.getValue()).asStringValue();
                        break;
                    default:
                        throw new IllegalArgumentException("Only url and name parts are allowed for Parameter: library");
                }
            }
            if (url == null) {
                throw new IllegalArgumentException("If library parameter must provide a url parameter part.");
            }
            libraryParameters.add(new LibraryParameter().withUrl(url).withName(name));
        }
    // Remove LocalLibrary from cache first...
    }
    VersionedIdentifier localLibraryIdentifier = new VersionedIdentifier().withId("LocalLibrary").withVersion("1.0.0");
    globalLibraryCache.remove(localLibraryIdentifier);
    CqlEngine engine = setupEngine(localLibraryIdentifier, expression, libraryParameters, subject, parameters, contentEndpoint, dataEndpoint, terminologyEndpoint, data, useServerData.booleanValue(), theRequestDetails);
    Map<String, Object> resolvedParameters = new HashMap<>();
    if (parameters != null) {
        for (Parameters.ParametersParameterComponent pc : parameters.getParameter()) {
            resolvedParameters.put(pc.getName(), pc.getValue());
        }
    }
    String contextType = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    String subjectId = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    EvaluationResult evalResult = engine.evaluate(localLibraryIdentifier, null, Pair.of(contextType != null ? contextType : "Unspecified", subjectId == null ? "null" : subject), resolvedParameters, this.getDebugMap());
    if (evalResult != null && evalResult.expressionResults != null) {
        if (evalResult.expressionResults.size() > 1) {
            logger.debug("Evaluation resulted in more than one expression result.  ");
        }
        Parameters result = new Parameters();
        resolveResult(theRequestDetails, evalResult, result);
        return result;
    }
    return null;
}
Also used : Parameters(org.hl7.fhir.r4.model.Parameters) HashMap(java.util.HashMap) NotImplementedException(org.apache.commons.lang3.NotImplementedException) BooleanType(org.hl7.fhir.r4.model.BooleanType) ArrayList(java.util.ArrayList) CqlEngine(org.opencds.cqf.cql.engine.execution.CqlEngine) CanonicalType(org.hl7.fhir.r4.model.CanonicalType) EvaluationResult(org.opencds.cqf.cql.engine.execution.EvaluationResult) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) ParametersParameterComponent(org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent) ParametersParameterComponent(org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent) Description(ca.uhn.fhir.model.api.annotation.Description) Operation(ca.uhn.fhir.rest.annotation.Operation)

Example 7 with Subject

use of org.hl7.fhir.r4.utils.formats.Turtle.Subject in project cqf-ruler by DBCG.

the class MeasureDataProcessProvider method getSubjectResultsFromList.

private List<Reference> getSubjectResultsFromList(Reference subjectResults) {
    List<Reference> results = new ArrayList<>();
    if (subjectResults.getReference() == null) {
        logger.debug("No subject results found.");
        return results;
    }
    IBaseResource baseList = read(subjectResults.getReferenceElement());
    if (!(baseList instanceof ListResource)) {
        throw new IllegalArgumentException(String.format("Population subject reference was not a List, found: %s", baseList.fhirType()));
    }
    ListResource list = (ListResource) baseList;
    list.getEntry().forEach(entry -> {
        if (entry.getItemTarget().getResourceType() == ResourceType.Patient || entry.getItemTarget().getResourceType() == ResourceType.Group) {
            results.add(entry.getItem());
        }
    });
    return results;
}
Also used : Reference(org.hl7.fhir.r4.model.Reference) ArrayList(java.util.ArrayList) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) ListResource(org.hl7.fhir.r4.model.ListResource)

Example 8 with Subject

use of org.hl7.fhir.r4.utils.formats.Turtle.Subject in project cqf-ruler by DBCG.

the class ReportProvider method report.

/**
 * Implements the <a href=
 * "https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-report.html">$report</a>
 * operation found in the
 * <a href="https://build.fhir.org/ig/HL7/davinci-ra/index.html">Da Vinci Risk
 * Adjustment IG</a>.
 *
 * @param requestDetails metadata about the current request being processed.
 *                       Generally auto-populated by the HAPI FHIR server
 *                       framework.
 * @param periodStart    the start of the clinical evaluation period
 * @param periodEnd      the end of the clinical evaluation period
 * @param subject        a Patient or Patient Group
 * @return a Parameters with Bundles of MeasureReports and evaluatedResource
 *         Resources
 */
@Description(shortDefinition = "$report", value = "Implements the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/OperationDefinition-report.html\">$report</a> operation found in the <a href=\"https://build.fhir.org/ig/HL7/davinci-ra/index.html\">Da Vinci Risk Adjustment IG</a>.")
@Operation(name = "$report", idempotent = true, type = MeasureReport.class)
public Parameters report(RequestDetails requestDetails, @OperationParam(name = "periodStart", min = 1, max = 1) String periodStart, @OperationParam(name = "periodEnd", min = 1, max = 1) String periodEnd, @OperationParam(name = "subject", min = 1, max = 1) String subject) throws FHIRException {
    validateParameters(periodStart, periodEnd, subject);
    Parameters result = newResource(Parameters.class, subject.replace("/", "-") + "-report");
    Date periodStartDate = Operations.resolveRequestDate(periodStart, true);
    Date periodEndDate = Operations.resolveRequestDate(periodEnd, false);
    Period period = new Period().setStart(periodStartDate).setEnd(periodEndDate);
    List<Patient> patients = getPatientListFromSubject(subject);
    (patients).forEach(patient -> {
        Parameters.ParametersParameterComponent patientParameter = patientReport(patient, period, requestDetails.getFhirServerBase());
        result.addParameter(patientParameter);
    });
    return result;
}
Also used : Parameters(org.hl7.fhir.r4.model.Parameters) Period(org.hl7.fhir.r4.model.Period) Patient(org.hl7.fhir.r4.model.Patient) Date(java.util.Date) Description(ca.uhn.fhir.model.api.annotation.Description) Operation(ca.uhn.fhir.rest.annotation.Operation)

Example 9 with Subject

use of org.hl7.fhir.r4.utils.formats.Turtle.Subject in project cqf-ruler by DBCG.

the class ReportProvider method patientReport.

private Parameters.ParametersParameterComponent patientReport(Patient thePatient, Period thePeriod, String serverBase) {
    String patientId = thePatient.getIdElement().getIdPart();
    final Map<IIdType, IAnyResource> bundleEntries = new HashMap<>();
    bundleEntries.put(thePatient.getIdElement(), thePatient);
    ReferenceParam subjectParam = new ReferenceParam(patientId);
    search(MeasureReport.class, Searches.byParam("subject", subjectParam)).getAllResourcesTyped().forEach(measureReport -> {
        if (measureReport.getPeriod().getEnd().before(thePeriod.getStart()) || measureReport.getPeriod().getStart().after(thePeriod.getEnd())) {
            return;
        }
        bundleEntries.putIfAbsent(measureReport.getIdElement(), measureReport);
        getEvaluatedResources(measureReport).values().forEach(resource -> bundleEntries.putIfAbsent(resource.getIdElement(), resource));
    });
    Bundle patientReportBundle = new Bundle();
    patientReportBundle.setMeta(new Meta().addProfile(PATIENT_REPORT_PROFILE_URL));
    patientReportBundle.setType(Bundle.BundleType.COLLECTION);
    patientReportBundle.setTimestamp(new Date());
    patientReportBundle.setId(patientId + "-report");
    patientReportBundle.setIdentifier(new Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:uuid:" + UUID.randomUUID().toString()));
    bundleEntries.entrySet().forEach(resource -> patientReportBundle.addEntry(new Bundle.BundleEntryComponent().setResource((Resource) resource.getValue()).setFullUrl(Operations.getFullUrl(serverBase, resource.getValue().fhirType(), resource.getValue().getIdElement().getIdPart()))));
    Parameters.ParametersParameterComponent patientParameter = new Parameters.ParametersParameterComponent();
    patientParameter.setResource(patientReportBundle);
    patientParameter.setId(thePatient.getIdElement().getIdPart() + "-report");
    patientParameter.setName("return");
    return patientParameter;
}
Also used : Meta(org.hl7.fhir.r4.model.Meta) Parameters(org.hl7.fhir.r4.model.Parameters) HashMap(java.util.HashMap) Bundle(org.hl7.fhir.r4.model.Bundle) IAnyResource(org.hl7.fhir.instance.model.api.IAnyResource) Resource(org.hl7.fhir.r4.model.Resource) ReferenceParam(ca.uhn.fhir.rest.param.ReferenceParam) Date(java.util.Date) Identifier(org.hl7.fhir.r4.model.Identifier) IAnyResource(org.hl7.fhir.instance.model.api.IAnyResource) IIdType(org.hl7.fhir.instance.model.api.IIdType)

Example 10 with Subject

use of org.hl7.fhir.r4.utils.formats.Turtle.Subject in project cqf-ruler by DBCG.

the class ReportProvider method validateParameters.

private Period validateParameters(String periodStart, String periodEnd, String subject) {
    if (periodStart == null) {
        throw new IllegalArgumentException("Parameter 'periodStart' is required.");
    }
    if (periodEnd == null) {
        throw new IllegalArgumentException("Parameter 'periodEnd' is required.");
    }
    Date periodStartDate = Operations.resolveRequestDate(periodStart, true);
    Date periodEndDate = Operations.resolveRequestDate(periodEnd, false);
    if (periodStartDate.after(periodEndDate)) {
        throw new IllegalArgumentException("Parameter 'periodStart' must be before 'periodEnd'.");
    }
    if (subject == null) {
        throw new IllegalArgumentException("Parameter 'subject' is required.");
    }
    if (!subject.startsWith("Patient/") && !subject.startsWith("Group/")) {
        throw new IllegalArgumentException("Parameter 'subject' must be in the format 'Patient/[id]' or 'Group/[id]'.");
    }
    return new Period().setStart(periodStartDate).setEnd(periodEndDate);
}
Also used : Period(org.hl7.fhir.r4.model.Period) Date(java.util.Date)

Aggregations

Test (org.junit.Test)124 Test (org.junit.jupiter.api.Test)68 MockHttpServletResponse (org.springframework.mock.web.MockHttpServletResponse)64 Bundle (org.hl7.fhir.r4.model.Bundle)56 Complex (org.hl7.fhir.r4.utils.formats.Turtle.Complex)54 Parameters (org.hl7.fhir.r4.model.Parameters)46 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)43 RestIntegrationTest (org.opencds.cqf.ruler.test.RestIntegrationTest)42 StringType (org.hl7.fhir.r4.model.StringType)41 IBundleProvider (ca.uhn.fhir.rest.api.server.IBundleProvider)39 Observation (org.hl7.fhir.r4.model.Observation)38 Complex (org.hl7.fhir.dstu3.utils.formats.Turtle.Complex)37 Bundle (org.hl7.fhir.dstu3.model.Bundle)35 ReferenceParam (ca.uhn.fhir.rest.param.ReferenceParam)32 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)32 ReferenceAndListParam (ca.uhn.fhir.rest.param.ReferenceAndListParam)31 ReferenceOrListParam (ca.uhn.fhir.rest.param.ReferenceOrListParam)31 Patient (org.hl7.fhir.r4.model.Patient)30 SearchParameterMap (org.openmrs.module.fhir2.api.search.param.SearchParameterMap)30 Complex (org.hl7.fhir.dstu2016may.formats.RdfGenerator.Complex)29