edu.harvard.i2b2.fhir.server.ws.I2b2FhirWS.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.i2b2.fhir.server.ws.I2b2FhirWS.java

Source

/*
 * Copyright (c) 2006-2007 Massachusetts General Hospital 
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the i2b2 Software License v1.0 
 * which accompanies this distribution. 
 * 
 * Contributors:
 *       Kavishwar Wagholikar (kavi)
 *       July 4, 2015
 */

package edu.harvard.i2b2.fhir.server.ws;

import java.net.URI;
import java.net.URISyntaxException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.xml.bind.JAXBException;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.NumberUtils;
import org.apache.commons.lang.StringUtils;
import org.hl7.fhir.Bundle;
import org.hl7.fhir.BundleLink;
import org.hl7.fhir.Code;
import org.hl7.fhir.Conformance;
import org.hl7.fhir.ConformanceInteraction;
import org.hl7.fhir.ConformanceResource;
import org.hl7.fhir.ConformanceRest;
import org.hl7.fhir.ConformanceSearchParam;
import org.hl7.fhir.ConformanceSecurity;
import org.hl7.fhir.ConformanceStatementKind;
import org.hl7.fhir.ConformanceStatementKindList;
import org.hl7.fhir.Extension;
import org.hl7.fhir.Id;
import org.hl7.fhir.IssueSeverity;
import org.hl7.fhir.IssueSeverityList;
import org.hl7.fhir.IssueType;
import org.hl7.fhir.IssueTypeList;
import org.hl7.fhir.Narrative;
import org.hl7.fhir.NarrativeStatusList;
import org.hl7.fhir.OperationOutcome;
import org.hl7.fhir.OperationOutcomeIssue;
import org.hl7.fhir.Parameters;
import org.hl7.fhir.ParametersParameter;
import org.hl7.fhir.Resource;
import org.hl7.fhir.TypeRestfulInteraction;
import org.hl7.fhir.TypeRestfulInteractionList;
import org.hl7.fhir.UnknownContentCode;
import org.hl7.fhir.UnknownContentCodeList;
import org.hl7.fhir.Uri;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3._1999.xhtml.Div;
import org.xml.sax.SAXException;

import ca.uhn.fhir.model.dstu2.resource.Patient;
import edu.harvard.i2b2.Icd9.Icd9Mapper;
import edu.harvard.i2b2.fhir.*;
import edu.harvard.i2b2.fhir.oauth2.ws.AuthenticationFilter;
import edu.harvard.i2b2.fhir.oauth2.ws.HttpHelper;
import edu.harvard.i2b2.fhir.server.ServerConfigs;
import edu.harvard.i2b2.fhir.server.ws.operation.CdsHook;
import edu.harvard.i2b2.fhir.server.ws.operation.DSSEvaluate;
import edu.harvard.i2b2.fhir.server.ws.operation.Validate;
import edu.harvard.i2b2.loinc.LoincMapper;
import edu.harvard.i2b2.oauth2.core.ejb.AuthenticationService;
import edu.harvard.i2b2.oauth2.core.ejb.PatientBundleManager;
import edu.harvard.i2b2.oauth2.core.ejb.ProjectPatientMapManager;
import edu.harvard.i2b2.oauth2.core.ejb.QueryService;
import edu.harvard.i2b2.rxnorm.NdcToRxNormMapper;

/*
 * to use accessToken for authentication
 */
@Path("")
public class I2b2FhirWS {
    static Logger logger = LoggerFactory.getLogger(I2b2FhirWS.class);

    @EJB
    AuthenticationService authService;

    String i2b2SessionId;
    // contains ids of patients already called.

    @EJB
    PatientBundleManager service;

    @EJB
    ProjectPatientMapManager ppmMgr;

    @EJB
    QueryService queryManager;

    @javax.ws.rs.core.Context
    ServletContext context;

    @EJB
    ServerConfigs serverConfigs;

