Merge branch 'JAL-972-dasobert-to-jdas' into JAL-972-jdas
[jalview.git] / src / jalview / ws / SequenceFetcher.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;\r
19 \r
20 import jalview.datamodel.Alignment;\r
21 import jalview.datamodel.AlignmentI;\r
22 import jalview.datamodel.DBRefSource;\r
23 import jalview.datamodel.SequenceI;\r
24 import jalview.ws.dbsources.das.api.jalviewSourceI;\r
25 import jalview.ws.seqfetcher.ASequenceFetcher;\r
26 import jalview.ws.seqfetcher.DbSourceProxy;\r
27 \r
28 import java.util.ArrayList;\r
29 import java.util.Enumeration;\r
30 import java.util.List;\r
31 import java.util.Vector;\r
32 \r
33 /**\r
34  * This is the the concrete implementation of the sequence retrieval interface\r
35  * and abstract class in jalview.ws.seqfetcher. This implements the run-time\r
36  * discovery of sequence database clients, and provides a hardwired main for\r
37  * testing all registered handlers.\r
38  * \r
39  */\r
40 public class SequenceFetcher extends ASequenceFetcher\r
41 {\r
42   /**\r
43    * Thread safe construction of database proxies TODO: extend to a configurable\r
44    * database plugin mechanism where classes are instantiated by reflection and\r
45    * queried for their DbRefSource and version association.\r
46    * \r
47    */\r
48   public SequenceFetcher()\r
49   {\r
50     addDBRefSourceImpl(jalview.ws.dbsources.EmblSource.class);\r
51     addDBRefSourceImpl(jalview.ws.dbsources.EmblCdsSouce.class);\r
52     addDBRefSourceImpl(jalview.ws.dbsources.Uniprot.class);\r
53     addDBRefSourceImpl(jalview.ws.dbsources.UnprotName.class);\r
54     addDBRefSourceImpl(jalview.ws.dbsources.Pdb.class);\r
55     addDBRefSourceImpl(jalview.ws.dbsources.PfamFull.class);\r
56     addDBRefSourceImpl(jalview.ws.dbsources.PfamSeed.class); // ensures Seed\r
57     // alignment is\r
58     // 'default' for\r
59     // PFAM\r
60     addDBRefSourceImpl(jalview.ws.dbsources.RfamFull.class);\r
61     addDBRefSourceImpl(jalview.ws.dbsources.RfamSeed.class);\r
62     registerDasSequenceSources();\r
63   }\r
64 \r
65   /**\r
66    * return an ordered list of database sources suitable for using in a GUI\r
67    * element\r
68    */\r
69   public String[] getOrderedSupportedSources()\r
70   {\r
71     String[] srcs = this.getSupportedDb();\r
72     ArrayList dassrc = new ArrayList(), nondas = new ArrayList();\r
73     for (int i = 0; i < srcs.length; i++)\r
74     {\r
75       String nm = getSourceProxy(srcs[i]).getDbName();\r
76       if (getSourceProxy(srcs[i]) instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)\r
77       {\r
78         if (nm.startsWith("das:"))\r
79         {\r
80           nm = nm.substring(4);\r
81         }\r
82         dassrc.add(new String[]\r
83         { srcs[i], nm.toUpperCase() });\r
84       }\r
85       else\r
86       {\r
87         nondas.add(new String[]\r
88         { srcs[i], nm.toUpperCase() });\r
89       }\r
90     }\r
91     Object[] sorted = nondas.toArray();\r
92     String[] tosort = new String[sorted.length];\r
93     nondas.clear();\r
94     for (int j = 0; j < sorted.length; j++)\r
95     {\r
96       tosort[j] = ((String[]) sorted[j])[1];\r
97     }\r
98     jalview.util.QuickSort.sort(tosort, sorted);\r
99     int i = 0;\r
100     for (int j = sorted.length - 1; j >= 0; j--, i++)\r
101     {\r
102       srcs[i] = ((String[]) sorted[j])[0];\r
103       sorted[j] = null;\r
104     }\r
105 \r
106     sorted = dassrc.toArray();\r
107     tosort = new String[sorted.length];\r
108     dassrc.clear();\r
109     for (int j = 0; j < sorted.length; j++)\r
110     {\r
111       tosort[j] = ((String[]) sorted[j])[1];\r
112     }\r
113     jalview.util.QuickSort.sort(tosort, sorted);\r
114     for (int j = sorted.length - 1; j >= 0; j--, i++)\r
115     {\r
116       srcs[i] = ((String[]) sorted[j])[0];\r
117       sorted[j] = null;\r
118     }\r
119     return srcs;\r
120   }\r
121 \r
122   /**\r
123    * simple run method to test dbsources.\r
124    * \r
125    * @param argv\r
126    */\r
127   public static void main(String[] argv)\r
128   {\r
129     AlignmentI ds = null;\r
130     Vector noProds = new Vector();\r
131     String usage = "SequenceFetcher.main [<DBNAME> <ACCNO>]\n"\r
132             + "With no arguments, all DbSources will be queried with their test Accession number.\n"\r
133             + "If given two arguments, SequenceFetcher will try to find the DbFetcher corresponding to <DBNAME> and retrieve <ACCNO> from it.";\r
134     if (argv != null && argv.length > 0)\r
135     {\r
136       DbSourceProxy sp = new SequenceFetcher().getSourceProxy(argv[0]);\r
137       if (sp != null)\r
138       {\r
139         AlignmentI al = null;\r
140         try\r
141         {\r
142           al = sp.getSequenceRecords(argv[1]);\r
143         } catch (Exception e)\r
144         {\r
145           e.printStackTrace();\r
146           System.err.println("Error when retrieving " + argv[1] + " from "\r
147                   + argv[0] + "\nUsage: " + usage);\r
148         }\r
149         SequenceI[] prod = al.getSequencesArray();\r
150         if (al != null)\r
151         {\r
152           for (int p = 0; p < prod.length; p++)\r
153           {\r
154             System.out.println("Prod " + p + ": "\r
155                     + prod[p].getDisplayId(true) + " : "\r
156                     + prod[p].getDescription());\r
157           }\r
158         }\r
159         return;\r
160       }\r
161       else\r
162       {\r
163         System.err.println("Can't resolve " + argv[0]\r
164                 + " as a database name. Allowed values are :\n"\r
165                 + new SequenceFetcher().getSupportedDb());\r
166       }\r
167       System.out.println(usage);\r
168     }\r
169     ASequenceFetcher sfetcher = new SequenceFetcher();\r
170     String[] dbSources = sfetcher.getSupportedDb();\r
171     for (int dbsource = 0; dbsource < dbSources.length; dbsource++)\r
172     {\r
173       String db = dbSources[dbsource];\r
174       // skip me\r
175       if (db.equals(DBRefSource.PDB))\r
176         continue;\r
177       DbSourceProxy sp = sfetcher.getSourceProxy(db);\r
178       System.out.println("Source: " + sp.getDbName() + " (" + db\r
179               + "): retrieving test:" + sp.getTestQuery());\r
180       AlignmentI al = null;\r
181       try\r
182       {\r
183         al = sp.getSequenceRecords(sp.getTestQuery());\r
184         if (al != null && al.getHeight() > 0\r
185                 && sp.getDbSourceProperties() != null)\r
186         {\r
187           boolean dna = sp.getDbSourceProperties().containsKey(\r
188                   DBRefSource.DNACODINGSEQDB)\r
189                   || sp.getDbSourceProperties().containsKey(\r
190                           DBRefSource.DNASEQDB)\r
191                   || sp.getDbSourceProperties().containsKey(\r
192                           DBRefSource.CODINGSEQDB);\r
193           // try and find products\r
194           String types[] = jalview.analysis.CrossRef.findSequenceXrefTypes(\r
195                   dna, al.getSequencesArray());\r
196           if (types != null)\r
197           {\r
198             System.out.println("Xref Types for: " + (dna ? "dna" : "prot"));\r
199             for (int t = 0; t < types.length; t++)\r
200             {\r
201               System.out.println("Type: " + types[t]);\r
202               SequenceI[] prod = jalview.analysis.CrossRef\r
203                       .findXrefSequences(al.getSequencesArray(), dna,\r
204                               types[t]).getSequencesArray();\r
205               System.out.println("Found "\r
206                       + ((prod == null) ? "no" : "" + prod.length)\r
207                       + " products");\r
208               if (prod != null)\r
209               {\r
210                 for (int p = 0; p < prod.length; p++)\r
211                 {\r
212                   System.out.println("Prod " + p + ": "\r
213                           + prod[p].getDisplayId(true));\r
214                 }\r
215               }\r
216             }\r
217           }\r
218           else\r
219           {\r
220             noProds.addElement((dna ? new Object[]\r
221             { al, al } : new Object[]\r
222             { al }));\r
223           }\r
224 \r
225         }\r
226       } catch (Exception ex)\r
227       {\r
228         System.out.println("ERROR:Failed to retrieve test query.");\r
229         ex.printStackTrace(System.out);\r
230       }\r
231       if (al == null)\r
232       {\r
233         System.out.println("ERROR:No alignment retrieved.");\r
234         StringBuffer raw = sp.getRawRecords();\r
235         if (raw != null)\r
236           System.out.println(raw.toString());\r
237         else\r
238           System.out.println("ERROR:No Raw results.");\r
239       }\r
240       else\r
241       {\r
242         System.out.println("Retrieved " + al.getHeight() + " sequences.");\r
243         for (int s = 0; s < al.getHeight(); s++)\r
244         {\r
245           SequenceI sq = al.getSequenceAt(s);\r
246           while (sq.getDatasetSequence() != null)\r
247           {\r
248             sq = sq.getDatasetSequence();\r
249 \r
250           }\r
251           if (ds == null)\r
252           {\r
253             ds = new Alignment(new SequenceI[]\r
254             { sq });\r
255 \r
256           }\r
257           else\r
258           {\r
259             ds.addSequence(sq);\r
260           }\r
261         }\r
262       }\r
263       System.out.flush();\r
264       System.err.flush();\r
265 \r
266     }\r
267     if (noProds.size() > 0)\r
268     {\r
269       Enumeration ts = noProds.elements();\r
270       while (ts.hasMoreElements())\r
271 \r
272       {\r
273         Object[] typeSq = (Object[]) ts.nextElement();\r
274         boolean dna = (typeSq.length > 1);\r
275         AlignmentI al = (AlignmentI) typeSq[0];\r
276         System.out.println("Trying getProducts for "\r
277                 + al.getSequenceAt(0).getDisplayId(true));\r
278         System.out.println("Search DS Xref for: " + (dna ? "dna" : "prot"));\r
279         // have a bash at finding the products amongst all the retrieved\r
280         // sequences.\r
281         SequenceI[] seqs = al.getSequencesArray();\r
282         Alignment prodal = jalview.analysis.CrossRef.findXrefSequences(\r
283                 seqs, dna, null, ds);\r
284         System.out.println("Found "\r
285                 + ((prodal == null) ? "no" : "" + prodal.getHeight())\r
286                 + " products");\r
287         if (prodal != null)\r
288         {\r
289           SequenceI[] prod = prodal.getSequencesArray(); // note\r
290           // should\r
291           // test\r
292           // rather\r
293           // than\r
294           // throw\r
295           // away\r
296           // codon\r
297           // mapping\r
298           // (if\r
299           // present)\r
300           for (int p = 0; p < prod.length; p++)\r
301           {\r
302             System.out.println("Prod " + p + ": "\r
303                     + prod[p].getDisplayId(true));\r
304           }\r
305         }\r
306       }\r
307 \r
308     }\r
309   }\r
310 \r
311   /**\r
312    * query the currently defined DAS source registry for sequence sources and\r
313    * add a DasSequenceSource instance for each source to the SequenceFetcher\r
314    * source list.\r
315    */\r
316   public void registerDasSequenceSources()\r
317   {\r
318     // TODO: define a context as a registry provider (either desktop,\r
319     // jalview.bin.cache, or something else).\r
320     for (jalviewSourceI source : jalview.bin.Cache.getDasSourceRegistry().getSources())\r
321     {\r
322       if (source.isSequenceSource())\r
323       {\r
324         List<DbSourceProxy> dassources = source.getSequenceSourceProxies();\r
325         for (DbSourceProxy seqsrc : dassources)\r
326         {\r
327           addDbRefSourceImpl(seqsrc);\r
328         }\r
329       }\r
330     }\r
331   }\r
332 }\r