edu.harvard.hms.dbmi.bd2k.irct.ri.i2b2transmart.I2B2TranSMARTResourceImplementation.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.hms.dbmi.bd2k.irct.ri.i2b2transmart.I2B2TranSMARTResourceImplementation.java

Source

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package edu.harvard.hms.dbmi.bd2k.irct.ri.i2b2transmart;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;

import edu.harvard.hms.dbmi.bd2k.irct.exception.ResourceInterfaceException;
import edu.harvard.hms.dbmi.bd2k.irct.model.find.FindByPath;
import edu.harvard.hms.dbmi.bd2k.irct.model.find.FindInformationInterface;
import edu.harvard.hms.dbmi.bd2k.irct.model.ontology.Entity;
import edu.harvard.hms.dbmi.bd2k.irct.model.ontology.OntologyRelationship;
import edu.harvard.hms.dbmi.bd2k.irct.model.query.ClauseAbstract;
import edu.harvard.hms.dbmi.bd2k.irct.model.query.Query;
import edu.harvard.hms.dbmi.bd2k.irct.model.query.SelectClause;
import edu.harvard.hms.dbmi.bd2k.irct.model.query.WhereClause;
import edu.harvard.hms.dbmi.bd2k.irct.model.resource.PrimitiveDataType;
import edu.harvard.hms.dbmi.bd2k.irct.model.resource.ResourceState;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.Result;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.ResultDataType;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.ResultStatus;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.exception.PersistableException;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.exception.ResultSetException;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.tabular.Column;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.tabular.ResultSet;
import edu.harvard.hms.dbmi.bd2k.irct.model.security.SecureSession;
import edu.harvard.hms.dbmi.bd2k.irct.ri.i2b2.I2B2XMLResourceImplementation;

/**
 * An implementation of a resource that communicates with the tranSMART
 * instance. It extends the i2b2 XML resource implementation.
 * 
 */
public class I2B2TranSMARTResourceImplementation extends I2B2XMLResourceImplementation {
    private String transmartURL;

    @Override
    public void setup(Map<String, String> parameters) throws ResourceInterfaceException {
        String[] strArray = { "resourceName", "resourceURL", "transmartURL", "domain" };
        if (!parameters.keySet().containsAll(Arrays.asList(strArray))) {
            throw new ResourceInterfaceException("Missing parameters");
        }

        this.transmartURL = parameters.get("transmartURL");

        super.setup(parameters);
    }

