update author list in license for (JAL-826)
[jalview.git] / src / jalview / ws / seqfetcher / ASequenceFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle\r
4  * \r
5  * This file is part of Jalview.\r
6  * \r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License \r
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
10  * \r
11  * Jalview is distributed in the hope that it will be useful, but \r
12  * WITHOUT ANY WARRANTY; without even the implied warranty \r
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
14  * PURPOSE.  See the GNU General Public License for more details.\r
15  * \r
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package jalview.ws.seqfetcher;\r
19 \r
20 import jalview.datamodel.AlignmentI;\r
21 import jalview.datamodel.SequenceI;\r
22 \r
23 import java.util.Enumeration;\r
24 import java.util.Hashtable;\r
25 import java.util.Vector;\r
26 \r
27 public class ASequenceFetcher\r
28 {\r
29 \r
30   /**\r
31    * set of databases we can retrieve entries from\r
32    */\r
33   protected Hashtable FETCHABLEDBS;\r
34 \r
35   public ASequenceFetcher()\r
36   {\r
37     super();\r
38   }\r
39 \r
40   /**\r
41    * get list of supported Databases\r
42    * \r
43    * @return database source string for each database - only the latest version\r
44    *         of a source db is bound to each source.\r
45    */\r
46   public String[] getSupportedDb()\r
47   {\r
48     if (FETCHABLEDBS == null)\r
49       return null;\r
50     String[] sf = new String[FETCHABLEDBS.size()];\r
51     Enumeration e = FETCHABLEDBS.keys();\r
52     int i = 0;\r
53     while (e.hasMoreElements())\r
54     {\r
55       sf[i++] = (String) e.nextElement();\r
56     }\r
57     ;\r
58     return sf;\r
59   }\r
60 \r
61   public boolean isFetchable(String source)\r
62   {\r
63     Enumeration e = FETCHABLEDBS.keys();\r
64     while (e.hasMoreElements())\r
65     {\r
66       String db = (String) e.nextElement();\r
67       if (source.compareToIgnoreCase(db) == 0)\r
68         return true;\r
69     }\r
70     jalview.bin.Cache.log.warn("isFetchable doesn't know about '" + source\r
71             + "'");\r
72     return false;\r
73   }\r
74 \r
75   public SequenceI[] getSequences(jalview.datamodel.DBRefEntry[] refs)\r
76   {\r
77     SequenceI[] ret = null;\r
78     Vector rseqs = new Vector();\r
79     Hashtable queries = new Hashtable();\r
80     for (int r = 0; r < refs.length; r++)\r
81     {\r
82       if (!queries.containsKey(refs[r].getSource()))\r
83       {\r
84         queries.put(refs[r].getSource(), new Vector());\r
85       }\r
86       Vector qset = (Vector) queries.get(refs[r].getSource());\r
87       if (!qset.contains(refs[r].getAccessionId()))\r
88       {\r
89         qset.addElement(refs[r].getAccessionId());\r
90       }\r
91     }\r
92     Enumeration e = queries.keys();\r
93     while (e.hasMoreElements())\r
94     {\r
95       Vector query = null;\r
96       String db = null;\r
97       try\r
98       {\r
99         db = (String) e.nextElement();\r
100         query = (Vector) queries.get(db);\r
101         if (!isFetchable(db))\r
102           throw new Exception(\r
103                   "Don't know how to fetch from this database :" + db);\r
104         DbSourceProxy fetcher = getSourceProxy(db);\r
105         boolean doMultiple = fetcher.getAccessionSeparator() != null; // No\r
106         // separator\r
107         // - no\r
108         // Multiple\r
109         // Queries\r
110         Enumeration qs = query.elements();\r
111         while (qs.hasMoreElements())\r
112         {\r
113           StringBuffer qsb = new StringBuffer();\r
114           do\r
115           {\r
116             qsb.append((String) qs.nextElement());\r
117             if (qs.hasMoreElements() && doMultiple) // and not reached limit for\r
118             // multiple queries at one\r
119             // time for this source\r
120             {\r
121               qsb.append(fetcher.getAccessionSeparator());\r
122             }\r
123           } while (doMultiple && qs.hasMoreElements());\r
124 \r
125           AlignmentI seqset = null;\r
126           try\r
127           {\r
128             // create a fetcher and go to it\r
129             seqset = fetcher.getSequenceRecords(qsb.toString());\r
130           } catch (Exception ex)\r
131           {\r
132             System.err.println("Failed to retrieve the following from "\r
133                     + db);\r
134             System.err.println(qsb);\r
135             ex.printStackTrace(System.err);\r
136           }\r
137           // TODO: Merge alignment together - perhaps\r
138           if (seqset != null)\r
139           {\r
140             SequenceI seqs[] = seqset.getSequencesArray();\r
141             if (seqs != null)\r
142             {\r
143               for (int is = 0; is < seqs.length; is++)\r
144               {\r
145                 rseqs.addElement(seqs[is]);\r
146                 seqs[is] = null;\r
147               }\r
148             }\r
149             else\r
150             {\r
151               if (fetcher.getRawRecords() != null)\r
152               {\r
153                 System.out.println("# Retrieved from " + db + ":"\r
154                         + qs.toString());\r
155                 StringBuffer rrb = fetcher.getRawRecords();\r
156                 /*\r
157                  * for (int rr = 0; rr<rrb.length; rr++) {\r
158                  */\r
159                 String hdr;\r
160                 // if (rr<qs.length)\r
161                 // {\r
162                 hdr = "# " + db + ":" + qsb.toString();\r
163                 /*\r
164                  * } else { hdr = "# part "+rr; }\r
165                  */\r
166                 System.out.println(hdr);\r
167                 if (rrb != null)\r
168                   System.out.println(rrb);\r
169                 System.out.println("# end of " + hdr);\r
170               }\r
171             }\r
172           }\r
173         }\r
174       } catch (Exception ex)\r
175       {\r
176         System.err\r
177                 .println("Failed to retrieve the following references from "\r
178                         + db);\r
179         Enumeration qv = query.elements();\r
180         int n = 0;\r
181         while (qv.hasMoreElements())\r
182         {\r
183           System.err.print(" " + qv.nextElement() + ";");\r
184           if (n++ > 10)\r
185           {\r
186             System.err.println();\r
187             n = 0;\r
188           }\r
189         }\r
190         System.err.println();\r
191         ex.printStackTrace();\r
192       }\r
193     }\r
194     if (rseqs.size() > 0)\r
195     {\r
196       ret = new SequenceI[rseqs.size()];\r
197       Enumeration sqs = rseqs.elements();\r
198       int si = 0;\r
199       while (sqs.hasMoreElements())\r
200       {\r
201         SequenceI s = (SequenceI) sqs.nextElement();\r
202         ret[si++] = s;\r
203         s.updatePDBIds();\r
204       }\r
205     }\r
206     return ret;\r
207   }\r
208 \r
209   /**\r
210    * Retrieve an instance of the proxy for the given source\r
211    * \r
212    * @param db\r
213    *          database source string TODO: add version string/wildcard for\r
214    *          retrieval of specific DB source/version combinations.\r
215    * @return an instance of DbSourceProxy for that db.\r
216    */\r
217   public DbSourceProxy getSourceProxy(String db)\r
218   {\r
219     DbSourceProxy dbs = (DbSourceProxy) FETCHABLEDBS.get(db);\r
220     return dbs;\r
221   }\r
222 \r
223   /**\r
224    * constructs and instance of the proxy and registers it as a valid\r
225    * dbrefsource\r
226    * \r
227    * @param dbSourceProxy\r
228    *          reference for class implementing\r
229    *          jalview.ws.seqfetcher.DbSourceProxy\r
230    * @throws java.lang.IllegalArgumentException\r
231    *           if class does not implement jalview.ws.seqfetcher.DbSourceProxy\r
232    */\r
233   protected void addDBRefSourceImpl(Class dbSourceProxy)\r
234           throws java.lang.IllegalArgumentException\r
235   {\r
236     DbSourceProxy proxy = null;\r
237     try\r
238     {\r
239       Object proxyObj = dbSourceProxy.getConstructor(null)\r
240               .newInstance(null);\r
241       if (!DbSourceProxy.class.isInstance(proxyObj))\r
242       {\r
243         throw new IllegalArgumentException(\r
244                 dbSourceProxy.toString()\r
245                         + " does not implement the jalview.ws.seqfetcher.DbSourceProxy");\r
246       }\r
247       proxy = (DbSourceProxy) proxyObj;\r
248     } catch (IllegalArgumentException e)\r
249     {\r
250       throw e;\r
251     } catch (Exception e)\r
252     {\r
253       // Serious problems if this happens.\r
254       throw new Error("DBRefSource Implementation Exception", e);\r
255     }\r
256     addDbRefSourceImpl(proxy);\r
257   }\r
258 \r
259   /**\r
260    * add the properly initialised DbSourceProxy object 'proxy' to the list of\r
261    * sequence fetchers\r
262    * \r
263    * @param proxy\r
264    */\r
265   protected void addDbRefSourceImpl(DbSourceProxy proxy)\r
266   {\r
267     if (proxy != null)\r
268     {\r
269       if (FETCHABLEDBS == null)\r
270       {\r
271         FETCHABLEDBS = new Hashtable();\r
272       }\r
273       FETCHABLEDBS.put(proxy.getDbSource(), proxy);\r
274     }\r
275   }\r
276 \r
277   /**\r
278    * test if the database handler for dbName contains the given dbProperty\r
279    * \r
280    * @param dbName\r
281    * @param dbProperty\r
282    * @return true if proxy has the given property\r
283    */\r
284   public boolean hasDbSourceProperty(String dbName, String dbProperty)\r
285   {\r
286     // TODO: decide if invalidDbName exception is thrown here.\r
287     DbSourceProxy proxy = getSourceProxy(dbName);\r
288     if (proxy != null)\r
289     {\r
290       if (proxy.getDbSourceProperties() != null)\r
291       {\r
292         return proxy.getDbSourceProperties().containsKey(dbProperty);\r
293       }\r
294     }\r
295     return false;\r
296   }\r
297 \r
298   /**\r
299    * select sources which are implemented by instances of the given class\r
300    * \r
301    * @param class that implements DbSourceProxy\r
302    * @return null or vector of source names for fetchers\r
303    */\r
304   public String[] getDbInstances(Class class1)\r
305   {\r
306     if (!jalview.ws.seqfetcher.DbSourceProxy.class.isAssignableFrom(class1))\r
307     {\r
308       throw new Error(\r
309               "Implmentation Error - getDbInstances must be given a class that implements jalview.ws.seqfetcher.DbSourceProxy (was given '"\r
310                       + class1 + "')");\r
311     }\r
312     if (FETCHABLEDBS == null)\r
313     {\r
314       return null;\r
315     }\r
316     String[] sources = null;\r
317     Vector src = new Vector();\r
318     Enumeration dbs = FETCHABLEDBS.keys();\r
319     while (dbs.hasMoreElements())\r
320     {\r
321       String dbn = (String) dbs.nextElement();\r
322       DbSourceProxy dbp = (DbSourceProxy) FETCHABLEDBS.get(dbn);\r
323       if (class1.isAssignableFrom(dbp.getClass()))\r
324       {\r
325         src.addElement(dbn);\r
326       }\r
327     }\r
328     if (src.size() > 0)\r
329     {\r
330       src.copyInto(sources = new String[src.size()]);\r
331     }\r
332     return sources;\r
333   }\r
334 }\r