diff --git a/server/src/main/java/org/hl7/davinci/endpoint/Utils.java b/server/src/main/java/org/hl7/davinci/endpoint/Utils.java index 4d407e93c..c85e2f452 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/Utils.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/Utils.java @@ -2,6 +2,7 @@ import java.net.MalformedURLException; import java.net.URL; +import java.util.List; import javax.servlet.http.HttpServletRequest; import com.google.common.net.HttpHeaders; @@ -38,4 +39,27 @@ public static URL getApplicationBaseUrl(HttpServletRequest request) { } } + public static String stripResourceType(String identifier) { + int indexOfDivider = identifier.indexOf('/'); + if (indexOfDivider+1 == identifier.length()) { + // remove the trailing '/' + return identifier.substring(0, indexOfDivider); + } else { + return identifier.substring(indexOfDivider+1); + } + } + + public static boolean idInSelectionsList(String identifier, List selections) { + if (selections.isEmpty()) { + return true; + } else { + for ( String selection : selections) { + if (identifier.contains(stripResourceType(selection))) { + return true; + } + } + return false; + } + } + } diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java new file mode 100644 index 000000000..750e37322 --- /dev/null +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsAbstract.java @@ -0,0 +1,161 @@ +package org.hl7.davinci.endpoint.cdshooks.services.crd; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.cdshooks.*; +import org.hl7.davinci.FhirComponentsT; +import org.hl7.davinci.PrefetchTemplateElement; +import org.hl7.davinci.endpoint.config.YamlConfig; +import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria; +import org.hl7.davinci.r4.crdhook.DiscoveryExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.List; + +@Component +public abstract class CdsAbstract>{ + static final Logger logger = LoggerFactory.getLogger(CdsAbstract.class); + + /** + * The {id} portion of the URL to this service which is available at + * {baseUrl}/cds-services/{id}. REQUIRED + */ + public String id; + + /** + * The hook this service should be invoked on. REQUIRED + */ + public Hook hook; + + /** + * The human-friendly name of this service. RECOMMENDED + */ + public String title; + + /** + * The description of this service. REQUIRED + */ + public String description; + + /** + * An object containing key/value pairs of FHIR queries that this service is + * requesting that the EHR prefetch and provide on each service call. The key is + * a string that describes the type of data being requested and the value is a + * string representing the FHIR query. OPTIONAL + */ + public Prefetch prefetch; + + private final List prefetchElements; + + protected FhirComponentsT fhirComponents; + + private final DiscoveryExtension extension; + + @Autowired + @JsonIgnore + public YamlConfig myConfig; + + public CdsAbstract(String id, Hook hook, String title, String description, + List prefetchElements, FhirComponentsT fhirComponents, + DiscoveryExtension extension) { + + if (id == null) { + throw new NullPointerException("CDSService id cannot be null"); + } + if (hook == null) { + throw new NullPointerException("CDSService hook cannot be null"); + } + if (description == null) { + throw new NullPointerException("CDSService description cannot be null"); + } + this.id = id; + this.hook = hook; + this.title = title; + this.description = description; + this.prefetchElements = prefetchElements; + prefetch = new Prefetch(); + for (PrefetchTemplateElement prefetchElement : prefetchElements) { + this.prefetch.put(prefetchElement.getKey(), prefetchElement.getQuery()); + } + this.fhirComponents = fhirComponents; + this.extension = extension; + } + + public DiscoveryExtension getExtension() { return extension; } + + public List getPrefetchElements() { + return prefetchElements; + } + + protected Link smartLinkBuilder(String patientId, String fhirBase, URL applicationBaseUrl, String questionnaireUri, + String reqResourceId, CoverageRequirementRuleCriteria criteria, boolean priorAuthRequired, String label) { + URI configLaunchUri = myConfig.getLaunchUrl(); + questionnaireUri = applicationBaseUrl + "/fhir/r4/" + questionnaireUri; + + String launchUrl; + if (myConfig.getLaunchUrl().isAbsolute()) { + launchUrl = myConfig.getLaunchUrl().toString(); + } else { + try { + launchUrl = new URL(applicationBaseUrl.getProtocol(), applicationBaseUrl.getHost(), + applicationBaseUrl.getPort(), applicationBaseUrl.getFile() + configLaunchUri.toString(), null).toString(); + } catch (MalformedURLException e) { + String msg = "Error creating smart launch URL"; + logger.error(msg); + throw new RuntimeException(msg); + } + } + + if (fhirBase != null && fhirBase.endsWith("/")) { + fhirBase = fhirBase.substring(0, fhirBase.length() - 1); + } + if (patientId != null && patientId.startsWith("Patient/")) { + patientId = patientId.substring(8); + } + + // PARAMS: + // template is the uri of the questionnaire + // request is the ID of the device request or medrec (not the full URI like the + // IG says, since it should be taken from fhirBase + + String filepath = "../../getfile/" + criteria.getQueryString(); + + String appContext = "template=" + questionnaireUri + "&request=" + reqResourceId; + appContext = appContext + "&fhirpath=" + applicationBaseUrl + "/fhir/"; + + appContext = appContext + "&priorauth=" + (priorAuthRequired ? "true" : "false"); + appContext = appContext + "&filepath=" + applicationBaseUrl + "/"; + if (myConfig.getUrlEncodeAppContext()) { + logger.info("CdsService::smartLinkBuilder: URL encoding appcontext"); + appContext = URLEncoder.encode(appContext, StandardCharsets.UTF_8).toString(); + } + + logger.info("smarLinkBuilder: appContext: " + appContext); + + if (myConfig.isAppendParamsToSmartLaunchUrl()) { + launchUrl = launchUrl + "?iss=" + fhirBase + "&patientId=" + patientId + "&template=" + questionnaireUri + + "&request=" + reqResourceId; + } else { + // TODO: The iss should be set by the EHR? + launchUrl = launchUrl; + } + + Link link = new Link(); + link.setType("smart"); + link.setLabel(label); + link.setUrl(launchUrl); + + link.setAppContext(appContext); + + return link; + } + + public abstract CdsResponse handleRequest(requestTypeT request, URL applicationBaseUrl); +} diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java index 8423ffbba..a2aec34ea 100755 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsService.java @@ -1,31 +1,19 @@ package org.hl7.davinci.endpoint.cdshooks.services.crd; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.ArrayList; -import java.util.Date; -import javax.validation.Valid; - import org.apache.commons.lang.StringUtils; import org.cdshooks.*; import org.hl7.davinci.FhirComponentsT; import org.hl7.davinci.PrefetchTemplateElement; import org.hl7.davinci.RequestIncompleteException; -import org.hl7.davinci.endpoint.config.YamlConfig; import org.hl7.davinci.endpoint.components.CardBuilder; import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard; import org.hl7.davinci.endpoint.components.PrefetchHydrator; import org.hl7.davinci.endpoint.database.RequestLog; import org.hl7.davinci.endpoint.database.RequestService; import org.hl7.davinci.endpoint.files.FileStore; -import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleCriteria; import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult; -import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest; import org.hl7.davinci.r4.crdhook.DiscoveryExtension; +import org.hl7.davinci.r4.crdhook.orderselect.OrderSelectRequest; import org.opencds.cqf.cql.engine.execution.Context; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,96 +21,26 @@ import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestBody; +import javax.validation.Valid; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + @Component -public abstract class CdsService> { +public abstract class CdsService> extends CdsAbstract { static final Logger logger = LoggerFactory.getLogger(CdsService.class); - /** - * The {id} portion of the URL to this service which is available at - * {baseUrl}/cds-services/{id}. REQUIRED - */ - public String id; - - /** - * The hook this service should be invoked on. REQUIRED - */ - public Hook hook; - - /** - * The human-friendly name of this service. RECOMMENDED - */ - public String title; - - /** - * The description of this service. REQUIRED - */ - public String description; - - /** - * An object containing key/value pairs of FHIR queries that this service is - * requesting that the EHR prefetch and provide on each service call. The key is - * a string that describes the type of data being requested and the value is a - * string representing the FHIR query. OPTIONAL - */ - public Prefetch prefetch; - - @Autowired - private YamlConfig myConfig; - @Autowired RequestService requestService; @Autowired FileStore fileStore; - private final List prefetchElements; - - protected FhirComponentsT fhirComponents; - - private final DiscoveryExtension extension; - - /** - * Create a new cdsservice. - * - * @param id Will be used in the url, should be unique. - * @param hook Which hook can call this. - * @param title Human title. - * @param description Human description. - * @param prefetchElements List of prefetch elements, will be in prefetch - * template. - * @param fhirComponents Fhir components to use - * @param extension Custom CDS Hooks extensions. - */ public CdsService(String id, Hook hook, String title, String description, List prefetchElements, FhirComponentsT fhirComponents, DiscoveryExtension extension) { - - if (id == null) { - throw new NullPointerException("CDSService id cannot be null"); - } - if (hook == null) { - throw new NullPointerException("CDSService hook cannot be null"); - } - if (description == null) { - throw new NullPointerException("CDSService description cannot be null"); - } - this.id = id; - this.hook = hook; - this.title = title; - this.description = description; - this.prefetchElements = prefetchElements; - prefetch = new Prefetch(); - for (PrefetchTemplateElement prefetchElement : prefetchElements) { - this.prefetch.put(prefetchElement.getKey(), prefetchElement.getQuery()); - } - this.fhirComponents = fhirComponents; - this.extension = extension; - } - - public DiscoveryExtension getExtension() { return extension; } - - public List getPrefetchElements() { - return prefetchElements; + super(id, hook, title, description, prefetchElements, fhirComponents, extension); } /** @@ -239,7 +157,7 @@ public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL a CardBuilder.errorCardIfNonePresent(response); } - // Ading card to requestLog + // Adding card to requestLog requestLog.setCardListFromCards(response.getCards()); requestService.edit(requestLog); @@ -304,68 +222,7 @@ protected Object evaluateStatement(String statement, Context context) { } } - private Link smartLinkBuilder(String patientId, String fhirBase, URL applicationBaseUrl, String questionnaireUri, - String reqResourceId, CoverageRequirementRuleCriteria criteria, boolean priorAuthRequired, String label) { - URI configLaunchUri = myConfig.getLaunchUrl(); - questionnaireUri = applicationBaseUrl + "/fhir/r4/" + questionnaireUri; - - String launchUrl; - if (myConfig.getLaunchUrl().isAbsolute()) { - launchUrl = myConfig.getLaunchUrl().toString(); - } else { - try { - launchUrl = new URL(applicationBaseUrl.getProtocol(), applicationBaseUrl.getHost(), - applicationBaseUrl.getPort(), applicationBaseUrl.getFile() + configLaunchUri.toString(), null).toString(); - } catch (MalformedURLException e) { - String msg = "Error creating smart launch URL"; - logger.error(msg); - throw new RuntimeException(msg); - } - } - - if (fhirBase != null && fhirBase.endsWith("/")) { - fhirBase = fhirBase.substring(0, fhirBase.length() - 1); - } - if (patientId != null && patientId.startsWith("Patient/")) { - patientId = patientId.substring(8); - } - - // PARAMS: - // template is the uri of the questionnaire - // request is the ID of the device request or medrec (not the full URI like the - // IG says, since it should be taken from fhirBase - - String filepath = "../../getfile/" + criteria.getQueryString(); - String appContext = "template=" + questionnaireUri + "&request=" + reqResourceId; - appContext = appContext + "&fhirpath=" + applicationBaseUrl + "/fhir/"; - - appContext = appContext + "&priorauth=" + (priorAuthRequired ? "true" : "false"); - appContext = appContext + "&filepath=" + applicationBaseUrl + "/"; - if (myConfig.getUrlEncodeAppContext()) { - logger.info("CdsService::smartLinkBuilder: URL encoding appcontext"); - appContext = URLEncoder.encode(appContext, StandardCharsets.UTF_8).toString(); - } - - logger.info("smarLinkBuilder: appContext: " + appContext); - - if (myConfig.isAppendParamsToSmartLaunchUrl()) { - launchUrl = launchUrl + "?iss=" + fhirBase + "&patientId=" + patientId + "&template=" + questionnaireUri - + "&request=" + reqResourceId; - } else { - // TODO: The iss should be set by the EHR? - launchUrl = launchUrl; - } - - Link link = new Link(); - link.setType("smart"); - link.setLabel(label); - link.setUrl(launchUrl); - - link.setAppContext(appContext); - - return link; - } // Implement these in child class public abstract List createCqlExecutionContexts(requestTypeT request, diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java index 2e08fbcbc..ca7ea731c 100755 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceInformation.java @@ -4,14 +4,14 @@ import java.util.List; public class CdsServiceInformation { - private List services = null; + private List services = null; /** * Add a service. * @param servicesItem The service. * @return */ - public CdsServiceInformation addServicesItem(CdsService servicesItem) { + public CdsServiceInformation addServicesItem(CdsAbstract servicesItem) { if (this.services == null) { this.services = new ArrayList<>(); } @@ -19,11 +19,11 @@ public CdsServiceInformation addServicesItem(CdsService servicesItem) { return this; } - public List getServices() { + public List getServices() { return services; } - public void setServices(List services) { + public void setServices(List services) { this.services = services; } } diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java new file mode 100644 index 000000000..f6e5dbe63 --- /dev/null +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/CdsServiceRems.java @@ -0,0 +1,86 @@ +package org.hl7.davinci.endpoint.cdshooks.services.crd; + +import org.cdshooks.Card; +import org.cdshooks.CdsRequest; +import org.cdshooks.CdsResponse; +import org.cdshooks.Hook; +import org.hl7.davinci.FhirComponentsT; +import org.hl7.davinci.PrefetchTemplateElement; +import org.hl7.davinci.endpoint.components.CardBuilder; +import org.hl7.davinci.r4.crdhook.DiscoveryExtension; +import org.hl7.fhir.r4.model.Coding; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.validation.Valid; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +@Component +public abstract class CdsServiceRems> extends CdsAbstract { + static final Logger logger = LoggerFactory.getLogger(CdsServiceRems.class); + + public List remsDrugs = new ArrayList<>(); + + public CdsServiceRems(String id, Hook hook, String title, String description, + List prefetchElements, FhirComponentsT fhirComponents, + DiscoveryExtension extension) { + super(id, hook, title, description, prefetchElements, fhirComponents, extension); + Coding turalio = new Coding() + .setCode("2183126") + .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") + .setDisplay("Turalio"); + Coding iPledge = new Coding() + .setCode("6064") + .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") + .setDisplay("Isotretinoin"); + Coding revlimid = new Coding() + .setCode("337535") + .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") + .setDisplay("Revlimid"); + Coding abstral = new Coding() + .setCode("1053648") + .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") + .setDisplay("Abstral"); + remsDrugs.add(turalio); + remsDrugs.add(iPledge); + remsDrugs.add(revlimid); + remsDrugs.add(abstral); + } + + /** + * Performs generic operations for incoming requests of any type. + * + * @param request the generically typed incoming request + * @return The response from the server + */ + public CdsResponse handleRequest(@Valid @RequestBody requestTypeT request, URL applicationBaseUrl) { + CdsResponse response = new CdsResponse(); + List medications = getMedications(request); + for (Coding medication : medications) { + Card card = CardBuilder.summaryCard(""); + if (isRemsDrug(medication)) { + card.setSummary(String.format("%s is a REMS drug", medication.getDisplay())); + } else { + card.setSummary(String.format("%s is not a REMS drug", medication.getDisplay())); + } + response.addCard(card); + } + return response; + } + + private boolean isRemsDrug(Coding medication) { + for( Coding remsDrug : remsDrugs){ + if (remsDrug.getCode().equals(medication.getCode())){ + return true; + } + } + return false; + } + + public abstract List getMedications(requestTypeT request); + +} \ No newline at end of file diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java index 538169ef9..a5be23692 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/FhirBundleProcessor.java @@ -18,6 +18,8 @@ import java.util.List; import java.util.stream.Collectors; +import static org.hl7.davinci.endpoint.Utils.idInSelectionsList; + public class FhirBundleProcessor { static final Logger logger = LoggerFactory.getLogger(FhirBundleProcessor.class); @@ -48,7 +50,7 @@ public void processDeviceRequests() { logger.info("r4/FhirBundleProcessor::getAndProcessDeviceRequests: DeviceRequest(s) found"); for (DeviceRequest deviceRequest : deviceRequestList) { - if (idInSelectionsList(deviceRequest.getId())) { + if (idInSelectionsList(deviceRequest.getId(), selections)) { List criteriaList = createCriteriaList(deviceRequest.getCodeCodeableConcept(), deviceRequest.getInsurance(), null); buildExecutionContexts(criteriaList, (Patient) deviceRequest.getSubject().getResource(), "device_request", deviceRequest); } @@ -63,7 +65,7 @@ public void processMedicationRequests() { logger.info("r4/FhirBundleProcessor::getAndProcessMedicationRequests: MedicationRequest(s) found"); for (MedicationRequest medicationRequest : medicationRequestList) { - if (idInSelectionsList(medicationRequest.getId())) { + if (idInSelectionsList(medicationRequest.getId(), selections)) { List criteriaList = createCriteriaList(medicationRequest.getMedicationCodeableConcept(), medicationRequest.getInsurance(), null); buildExecutionContexts(criteriaList, (Patient) medicationRequest.getSubject().getResource(), "medication_request", medicationRequest); } @@ -81,7 +83,7 @@ public void processMedicationDispenses() { medicationDispenseBundle); for (MedicationDispense medicationDispense : medicationDispenseList) { - if (idInSelectionsList(medicationDispense.getId())) { + if (idInSelectionsList(medicationDispense.getId(), selections)) { List criteriaList = createCriteriaList(medicationDispense.getMedicationCodeableConcept(), null, payorList); buildExecutionContexts(criteriaList, (Patient) medicationDispense.getSubject().getResource(), "medication_dispense", medicationDispense); } @@ -96,7 +98,7 @@ public void processServiceRequests() { logger.info("r4/FhirBundleProcessor::getAndProcessServiceRequests: ServiceRequest(s) found"); for (ServiceRequest serviceRequest : serviceRequestList) { - if (idInSelectionsList(serviceRequest.getId())) { + if (idInSelectionsList(serviceRequest.getId(), selections)) { List criteriaList = createCriteriaList(serviceRequest.getCode(), serviceRequest.getInsurance(), null); buildExecutionContexts(criteriaList, (Patient) serviceRequest.getSubject().getResource(), "service_request", serviceRequest); } @@ -116,7 +118,7 @@ public void processOrderSelectMedicationStatements() { // process each of the MedicationRequests for (MedicationRequest medicationRequest : medicationRequestList) { - if (idInSelectionsList(medicationRequest.getId())) { + if (idInSelectionsList(medicationRequest.getId(), selections)) { // run on each of the MedicationStatements for (MedicationStatement medicationStatement : medicationStatementList) { @@ -210,29 +212,4 @@ private void buildExecutionContexts(List criter } } - private String stripResourceType(String identifier) { - int indexOfDivider = identifier.indexOf('/'); - if (indexOfDivider+1 == identifier.length()) { - // remove the trailing '/' - return identifier.substring(0, indexOfDivider); - } else { - return identifier.substring(indexOfDivider+1); - } - } - - private boolean idInSelectionsList(String identifier) { - if (this.selections.isEmpty()) { - // if selections list is empty, just assume we should process the request - return true; - } else { - for ( String selection : selections) { - if (identifier.contains(stripResourceType(selection))) { - logger.info("r4/FhirBundleProcessor::idInSelectionsList(" + identifier + "): identifier found in selections list"); - return true; - } - } - return false; - } - } - } diff --git a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java index 2c0a671f1..a5cf2824b 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/cdshooks/services/crd/r4/OrderSelectServiceRems.java @@ -1,14 +1,9 @@ package org.hl7.davinci.endpoint.cdshooks.services.crd.r4; -import org.cdshooks.Card; -import org.cdshooks.CdsResponse; import org.cdshooks.Hook; import org.hl7.davinci.PrefetchTemplateElement; -import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsService; -import org.hl7.davinci.endpoint.components.CardBuilder; -import org.hl7.davinci.endpoint.components.CardBuilder.CqlResultsForCard; -import org.hl7.davinci.endpoint.files.FileStore; -import org.hl7.davinci.endpoint.rules.CoverageRequirementRuleResult; +import org.hl7.davinci.endpoint.Utils; +import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsServiceRems; import org.hl7.davinci.r4.FhirComponents; import org.hl7.davinci.r4.Utilities; import org.hl7.davinci.r4.crdhook.CrdPrefetch; @@ -17,25 +12,17 @@ import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.MedicationRequest; -import org.opencds.cqf.cql.engine.execution.Context; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.RequestBody; -import javax.validation.Valid; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Component("r4_OrderSelectServiceRems") -public class OrderSelectServiceRems extends CdsService { - - @Autowired - FileStore fileStore; +public class OrderSelectServiceRems extends CdsServiceRems { public static final String ID = "order-select-rems"; public static final String TITLE = "order-select-rems Coverage Requirements Discovery"; @@ -52,80 +39,15 @@ public class OrderSelectServiceRems extends CdsService { public OrderSelectServiceRems() { super(ID, HOOK, TITLE, DESCRIPTION, PREFETCH_ELEMENTS, FHIRCOMPONENTS, null); - Coding turalio = new Coding() - .setCode("2183126") - .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") - .setDisplay("Turalio"); - Coding iPledge = new Coding() - .setCode("6064") - .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") - .setDisplay("Isotretinoin"); - Coding revlimid = new Coding() - .setCode("337535") - .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") - .setDisplay("Revlimid"); - Coding abstral = new Coding() - .setCode("1053648") - .setSystem("http://www.nlm.nih.gov/research/umls/rxnorm") - .setDisplay("Abstral"); - remsDrugs.add(turalio); - remsDrugs.add(iPledge); - remsDrugs.add(revlimid); - remsDrugs.add(abstral); } - @Override - public CdsResponse handleRequest(@Valid @RequestBody OrderSelectRequest request, URL applicationBaseUrl) { - CdsResponse response = new CdsResponse(); + + public List getMedications(OrderSelectRequest request) { List selections = Arrays.asList(request.getContext().getSelections()); CrdPrefetch prefetch = request.getPrefetch(); List medications = getSelections(prefetch, selections); - for (Coding medication : medications) { - Card card = CardBuilder.summaryCard(""); - if (isRemsDrug(medication)) { - card.setSummary(String.format("%s is a REMS drug", medication.getDisplay())); - } else { - card.setSummary(String.format("%s is not a REMS drug", medication.getDisplay())); - } - response.addCard(card); - } - return response; - } - - // TODO: Change hard-coded drug checking - private boolean isRemsDrug(Coding medication) { - for( Coding remsDrug : remsDrugs){ - if (remsDrug.getCode().equals(medication.getCode())){ - return true; - } - } - return false; + return medications; } - // TODO: This function is direct from FhirBundleProcessor, it should be moved to a util class - private boolean idInSelectionsList(String identifier, List selections) { - if (selections.isEmpty()) { - return true; - } else { - for ( String selection : selections) { - if (identifier.contains(stripResourceType(selection))) { - return true; - } - } - return false; - } - } - - // TODO: This function is direct from FhirBundleProcessor, it should be moved to a util class - private String stripResourceType(String identifier) { - int indexOfDivider = identifier.indexOf('/'); - if (indexOfDivider+1 == identifier.length()) { - // remove the trailing '/' - return identifier.substring(0, indexOfDivider); - } else { - return identifier.substring(indexOfDivider+1); - } - } - public List getSelections(CrdPrefetch prefetch, List selections) { Bundle medicationRequestBundle = prefetch.getMedicationRequestBundle(); List medicationRequestList = Utilities.getResourcesOfTypeFromBundle(MedicationRequest.class, medicationRequestBundle); @@ -133,7 +55,7 @@ public List getSelections(CrdPrefetch prefetch, List selections) if (!medicationRequestList.isEmpty()) { for (MedicationRequest medicationRequest : medicationRequestList) { - if (idInSelectionsList(medicationRequest.getId(), selections)) { + if (Utils.idInSelectionsList(medicationRequest.getId(), selections)) { codings.add(medicationRequest.getMedicationCodeableConcept().getCodingFirstRep()); // assume there is only 1 coding per MR } } @@ -142,14 +64,4 @@ public List getSelections(CrdPrefetch prefetch, List selections) return codings; } - // This function could be removed, need to evaluate if we should make this class not an extension of CdsService - @Override - public List createCqlExecutionContexts(OrderSelectRequest orderSelectRequest, FileStore fileStore, String baseUrl) { - return new ArrayList<>(); - } - - // This function could be removed, need to evaluate if we should make this class not an extension of CdsService - protected CqlResultsForCard executeCqlAndGetRelevantResults(Context context, String topic) { - return new CqlResultsForCard(); - } } diff --git a/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java b/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java index fd799d2b9..b3afdfcc3 100644 --- a/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java +++ b/server/src/main/java/org/hl7/davinci/endpoint/controllers/r4/CdsHooksController.java @@ -1,7 +1,5 @@ package org.hl7.davinci.endpoint.controllers.r4; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; import org.cdshooks.CdsResponse; import org.hl7.davinci.endpoint.Utils; import org.hl7.davinci.endpoint.cdshooks.services.crd.CdsServiceInformation; @@ -14,14 +12,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import java.io.IOException; -import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; @RestController("r4_CdsHooksController") public class CdsHooksController {