use of ca.uhn.fhir.jpa.partition.SystemRequestDetails in project cqf-ruler by DBCG.
the class LibraryEvaluationProvider method evaluate.
@SuppressWarnings({ "unchecked" })
@Operation(name = "$evaluate", idempotent = true, type = Library.class)
public Bundle evaluate(@IdParam IdType theId, @OperationParam(name = "patientId") String patientId, @OperationParam(name = "periodStart") String periodStart, @OperationParam(name = "periodEnd") String periodEnd, @OperationParam(name = "productLine") String productLine, @OperationParam(name = "terminologyEndpoint") Endpoint terminologyEndpoint, @OperationParam(name = "dataEndpoint") Endpoint dataEndpoint, @OperationParam(name = "context") String contextParam, @OperationParam(name = "executionResults") String executionResults, @OperationParam(name = "parameters") Parameters parameters, @OperationParam(name = "additionalData") Bundle additionalData, RequestDetails theRequestDetails) {
log.info("Library evaluation started..");
if (patientId == null && contextParam != null && contextParam.equals("Patient")) {
log.error("Patient id null");
throw new IllegalArgumentException("Must specify a patientId when executing in Patient context.");
}
Bundle libraryBundle = new Bundle();
Library theResource = null;
if (additionalData != null) {
for (Bundle.BundleEntryComponent entry : additionalData.getEntry()) {
if (entry.getResource().fhirType().equals("Library")) {
libraryBundle.addEntry(entry);
if (entry.getResource().getIdElement().equals(theId)) {
theResource = (Library) entry.getResource();
}
}
}
}
if (theResource == null) {
theResource = read(theId, theRequestDetails);
}
VersionedIdentifier libraryIdentifier = new VersionedIdentifier().withId(theResource.getName()).withVersion(theResource.getVersion());
TerminologyProvider terminologyProvider;
if (terminologyEndpoint != null) {
IGenericClient client = Clients.forEndpoint(getFhirContext(), terminologyEndpoint);
terminologyProvider = new R4FhirTerminologyProvider(client);
} else {
terminologyProvider = myJpaTerminologyProviderFactory.create(new SystemRequestDetails());
}
DataProvider dataProvider;
if (dataEndpoint != null) {
List<RetrieveProvider> retrieveProviderList = new ArrayList<>();
IGenericClient client = Clients.forEndpoint(dataEndpoint);
RestFhirRetrieveProvider retriever = new RestFhirRetrieveProvider(new SearchParameterResolver(getFhirContext()), client);
retriever.setTerminologyProvider(terminologyProvider);
if (terminologyEndpoint == null || (terminologyEndpoint != null && !terminologyEndpoint.getAddress().equals(dataEndpoint.getAddress()))) {
retriever.setExpandValueSets(true);
}
retrieveProviderList.add(retriever);
if (additionalData != null) {
BundleRetrieveProvider bundleProvider = new BundleRetrieveProvider(getFhirContext(), additionalData);
bundleProvider.setTerminologyProvider(terminologyProvider);
retrieveProviderList.add(bundleProvider);
PriorityRetrieveProvider priorityProvider = new PriorityRetrieveProvider(retrieveProviderList);
dataProvider = new CompositeDataProvider(myModelResolver, priorityProvider);
} else {
dataProvider = new CompositeDataProvider(myModelResolver, retriever);
}
} else {
List<RetrieveProvider> retrieveProviderList = new ArrayList<>();
JpaFhirRetrieveProvider retriever = new JpaFhirRetrieveProvider(getDaoRegistry(), new SearchParameterResolver(getFhirContext()));
retriever.setTerminologyProvider(terminologyProvider);
// Assume it's a different server, therefore need to expand.
if (terminologyEndpoint != null) {
retriever.setExpandValueSets(true);
}
retrieveProviderList.add(retriever);
if (additionalData != null) {
BundleRetrieveProvider bundleProvider = new BundleRetrieveProvider(getFhirContext(), additionalData);
bundleProvider.setTerminologyProvider(terminologyProvider);
retrieveProviderList.add(bundleProvider);
PriorityRetrieveProvider priorityProvider = new PriorityRetrieveProvider(retrieveProviderList);
dataProvider = new CompositeDataProvider(myModelResolver, priorityProvider);
} else {
dataProvider = new CompositeDataProvider(myModelResolver, retriever);
}
}
LibraryContentProvider bundleLibraryProvider = new BundleFhirLibraryContentProvider(this.getFhirContext(), libraryBundle, adapterFactory, libraryVersionSelector);
LibraryContentProvider jpaLibraryContentProvider = this.myJpaLibraryContentProviderFactory.create(theRequestDetails);
List<LibraryContentProvider> sourceProviders = new ArrayList<LibraryContentProvider>(Arrays.asList(bundleLibraryProvider, jpaLibraryContentProvider));
LibraryLoader libraryLoader = this.myLibraryLoaderFactory.create(sourceProviders);
CqlEngine engine = new CqlEngine(libraryLoader, Collections.singletonMap("http://hl7.org/fhir", dataProvider), terminologyProvider);
Map<String, Object> resolvedParameters = new HashMap<>();
if (parameters != null) {
for (Parameters.ParametersParameterComponent pc : parameters.getParameter()) {
resolvedParameters.put(pc.getName(), pc.getValue());
}
}
if (periodStart != null && periodEnd != null) {
// resolve the measurement period
Interval measurementPeriod = new Interval(Operations.resolveRequestDate(periodStart, true), true, Operations.resolveRequestDate(periodEnd, false), true);
resolvedParameters.put("Measurement Period", new Interval(DateTime.fromJavaDate((Date) measurementPeriod.getStart()), true, DateTime.fromJavaDate((Date) measurementPeriod.getEnd()), true));
}
if (productLine != null) {
resolvedParameters.put("Product Line", productLine);
}
EvaluationResult evalResult = engine.evaluate(libraryIdentifier, null, Pair.of(contextParam != null ? contextParam : "Unspecified", patientId == null ? "null" : patientId), resolvedParameters, this.getDebugMap());
List<Resource> results = new ArrayList<>();
FhirMeasureBundler bundler = new FhirMeasureBundler();
if (evalResult != null && evalResult.expressionResults != null) {
for (Map.Entry<String, Object> def : evalResult.expressionResults.entrySet()) {
Parameters result = new Parameters();
try {
result.setId(def.getKey());
Object res = def.getValue();
if (res == null) {
result.addParameter().setName("value").setValue(new StringType("null"));
} else if (res instanceof List<?>) {
if (((List<?>) res).size() > 0 && ((List<?>) res).get(0) instanceof Resource) {
if (executionResults != null && executionResults.equals("Summary")) {
result.addParameter().setName("value").setValue(new StringType(((Resource) ((List<?>) res).get(0)).getIdElement().getResourceType() + "/" + ((Resource) ((List<?>) res).get(0)).getIdElement().getIdPart()));
} else {
result.addParameter().setName("value").setResource(bundler.bundle((Iterable<Resource>) res, theRequestDetails.getFhirServerBase()));
}
} else {
result.addParameter().setName("value").setValue(new StringType(res.toString()));
}
} else if (res instanceof Iterable) {
result.addParameter().setName("value").setResource(bundler.bundle((Iterable<Resource>) res, theRequestDetails.getFhirServerBase()));
} else if (res instanceof Resource) {
if (executionResults != null && executionResults.equals("Summary")) {
result.addParameter().setName("value").setValue(new StringType(((Resource) res).getIdElement().getResourceType() + "/" + ((Resource) res).getIdElement().getIdPart()));
} else {
result.addParameter().setName("value").setResource((Resource) res);
}
} else if (res instanceof Type) {
result.addParameter().setName("value").setValue((Type) res);
} else {
result.addParameter().setName("value").setValue(new StringType(res.toString()));
}
result.addParameter().setName("resultType").setValue(new StringType(resolveType(res)));
} catch (RuntimeException re) {
re.printStackTrace();
String message = re.getMessage() != null ? re.getMessage() : re.getClass().getName();
result.addParameter().setName("error").setValue(new StringType(message));
}
results.add(result);
}
}
return bundler.bundle(results, theRequestDetails.getFhirServerBase());
}
use of ca.uhn.fhir.jpa.partition.SystemRequestDetails 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);
}
}
use of ca.uhn.fhir.jpa.partition.SystemRequestDetails 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);
}
}
use of ca.uhn.fhir.jpa.partition.SystemRequestDetails in project cqf-ruler by DBCG.
the class PlanDefinitionApplyProviderIT method testPlanDefinitionApplyFormerSmoker.
@Test
public void testPlanDefinitionApplyFormerSmoker() throws Exception {
DomainResource plandefinition = (DomainResource) planDefinitions.get("lcs-cds-patient-view");
// Patient First
uploadTests("test/plandefinition/LungCancerScreening/Former-Smoker/Patient");
Map<String, IBaseResource> resources = uploadTests("test/plandefinition/LungCancerScreening/Former-Smoker");
IBaseResource patient = resources.get("Former-Smoker");
Object isFormerSmoker = planDefinitionApplyProvider.applyPlanDefinition(new SystemRequestDetails(), plandefinition.getIdElement(), patient.getIdElement().getIdPart(), null, null, null, null, null, null, null, null);
assertTrue(isFormerSmoker instanceof CarePlan);
}
use of ca.uhn.fhir.jpa.partition.SystemRequestDetails in project cqf-ruler by DBCG.
the class SubmitDataProviderIT method testSubmitData.
@Test
public void testSubmitData() {
// Create a MR and a resource
MeasureReport mr = newResource(MeasureReport.class, "test-mr");
Observation obs = newResource(Observation.class, "test-obs");
// Submit it
mySubmitDataProvider.submitData(new SystemRequestDetails(), new IdType("Measure", "test-m"), mr, Lists.newArrayList(obs));
// Check if they made it to the db
Observation savedObs = read(obs.getIdElement());
assertNotNull(savedObs);
MeasureReport savedMr = read(mr.getIdElement());
assertNotNull(savedMr);
}
Aggregations