    @Override
    public List<Entity> getPathRelationship(Entity path, OntologyRelationship relationship, SecureSession session)
            throws ResourceInterfaceException {
        List<Entity> returns = super.getPathRelationship(path, relationship, session);

        // Get the counts from the tranSMART server
        try {
            HttpClient client = createClient(session);
            String basePath = path.getPui();
            String[] pathComponents = basePath.split("/");

            if (pathComponents.length > 3) {
                String myPath = "\\";
                for (String pathComponent : Arrays.copyOfRange(pathComponents, 3, pathComponents.length)) {
                    myPath += "\\" + pathComponent;
                }
                basePath = pathComponents[0] + "/" + pathComponents[1] + "/" + pathComponents[2];

                HttpPost post = new HttpPost(this.transmartURL + "/chart/childConceptPatientCounts");
                List<NameValuePair> formParameters = new ArrayList<NameValuePair>();
                formParameters.add(new BasicNameValuePair("charttype", "childconceptpatientcounts"));
                formParameters.add(new BasicNameValuePair("concept_key", myPath + "\\"));
                formParameters.add(new BasicNameValuePair("concept_level", ""));

                post.setEntity(new UrlEncodedFormEntity(formParameters));

                HttpResponse response = client.execute(post);

                JsonReader jsonReader = Json.createReader(response.getEntity().getContent());

                JsonObject counts = jsonReader.readObject().getJsonObject("counts");

                for (Entity singleReturn : returns) {
                    String singleReturnMyPath = convertPUItoI2B2Path(singleReturn.getPui());

                    if (counts.containsKey(singleReturnMyPath)) {
                        singleReturn.getCounts().put("count", counts.getInt(singleReturnMyPath));
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return returns;
    }

    @Override
    public Result runQuery(SecureSession session, Query query, Result result) throws ResourceInterfaceException {
        result = super.runQuery(session, query, result);

        if (result.getResultStatus() != ResultStatus.ERROR) {
            String resultInstanceId = result.getResourceActionId();
            String resultId = resultInstanceId.split("\\|")[2];
            try {
                // Wait for it to be either ready or fail
                result = checkForResult(session, result);
                while ((result.getResultStatus() != ResultStatus.ERROR)
                        && (result.getResultStatus() != ResultStatus.COMPLETE)) {
                    Thread.sleep(3000);
                    result = checkForResult(session, result);
                }
                if (result.getResultStatus() == ResultStatus.ERROR) {
                    return result;
                }
                result.setResultStatus(ResultStatus.RUNNING);
                // Loop through the select clauses to build up the select string
                String gatherAllEncounterFacts = "false";
                Map<String, String> aliasMap = new HashMap<String, String>();

                for (ClauseAbstract clause : query.getClauses().values()) {
                    if (clause instanceof SelectClause) {
                        SelectClause selectClause = (SelectClause) clause;
                        String pui = convertPUItoI2B2Path(selectClause.getParameter().getPui());
                        aliasMap.put(pui, selectClause.getAlias());

                    } else if (clause instanceof WhereClause) {
                        WhereClause whereClause = (WhereClause) clause;
                        String encounter = whereClause.getStringValues().get("ENCOUNTER");
                        if ((encounter != null) && (encounter.equalsIgnoreCase("yes"))) {
                            gatherAllEncounterFacts = "true";
                        }
                    }

                }

                if (!aliasMap.isEmpty()) {

                    ResultSet rs = (ResultSet) result.getData();
                    if (rs.getSize() == 0) {
                        rs = createInitialDataset(result, aliasMap, gatherAllEncounterFacts);
                        result.setData(rs);
                    }

                    // Loop through the columns submitting and appending to the
                    // rows every 10
                    List<String> parameterList = new ArrayList<String>();
                    int counter = 0;
                    String parameters = "";
                    for (String param : aliasMap.keySet()) {
                        if (counter == 10) {
                            parameterList.add(parameters);
                            counter = 0;
                            parameters = "";
                        }
                        if (!parameters.equals("")) {
                            parameters += "|";
                        }
                        parameters += param;
                    }
                    if (!parameters.equals("")) {
                        parameterList.add(parameters);
                    }

                    for (String parameter : parameterList) {
                        // Call the tranSMART API to get the dataset
                        String url = this.transmartURL + "/ClinicalData/retrieveClinicalData?rid=" + resultId
                                + "&conceptPaths=" + URLEncoder.encode(parameter, "UTF-8")
                                + "&gatherAllEncounterFacts=" + gatherAllEncounterFacts;
                        HttpClient client = createClient(session);
                        HttpGet get = new HttpGet(url);
                        try {
                            HttpResponse response = client.execute(get);
                            JsonReader reader = Json.createReader(response.getEntity().getContent());
                            JsonArray arrayResults = reader.readArray();
                            // Convert the dataset to Tabular format
                            result = convertJsonToResultSet(result, arrayResults, aliasMap,
                                    gatherAllEncounterFacts);
                        } catch (JsonException e) {
                        }
                    }

                }
                // Set the status to complete
                result.setResultStatus(ResultStatus.COMPLETE);
            } catch (InterruptedException | UnsupportedOperationException | IOException | ResultSetException
                    | PersistableException e) {
                result.setResultStatus(ResultStatus.ERROR);
                result.setMessage(e.getMessage());
            }
        }
        return result;
    }

    private ResultSet createInitialDataset(Result result, Map<String, String> aliasMap,
            String gatherAllEncounterFacts) throws ResultSetException {
        ResultSet rs = (ResultSet) result.getData();

        // Set up the columns
        Column idColumn = new Column();
        idColumn.setName("PATIENT_NUM");
        idColumn.setDataType(PrimitiveDataType.STRING);
        rs.appendColumn(idColumn);

        if (gatherAllEncounterFacts.equalsIgnoreCase("true")) {
            Column encounterColumn = new Column();
            encounterColumn.setName("ENCOUNTER_NUM");
            encounterColumn.setDataType(PrimitiveDataType.STRING);
            rs.appendColumn(encounterColumn);
        }

        for (String aliasKey : aliasMap.keySet()) {
            Column newColumn = new Column();
            if (aliasMap.get(aliasKey) == null) {
                newColumn.setName(aliasKey);
            } else {
                newColumn.setName(aliasMap.get(aliasKey));
            }
            newColumn.setDataType(PrimitiveDataType.STRING);

            rs.appendColumn(newColumn);
        }

        return rs;
    }

    private Result convertJsonToResultSet(Result result, JsonArray arrayResults, Map<String, String> aliasMap,
            String gatherAllEncounterFacts) throws ResultSetException, PersistableException {
        // If the resultset is empty create the initial result set
        ResultSet rs = (ResultSet) result.getData();

        // Create the initial Matrix
        Map<String, Map<String, String>> dataMatrix = new HashMap<String, Map<String, String>>();

        String pivot = "PATIENT_NUM";
        if (gatherAllEncounterFacts.equalsIgnoreCase("true")) {
            pivot = "ENCOUNTER_NUM";
        }

        for (JsonValue val : arrayResults) {
            JsonObject obj = (JsonObject) val;
            String rowId = obj.getString(pivot);

            if (!dataMatrix.containsKey(rowId)) {
                dataMatrix.put(rowId, new HashMap<String, String>());
            }

            dataMatrix.get(rowId).put(obj.getString("CONCEPT_PATH"), obj.getString("VALUE"));
        }

        // Loop through the result set and add the information in the matrix to
        // the result set
        rs.first();
        while (rs.next()) {
            String rsRowId = rs.getString(pivot);
            if (dataMatrix.containsKey(rsRowId)) {
                Map<String, String> newRowData = dataMatrix.get(rsRowId);
                for (String colKeySet : newRowData.keySet()) {
                    // Check to see if an alias exists
                    if (aliasMap.get(colKeySet) != null) {
                        rs.updateString(aliasMap.get(colKeySet), newRowData.get(colKeySet));
                    } else {
                        rs.updateString(colKeySet, newRowData.get(colKeySet));
                    }
                }
                dataMatrix.remove(rsRowId);
            }
        }
        // If the information is still in the matrix add it to the result set at
        // the end
        for (String rowId : dataMatrix.keySet()) {
            rs.appendRow();
            rs.updateString(pivot, rowId);

            Map<String, String> newRowData = dataMatrix.get(rowId);
            for (String colKeySet : newRowData.keySet()) {
                // Check to see if an alias exists
                if (aliasMap.get(colKeySet) != null) {
                    rs.updateString(aliasMap.get(colKeySet), newRowData.get(colKeySet));
                } else {
                    rs.updateString(colKeySet, newRowData.get(colKeySet));
                }
            }
        }

        // Add results back
        result.setData(rs);
        return result;
    }

    @Override
    public Result getResults(SecureSession session, Result result) throws ResourceInterfaceException {
        // This method only exists so the results for i2b2XML do not get called
        return result;
    }

    @Override
    public ResourceState getState() {
        return resourceState;
    }

    @Override
    public ResultDataType getQueryDataType(Query query) {
        return ResultDataType.TABULAR;
    }

    @Override
    public String getType() {
        return "i2b2/tranSMART";
    }

    @Override
    public List<Entity> find(Entity path, FindInformationInterface findInformation, SecureSession session)
            throws ResourceInterfaceException {
        List<Entity> returns = new ArrayList<Entity>();

        if (findInformation instanceof FindByPath) {
            FindByPath findPath = (FindByPath) findInformation;
            if (findInformation.getValues().containsKey("tmObservationOnly")) {
                returns = searchObservationOnly(findPath.getValues().get("term"),
                        findPath.getValues().get("strategy"), session,
                        findPath.getValues().get("tmObservationOnly"));
            } else {
                returns = searchObservationOnly(findPath.getValues().get("term"),
                        findPath.getValues().get("strategy"), session, "FALSE");
            }
        } else {
            returns = super.find(path, findInformation, session);
        }
        return returns;
    }

    public List<Entity> searchObservationOnly(String searchTerm, String strategy, SecureSession session,
            String onlObs) {
        List<Entity> entities = new ArrayList<Entity>();

        try {
            URI uri = new URI(this.transmartURL.split("://")[0], this.transmartURL.split("://")[1].split("/")[0],
                    "/" + this.transmartURL.split("://")[1].split("/")[1] + "/textSearch/findPaths",
                    "oblyObs=" + onlObs + "&term=" + searchTerm, null);

            HttpClient client = createClient(session);
            HttpGet get = new HttpGet(uri);
            HttpResponse response = client.execute(get);
            JsonReader reader = Json.createReader(response.getEntity().getContent());
            JsonArray arrayResults = reader.readArray();

            for (JsonValue val : arrayResults) {
                JsonObject returnObject = (JsonObject) val;

                Entity returnedEntity = new Entity();
                returnedEntity
                        .setPui("/" + this.resourceName + converti2b2Path(returnObject.getString("conceptPath")));

                if (!returnObject.isNull("text")) {
                    returnedEntity.getAttributes().put("text", returnObject.getString("text"));
                }
                entities.add(returnedEntity);
            }

        } catch (URISyntaxException | JsonException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return entities;
    }

    private String convertPUItoI2B2Path(String pui) {
        String[] singleReturnPathComponents = pui.split("/");
        String singleReturnMyPath = "";
        for (String pathComponent : Arrays.copyOfRange(singleReturnPathComponents, 4,
                singleReturnPathComponents.length)) {
            singleReturnMyPath += "\\" + pathComponent;
        }

        singleReturnMyPath += "\\";

        return singleReturnMyPath;
    }
}