Search in sources :

Example 1 with Context

use of org.opencds.cqf.cql.engine.execution.Context in project cqf-ruler by DBCG.

the class CdsHooksServlet method doPost.

@Override
@SuppressWarnings("deprecation")
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    logger.info(request.getRequestURI());
    try {
        // validate that we are dealing with JSON
        if (request.getContentType() == null || !request.getContentType().startsWith("application/json")) {
            throw new ServletException(String.format("Invalid content type %s. Please use application/json.", request.getContentType()));
        }
        String baseUrl = this.myAppProperties.getServer_address();
        String service = request.getPathInfo().replace("/", "");
        JsonParser parser = new JsonParser();
        JsonObject requestJson = parser.parse(request.getReader()).getAsJsonObject();
        logger.info(requestJson.toString());
        Request cdsHooksRequest = new Request(service, requestJson, JsonHelper.getObjectRequired(getService(service), "prefetch"));
        Hook hook = HookFactory.createHook(cdsHooksRequest);
        String hookName = hook.getRequest().getHook();
        logger.info("cds-hooks hook: {}", hookName);
        logger.info("cds-hooks hook instance: {}", hook.getRequest().getHookInstance());
        logger.info("cds-hooks maxCodesPerQuery: {}", this.getProviderConfiguration().getMaxCodesPerQuery());
        logger.info("cds-hooks expandValueSets: {}", this.getProviderConfiguration().getExpandValueSets());
        logger.info("cds-hooks searchStyle: {}", this.getProviderConfiguration().getSearchStyle());
        logger.info("cds-hooks prefetch maxUriLength: {}", this.getProviderConfiguration().getMaxUriLength());
        logger.info("cds-hooks local server address: {}", baseUrl);
        logger.info("cds-hooks fhir server address: {}", hook.getRequest().getFhirServerUrl());
        logger.info("cds-hooks cql_logging_enabled: {}", this.getProviderConfiguration().getCqlLoggingEnabled());
        PlanDefinition planDefinition = read(Ids.newId(PlanDefinition.class, hook.getRequest().getServiceName()));
        AtomicBoolean planDefinitionHookMatchesRequestHook = new AtomicBoolean(false);
        planDefinition.getAction().forEach(action -> {
            action.getTriggerDefinition().forEach(triggerDefn -> {
                if (hookName.equals(triggerDefn.getEventName())) {
                    planDefinitionHookMatchesRequestHook.set(true);
                    return;
                }
            });
            if (planDefinitionHookMatchesRequestHook.get()) {
                return;
            }
        });
        if (!planDefinitionHookMatchesRequestHook.get()) {
            throw new ServletException("ERROR: Request hook does not match the service called.");
        }
        // No tenant information available, so create local system request
        RequestDetails requestDetails = new SystemRequestDetails();
        LibraryLoader libraryLoader = libraryLoaderFactory.create(Lists.newArrayList(jpaLibraryContentProviderFactory.create(requestDetails)));
        Reference reference = planDefinition.getLibrary().get(0);
        Library library = read(reference.getReferenceElement());
        org.cqframework.cql.elm.execution.Library elm = libraryLoader.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion()));
        Context context = new Context(elm);
        context.setDebugMap(this.getDebugMap());
        // provider case
        // No tenant information available for cds-hooks
        TerminologyProvider serverTerminologyProvider = myJpaTerminologyProviderFactory.create(requestDetails);
        // TODO make sure tooling handles remote
        context.registerDataProvider("http://hl7.org/fhir", fhirRetrieveProviderFactory.create(requestDetails, serverTerminologyProvider));
        context.registerTerminologyProvider(serverTerminologyProvider);
        context.registerLibraryLoader(libraryLoader);
        context.setContextValue("Patient", hook.getRequest().getContext().getPatientId().replace("Patient/", ""));
        context.setExpressionCaching(true);
        EvaluationContext<PlanDefinition> evaluationContext = new Stu3EvaluationContext(hook, FhirContext.forCached(FhirVersionEnum.DSTU3).newRestfulGenericClient(baseUrl), context, elm, planDefinition, this.getProviderConfiguration(), this.modelResolver);
        this.setAccessControlHeaders(response);
        response.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
        Stu3HookEvaluator evaluator = new Stu3HookEvaluator(this.modelResolver);
        String jsonResponse = toJsonResponse(evaluator.evaluate(evaluationContext));
        logger.info(jsonResponse);
        response.getWriter().println(jsonResponse);
    } catch (BaseServerResponseException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception connecting to remote server.");
        this.printMessageAndCause(e, response);
        this.handleServerResponseException(e, response);
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (DataProviderException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception in DataProvider.");
        this.printMessageAndCause(e, response);
        if (e.getCause() != null && (e.getCause() instanceof BaseServerResponseException)) {
            this.handleServerResponseException((BaseServerResponseException) e.getCause(), response);
        }
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (CqlException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception in CQL Execution.");
        this.printMessageAndCause(e, response);
        if (e.getCause() != null && (e.getCause() instanceof BaseServerResponseException)) {
            this.handleServerResponseException((BaseServerResponseException) e.getCause(), response);
        }
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (Exception e) {
        logger.error(e.toString());
        throw new ServletException("ERROR: Exception in cds-hooks processing.", e);
    }
}
Also used : JsonObject(com.google.gson.JsonObject) LibraryLoader(org.opencds.cqf.cql.engine.execution.LibraryLoader) ServletException(javax.servlet.ServletException) Stu3EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.Stu3EvaluationContext) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) SystemRequestDetails(ca.uhn.fhir.jpa.partition.SystemRequestDetails) DataProviderException(org.opencds.cqf.cql.engine.fhir.exception.DataProviderException) JsonParser(com.google.gson.JsonParser) FhirContext(ca.uhn.fhir.context.FhirContext) EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.EvaluationContext) Stu3EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.Stu3EvaluationContext) Context(org.opencds.cqf.cql.engine.execution.Context) Hook(org.opencds.cqf.ruler.cdshooks.hooks.Hook) Reference(org.hl7.fhir.dstu3.model.Reference) AtomicReference(java.util.concurrent.atomic.AtomicReference) Request(org.opencds.cqf.ruler.cdshooks.request.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) Stu3HookEvaluator(org.opencds.cqf.ruler.cdshooks.hooks.Stu3HookEvaluator) BaseServerResponseException(ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException) RequestDetails(ca.uhn.fhir.rest.api.server.RequestDetails) SystemRequestDetails(ca.uhn.fhir.jpa.partition.SystemRequestDetails) ServletException(javax.servlet.ServletException) CqlException(org.opencds.cqf.cql.engine.exception.CqlException) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) DataProviderException(org.opencds.cqf.cql.engine.fhir.exception.DataProviderException) BaseServerResponseException(ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TerminologyProvider(org.opencds.cqf.cql.engine.terminology.TerminologyProvider) PlanDefinition(org.hl7.fhir.dstu3.model.PlanDefinition) Library(org.hl7.fhir.dstu3.model.Library) CqlException(org.opencds.cqf.cql.engine.exception.CqlException)

Example 2 with Context

use of org.opencds.cqf.cql.engine.execution.Context in project cqf-ruler by DBCG.

the class CdsHooksServlet method doPost.

@Override
@SuppressWarnings("deprecation")
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    logger.info(request.getRequestURI());
    try {
        // validate that we are dealing with JSON
        if (request.getContentType() == null || !request.getContentType().startsWith("application/json")) {
            throw new ServletException(String.format("Invalid content type %s. Please use application/json.", request.getContentType()));
        }
        String baseUrl = this.myAppProperties.getServer_address();
        String service = request.getPathInfo().replace("/", "");
        JsonParser parser = new JsonParser();
        Request cdsHooksRequest = new Request(service, parser.parse(request.getReader()).getAsJsonObject(), JsonHelper.getObjectRequired(getService(service), "prefetch"));
        logger.info(cdsHooksRequest.getRequestJson().toString());
        Hook hook = HookFactory.createHook(cdsHooksRequest);
        String hookName = hook.getRequest().getHook();
        logger.info("cds-hooks hook: {}", hookName);
        logger.info("cds-hooks hook instance: {}", hook.getRequest().getHookInstance());
        logger.info("cds-hooks maxCodesPerQuery: {}", this.getProviderConfiguration().getMaxCodesPerQuery());
        logger.info("cds-hooks expandValueSets: {}", this.getProviderConfiguration().getExpandValueSets());
        logger.info("cds-hooks searchStyle: {}", this.getProviderConfiguration().getSearchStyle());
        logger.info("cds-hooks prefetch maxUriLength: {}", this.getProviderConfiguration().getMaxUriLength());
        logger.info("cds-hooks local server address: {}", baseUrl);
        logger.info("cds-hooks fhir server address: {}", hook.getRequest().getFhirServerUrl());
        logger.info("cds-hooks cql_logging_enabled: {}", this.getProviderConfiguration().getCqlLoggingEnabled());
        PlanDefinition planDefinition = read(Ids.newId(PlanDefinition.class, hook.getRequest().getServiceName()));
        AtomicBoolean planDefinitionHookMatchesRequestHook = new AtomicBoolean(false);
        planDefinition.getAction().forEach(action -> {
            action.getTrigger().forEach(trigger -> {
                if (hookName.equals(trigger.getName())) {
                    planDefinitionHookMatchesRequestHook.set(true);
                    return;
                }
            });
            if (planDefinitionHookMatchesRequestHook.get()) {
                return;
            }
        });
        if (!planDefinitionHookMatchesRequestHook.get()) {
            throw new ServletException("ERROR: Request hook does not match the service called.");
        }
        // No tenant information available, so create local system request
        RequestDetails requestDetails = new SystemRequestDetails();
        LibraryLoader libraryLoader = libraryLoaderFactory.create(Lists.newArrayList(jpaLibraryContentProviderFactory.create(requestDetails)));
        CanonicalType canonical = planDefinition.getLibrary().get(0);
        Library library = search(Library.class, Searches.byCanonical(canonical)).single();
        org.cqframework.cql.elm.execution.Library elm = libraryLoader.load(new VersionedIdentifier().withId(library.getName()).withVersion(library.getVersion()));
        Context context = new Context(elm);
        context.setDebugMap(this.getDebugMap());
        // provider case
        // No tenant information available for cds-hooks
        TerminologyProvider serverTerminologyProvider = myJpaTerminologyProviderFactory.create(requestDetails);
        context.registerDataProvider("http://hl7.org/fhir", // TODO make sure tooling
        fhirRetrieveProviderFactory.create(requestDetails, serverTerminologyProvider));
        // handles remote
        context.registerTerminologyProvider(serverTerminologyProvider);
        context.registerLibraryLoader(libraryLoader);
        context.setContextValue("Patient", hook.getRequest().getContext().getPatientId().replace("Patient/", ""));
        context.setExpressionCaching(true);
        EvaluationContext<PlanDefinition> evaluationContext = new R4EvaluationContext(hook, FhirContext.forCached(FhirVersionEnum.R4).newRestfulGenericClient(baseUrl), context, elm, planDefinition, this.getProviderConfiguration(), this.modelResolver);
        this.setAccessControlHeaders(response);
        response.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
        R4HookEvaluator evaluator = new R4HookEvaluator(this.modelResolver);
        String jsonResponse = toJsonResponse(evaluator.evaluate(evaluationContext));
        logger.info(jsonResponse);
        response.getWriter().println(jsonResponse);
    } catch (BaseServerResponseException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception connecting to remote server.");
        this.printMessageAndCause(e, response);
        this.handleServerResponseException(e, response);
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (DataProviderException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception in DataProvider.");
        this.printMessageAndCause(e, response);
        if (e.getCause() != null && (e.getCause() instanceof BaseServerResponseException)) {
            this.handleServerResponseException((BaseServerResponseException) e.getCause(), response);
        }
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (CqlException e) {
        this.setAccessControlHeaders(response);
        // This will be overwritten with the correct status code downstream if needed.
        response.setStatus(500);
        response.getWriter().println("ERROR: Exception in CQL Execution.");
        this.printMessageAndCause(e, response);
        if (e.getCause() != null && (e.getCause() instanceof BaseServerResponseException)) {
            this.handleServerResponseException((BaseServerResponseException) e.getCause(), response);
        }
        this.printStackTrack(e, response);
        logger.error(e.toString());
    } catch (Exception e) {
        logger.error(e.toString());
        throw new ServletException("ERROR: Exception in cds-hooks processing.", e);
    }
}
Also used : LibraryLoader(org.opencds.cqf.cql.engine.execution.LibraryLoader) CanonicalType(org.hl7.fhir.r4.model.CanonicalType) ServletException(javax.servlet.ServletException) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) SystemRequestDetails(ca.uhn.fhir.jpa.partition.SystemRequestDetails) DataProviderException(org.opencds.cqf.cql.engine.fhir.exception.DataProviderException) JsonParser(com.google.gson.JsonParser) FhirContext(ca.uhn.fhir.context.FhirContext) EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.EvaluationContext) Context(org.opencds.cqf.cql.engine.execution.Context) R4EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.R4EvaluationContext) Hook(org.opencds.cqf.ruler.cdshooks.hooks.Hook) Request(org.opencds.cqf.ruler.cdshooks.request.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) R4EvaluationContext(org.opencds.cqf.ruler.cdshooks.evaluation.R4EvaluationContext) BaseServerResponseException(ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException) RequestDetails(ca.uhn.fhir.rest.api.server.RequestDetails) SystemRequestDetails(ca.uhn.fhir.jpa.partition.SystemRequestDetails) ServletException(javax.servlet.ServletException) CqlException(org.opencds.cqf.cql.engine.exception.CqlException) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) DataProviderException(org.opencds.cqf.cql.engine.fhir.exception.DataProviderException) BaseServerResponseException(ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TerminologyProvider(org.opencds.cqf.cql.engine.terminology.TerminologyProvider) PlanDefinition(org.hl7.fhir.r4.model.PlanDefinition) Library(org.hl7.fhir.r4.model.Library) R4HookEvaluator(org.opencds.cqf.ruler.cdshooks.hooks.R4HookEvaluator) CqlException(org.opencds.cqf.cql.engine.exception.CqlException)

Example 3 with Context

use of org.opencds.cqf.cql.engine.execution.Context in project quality-measure-and-cohort-service by Alvearie.

the class ShortCircuitEvaluatorTest method testShortCircuitOr.

@Test
public void testShortCircuitOr() {
    Context context = new Context(library);
    verifyOr(context, "TrueOrTrue", true, true);
    verifyOr(context, "TrueOrFalse", true, true);
    verifyOr(context, "TrueOrNull", true, true);
    verifyOr(context, "FalseOrTrue", true, false);
    verifyOr(context, "FalseOrFalse", false, false);
    verifyOr(context, "FalseOrNull", null, false);
    verifyOr(context, "NullOrTrue", true, false);
    verifyOr(context, "NullOrFalse", null, false);
    verifyOr(context, "NullOrNull", null, false);
}
Also used : Context(org.opencds.cqf.cql.engine.execution.Context) Test(org.junit.Test)

Example 4 with Context

use of org.opencds.cqf.cql.engine.execution.Context in project quality-measure-and-cohort-service by Alvearie.

the class CqlEvaluator method evaluate.

public CqlEvaluationResult evaluate(CqlVersionedIdentifier topLevelLibraryIdentifier, Map<String, Parameter> parameters, Pair<String, String> context, Set<String> expressions, CqlDebug debug, ZonedDateTime batchDateTime) throws CqlLibraryDeserializationException {
    if (this.libraryProvider == null) {
        throw new IllegalArgumentException("Missing libraryProvider");
    } else if (this.dataProvider == null) {
        throw new IllegalArgumentException("Missing dataProvider");
    } else if (this.terminologyProvider == null) {
        throw new IllegalArgumentException("Missing terminologyProvider");
    } else if (topLevelLibraryIdentifier == null) {
        throw new IllegalArgumentException("Missing library identifier");
    }
    CqlContextFactory contextFactory = new CqlContextFactory();
    contextFactory.setExternalFunctionProvider(this.externalFunctionProvider);
    contextFactory.setCacheContexts(cacheContexts);
    Context cqlContext = contextFactory.createContext(libraryProvider, topLevelLibraryIdentifier, terminologyProvider, dataProvider, batchDateTime, context, parameters, debug);
    if (expressions == null) {
        expressions = cqlContext.getCurrentLibrary().getStatements().getDef().stream().map(ExpressionDef::getName).collect(Collectors.toCollection(LinkedHashSet::new));
    }
    Map<String, Object> results = new LinkedHashMap<>();
    for (String expression : expressions) {
        ExpressionDef expressionDef = cqlContext.resolveExpressionRef(expression);
        // also explicitly skips over FunctionDefs.
        if (!(expressionDef instanceof FunctionDef)) {
            Object result = cqlContext.resolveExpressionRef(expression).evaluate(cqlContext);
            results.put(expression, result);
        }
    }
    if (context != null) {
        cqlContext.setContextValue(context.getLeft(), context.getRight());
    }
    return new CqlEvaluationResult(results);
}
Also used : Context(org.opencds.cqf.cql.engine.execution.Context) LinkedHashSet(java.util.LinkedHashSet) ExpressionDef(org.cqframework.cql.elm.execution.ExpressionDef) FunctionDef(org.cqframework.cql.elm.execution.FunctionDef) LinkedHashMap(java.util.LinkedHashMap)

Example 5 with Context

use of org.opencds.cqf.cql.engine.execution.Context in project quality-measure-and-cohort-service by Alvearie.

the class CqlContextFactory method createContext.

/**
 * Initialize a CQL Engine Context object with the provided settings.
 *
 * @param libraryProvider           Provider for CQL library resources
 * @param topLevelLibraryIdentifier Identifier for the top level library
 * @param terminologyProvider       Provider for CQL terminology resources
 * @param dataProvider              Provider for data that underlies the evaluation
 * @param evaluationDateTime        Date and time that will be considered "now" during
 *                                  CQL evaluation. If null, then ZonedDateTime.now()
 *                                  will be used each time a context object is
 *                                  initialized.
 * @param contextData               Name-Value pair of context name + context value
 *                                  corresponding to the unique ID of an individual
 *                                  context that is being evaluated. In a Patient
 *                                  context, this would be the Patient ID, etc.
 * @param parameters                Optional input parameters for the CQL evaluation
 * @param debug                     Debug configuration.
 * @return initialized Context object
 * @throws CqlLibraryDeserializationException if the specified library cannot be
 *                                            loaded
 */
public Context createContext(CqlLibraryProvider libraryProvider, CqlVersionedIdentifier topLevelLibraryIdentifier, CqlTerminologyProvider terminologyProvider, CqlDataProvider dataProvider, ZonedDateTime evaluationDateTime, Pair<String, String> contextData, Map<String, Parameter> parameters, CqlDebug debug) throws CqlLibraryDeserializationException {
    ContextCacheKey key = new ContextCacheKey(libraryProvider, topLevelLibraryIdentifier, terminologyProvider, this.externalFunctionProvider, evaluationDateTime, parameters);
    Context cqlContext;
    if (cacheContexts) {
        cqlContext = CONTEXT_CACHE.computeIfAbsent(key, this::createContext);
    } else {
        cqlContext = createContext(key);
    }
    // The following data elements need to be reset on every evaluation...
    Set<String> uris = getModelUrisForLibrary(cqlContext.getCurrentLibrary());
    for (String modelUri : uris) {
        cqlContext.registerDataProvider(modelUri, dataProvider);
    }
    resetContextValues(cqlContext);
    cqlContext.clearExpressions();
    if (contextData != null) {
        cqlContext.setContextValue(contextData.getKey(), contextData.getValue());
    }
    DebugMap debugMap = createDebugMap(debug);
    cqlContext.setDebugMap(debugMap);
    cqlContext.setExpressionCaching(this.cacheExpressions);
    cqlContext.clearEvaluatedResources();
    return cqlContext;
}
Also used : Context(org.opencds.cqf.cql.engine.execution.Context) DebugMap(org.opencds.cqf.cql.engine.debug.DebugMap)

Aggregations

Context (org.opencds.cqf.cql.engine.execution.Context)13 VersionedIdentifier (org.cqframework.cql.elm.execution.VersionedIdentifier)6 LibraryLoader (org.opencds.cqf.cql.engine.execution.LibraryLoader)6 FhirContext (ca.uhn.fhir.context.FhirContext)4 TerminologyProvider (org.opencds.cqf.cql.engine.terminology.TerminologyProvider)4 Map (java.util.Map)3 Test (org.junit.Test)3 DataProvider (org.opencds.cqf.cql.engine.data.DataProvider)3 SystemRequestDetails (ca.uhn.fhir.jpa.partition.SystemRequestDetails)2 RequestDetails (ca.uhn.fhir.rest.api.server.RequestDetails)2 BaseServerResponseException (ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException)2 InvalidRequestException (ca.uhn.fhir.rest.server.exceptions.InvalidRequestException)2 JsonParser (com.google.gson.JsonParser)2 CqlDataProvider (com.ibm.cohort.cql.data.CqlDataProvider)2 Parameter (com.ibm.cohort.cql.evaluation.parameters.Parameter)2 CqlVersionedIdentifier (com.ibm.cohort.cql.library.CqlVersionedIdentifier)2 CqlToElmTranslator (com.ibm.cohort.cql.translation.CqlToElmTranslator)2 CDMContext (com.ibm.cohort.engine.cqfruler.CDMContext)2 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2