edu.harvard.hms.dbmi.bd2k.irct.ri.exac.EXACResourceImplementation.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.hms.dbmi.bd2k.irct.ri.exac.EXACResourceImplementation.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.exac;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonStructure;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;

import edu.harvard.hms.dbmi.bd2k.irct.exception.ResourceInterfaceException;
import edu.harvard.hms.dbmi.bd2k.irct.model.find.FindInformationInterface;
import edu.harvard.hms.dbmi.bd2k.irct.model.ontology.OntologyRelationship;
import edu.harvard.hms.dbmi.bd2k.irct.model.ontology.Entity;
import edu.harvard.hms.dbmi.bd2k.irct.model.process.IRCTProcess;
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.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.resource.implementation.PathResourceImplementationInterface;
import edu.harvard.hms.dbmi.bd2k.irct.model.resource.implementation.ProcessResourceImplementationInterface;
import edu.harvard.hms.dbmi.bd2k.irct.model.resource.implementation.QueryResourceImplementationInterface;
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.FileResultSet;
import edu.harvard.hms.dbmi.bd2k.irct.model.result.tabular.ResultSet;
import edu.harvard.hms.dbmi.bd2k.irct.model.security.SecureSession;

public class EXACResourceImplementation implements QueryResourceImplementationInterface,
        PathResourceImplementationInterface, ProcessResourceImplementationInterface {

    private ResourceState resourceState;
    private String resourceName;
    private String resourceURL;
    private String[] exacColumns = { "allele_count", "allele_freq", "allele_num", "alt", "chrom", "filter",
            "hom_count", "pop_acs.African", "pop_acs.East Asian", "pop_acs.European (Finnish)",
            "pop_acs.European (Non-Finnish)", "pop_acs.Latino", "pop_acs.Other", "pop_acs.South Asian",
            "pop_ans.African", "pop_ans.East Asian", "pop_ans.European (Finnish)", "pop_ans.European (Non-Finnish)",
            "pop_ans.Latino", "pop_ans.Other", "pop_ans.South Asian", "pop_homs.African", "pop_homs.East Asian",
            "pop_homs.European (Finnish)", "pop_homs.European (Non-Finnish)", "pop_homs.Latino", "pop_homs.Other",
            "pop_homs.South Asian", "pos", "quality_metrics.BaseQRankSum", "quality_metrics.ClippingRankSum",
            "quality_metrics.DP", "quality_metrics.FS", "quality_metrics.InbreedingCoeff", "quality_metrics.MQ",
            "quality_metrics.MQRankSum", "quality_metrics.QD", "quality_metrics.ReadPosRankSum",
            "quality_metrics.VQSLOD", "ref", "rsid", "site_quality", "variant_id", "xpos", "xstart", "xstop" };

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

    @Override
    public List<Entity> getPathRelationship(Entity path, OntologyRelationship relationship, SecureSession session)
            throws ResourceInterfaceException {
        List<Entity> returns = new ArrayList<Entity>();
        String resourcePath = getResourcePathFromPUI(path.getPui());

        if (resourcePath.equals("/")) {
            // Variant
            returns.add(createEntity("Variant", "/variant", EXACDataType.VARIANT));
            // Gene
            returns.add(createEntity("Gene", "/gene", EXACDataType.GENE));
            // Transcript
            returns.add(createEntity("Transcript", "/transcript", EXACDataType.TRANSCRIPT));
            // Region
            returns.add(createEntity("Region", "/region", EXACDataType.REGION));
        } else if (resourcePath.equals("/variant")) {
            // Base Coverage
            returns.add(createEntity("Base Coverage", resourcePath + "/" + "base_coverage", EXACDataType.VARIANT));
            // Consequences
            returns.add(createEntity("Consequences", resourcePath + "/" + "consequences", EXACDataType.VARIANT));
            // Any Covered
            returns.add(createEntity("Any Covered", resourcePath + "/" + "any_covered", EXACDataType.VARIANT));
            // Ordered CSQS
            returns.add(createEntity("Ordered CSQS", resourcePath + "/" + "ordered_csqs", EXACDataType.VARIANT));
            // Metrics
            returns.add(createEntity("Metrics", resourcePath + "/" + "metrics", EXACDataType.VARIANT));
        } else if (resourcePath.equals("/gene")) {
            returns.add(createEntity("Transcripts", resourcePath + "/" + "transcript", EXACDataType.GENE));
            returns.add(
                    createEntity("Variants in Gene", resourcePath + "/" + "variants_in_gene", EXACDataType.GENE));
            returns.add(createEntity("Variants in Transcript", resourcePath + "/" + "variants_in_transcript",
                    EXACDataType.GENE));
            returns.add(createEntity("Transcripts in Gene", resourcePath + "/" + "transcripts_in_gene",
                    EXACDataType.GENE));
            returns.add(createEntity("Coverage Stats", resourcePath + "/" + "coverage_stats", EXACDataType.GENE));
        } else if (resourcePath.equals("/transcript")) {
            returns.add(createEntity("Variants in Transcript", resourcePath + "/" + "variants_in_transcript",
                    EXACDataType.TRANSCRIPT));
            returns.add(
                    createEntity("Coverage Stats", resourcePath + "/" + "coverage_stats", EXACDataType.TRANSCRIPT));
            returns.add(createEntity("Gene", resourcePath + "/" + "gene", EXACDataType.TRANSCRIPT));
        } else if (resourcePath.equals("/region")) {
            returns.add(
                    createEntity("Genes in region", resourcePath + "/" + "genes_in_region", EXACDataType.REGION));
            returns.add(createEntity("Variants in region", resourcePath + "/" + "variants_in_region",
                    EXACDataType.REGION));
            returns.add(createEntity("Coverage Array", resourcePath + "/" + "coverage_array", EXACDataType.REGION));
        }

        return returns;
    }

    @Override
    public Result runQuery(SecureSession session, Query qep, Result result) throws ResourceInterfaceException {
        // TODO Auto-generated method stub
        HttpClient client = createClient(session);
        result.setResultStatus(ResultStatus.CREATED);

        // Check Clause
        if (qep.getClauses().size() != 1) {
            result.setResultStatus(ResultStatus.ERROR);
            result.setMessage("Wrong number of clauses");
            return result;
        }
        ClauseAbstract clause = qep.getClauses().values().iterator().next();

        if (!(clause instanceof WhereClause)) {
            result.setResultStatus(ResultStatus.ERROR);
            result.setMessage("Clause is not a where Clause");
            return result;
        }

        WhereClause whereClause = (WhereClause) clause;
        // Create Query
        String urlString = null;

        // BY ENSEMBL
        if (whereClause.getPredicateType().getName().equals("ENSEMBL")) {
            urlString = resourceURL + "/rest" + getResourcePathFromPUI(whereClause.getField().getPui()) + "/"
                    + whereClause.getStringValues().get("ENSEMBLID");

        } else if (whereClause.getPredicateType().getName().equals("QUERY")) {
            // BY QUERY
            String[] resourcePath = getResourcePathFromPUI(whereClause.getField().getPui()).split("/");
            String service = "";
            if (resourcePath.length >= 3) {
                service = "&service=" + resourcePath[2];
            }

            urlString = resourceURL + "/rest/awesome?query=" + whereClause.getStringValues().get("QUERY") + service;
        } else if (whereClause.getPredicateType().getName().equals("REGION")) {
            // BY REGION
            urlString = resourceURL + "/rest" + getResourcePathFromPUI(whereClause.getField().getPui()) + "/"
                    + whereClause.getStringValues().get("CHROMOSOME") + "-"
                    + whereClause.getStringValues().get("START");
            if (whereClause.getStringValues().containsKey("STOP")) {
                urlString += "-" + whereClause.getStringValues().get("STOP");
            }

        } else if (whereClause.getPredicateType().getName().equals("VARIANT")) {
            // BY VARIANT
            urlString = resourceURL + "/rest" + getResourcePathFromPUI(whereClause.getField().getPui()) + "/"
                    + whereClause.getStringValues().get("CHROMOSOME") + "-"
                    + whereClause.getStringValues().get("POSITION") + "-"
                    + whereClause.getStringValues().get("REFERENCE") + "-"
                    + whereClause.getStringValues().get("VARIANT");
        }
        // Run Query
        if (urlString == null) {
            result.setResultStatus(ResultStatus.ERROR);
            result.setMessage("Unknown predicate");
            return result;
        }

        HttpGet get = new HttpGet(urlString);
        try {
            HttpResponse response = client.execute(get);
            JsonReader reader = Json.createReader(response.getEntity().getContent());
            JsonStructure results = reader.read();
            if (results.getValueType().equals(ValueType.ARRAY)) {
                result = convertJsonArrayToResultSet((JsonArray) results, result);
            } else {
                result = convertJsonObjectToResultSet((JsonObject) results, result);
            }
            reader.close();
            result.setResultStatus(ResultStatus.COMPLETE);
        } catch (IOException e) {
            result.setResultStatus(ResultStatus.ERROR);
            result.setMessage(e.getMessage());
        }

        // Format Results

        return result;
    }

    @Override
    public Result runProcess(SecureSession session, IRCTProcess process, Result result)
            throws ResourceInterfaceException {
        HttpClient client = createClient(session);
        try {
            ResultSet resultSetField = (ResultSet) process.getObjectValues().get("RESULTSET");
            String chromosomeColumn = process.getStringValues().get("CHROMOSOME");
            String positionColumn = process.getStringValues().get("POSITION");
            String referenceColumn = process.getStringValues().get("REFERENCE");
            String variantColumn = process.getStringValues().get("VARIANT");

            ResultSet rs = createResultSet(result, resultSetField);

            // Move to First
            resultSetField.first();
            // Loop through all rows and get the data needed for the bulk
            // request
            resultSetField.beforeFirst();
            JsonArrayBuilder jsonArray = Json.createArrayBuilder();
            while (resultSetField.next()) {

                String queryString = resultSetField.getString(chromosomeColumn);
                queryString += "-" + resultSetField.getString(positionColumn);
                queryString += "-" + resultSetField.getString(referenceColumn);
                queryString += "-" + resultSetField.getString(variantColumn);

                // Run the Bulk request(s)
                jsonArray.add(queryString);

            }

            HttpPost post = new HttpPost(this.resourceURL + "/rest/bulk/variant");

            // Set Header
            try {
                post.setEntity(new StringEntity(jsonArray.build().toString()));
                HttpResponse response = client.execute(post);
                JsonReader reader = Json.createReader(response.getEntity().getContent());
                JsonObject responseObject = reader.readObject();

                //Merge the results back into the result set
                resultSetField.beforeFirst();
                rs.first();
                while (resultSetField.next()) {
                    rs.appendRow();
                    //Copy the original data over
                    for (Column column : resultSetField.getColumns()) {
                        rs.updateString(column.getName(), resultSetField.getString(column.getName()));
                    }
                    //Add the new data if it exists
                    String queryString = resultSetField.getString(chromosomeColumn);
                    queryString += "-" + resultSetField.getString(positionColumn);
                    queryString += "-" + resultSetField.getString(referenceColumn);
                    queryString += "-" + resultSetField.getString(variantColumn);

                    if (responseObject.containsKey(queryString)) {
                        JsonObject varObject = responseObject.getJsonObject(queryString).getJsonObject("variant");
                        for (String newColumnString : this.exacColumns) {
                            String value = getValue(varObject, newColumnString);
                            if (value != null) {
                                rs.updateString(newColumnString, value.toString());
                            }
                        }
                    }
                }

                result.setData(rs);
                result.setResultStatus(ResultStatus.COMPLETE);
            } catch (IOException | PersistableException e) {
                e.printStackTrace();
                result.setResultStatus(ResultStatus.ERROR);
                result.setMessage(e.getMessage());
            }

        } catch (ResultSetException e) {
            e.printStackTrace();
            result.setResultStatus(ResultStatus.ERROR);
            result.setMessage(e.getMessage());
        }

        return result;
    }

    //   private JsonValue getValueFromJson(JsonObject varObject, String newColumnString) {
    ////      String[] columnPath = newColumnString.split("\\.");
    //      
    //      if(!newColumnString.contains(".") && (varObject.containsKey(newColumnString))) {
    //         return varObject.get(newColumnString);
    //      }
    //      return null;
    //   }

    private ResultSet createResultSet(Result result, ResultSet resultSetField) throws ResultSetException {
        ResultSet rs = (ResultSet) result.getData();

        for (Column column : resultSetField.getColumns()) {
            rs.appendColumn(column);
        }

        for (String newColumnString : this.exacColumns) {
            Column newColumn = new Column();
            newColumn.setName(newColumnString);
            newColumn.setDataType(PrimitiveDataType.STRING);
            rs.appendColumn(newColumn);
        }

        return rs;
    }

    @Override
    public Result getResults(SecureSession session, Result result) throws ResourceInterfaceException {
        if (result.getResultStatus() != ResultStatus.COMPLETE) {
            result.setResultStatus(ResultStatus.ERROR);
        }
        return result;
    }

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

    @Override
    public String getType() {
        return "exac";
    }

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

    @Override
    public ResultDataType getQueryDataType(Query query) {
        // Check Clause
        if (query.getClauses().size() != 1) {
            return null;
        }
        ClauseAbstract clause = query.getClauses().values().iterator().next();

        if (!(clause instanceof WhereClause)) {
            return null;
        }

        WhereClause whereClause = (WhereClause) clause;
        String resourcePath = getResourcePathFromPUI(whereClause.getField().getPui());

        if (resourcePath.split("/").length >= 2) {
            return ResultDataType.TABULAR;
        }

        return ResultDataType.JSON;
    }

    @Override
    public ResultDataType getProcessDataType(IRCTProcess pep) {
        return ResultDataType.TABULAR;
    }

    private Result convertJsonObjectToResultSet(JsonObject exacJSONResults, Result result) {
        // TODO: BUILD OUT
        return result;
    }

    private Result convertJsonArrayToResultSet(JsonArray exacJSONResults, Result result) {

        FileResultSet mrs = (FileResultSet) result.getData();
        try {
            if (exacJSONResults.size() == 0) {
                result.setData(mrs);
                return result;
            }
            // Setup columns
            JsonObject columnObject = (JsonObject) exacJSONResults.get(0);

            List<String> fields = getNames("", columnObject);
            for (String field : fields) {
                Column column = new Column();
                column.setName(field);
                column.setDataType(PrimitiveDataType.STRING);
                mrs.appendColumn(column);
            }

            // Add data
            for (JsonValue val : exacJSONResults) {
                JsonObject obj = (JsonObject) val;
                mrs.appendRow();
                for (String field : fields) {
                    mrs.updateString(field, getValue(obj, field));
                }
            }
        } catch (ResultSetException | PersistableException e) {
            e.printStackTrace();
        }

        result.setData(mrs);
        return result;
    }

    private String getValue(JsonObject obj, String field) {
        if (field.contains(".")) {
            String thisField = field.split("\\.")[0];
            String remaining = field.replaceFirst(thisField + ".", "");
            return getValue(obj.getJsonObject(thisField), remaining);
        }
        if (obj.containsKey(field)) {
            ValueType vt = obj.get(field).getValueType();
            if (vt == ValueType.NUMBER) {
                return obj.getJsonNumber(field).toString();
            } else if (vt == ValueType.TRUE) {
                return "TRUE";
            } else if (vt == ValueType.FALSE) {
                return "FALSE";
            }
            return obj.getString(field);
        }
        return "";
    }

    private List<String> getNames(String prefix, JsonObject obj) {
        List<String> returns = new ArrayList<String>();
        for (String field : obj.keySet()) {
            if (obj.get(field).getValueType() == ValueType.OBJECT) {
                if (prefix.equals("")) {
                    returns.addAll(getNames(field, obj.getJsonObject(field)));
                } else {
                    returns.addAll(getNames(prefix + "." + field, obj.getJsonObject(field)));
                }
            } else if (obj.get(field).getValueType() != ValueType.ARRAY) {
                if (prefix.equals("")) {
                    returns.add(field);
                } else {
                    returns.add(prefix + "." + field);
                }
            }
        }

        return returns;
    }

    private String getResourcePathFromPUI(String pui) {
        String[] pathComponents = pui.split("/");

        if (pathComponents.length <= 2) {
            return "/";
        }
        String myPath = "";

        for (String pathComponent : Arrays.copyOfRange(pathComponents, 2, pathComponents.length)) {
            myPath += "/" + pathComponent;
        }

        return myPath;
    }

    private HttpClient createClient(SecureSession session) {
        HttpClientBuilder returns = HttpClientBuilder.create();
        return returns.build();
    };

    private Entity createEntity(String name, String resourceString, EXACDataType type) {

        Entity newEntity = new Entity();
        newEntity.setName(name);
        newEntity.setDisplayName(name);
        newEntity.setPui("/" + this.resourceName + resourceString);
        newEntity.setDataType(type);

        return newEntity;
    }
}