// PathVisio, // a tool for data visualization and analysis using Biological Pathways // Copyright 2006-2011 BiGCaT Bioinformatics // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.pathvisio.wikipathways; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import org.apache.commons.codec.binary.Base64; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; /** * In this class the pathways can be downloaded from the internet. */ public class WikiPathwaysClient { private static final URL DEFAULT_RPCURL; static { URL url = null; try { url = new URL("http://137.120.89.38/wikipathways-test/wpi/wpi_rpc.php"); } catch (MalformedURLException e) { e.printStackTrace(); //Shouldn't happen } DEFAULT_RPCURL = url; } private URL rpcUrl = DEFAULT_RPCURL; private XmlRpcClient client; private String token = null; private String username = null; /** * A representation of WikiPathways that allows you to obtain a list * of currently available pathways, * as well as the pathways themselves. * Uses DEFAULT_RPCURL as url to WikiPathways. */ public WikiPathwaysClient() { this(DEFAULT_RPCURL); } /** * A representation of WikiPathways that allows you to obtain a list * of currently available pathways, * as well as the pathways themselves */ public WikiPathwaysClient(URL rpcUrl) { this.rpcUrl = rpcUrl; XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); config.setServerURL(rpcUrl); client = new XmlRpcClient(); client.setConfig (config); } public URL getRpUrl() { return rpcUrl; } /** * make sure request are sent no faster than once per REQUEST_WAIT_MILLIS */ private Object throttledRequest (String method, Object[] args) throws WikiPathwaysException { beforeRequest(); Object result; try { result = client.execute (method, args); } catch (XmlRpcException e) { throw new WikiPathwaysException ("Error while running " + method, e); } finally { afterRequest(); } return result; } /** * Login using WikiPathways account: necessary for submitting pathways */ public void login(String username, String pass) throws WikiPathwaysException { Object response = throttledRequest ("WikiPathways.login", new Object[] { username, pass }); token = (String) response; this.username = username; } /** * Exception wrapper for exceptions generated by WikiPathwaysClient */ public static class WikiPathwaysException extends Exception { private static final long serialVersionUID = 1L; WikiPathwaysException(String msg) { super (msg); } public WikiPathwaysException(String msg, Throwable t) { super (msg, t); } } /** * returns new revision if successfull or 0 on failure. */ public int uploadPathway(String fullName, File f, int baseRevision, String description) throws WikiPathwaysException { String[] fields = fullName.split(":"); if (fields.length != 2) throw new IllegalArgumentException ("fullName must be of the form species:name"); if (token == null || username == null) { throw new WikiPathwaysException ("Not logged in, need to be logged in for uploadPathway"); } byte[] bytes; try { InputStream is = new FileInputStream (f); long length = f.length(); if (length > Integer.MAX_VALUE) { throw new WikiPathwaysException ("File too large!"); } bytes = new byte[(int)length]; int numRead = is.read(bytes); if (numRead != length) { throw new WikiPathwaysException ("Could not completely read file " + f); } } catch (IOException e) { throw new WikiPathwaysException ("Could not read pathway", e); } Map struct = new HashMap (); struct.put ("user", username); struct.put ("token", token); Object[] params = { fields[1], fields[0], description, bytes, baseRevision, struct }; Object response = throttledRequest ("WikiPathways.updatePathway", params); int newRevision = Integer.parseInt ("" + response); return newRevision; } /** * Get a list of all available pathways on wikipathways. * The returned list contains Strings of the form * * Species:PathwayName */ public List getPathwayList () throws WikiPathwaysException { Object response = throttledRequest ("WikiPathways.getPathwayList", (Object[])null); Object[] objs = (Object[])response; List result = new ArrayList(); for (Object o : objs) { result.add ("" + o); } return result; } /** * Get a list of pathway names in Species:Name format * These are the pathways that have changed since the cutoff date. */ public List getRecentChanges (Date cutoff) throws WikiPathwaysException { // turn Date into expected timestamp format, in GMT: SimpleDateFormat sdf = new SimpleDateFormat ("yyyyMMddHHmmss"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); String timestamp = sdf.format(cutoff); Object[] params = new Object[] { timestamp }; Object response = throttledRequest ("WikiPathways.getRecentChanges", params); Object[] objs = (Object[])response; List result = new ArrayList(); for (Object o : objs) { result.add ("" + o); } return result; } static private long lastRequest = 0; /** minimum number of milliseconds between requests */ private static final long REQUEST_WAIT_MILLIS = 3000; /** waits before new request */ private void beforeRequest() { long now = System.currentTimeMillis(); long remain = (lastRequest + REQUEST_WAIT_MILLIS) - now; if (remain > 0) { try { Thread.sleep (remain); } catch (InterruptedException e) { // safely ignore } } } private void afterRequest() { lastRequest = System.currentTimeMillis(); } /** * Download a pathway from wikipathways. * * @param fullName has to be of the form Homo_sapiens:pwyname, * (as returned by getPathwayList) * @param destination: the file where the pathway will be stored. * any existing files will be overwritten * * @returns returns revision if pathway was succesfully downloaded, or -1 otherwise */ public int downloadPathway (String fullName, File destination) throws WikiPathwaysException { String[] fields = fullName.split(":"); if (fields.length != 2) throw new IllegalArgumentException ("fullName must be of the form species:name"); Object[] params = new Object[] { fields[1], fields[0] }; Object response = throttledRequest ("WikiPathways.getPathway", params); try { Map response2 = (HashMap)response; String data = (String)response2.get("gpml"); byte[] converted = Base64.decodeBase64(data.getBytes()); FileOutputStream fout = new FileOutputStream(destination); fout.write(converted); fout.close(); int revision = Integer.parseInt ("" + response2.get("revision")); return revision; } catch (IOException e) { throw new WikiPathwaysException ("IO error", e); } catch (ClassCastException e) { throw new WikiPathwaysException ("Returned object was different class than expected", e); } } }