    @PostConstruct
    private void init() {

        try {
            // to remove prop and use server config
            // Properties props = new Properties();
            // props.load(getClass().getResourceAsStream("/log4j.properties"));
            // PropertyConfigurator.configure(props);

            logger.info("Got init request");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // everything
    @GET
    @Path("Patient/{resourceId:[0-9a-zA-Z|-]+}/$everything")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response everythingWrapper(@PathParam("compartmentName") String compartmentName,
            @PathParam("resourceId") String resourceId, @QueryParam("_include") List<String> includeResources,
            @QueryParam("filterf") String filterf, @HeaderParam("accept") String acceptHeader,
            @Context HttpHeaders headers, @Context HttpServletRequest request,
            @Context ServletContext servletContext) throws IOException, URISyntaxException {

        HttpSession session = request.getSession();
        URI fhirBase = HttpHelper.getBasePath(request, serverConfigs);
        String basePath = fhirBase.toString().split("patient")[0];
        String serverUriPath = HttpHelper.getServerUri(request, serverConfigs).toString();
        // basePath=(new URI(basePath)).toString();
        logger.trace("basePath:" + basePath);
        String queryString = "patient=" + resourceId;
        String requestUri = compartmentName;
        String rawRequest = basePath + request.getRequestURI();
        return getQueryResultCore("everything", basePath, requestUri, queryString,
                request.getRequestURL().toString(), includeResources, filterf, acceptHeader, headers, session,
                serverUriPath);

    }

    // compartment
    @GET
    @Path("Patient/{resourceId:[0-9a-zA-Z|-]+}/{compartmentName:" + FhirUtil.RESOURCE_LIST_REGEX + "}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response compartmentWrapper(@PathParam("compartmentName") String compartmentName,
            @PathParam("resourceId") String resourceId, @QueryParam("_include") List<String> includeResources,
            @QueryParam("filterf") String filterf, @HeaderParam("accept") String acceptHeader,
            @Context HttpHeaders headers, @Context HttpServletRequest request,
            @Context ServletContext servletContext) throws IOException, URISyntaxException {

        HttpSession session = request.getSession();
        URI fhirBase = HttpHelper.getBasePath(request, serverConfigs);
        String basePath = fhirBase.toString().split("patient")[0];
        String serverUriPath = HttpHelper.getServerUri(request, serverConfigs).toString();
        // basePath=(new URI(basePath)).toString();
        logger.trace("basePath:" + basePath);
        String queryString = "patient=" + resourceId;
        String requestUri = compartmentName;
        String rawRequest = basePath + request.getRequestURI();
        return getQueryResultCore(compartmentName, basePath, requestUri, queryString,
                request.getRequestURL().toString(), includeResources, filterf, acceptHeader, headers, session,
                serverUriPath);

    }

    @GET
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response getQueryResult(@PathParam("resourceName") String resourceName,
            @QueryParam("_include") List<String> includeResources, @QueryParam("filterf") String filterf,
            @QueryParam("_include") List<String> pageNum, @HeaderParam("accept") String acceptHeader,
            @Context HttpHeaders headers, @Context HttpServletRequest request,
            @Context ServletContext servletContext) throws IOException, URISyntaxException {

        HttpSession session = request.getSession();
        URI fhirBase = HttpHelper.getBasePath(request, serverConfigs);
        String basePath = fhirBase.toString();
        String serverUriPath = HttpHelper.getServerUri(request, serverConfigs).toString();
        logger.trace("basePath:" + basePath);

        return getQueryResultCore(resourceName, basePath, request.getRequestURI(), request.getQueryString(),
                request.getRequestURI() + "?" + request.getQueryString(), includeResources, filterf, acceptHeader,
                headers, session, serverUriPath);

    }

    public Response getQueryResultCore(String resourceName, String basePath, String requestUri, String queryString,
            String rawRequestUrl, List<String> includeResources, String filterf, String acceptHeader,
            HttpHeaders headers, HttpSession session, String serverUriPath) throws IOException {

        String msg = null;
        String mediaType = null;
        Bundle s = null;

        MetaResourceDb md = new MetaResourceDb();

        logger.debug("got request parts: " + requestUri + "?" + queryString);
        logger.trace("basePath:" + basePath);

        try {
            logger.info("Query string:" + queryString);

            String head = "";
            for (String h : headers.getRequestHeaders().keySet()) {
                head += "Header->" + h + ":" + headers.getRequestHeader(h);

            }
            logger.info(head);

            // md = I2b2Helper.getMetaResourceDb(session, sbb);

            Class c = FhirUtil.getResourceClass(resourceName);

            logger.trace("rawRequestUrl:" + rawRequestUrl);
            // String basePath =rawRequestUrl.split(resourceName)[0];
            logger.debug("session id:" + session.getId());

            authService.authenticateSession(
                    headers.getRequestHeader(AuthenticationFilter.AUTHENTICATION_HEADER).get(0), session);

            s = I2b2Helper.parsePatientIdToFetchPDO(session, requestUri, queryString, c.getSimpleName(), service,
                    ppmMgr, null);

            if (!(c.equals("$everything"))) {

                if (FhirHelper.isPatientDependentResource(c)) {
                    md.addBundle(s);
                } else {
                    FhirHelper.loadTestResources(md);
                }
                logger.info("running filter...");
                s = FhirUtil.getResourceBundle(md.getAll(c), basePath, "url");
            }
            logger.info("running sophisticated query for:" + queryString);

            if (queryString != null) {
                String fhirQuery = c.getSimpleName() + "?" + queryString;

                // optimization to avoid query search on patient id
                if (false// XXX
                        && !c.equals(Patient.class)) {
                    fhirQuery = fhirQuery.replaceAll("\\?patient=(\\d+)", "");
                    fhirQuery = fhirQuery.replaceAll("\\?subject=(\\d+)", "");
                    logger.trace("bypassing sophisticated query");
                } else {
                    s = queryManager.runQueryEngine(fhirQuery, s, basePath);
                }
            }

            logger.info("including...._include:" + includeResources.toString());
            if (s.getEntry().size() > 0) {
                List<Resource> list = md.getIncludedResources(c, FhirUtil.getResourceListFromBundle(s),
                        includeResources);
                logger.trace("includedListsize:" + list.size());
                logger.trace("basePath:" + basePath);
                s = FhirUtil.getResourceBundle(list, basePath, "url");
            }

            s.getLink().add(FhirUtil.createBundleLink("self", serverUriPath + requestUri + "?"
                    + ((queryString != null) ? queryString.replaceAll("&page=\\d+", "") : "")));

            // logger.info("getting bundle string..."+JAXBUtil.toXml(s));
            // logger.info("size of db:" + md.getSize());

            int pageNum = 1;
            int countNum = 20;
            if (queryString != null) {
                Pattern p = Pattern.compile(".*page=(\\d+).*");
                Matcher m = p.matcher(queryString);
                if (m.matches()) {
                    String pageNumStr = m.group(1);
                    logger.info("pageNum=" + pageNumStr);
                    try {
                        pageNum = Integer.valueOf(pageNumStr, 10);
                    } catch (Exception e) {
                        throw new FhirServerException(
                                "page parameter should be a number: Current value is :" + pageNumStr);
                    }
                }

                p = Pattern.compile(".*_count=(\\d+).*");
                m = p.matcher(queryString);
                if (m.matches()) {
                    String countNumStr = m.group(1);
                    logger.info("countNum=" + countNumStr);
                    try {
                        countNum = Integer.valueOf(countNumStr, 10);
                    } catch (Exception e) {
                        throw new FhirServerException(
                                "count parameter should be a number: Current value is :" + countNumStr);
                    }
                }

            }
            s = FhirUtil.pageBundle(s, countNum, pageNum);

            logger.info("returning response..." + JAXBUtil.toXml(s));
            if (acceptHeader.contains("application/json") || acceptHeader.contains("application/json+fhir")) {
                msg = FhirUtil.bundleToJsonString(s);
                mediaType = "application/json+fhir";
            } else {
                msg = JAXBUtil.toXml(s);
                mediaType = "application/xml+fhir";
            }
            msg = I2b2Helper.removeSpace(msg);
            logger.info("acceptHeader:" + acceptHeader);
            return Response.ok().type(mediaType).header("session_id", session.getId()).entity(msg).build();

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            return Response
                    .ok(FhirHelper.generateOperationOutcome(e.getMessage(), IssueTypeList.EXCEPTION,
                            IssueSeverityList.FATAL))
                    .header("xreason", e.getMessage()).header("session_id", session.getId()).build();

        }

    }

    // POST version of getQueryResult using _search
    @POST
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}/_search")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response getQueryResult_search(@PathParam("resourceName") String resourceName,
            @QueryParam("_include") List<String> includeResources, @QueryParam("filterf") String filterf,
            @HeaderParam("accept") String acceptHeader, @Context HttpHeaders headers,
            @Context HttpServletRequest request, @Context ServletContext servletContext)
            throws IOException, URISyntaxException {

        URI fhirBase = HttpHelper.getBasePath(request, serverConfigs);
        String serverUriPath = HttpHelper.getServerUri(request, serverConfigs).toString();
        String basePath = fhirBase.toString();
        HttpSession session = request.getSession();
        return getQueryResultCore(resourceName, basePath, request.getRequestURI().replace("/_search", ""),
                request.getQueryString(), request.getRequestURI() + "?" + request.getQueryString(),
                includeResources, filterf, acceptHeader, headers, session, serverUriPath);
    }

