net.bioclipse.opentox.api.Dataset.java Source code

Java tutorial

Introduction

Here is the source code for net.bioclipse.opentox.api.Dataset.java

Source

/* Copyright (C) 2010  Egon Willighagen <egonw@users.sf.net>
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version. All we ask is that proper credit is given for our work,
 * which includes - but is not limited to - adding the above copyright notice to
 * the beginning of your source code files, and to any copyright notice that you
 * may distribute with programs based on this work.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package net.bioclipse.opentox.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import net.bioclipse.cdk.business.CDKManager;
import net.bioclipse.core.business.BioclipseException;
import net.bioclipse.core.domain.IMolecule;
import net.bioclipse.core.domain.StringMatrix;
import net.bioclipse.rdf.business.IRDFStore;
import net.bioclipse.rdf.business.RDFManager;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.openscience.cdk.AtomContainer;
import org.openscience.cdk.io.SDFWriter;

public class Dataset {

    private static final Logger logger = Logger.getLogger(Dataset.class);

    private final static String QUERY_PREDICTED_FEATURES = "SELECT ?desc ?label ?numval {"
            + "  ?entry a <http://www.opentox.org/api/1.1#DataEntry> ;"
            + "     <http://www.opentox.org/api/1.1#values> ?value ."
            + "  ?value <http://www.opentox.org/api/1.1#feature> ?feature;"
            + "     <http://www.opentox.org/api/1.1#value> ?numval ."
            + "  ?feature <http://www.opentox.org/api/1.1#hasSource> ?desc ."
            + "  ?feature <http://purl.org/dc/elements/1.1/title> ?label ." + "}";

    static CDKManager cdk = new CDKManager();
    static RDFManager rdf = new RDFManager();

    @SuppressWarnings("serial")
    public static List<String> getListOfAvailableDatasets(String service) throws IOException {
        HttpClient client = new HttpClient();
        GetMethod method = new GetMethod(service + "dataset");
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Accept", "text/uri-list");
            }
        });
        client.executeMethod(method);

        List<String> datasets = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new StringReader(method.getResponseBodyAsString()));
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.length() > 0)
                datasets.add(line);
        }
        reader.close();
        method.releaseConnection();
        return datasets;
    }

    public static String normalizeURI(String datasetURI) {
        datasetURI = datasetURI.replaceAll("\\n", "");
        datasetURI = datasetURI.replaceAll("\\r", "");
        if (!datasetURI.endsWith("/"))
            datasetURI += "/";
        return datasetURI;
    }

    @SuppressWarnings("serial")
    public static List<String> getCompoundList(String datasetURI) throws IOException {
        HttpClient client = new HttpClient();
        datasetURI = normalizeURI(datasetURI);
        GetMethod method = new GetMethod(datasetURI + "compounds");
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Accept", "text/uri-list");
            }
        });
        client.executeMethod(method);
        List<String> compounds = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new StringReader(method.getResponseBodyAsString()));
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.length() > 0)
                compounds.add(line);
        }
        reader.close();
        method.releaseConnection();
        return compounds;
    }

    @SuppressWarnings("serial")
    public static StringMatrix listPredictedFeatures(String datasetURI) throws Exception {
        logger.debug("Listing features for: " + datasetURI);
        datasetURI = datasetURI.replaceAll("\n", "");
        if (datasetURI.contains("feature_uris[]=")) {
            String baseURI = datasetURI.substring(0, datasetURI.indexOf("feature_uris[]="));
            String featureURIs = datasetURI.substring(datasetURI.indexOf("feature_uris[]=") + 15);
            featureURIs = URIUtil.decode(featureURIs);
            String fullURI = baseURI + "feature_uris[]=" + featureURIs;
            datasetURI = URIUtil.encodeQuery(fullURI);
        }
        HttpClient client = new HttpClient();
        GetMethod method = new GetMethod(datasetURI);
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Accept", "application/rdf+xml");
            }
        });
        client.executeMethod(method);
        String result = method.getResponseBodyAsString(); // without this things will fail??
        IRDFStore store = rdf.createInMemoryStore();
        rdf.importFromStream(store, method.getResponseBodyAsStream(), "RDF/XML", null);
        method.releaseConnection();
        String dump = rdf.asRDFN3(store);
        StringMatrix matrix = rdf.sparql(store, QUERY_PREDICTED_FEATURES);
        return matrix;
    }

    public static void deleteDataset(String datasetURI) throws Exception {
        HttpClient client = new HttpClient();
        DeleteMethod method = new DeleteMethod(datasetURI);
        HttpMethodHelper.addMethodHeaders(method, null);
        client.executeMethod(method);
        int status = method.getStatusCode();
        method.releaseConnection();
        if (status == 404)
            throw new IllegalArgumentException("Dataset does not exist.");
        if (status == 503)
            throw new IllegalStateException("Service error: " + status);
    }

    public static void addMolecule(String datasetURI, IMolecule mol) throws Exception {
        StringWriter strWriter = new StringWriter();
        SDFWriter writer = new SDFWriter(strWriter);
        writer.write(cdk.asCDKMolecule(mol).getAtomContainer());
        writer.close();
        addMolecules(datasetURI, strWriter.toString(), null);
    }

    public static void addMolecules(String datasetURI, List<IMolecule> mols) throws Exception {
        StringWriter strWriter = new StringWriter();
        SDFWriter writer = new SDFWriter(strWriter);
        for (IMolecule mol : mols) {
            writer.write(cdk.asCDKMolecule(mol).getAtomContainer());
        }
        writer.close();
        addMolecules(datasetURI, strWriter.toString(), null);
    }

    public static void setMetadata(String datasetURI, String predicate, String value) throws Exception {
        HttpClient client = new HttpClient();
        PutMethod method = new PutMethod(normalizeURI(datasetURI) + "metadata");
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Content-type", "text/n3");
            }
        });
        String triples = "<" + datasetURI + "> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> "
                + "<http://www.opentox.org/api/1.1#Dataset> .\n" + "<" + datasetURI + "> <" + predicate + "> "
                + value + " .";
        System.out.println("Triples:\n" + triples);
        method.setRequestBody(triples);
        client.executeMethod(method);
        int status = method.getStatusCode();
        if (status == 200) {
            // OK, that was quick!
            String response = method.getResponseBodyAsString();
            System.out.println("Set value response: " + response);
        } else if (status == 202) {
            // OK, we got a task... let's wait until it is done
            String task = method.getResponseBodyAsString();
            Thread.sleep(1000); // let's be friendly, and wait 1 sec
            TaskState state = Task.getState(task);
            while (!state.isFinished()) {
                Thread.sleep(3000); // let's be friendly, and wait 3 sec
                state = Task.getState(task);
                if (state.isRedirected()) {
                    task = state.getResults();
                }
            }
            // OK, it should be finished now
            String dataset = state.getResults();
        } else {
            throw new BioclipseException("Status : " + status);
        }
        method.releaseConnection();
    }

    public static void setLicense(String datasetURI, String license) throws Exception {
        setMetadata(datasetURI, "http://purl.org/dc/terms/license", "<" + license + ">");
    }

    public static void setRightsHolder(String datasetURI, String holder) throws Exception {
        setMetadata(datasetURI, "http://purl.org/dc/terms/rightsHolder", "<" + holder + ">");
    }

    public static void setTitle(String datasetURI, String title) throws Exception {
        setMetadata(datasetURI, "http://purl.org/dc/elements/1.1/title", "\"" + title + "\"");
    }

    @SuppressWarnings("serial")
    public static void addMolecules(String datasetURI, String sdFile, IProgressMonitor monitor) throws Exception {
        if (monitor == null)
            monitor = new NullProgressMonitor();

        HttpClient client = new HttpClient();
        datasetURI = normalizeURI(datasetURI);
        PutMethod method = new PutMethod(datasetURI);
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Accept", "text/uri-list");
                put("Content-type", "chemical/x-mdl-sdfile");
            }
        });
        method.setRequestBody(sdFile);
        client.executeMethod(method);
        int status = method.getStatusCode();
        String dataset = "";
        String responseString = method.getResponseBodyAsString();
        logger.debug("Response: " + responseString);
        int tailing = 1;
        if (status == 200) {
            // OK, that was quick!
            dataset = method.getResponseBodyAsString();
            logger.debug("No Task, Data set: " + dataset);
        } else if (status == 202 || status == 201) {
            // OK, we got a task... let's wait until it is done
            String task = method.getResponseBodyAsString();
            Thread.sleep(1000); // let's be friendly, and wait 1 sec
            TaskState state = Task.getState(task);
            while (!state.isFinished() && !monitor.isCanceled()) {
                // let's be friendly, and wait 2 secs and a bit and increase
                // that time after each wait
                int waitingTime = andABit(2000 * tailing);
                logger.debug("Waiting " + waitingTime + "ms.");
                waitUnlessInterrupted(waitingTime, monitor);
                state = Task.getState(task);
                if (state.isRedirected()) {
                    task = state.getResults();
                    logger.debug("  new task, new task!!: " + task);
                }
                // but wait at most 20 secs and a bit
                if (tailing < 10)
                    tailing++;
            }
            if (monitor.isCanceled())
                Task.delete(task);
            // OK, it should be finished now
            dataset = state.getResults();
        } else {
            logger.warn("Unexpected return code when adding molecules: " + status);
        }
        method.releaseConnection();
    }

    public static String createNewDataset(String service, List<IMolecule> molecules, IProgressMonitor monitor)
            throws Exception {
        StringWriter strWriter = new StringWriter();
        SDFWriter writer = new SDFWriter(strWriter);
        for (IMolecule mol : molecules) {
            writer.write(cdk.asCDKMolecule(mol).getAtomContainer());
        }
        writer.close();
        return createNewDataset(normalizeURI(service), strWriter.toString(), monitor);
    }

    public static String createNewDataset(String service, IMolecule mol, IProgressMonitor monitor)
            throws Exception {
        StringWriter strWriter = new StringWriter();
        SDFWriter writer = new SDFWriter(strWriter);
        writer.write(cdk.asCDKMolecule(mol).getAtomContainer());
        writer.close();
        return createNewDataset(service, strWriter.toString(), monitor);
    }

    public static String createNewDataset(String service, IProgressMonitor monitor) throws Exception {
        StringWriter strWriter = new StringWriter();
        SDFWriter writer = new SDFWriter(strWriter);
        writer.write(new AtomContainer());
        writer.close();
        return createNewDataset(service, strWriter.toString(), monitor);
    }

    public static String createNewDataset(String service, String sdFile, IProgressMonitor monitor)
            throws Exception {
        if (monitor == null)
            monitor = new NullProgressMonitor();

        HttpClient client = new HttpClient();
        PostMethod method = new PostMethod(service + "dataset");
        HttpMethodHelper.addMethodHeaders(method, new HashMap<String, String>() {
            {
                put("Accept", "text/uri-list");
                put("Content-type", "chemical/x-mdl-sdfile");
            }
        });
        System.out.println("Method: " + method.toString());
        method.setRequestBody(sdFile);
        client.executeMethod(method);
        int status = method.getStatusCode();
        String dataset = "";
        String responseString = method.getResponseBodyAsString();
        logger.debug("Response: " + responseString);
        int tailing = 1;
        if (status == 200 || status == 201 || status == 202) {
            if (responseString.contains("/task/")) {
                logger.debug("Task: " + responseString);
                // OK, we got a task... let's wait until it is done
                String task = method.getResponseBodyAsString();
                Thread.sleep(1000); // let's be friendly, and wait 1 sec
                TaskState state = Task.getState(task);
                while (!state.isFinished() && !monitor.isCanceled()) {
                    // let's be friendly, and wait 2 secs and a bit and increase
                    // that time after each wait
                    int waitingTime = andABit(2000 * tailing);
                    logger.debug("Waiting " + waitingTime + "ms.");
                    waitUnlessInterrupted(waitingTime, monitor);
                    state = Task.getState(task);
                    if (state.isRedirected()) {
                        task = state.getResults();
                        logger.debug("  new task, new task!!: " + task);
                    }
                    // but wait at most 20 secs and a bit
                    if (tailing < 10)
                        tailing++;
                }
                if (monitor.isCanceled())
                    Task.delete(task);
                // OK, it should be finished now
                dataset = state.getResults();
            } else {
                // OK, that was quick!
                dataset = method.getResponseBodyAsString();
                logger.debug("No Task, Data set: " + dataset);
            }
        }
        method.releaseConnection();
        if (monitor.isCanceled())
            return "";
        logger.debug("Data set: " + dataset);
        dataset = dataset.replaceAll("\n", "");
        return dataset;
    }

    private static void waitUnlessInterrupted(int waitingTime, IProgressMonitor monitor)
            throws InterruptedException {
        int passed = 0;
        final int step = 300; // every 0.3 sec check if the process is canceled 
        while (passed < waitingTime && !monitor.isCanceled()) {
            Thread.sleep(step);
            passed += step;
        }
    }

    private static int andABit(int minimum) {
        return (minimum + (int) Math.round(minimum * Math.random()));
    }

    public static void main(String[] args) throws Exception {
        //      String service = "http://194.141.0.136:8080/";
        String service = "http://apps.ideaconsult.net:8080/ambit2/";
        //      List<String> sets = getListOfAvailableDatasets(service);
        //      for (String set : sets) System.out.println(set);
        String dataset = createNewDataset(service, null);
        List<IMolecule> mols = new ArrayList<IMolecule>();
        mols.add(cdk.fromSMILES("COC"));
        mols.add(cdk.fromSMILES("CNC"));
        mols.add(cdk.fromSMILES("CC"));
        addMolecules(dataset, mols);
        //      deleteDataset(dataset);
    }

}