Search in sources :

Example 46 with Expression

use of org.hl7.elm.r1.Expression in project datawave by NationalSecurityAgency.

the class ContentFunctionsTest method testSomeEmptyOffsetsAdjacency.

@Test
public void testSomeEmptyOffsetsAdjacency() {
    String query = buildFunction(ContentFunctions.CONTENT_ADJACENT_FUNCTION_NAME, "BODY", Constants.TERM_OFFSET_MAP_JEXL_VARIABLE_NAME, "'foo'", "'bar'", "'car'");
    Expression expr = engine.createExpression(query);
    List<TermWeightPosition> list1, list2, list3, list4;
    list1 = asList(296);
    list2 = asList(1079);
    list3 = asList(260, 284, 304);
    list4 = asList(1165);
    termOffSetMap.put("foo", new TermFrequencyList(Maps.immutableEntry(new Zone("BODY", true, eventId), list1)));
    termOffSetMap.put("bar", new TermFrequencyList(Maps.immutableEntry(new Zone("BODY", true, eventId), list2)));
    termOffSetMap.put("car", new TermFrequencyList(Maps.immutableEntry(new Zone("BODY", true, eventId), list3), Maps.immutableEntry(new Zone("META", true, eventId), list4)));
    context.set(Constants.TERM_OFFSET_MAP_JEXL_VARIABLE_NAME, termOffSetMap);
    context.set("BODY", Arrays.asList("foo", "bar", "car"));
    Object o = expr.evaluate(context);
    Assert.assertTrue(expect(o, false));
}
Also used : Expression(org.apache.commons.jexl2.Expression) Zone(datawave.query.jexl.functions.TermFrequencyList.Zone) TermWeightPosition(datawave.ingest.protobuf.TermWeightPosition) Test(org.junit.Test)

Example 47 with Expression

use of org.hl7.elm.r1.Expression in project azkaban by azkaban.

the class PropsUtils method resolveVariableExpression.

/**
 * Function that looks for expressions to parse. It parses backwards to capture embedded
 * expressions
 */
private static String resolveVariableExpression(final String value, final int last, final JexlEngine jexl) {
    final int lastIndex = value.lastIndexOf("$(", last);
    if (lastIndex == -1) {
        return value;
    }
    // Want to check that everything is well formed, and that
    // we properly capture $( ...(...)...).
    int bracketCount = 0;
    int nextClosed = lastIndex + 2;
    for (; nextClosed < value.length(); ++nextClosed) {
        if (value.charAt(nextClosed) == '(') {
            bracketCount++;
        } else if (value.charAt(nextClosed) == ')') {
            bracketCount--;
            if (bracketCount == -1) {
                break;
            }
        }
    }
    if (nextClosed == value.length()) {
        throw new IllegalArgumentException("Expression " + value + " not well formed.");
    }
    final String innerExpression = value.substring(lastIndex + 2, nextClosed);
    Object result = null;
    try {
        final Expression e = jexl.createExpression(innerExpression);
        result = e.evaluate(new MapContext());
    } catch (final JexlException e) {
        throw new IllegalArgumentException("Expression " + value + " not well formed. " + e.getMessage(), e);
    }
    if (result == null) {
        // for backward compatibility it is best to return value
        return value;
    }
    final String newValue = value.substring(0, lastIndex) + result.toString() + value.substring(nextClosed + 1);
    return resolveVariableExpression(newValue, lastIndex, jexl);
}
Also used : Expression(org.apache.commons.jexl2.Expression) JexlException(org.apache.commons.jexl2.JexlException) MapContext(org.apache.commons.jexl2.MapContext)

Example 48 with Expression