    // http://localhost:8080/fhir-server-api-mvn/resources/i2b2/MedicationStatement/1000000005-1

    @GET
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}/{id:[0-9|-]+}")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response getParticularResourceWrapper(@PathParam("resourceName") String resourceName,
            @PathParam("id") String id, @HeaderParam("accept") String acceptHeader, @Context HttpHeaders headers,
            @Context HttpServletRequest request,
            @HeaderParam(AuthenticationFilter.AUTHENTICATION_HEADER) String tokString)
            throws DatatypeConfigurationException, ParserConfigurationException, SAXException, IOException,
            JAXBException, JSONException, XQueryUtilException, InterruptedException {

        logger.debug("got request " + request.getPathInfo() + "?" + request.getQueryString());
        HttpSession session = request.getSession();

        try {
            String msg = null;
            String mediaType = "";
            authService.authenticateSession(
                    headers.getRequestHeader(AuthenticationFilter.AUTHENTICATION_HEADER).get(0), session);
            Resource r = getParticularResource(request, resourceName, id, headers);

            if (r != null) {
                return generateResponse(acceptHeader, request, r);
            } else {
                msg = "xreason:" + resourceName + " with id:" + id + " NOT found";
                return Response.ok(
                        FhirHelper.generateOperationOutcome(msg, IssueTypeList.EXCEPTION, IssueSeverityList.ERROR))
                        .header("session_id", session.getId()).build();
            }

        } catch (Exception e) {
            logger.error("", e);
            return Response
                    .ok(FhirHelper.generateOperationOutcome(e.getMessage(), IssueTypeList.EXCEPTION,
                            IssueSeverityList.FATAL))
                    .header("xreason", e.getMessage()).header("session_id", session.getId()).build();
        }

    }

    private Resource getParticularResource(HttpServletRequest request, String resourceName, String id,
            HttpHeaders headers) throws IOException, XQueryUtilException, JAXBException, AuthenticationFailure,
            FhirServerException, InterruptedException {
        MetaResourceDb md = new MetaResourceDb();
        String msg = null;
        Resource r = null;
        Bundle s = null;
        String mediaType = null;

        HttpSession session = request.getSession();
        authService.authenticateSession(headers.getRequestHeader(AuthenticationFilter.AUTHENTICATION_HEADER).get(0),
                session);

        logger.debug("session id:" + session.getId());
        logger.info("searching particular resource:<" + resourceName + "> with id:<" + id + ">");
        Class c = FhirUtil.getResourceClass(resourceName);
        if (c == null)
            throw new RuntimeException("class not found for resource:" + resourceName);

        if (FhirHelper.isPatientDependentResource(c)) {

            String patientId = id;
            if (patientId.contains("-"))
                patientId = patientId.split("-")[0];

            s = I2b2Helper.parsePatientIdToFetchPDO(session, request.getRequestURI(), request.getQueryString(),
                    resourceName, service, ppmMgr, patientId);
            md.addBundle(s);
        } else {
            FhirHelper.loadTestResources(md);
        }
        r = md.getParticularResource(c, id);
        return r;
    }

    @GET
    @Path("")
    public Response info2() {
        return dummyToByPassAuthentication();
    }

    /*
     * 
     * 
     * @GET
     * 
     * @Path("")
     * 
     * @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON,
     * "application/xml+fhir", "application/json+fhir" }) public Response
     * info(){ return info2(); }
     */

    @GET
    @Path("open")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir", MediaType.TEXT_HTML })
    public Response dummyToByPassAuthentication() {
        // return Response.ok().entity("<html><header><META
        // http-equiv=\"refresh\" content=\"0;URL=../demo/\"></header><body>This
        // is the FHIR endpoint. Append a resource e.g. /Patient to this URL to
        // get data</body></html>").build();
        return Response.ok()
                .entity("This is the FHIR endpoint. Append a resource e.g. /Patient to this URL to get data")
                .build();
    }

    @OPTIONS
    @Path("")
    public Response conformanceStatement2(@HeaderParam("accept") String acceptHeader,
            @Context HttpServletRequest request) throws JAXBException, JSONException, IOException,
            ParserConfigurationException, SAXException, URISyntaxException {
        return conformanceStatement(acceptHeader, request);

    }

    @GET
    @Path("reset_cache")
    public Response resetCache() throws IOException {
        service.resetCache();
        ppmMgr.resetCache();
        return Response.ok().entity("Cache has been reset").build();
    }

    @GET
    @Path("smartstyleuri")
    public Response smartStyleUri() throws IOException {
        return Response.ok().entity(Utils.fileToString("/smartStyleUri.json")).build();
    }

    @GET
    @Path("metadata")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response conformanceStatement(@HeaderParam("accept") String acceptHeader,
            @Context HttpServletRequest request) throws JAXBException, JSONException, IOException,
            ParserConfigurationException, SAXException, URISyntaxException {

        URI fhirBase = HttpHelper.getBasePath(request, serverConfigs);

        Conformance c = ConformanceStatement.getStatement(fhirBase);

        logger.trace("conf:" + JAXBUtil.toXml(c));

        Code statusCode = new Code();
        statusCode.setValue("active");
        c.setStatus(statusCode);

        c.setId(FhirUtil.generateId(Integer.toString(request.getRequestURI().hashCode())));
        ConformanceStatementKind kindValue = new ConformanceStatementKind();
        kindValue.setValue(ConformanceStatementKindList.INSTANCE);
        c.setKind(kindValue);
        c.setFhirVersion(FhirUtil.generateId("1.2.0"));

        UnknownContentCode uccValue = new UnknownContentCode();
        uccValue.setValue(UnknownContentCodeList.NO);
        c.setAcceptUnknown(uccValue);

        Code fc1 = new Code();
        fc1.setValue("xml");
        c.getFormat().add(fc1);

        Code fc2 = new Code();
        fc2.setValue("json");
        c.getFormat().add(fc2);

        request.getRequestURI().hashCode();

        return generateResponse(acceptHeader, request, c);

    }

    // URL: [base]/Resource/$Validate
    // URL: [base]/Resource/[id]/$Validate

    @GET
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}/{id:[0-9a-zA-Z|-]+}/$validate")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response validateWrapperGet(@PathParam("resourceName") String resourceName, @PathParam("id") String id,
            @QueryParam("profile") String profile, @HeaderParam("accept") String acceptHeader,
            @Context HttpHeaders headers, @Context HttpServletRequest request, String inTxt)
            throws IOException, JAXBException, URISyntaxException, XQueryUtilException, AuthenticationFailure,
            FhirServerException, InterruptedException, ParserConfigurationException, SAXException {
        Resource r = getParticularResource(request, resourceName, id, headers);
        inTxt = JAXBUtil.toXml(r);
        return validate(resourceName, acceptHeader, request, inTxt, profile);
    }

    @POST
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}/{id:[0-9a-zA-Z|-]+}/$validate")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response validateWrapperPost(@PathParam("resourceName") String resourceName, @PathParam("id") String id,
            @QueryParam("profile") String profile, @HeaderParam("accept") String acceptHeader,
            @Context HttpHeaders headers, @Context HttpServletRequest request, String inTxt)
            throws IOException, JAXBException, URISyntaxException, XQueryUtilException, AuthenticationFailure,
            FhirServerException, InterruptedException, ParserConfigurationException, SAXException {
        Resource r = getParticularResource(request, resourceName, id, headers);
        inTxt = JAXBUtil.toXml(r);
        return validate(resourceName, acceptHeader, request, inTxt, profile);
    }

    @POST
    @Path("{resourceName:" + FhirUtil.RESOURCE_LIST_REGEX + "}/$validate")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response validate(@PathParam("resourceName") String resourceName,
            @HeaderParam("accept") String acceptHeader, @Context HttpServletRequest request, String inTxt,
            String profile) throws IOException, URISyntaxException, ParserConfigurationException, SAXException,
            FhirServerException, JAXBException {
        HttpSession session = request.getSession();
        String mediaType;
        Parameters ps = null;
        String resourceTxt = null;
        Resource r = null;
        String outTxt = "-";
        logger.trace("will run validator");

        try {
            Class resourceClass = FhirUtil.getResourceClass(resourceName);

            try {
                ps = JAXBUtil.fromXml(inTxt, Parameters.class);
                if (ps != null) {
                    for (ParametersParameter p : ps.getParameter()) {
                        logger.trace("pname:" + p.getName().getValue());
                    }
                } else {
                    logger.trace("ps is null");
                }
            } catch (ClassCastException e) {
            }

            if (ps == null) {
                resourceTxt = inTxt;
                try {
                    r = JAXBUtil.fromXml(resourceTxt, resourceClass);
                } catch (JAXBException e) {

                    Throwable e2 = e.getLinkedException();
                    throw new FhirServerException(e2.getMessage(), e2);
                }
                logger.trace(
                        "could transform to" + resourceClass.getSimpleName() + "\n" + r.getClass().getSimpleName());

            } else {
                for (ParametersParameter p : ps.getParameter()) {
                    logger.trace("getting pname:" + p.getName().getValue());
                    if (p.getName().getValue().equals("resource")) {
                        r = FhirUtil.getResourceFromContainer(p.getResource());
                        resourceTxt = JAXBUtil.toXml(r);
                    }

                }
                if (r == null) {
                    String msg = "Resource was not specified correctly in the Parameters";
                    logger.warn(msg);
                    throw new FhirServerException(msg);
                }
            }

            if (!r.getClass().getSimpleName().equals(resourceClass.getSimpleName())) {
                String msg = "The input is not an instance of class:" + resourceClass;
                logger.warn(msg);
                throw new FhirServerException(msg);
            }

            outTxt = Validate.runValidate(resourceTxt, profile);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage(), e);
            return generateResponse(acceptHeader, request, FhirHelper.generateOperationOutcome(e.toString(),
                    IssueTypeList.EXCEPTION, IssueSeverityList.FATAL));
        }

        Resource rOut = JAXBUtil.fromXml(outTxt, OperationOutcome.class);
        return generateResponse(acceptHeader, request, rOut);
    }

    @POST
    @Path("{resourceName:(DecisionSupportServiceModule|DecisionSupportRule|CQIF-Questionnaire|OrderSet)}/{id:[0-9a-zA-Z|-]+}/$evaluate")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response evaluate(@PathParam("resourceName") String resourceName, @PathParam("id") String id,
            @HeaderParam("accept") String acceptHeader, @Context HttpHeaders headers,
            @Context HttpServletRequest request, String inTxt)
            throws IOException, JAXBException, URISyntaxException, ParserConfigurationException, SAXException {
        Resource outR = null;
        if (resourceName.equals("DecisionSupportServiceModule")) {
            logger.trace("called DSS");
            outR = DSSEvaluate.evaluate(id, inTxt);
        } else {
            logger.trace("called evaluate for:" + resourceName);
            outR = FhirHelper.generateOperationOutcome("evaluate not (yet) implemented for " + resourceName,
                    IssueTypeList.EXCEPTION, IssueSeverityList.ERROR);
        }
        return generateResponse(acceptHeader, request, outR);

    }

    @POST
    @Path("$cds-hook")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response cdsHook(@HeaderParam("accept") String acceptHeader, @Context HttpHeaders headers,
            @Context HttpServletRequest request, String inTxt) {
        try {
            Resource outR = null;
            logger.trace("called cds-hook");
            Parameters parameters = JAXBUtil.fromXml(inTxt, Parameters.class);
            if (parameters != null) {
                outR = (new CdsHook(parameters)).execute();
            } else {
                logger.trace("called cds-hook with null parameters");
                outR = FhirHelper.generateOperationOutcome("cds not (yet) implemented for ",
                        IssueTypeList.EXCEPTION, IssueSeverityList.ERROR);
            }
            return generateResponse(acceptHeader, request, outR);
        } catch (Exception e) {
            return generateFatalResponse(e, request);
        }

    }

    // GET [base]/ValueSet/$lookup?system=http://loinc.org&code=1963-8
    // GET ValueSet/$lookup?system=http://hl7.org/fhir/sid/icd-9-cm&code=174.9
    // GET
    // ValueSet/$lookup?system=http://www.nlm.nih.gov/research/umls/rxnorm&code=1191

    @GET
    @Path("ValueSet/$lookup")
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/xml+fhir",
            "application/json+fhir" })
    public Response valueSetLookup(@QueryParam("code") String code, @QueryParam("system") String system,
            @HeaderParam("accept") String acceptHeader, @Context HttpHeaders headers,
            @Context HttpServletRequest request)
            throws IOException, JAXBException, URISyntaxException, ParserConfigurationException, SAXException {
        Resource r = null;
        if (system.equals("http://loinc.org")) {
            LoincMapper loincMapper = new LoincMapper();
            String display = loincMapper.getLoincName(code);
            if (display != null)
                r = FhirHelper.generateConceptLookUpOutput(display, null, display, false, null, code);
        } else if (system.equals("http://hl7.org/fhir/sid/icd-9-cm")) {
            Icd9Mapper icd9Mapper = new Icd9Mapper();
            String display = icd9Mapper.getIcd9Name(code);
            if (display != null)
                r = FhirHelper.generateConceptLookUpOutput(display, null, display, false, null, code);
        } else if (system.equals("http://www.nlm.nih.gov/research/umls/rxnorm")) {
            NdcToRxNormMapper rxMapper = new NdcToRxNormMapper();
            String display = rxMapper.getRxCuiName(code);
            if (display != null)
                r = FhirHelper.generateConceptLookUpOutput(display, null, display, false, null, code);
        } else {
            r = FhirHelper.generateOperationOutcome("lookup not implemented for code system:" + system,
                    IssueTypeList.EXCEPTION, IssueSeverityList.ERROR);
        }
        if (r == null)
            r = FhirHelper.generateOperationOutcome("code:" + code + " is invalid for system:" + system,
                    IssueTypeList.NOT_FOUND, IssueSeverityList.ERROR);
        return generateResponse(acceptHeader, request, r);

    }

    public Response generateResponse(@HeaderParam("accept") String acceptHeader,
            @Context HttpServletRequest request, Resource r)
            throws JAXBException, IOException, ParserConfigurationException, SAXException {
        if (r == null)
            throw new IllegalArgumentException("input resource is null");
        String mediaType;
        String outTxt = "-";
        HttpSession session = request.getSession();
        if (acceptHeader.contains("application/json") || acceptHeader.contains("application/json+fhir")) {
            outTxt = FhirUtil.resourceToJsonString(r);
            mediaType = "application/json";
        } else {
            outTxt = JAXBUtil.toXml(r);
            mediaType = "application/xml+fhir";
        }
        outTxt = I2b2Helper.removeSpace(outTxt);
        logger.info("acceptHeader:" + acceptHeader);

        return Response.ok().type(mediaType).header("session_id", session.getId()).entity(outTxt).build();

    }

    public Response generateFatalResponse(Exception e, HttpServletRequest request) {
        HttpSession session = request.getSession();
        return Response
                .ok(FhirHelper.generateOperationOutcome(e.getMessage(), IssueTypeList.EXCEPTION,
                        IssueSeverityList.FATAL))
                .header("xreason", e.getMessage()).header("session_id", session.getId()).build();

    }
    // [base]/$meta
    // GET /fhir/Patient/$meta
    // GET /fhir/Patient/id/$meta
    // GET /fhir/Patient/id/$meta-add
    // GET /fhir/Patient/id/$meta-del

}