b246d0d88dd152b573b37d78de29b71ba119e60e
[jalview.git] / src / jalview / ext / ensembl / SeqFetcher.java
1 package jalview.ext.ensembl;
2
3 import jalview.io.FileParse;
4
5 import java.io.BufferedReader;
6 import java.io.DataOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.net.HttpURLConnection;
11 import java.net.URL;
12 import java.net.URLConnection;
13 import java.util.Arrays;
14 import java.util.List;
15
16 import org.apache.http.NameValuePair;
17 import org.apache.http.message.BasicNameValuePair;
18
19 public class SeqFetcher
20 {
21   private static String ensemblRest = "rest.ensembl.org";
22
23   private static boolean ensemblRestavailable = false;
24
25   private static long lastCheck = -1;
26
27   public boolean isEnsemblAvailable()
28   {
29     if (isTesting || !ensemblRestavailable
30             || System.currentTimeMillis() - lastCheck > 10000)
31     {
32       checkEnsembl();
33       lastCheck = System.currentTimeMillis();
34     }
35     return ensemblRestavailable;
36   }
37
38   private boolean isTesting, testEnsemblStatus;
39
40   /**
41    * @return the isTesting
42    */
43   public boolean isTesting()
44   {
45     return isTesting;
46   }
47
48   /**
49    * @param isTesting
50    *          the isTesting to set
51    */
52   public void setTesting(boolean isTesting)
53   {
54     this.isTesting = isTesting;
55   }
56
57   /**
58    * @return the testEnsemblStatus
59    */
60   public boolean isTestEnsemblStatus()
61   {
62     return testEnsemblStatus;
63   }
64
65   /**
66    * @param testEnsemblStatus
67    *          the testEnsemblStatus to set
68    */
69   public void setTestEnsemblStatus(boolean testEnsemblStatus)
70   {
71     this.testEnsemblStatus = testEnsemblStatus;
72   }
73
74   private void checkEnsembl()
75   {
76     if (isTesting)
77     {
78       ensemblRestavailable = testEnsemblStatus;
79       return;
80     }
81     try
82     {
83       URL ping = new URL("http://" + ensemblRest + "/info/ping");
84       HttpURLConnection conn = (HttpURLConnection) (ping.openConnection());
85       if (conn.getResponseCode() >= 200 && conn.getResponseCode() < 300)
86       {
87         ensemblRestavailable = true;
88         return;
89       }
90     } catch (Error err)
91     {
92       err.printStackTrace();
93     } catch (Exception exx)
94     {
95       exx.printStackTrace();
96     }
97     ensemblRestavailable = false;
98   }
99
100   public SeqFetcher()
101   {
102
103     // TODO Auto-generated constructor stub
104   }
105
106   public enum EnsemblSeqType
107   {
108     GENOMIC, CDS, TRANSCRIPT, PROTEIN, CDNA;
109   }
110
111   /**
112    * reolve request type as an argument for sequence and features queries
113    * 
114    * @param type
115    */
116   public List<NameValuePair> getObjectTypeArg(EnsemblSeqType type)
117   {
118     String arg;
119     switch (type)
120     {
121     case CDS:
122       arg = "cds";
123       break;
124     case TRANSCRIPT:
125       arg = "cds";
126       break;
127     case CDNA:
128       arg = "CDNA";
129       break;
130     case PROTEIN:
131       arg = "protein";
132       break;
133     case GENOMIC:
134     default:
135       arg = "genomic";
136     }
137     return Arrays.asList(new NameValuePair[]
138     { new BasicNameValuePair("type", arg) });
139   }
140
141   /**
142    * return a reader to a Fasta response from the Ensembl sequence endpoint
143    * 
144    * @param returnType
145    * @param ids
146    * @return
147    * @throws IOException
148    */
149   public FileParse getSequenceReader(EnsemblSeqType returnType,
150           List<String> ids) throws IOException
151   {
152
153     // adapted From the rest.ensembl.org documentation for sequence_id
154
155     String urls = "http://" + ensemblRest + "/sequence/id";
156     List<NameValuePair> vals = getObjectTypeArg(returnType);
157     boolean f = true;
158     for (NameValuePair nvp : vals)
159     {
160       if (f)
161       {
162         f = false;
163         urls += "?";
164       }
165       else
166       {
167         urls += "&";
168       }
169       urls += nvp.getName() + "=" + nvp.getValue();
170     }
171
172     URL url = new URL(urls);
173
174     URLConnection connection = url.openConnection();
175     HttpURLConnection httpConnection = (HttpURLConnection) connection;
176
177     httpConnection.setRequestMethod("POST");
178     httpConnection.setRequestProperty("Content-Type", "application/json");
179     httpConnection.setRequestProperty("Accept", "text/x-fasta");
180     byte[] thepostbody;
181     {
182       StringBuilder postBody = new StringBuilder();
183       postBody.append("{\"ids\":[");
184       boolean first = true;
185       for (String id : ids)
186       {
187         if (first)
188         {
189           first = false;
190         }
191         else
192         {
193           postBody.append(",");
194         }
195         postBody.append("\"");
196         postBody.append(id.trim());
197         postBody.append("\"");
198       }
199       postBody.append("]}");
200       thepostbody = postBody.toString().getBytes();
201     }
202     httpConnection.setRequestProperty("Content-Length",
203             Integer.toString(thepostbody.length));
204     httpConnection.setUseCaches(false);
205     httpConnection.setDoInput(true);
206     httpConnection.setDoOutput(true);
207
208     DataOutputStream wr = new DataOutputStream(
209             httpConnection.getOutputStream());
210     wr.write(thepostbody);
211     wr.flush();
212     wr.close();
213
214     InputStream response = connection.getInputStream();
215     int responseCode = httpConnection.getResponseCode();
216
217     if (responseCode != 200)
218     {
219       throw new RuntimeException(
220               "Response code was not 200. Detected response was "
221                       + responseCode);
222     }
223
224     BufferedReader reader = null;
225     reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
226     FileParse fp = new FileParse(reader, url.toString(), "HTTP_POST");
227     return fp;
228   }
229
230 }