use of org.hl7.elm.r1.Expression 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             ***Only Patient is supported as of now*** 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) {
            String url = null;
            String name = null;
            for (ParametersParameterComponent param : libraryParameter.getParameter()) {
                switch(param.getName()) {
                    case "url":
                        url = ((StringType) param.getValue()).asStringValue();
                        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<String, Object>();
    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.dstu3.model.Parameters) HashMap(java.util.HashMap) NotImplementedException(org.apache.commons.lang3.NotImplementedException) BooleanType(org.hl7.fhir.dstu3.model.BooleanType) ArrayList(java.util.ArrayList) CqlEngine(org.opencds.cqf.cql.engine.execution.CqlEngine) EvaluationResult(org.opencds.cqf.cql.engine.execution.EvaluationResult) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) ParametersParameterComponent(org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent) ParametersParameterComponent(org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent) Description(ca.uhn.fhir.model.api.annotation.Description) Operation(ca.uhn.fhir.rest.annotation.Operation)

Example 49 with Expression

use of org.hl7.elm.r1.Expression 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 50 with Expression

use of org.hl7.elm.r1.Expression in project cqf-ruler by DBCG.

the class ExpressionEvaluation method setupContext.

private Context setupContext(DomainResource instance, String cql, String patientId, Boolean aliasedExpression, RequestDetails theRequest) {
    JpaFhirDal jpaFhirDal = jpaFhirDalFactory.create(theRequest);
    List<CanonicalType> libraries = getLibraryReferences(instance, theRequest);
    String fhirVersion = this.fhirContext.getVersion().getVersion().getFhirVersionString();
    // Remove LocalLibrary from cache first...
    VersionedIdentifier localLibraryIdentifier = new VersionedIdentifier().withId("LocalLibrary");
    globalLibraryCache.remove(localLibraryIdentifier);
    // temporary LibraryLoader to resolve library dependencies when building
    // includes
    LibraryLoader tempLibraryLoader = libraryLoaderFactory.create(new ArrayList<LibraryContentProvider>(Arrays.asList(jpaLibraryContentProviderFactory.create(theRequest))));
    String source = "";
    if (aliasedExpression) {
        if (libraries.size() != 1) {
            throw new RuntimeException("If an aliased expression is provided, there must be exactly one primary Library");
        }
        VersionedIdentifier vi = getVersionedIdentifierFromCanonical(libraries.get(0));
        // Still not the best way to build include, but at least checks dal for an
        // existing library
        // Check if id works for LibraryRetrieval
        org.cqframework.cql.elm.execution.Library executionLibrary = null;
        try {
            executionLibrary = tempLibraryLoader.load(vi);
        } catch (Exception e) {
        // log error
        }
        if (executionLibrary == null) {
            Library library = (Library) jpaFhirDal.read(new IdType("Library", Canonicals.getIdPart(libraries.get(0))));
            vi.setId(library.getName());
            if (library.getVersion() != null) {
                vi.setVersion(library.getVersion());
            }
        }
        source = String.format("library LocalLibrary using FHIR version '" + fhirVersion + "' include FHIRHelpers version '" + fhirVersion + "' called FHIRHelpers %s parameter %s %s parameter \"%%context\" %s define Expression: %s", buildIncludes(tempLibraryLoader, jpaFhirDal, libraries, theRequest), instance.fhirType(), instance.fhirType(), instance.fhirType(), vi.getId() + ".\"" + cql + "\"");
    } else {
        source = String.format("library LocalLibrary using FHIR version '" + fhirVersion + "' include FHIRHelpers version '" + fhirVersion + "' called FHIRHelpers %s parameter %s %s parameter \"%%context\" %s define Expression: %s", buildIncludes(tempLibraryLoader, jpaFhirDal, libraries, theRequest), instance.fhirType(), instance.fhirType(), instance.fhirType(), cql);
    }
    LibraryLoader libraryLoader = libraryLoaderFactory.create(new ArrayList<LibraryContentProvider>(Arrays.asList(jpaLibraryContentProviderFactory.create(theRequest), new InMemoryLibraryContentProvider(Arrays.asList(source)))));
    // resolve execution context
    return setupContext(instance, patientId, libraryLoader, theRequest);
}
Also used : LibraryContentProvider(org.opencds.cqf.cql.evaluator.cql2elm.content.LibraryContentProvider) InMemoryLibraryContentProvider(org.opencds.cqf.cql.evaluator.cql2elm.content.InMemoryLibraryContentProvider) InMemoryLibraryContentProvider(org.opencds.cqf.cql.evaluator.cql2elm.content.InMemoryLibraryContentProvider) JpaFhirDal(org.opencds.cqf.ruler.cql.JpaFhirDal) CanonicalType(org.hl7.fhir.r4.model.CanonicalType) LibraryLoader(org.opencds.cqf.cql.engine.execution.LibraryLoader) IdType(org.hl7.fhir.r4.model.IdType) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) Library(org.hl7.fhir.r4.model.Library)

Aggregations

Test (org.junit.Test)102 Expression (org.apache.commons.jexl2.Expression)98 TermWeightPosition (datawave.ingest.protobuf.TermWeightPosition)66 Zone (datawave.query.jexl.functions.TermFrequencyList.Zone)66 Test (org.junit.jupiter.api.Test)60 ArrayList (java.util.ArrayList)36 HashMap (java.util.HashMap)35 Patient (org.hl7.fhir.r4.model.Patient)29 CqlEvaluator (com.ibm.cohort.cql.evaluation.CqlEvaluator)28 CqlVersionedIdentifier (com.ibm.cohort.cql.library.CqlVersionedIdentifier)28 Expression (io.atlasmap.v2.Expression)26 JexlContext (org.apache.commons.jexl2.JexlContext)26 Expression (org.hl7.elm.r1.Expression)26 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)25 CqlEvaluationResult (com.ibm.cohort.cql.evaluation.CqlEvaluationResult)24 JexlEngine (org.apache.commons.jexl2.JexlEngine)22 MapContext (org.apache.commons.jexl2.MapContext)22 FHIRException (org.hl7.fhir.exceptions.FHIRException)19 FhirServerConfig (com.ibm.cohort.fhir.client.config.FhirServerConfig)16 Coding (org.hl7.fhir.r4.model.Coding)15