formatting
[jalview.git] / src / jalview / ws / DBRefFetcher.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.analysis.AlignSeq;\r
21 import jalview.bin.Cache;\r
22 import jalview.datamodel.AlignmentI;\r
23 import jalview.datamodel.DBRefEntry;\r
24 import jalview.datamodel.DBRefSource;\r
25 import jalview.datamodel.Mapping;\r
26 import jalview.datamodel.SequenceFeature;\r
27 import jalview.datamodel.SequenceI;\r
28 import jalview.gui.AlignFrame;\r
29 import jalview.gui.CutAndPasteTransfer;\r
30 import jalview.gui.Desktop;\r
31 import jalview.gui.IProgressIndicator;\r
32 import jalview.gui.OOMWarning;\r
33 import jalview.ws.dbsources.das.api.jalviewSourceI;\r
34 import jalview.ws.seqfetcher.DbSourceProxy;\r
35 \r
36 import java.lang.reflect.Array;\r
37 import java.util.ArrayList;\r
38 import java.util.Enumeration;\r
39 import java.util.Hashtable;\r
40 import java.util.List;\r
41 import java.util.StringTokenizer;\r
42 import java.util.Vector;\r
43 \r
44 import uk.ac.ebi.picr.model.UPEntry;\r
45 \r
46 /**\r
47  * Implements a runnable for validating a sequence against external databases\r
48  * and then propagating references and features onto the sequence(s)\r
49  * \r
50  * @author $author$\r
51  * @version $Revision$\r
52  */\r
53 public class DBRefFetcher implements Runnable\r
54 {\r
55   SequenceI[] dataset;\r
56 \r
57   IProgressIndicator af;\r
58 \r
59   CutAndPasteTransfer output = new CutAndPasteTransfer();\r
60 \r
61   StringBuffer sbuffer = new StringBuffer();\r
62 \r
63   boolean running = false;\r
64 \r
65   /**\r
66    * picr client instance\r
67    */\r
68   uk.ac.ebi.www.picr.AccessionMappingService.AccessionMapperInterface picrClient = null;\r
69 \r
70   // /This will be a collection of Vectors of sequenceI refs.\r
71   // The key will be the seq name or accession id of the seq\r
72   Hashtable seqRefs;\r
73 \r
74   DbSourceProxy[] dbSources;\r
75 \r
76   SequenceFetcher sfetcher;\r
77 \r
78   private SequenceI[] alseqs;\r
79 \r
80   public DBRefFetcher()\r
81   {\r
82   }\r
83 \r
84   /**\r
85    * Creates a new SequenceFeatureFetcher object and fetches from the currently\r
86    * selected set of databases.\r
87    * \r
88    * @param seqs\r
89    *          fetch references for these sequences\r
90    * @param af\r
91    *          the parent alignframe for progress bar monitoring.\r
92    */\r
93   public DBRefFetcher(SequenceI[] seqs, AlignFrame af)\r
94   {\r
95     this(seqs, af, null);\r
96   }\r
97 \r
98   /**\r
99    * Creates a new SequenceFeatureFetcher object and fetches from the currently\r
100    * selected set of databases.\r
101    * \r
102    * @param seqs\r
103    *          fetch references for these sequences\r
104    * @param af\r
105    *          the parent alignframe for progress bar monitoring.\r
106    * @param sources\r
107    *          array of database source strings to query references from\r
108    */\r
109   public DBRefFetcher(SequenceI[] seqs, AlignFrame af,\r
110           DbSourceProxy[] sources)\r
111   {\r
112     this.af = af;\r
113     alseqs = new SequenceI[seqs.length];\r
114     SequenceI[] ds = new SequenceI[seqs.length];\r
115     for (int i = 0; i < seqs.length; i++)\r
116     {\r
117       alseqs[i] = seqs[i];\r
118       if (seqs[i].getDatasetSequence() != null)\r
119         ds[i] = seqs[i].getDatasetSequence();\r
120       else\r
121         ds[i] = seqs[i];\r
122     }\r
123     this.dataset = ds;\r
124     // TODO Jalview 2.5 lots of this code should be in the gui package!\r
125     sfetcher = jalview.gui.SequenceFetcher.getSequenceFetcherSingleton(af);\r
126     if (sources == null)\r
127     {\r
128       // af.featureSettings_actionPerformed(null);\r
129       String[] defdb = null, otherdb = sfetcher\r
130               .getDbInstances(jalview.ws.dbsources.das.datamodel.DasSequenceSource.class);\r
131       List<DbSourceProxy> selsources = new ArrayList<DbSourceProxy>();\r
132       Vector dasselsrc = (af.featureSettings != null) ? af.featureSettings\r
133               .getSelectedSources() : new jalview.gui.DasSourceBrowser()\r
134               .getSelectedSources();\r
135       Enumeration<jalviewSourceI> en = dasselsrc.elements();\r
136       while (en.hasMoreElements())\r
137       {\r
138         jalviewSourceI src = en.nextElement();\r
139         List<DbSourceProxy> sp = src.getSequenceSourceProxies();\r
140         selsources.addAll(sp);\r
141         if (sp.size() > 1)\r
142         {\r
143           Cache.log.debug("Added many Db Sources for :" + src.getTitle());\r
144         }\r
145       }\r
146       // select appropriate databases based on alignFrame context.\r
147       if (af.getViewport().getAlignment().isNucleotide())\r
148       {\r
149         defdb = DBRefSource.DNACODINGDBS;\r
150       }\r
151       else\r
152       {\r
153         defdb = DBRefSource.PROTEINDBS;\r
154       }\r
155       List<DbSourceProxy> srces = new ArrayList<DbSourceProxy>();\r
156       for (String ddb : defdb)\r
157       {\r
158         List<DbSourceProxy> srcesfordb = sfetcher.getSourceProxy(ddb);\r
159         if (srcesfordb != null)\r
160         {\r
161           srces.addAll(srcesfordb);\r
162         }\r
163       }\r
164 \r
165       // append the selected sequence sources to the default dbs\r
166       srces.addAll(selsources);\r
167       dbSources = srces.toArray(new DbSourceProxy[0]);\r
168     }\r
169     else\r
170     {\r
171       // we assume the caller knows what they're doing and ensured that all the\r
172       // db source names are valid\r
173       dbSources = sources;\r
174     }\r
175   }\r
176 \r
177   /**\r
178    * retrieve all the das sequence sources and add them to the list of db\r
179    * sources to retrieve from\r
180    */\r
181   public void appendAllDasSources()\r
182   {\r
183     if (dbSources == null)\r
184     {\r
185       dbSources = new DbSourceProxy[0];\r
186     }\r
187     // append additional sources\r
188     DbSourceProxy[] otherdb = sfetcher\r
189             .getDbSourceProxyInstances(jalview.ws.dbsources.das.datamodel.DasSequenceSource.class);\r
190     if (otherdb != null && otherdb.length > 0)\r
191     {\r
192       DbSourceProxy[] newsrc = new DbSourceProxy[dbSources.length\r
193               + otherdb.length];\r
194       System.arraycopy(dbSources, 0, newsrc, 0, dbSources.length);\r
195       System.arraycopy(otherdb, 0, newsrc, dbSources.length, otherdb.length);\r
196       dbSources = newsrc;\r
197     }\r
198   }\r
199 \r
200   /**\r
201    * start the fetcher thread\r
202    * \r
203    * @param waitTillFinished\r
204    *          true to block until the fetcher has finished\r
205    */\r
206   public void fetchDBRefs(boolean waitTillFinished)\r
207   {\r
208     Thread thread = new Thread(this);\r
209     thread.start();\r
210     running = true;\r
211 \r
212     if (waitTillFinished)\r
213     {\r
214       while (running)\r
215       {\r
216         try\r
217         {\r
218           Thread.sleep(500);\r
219         } catch (Exception ex)\r
220         {\r
221         }\r
222       }\r
223     }\r
224   }\r
225 \r
226   /**\r
227    * The sequence will be added to a vector of sequences belonging to key which\r
228    * could be either seq name or dbref id\r
229    * \r
230    * @param seq\r
231    *          SequenceI\r
232    * @param key\r
233    *          String\r
234    */\r
235   void addSeqId(SequenceI seq, String key)\r
236   {\r
237     key = key.toUpperCase();\r
238 \r
239     Vector seqs;\r
240     if (seqRefs.containsKey(key))\r
241     {\r
242       seqs = (Vector) seqRefs.get(key);\r
243 \r
244       if (seqs != null && !seqs.contains(seq))\r
245       {\r
246         seqs.addElement(seq);\r
247       }\r
248       else if (seqs == null)\r
249       {\r
250         seqs = new Vector();\r
251         seqs.addElement(seq);\r
252       }\r
253 \r
254     }\r
255     else\r
256     {\r
257       seqs = new Vector();\r
258       seqs.addElement(seq);\r
259     }\r
260 \r
261     seqRefs.put(key, seqs);\r
262   }\r
263 \r
264   /**\r
265    * DOCUMENT ME!\r
266    */\r
267   public void run()\r
268   {\r
269     if (dbSources == null)\r
270     {\r
271       throw new Error("Implementation error. Must initialise dbSources");\r
272     }\r
273     running = true;\r
274     long startTime = System.currentTimeMillis();\r
275     af.setProgressBar("Fetching db refs", startTime);\r
276     try\r
277     {\r
278       if (Cache.getDefault("DBREFFETCH_USEPICR", false))\r
279       {\r
280         picrClient = new uk.ac.ebi.www.picr.AccessionMappingService.AccessionMapperServiceLocator()\r
281                 .getAccessionMapperPort();\r
282       }\r
283     } catch (Exception e)\r
284     {\r
285       System.err.println("Couldn't locate PICR service instance.\n");\r
286       e.printStackTrace();\r
287     }\r
288     int db = 0;\r
289     Vector sdataset = new Vector();\r
290     for (int s = 0; s < dataset.length; s++)\r
291     {\r
292       sdataset.addElement(dataset[s]);\r
293     }\r
294     while (sdataset.size() > 0 && db < dbSources.length)\r
295     {\r
296       int maxqlen = 1; // default number of queries made to at one time\r
297       System.err.println("Verifying against " + dbSources[db].getDbName());\r
298       boolean dn = false;\r
299 \r
300       // iterate through db for each remaining un-verified sequence\r
301       SequenceI[] currSeqs = new SequenceI[sdataset.size()];\r
302       sdataset.copyInto(currSeqs);// seqs that are to be validated against\r
303       // dbSources[db]\r
304       Vector queries = new Vector(); // generated queries curSeq\r
305       seqRefs = new Hashtable();\r
306 \r
307       int seqIndex = 0;\r
308 \r
309       jalview.ws.seqfetcher.DbSourceProxy dbsource = dbSources[db];\r
310       {\r
311         // for moment, we dumbly iterate over all retrieval sources for a\r
312         // particular database\r
313         // TODO: introduce multithread multisource queries and logic to remove a\r
314         // query from other sources if any source for a database returns a\r
315         // record\r
316         if (dbsource.getDbSourceProperties().containsKey(\r
317                 DBRefSource.MULTIACC))\r
318         {\r
319           maxqlen = ((Integer) dbsource.getDbSourceProperties().get(\r
320                   DBRefSource.MULTIACC)).intValue();\r
321         }\r
322         else\r
323         {\r
324           maxqlen = 1;\r
325         }\r
326         while (queries.size() > 0 || seqIndex < currSeqs.length)\r
327         {\r
328           if (queries.size() > 0)\r
329           {\r
330             // Still queries to make for current seqIndex\r
331             StringBuffer queryString = new StringBuffer("");\r
332             int numq = 0, nqSize = (maxqlen > queries.size()) ? queries\r
333                     .size() : maxqlen;\r
334 \r
335             while (queries.size() > 0 && numq < nqSize)\r
336             {\r
337               String query = (String) queries.elementAt(0);\r
338               if (dbsource.isValidReference(query))\r
339               {\r
340                 queryString.append((numq == 0) ? "" : dbsource\r
341                         .getAccessionSeparator());\r
342                 queryString.append(query);\r
343                 numq++;\r
344               }\r
345               // remove the extracted query string\r
346               queries.removeElementAt(0);\r
347             }\r
348             // make the queries and process the response\r
349             AlignmentI retrieved = null;\r
350             try\r
351             {\r
352               if (jalview.bin.Cache.log.isDebugEnabled())\r
353               {\r
354                 jalview.bin.Cache.log.debug("Querying "\r
355                         + dbsource.getDbName() + " with : '"\r
356                         + queryString.toString() + "'");\r
357               }\r
358               retrieved = dbsource.getSequenceRecords(queryString\r
359                       .toString());\r
360             } catch (Exception ex)\r
361             {\r
362               ex.printStackTrace();\r
363             } catch (OutOfMemoryError err)\r
364             {\r
365               new OOMWarning("retrieving database references ("\r
366                       + queryString.toString() + ")", err);\r
367             }\r
368             if (retrieved != null)\r
369             {\r
370               transferReferences(sdataset, dbsource.getDbSource(),\r
371                       retrieved);\r
372             }\r
373           }\r
374           else\r
375           {\r
376             // make some more strings for use as queries\r
377             for (int i = 0; (seqIndex < dataset.length) && (i < 50); seqIndex++, i++)\r
378             {\r
379               SequenceI sequence = dataset[seqIndex];\r
380               DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(\r
381                       sequence.getDBRef(), new String[]\r
382                       { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT\r
383               // });\r
384               // check for existing dbrefs to use\r
385               if (uprefs != null && uprefs.length > 0)\r
386               {\r
387                 for (int j = 0; j < uprefs.length; j++)\r
388                 {\r
389                   addSeqId(sequence, uprefs[j].getAccessionId());\r
390                   queries.addElement(uprefs[j].getAccessionId()\r
391                           .toUpperCase());\r
392                 }\r
393               }\r
394               else\r
395               {\r
396                 // generate queries from sequence ID string\r
397                 StringTokenizer st = new StringTokenizer(\r
398                         sequence.getName(), "|");\r
399                 while (st.hasMoreTokens())\r
400                 {\r
401                   String token = st.nextToken();\r
402                   UPEntry[] presp = null;\r
403                   if (picrClient != null)\r
404                   {\r
405                     // resolve the string against PICR to recover valid IDs\r
406                     try\r
407                     {\r
408                       presp = picrClient.getUPIForAccession(token, null,\r
409                               picrClient.getMappedDatabaseNames(), null,\r
410                               true);\r
411                     } catch (Exception e)\r
412                     {\r
413                       System.err.println("Exception with Picr for '"\r
414                               + token + "'\n");\r
415                       e.printStackTrace();\r
416                     }\r
417                   }\r
418                   if (presp != null && presp.length > 0)\r
419                   {\r
420                     for (int id = 0; id < presp.length; id++)\r
421                     {\r
422                       // construct sequences from response if sequences are\r
423                       // present, and do a transferReferences\r
424                       // otherwise transfer non sequence x-references directly.\r
425                     }\r
426                     System.out\r
427                             .println("Validated ID against PICR... (for what its worth):"\r
428                                     + token);\r
429                     addSeqId(sequence, token);\r
430                     queries.addElement(token.toUpperCase());\r
431                   }\r
432                   else\r
433                   {\r
434                     // if ()\r
435                     // System.out.println("Not querying source with token="+token+"\n");\r
436                     addSeqId(sequence, token);\r
437                     queries.addElement(token.toUpperCase());\r
438                   }\r
439                 }\r
440               }\r
441             }\r
442           }\r
443         }\r
444       }\r
445       // advance to next database\r
446       db++;\r
447     } // all databases have been queries.\r
448     if (sbuffer.length() > 0)\r
449     {\r
450       output.setText("Your sequences have been verified against known sequence databases. Some of the ids have been\n"\r
451               + "altered, most likely the start/end residue will have been updated.\n"\r
452               + "Save your alignment to maintain the updated id.\n\n"\r
453               + sbuffer.toString());\r
454       Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);\r
455       // The above is the dataset, we must now find out the index\r
456       // of the viewed sequence\r
457 \r
458     }\r
459 \r
460     af.setProgressBar("DBRef search completed", startTime);\r
461     // promptBeforeBlast();\r
462 \r
463     running = false;\r
464 \r
465   }\r
466 \r
467   /**\r
468    * Verify local sequences in seqRefs against the retrieved sequence database\r
469    * records.\r
470    * \r
471    */\r
472   void transferReferences(Vector sdataset, String dbSource,\r
473           AlignmentI retrievedAl) // File\r
474   // file)\r
475   {\r
476     if (retrievedAl == null || retrievedAl.getHeight() == 0)\r
477     {\r
478       return;\r
479     }\r
480     SequenceI[] retrieved = recoverDbSequences(retrievedAl\r
481             .getSequencesArray());\r
482     SequenceI sequence = null;\r
483     boolean transferred = false;\r
484     StringBuffer messages = new StringBuffer();\r
485 \r
486     // Vector entries = new Uniprot().getUniprotEntries(file);\r
487 \r
488     int i, iSize = retrieved.length; // entries == null ? 0 : entries.size();\r
489     // UniprotEntry entry;\r
490     for (i = 0; i < iSize; i++)\r
491     {\r
492       SequenceI entry = retrieved[i]; // (UniprotEntry) entries.elementAt(i);\r
493 \r
494       // Work out which sequences this sequence matches,\r
495       // taking into account all accessionIds and names in the file\r
496       Vector sequenceMatches = new Vector();\r
497       // look for corresponding accession ids\r
498       DBRefEntry[] entryRefs = jalview.util.DBRefUtils.selectRefs(\r
499               entry.getDBRef(), new String[]\r
500               { dbSource });\r
501       if (entryRefs == null)\r
502       {\r
503         System.err\r
504                 .println("Dud dbSource string ? no entryrefs selected for "\r
505                         + dbSource + " on " + entry.getName());\r
506         continue;\r
507       }\r
508       for (int j = 0; j < entryRefs.length; j++)\r
509       {\r
510         String accessionId = entryRefs[j].getAccessionId(); // .getAccession().elementAt(j).toString();\r
511         // match up on accessionId\r
512         if (seqRefs.containsKey(accessionId.toUpperCase()))\r
513         {\r
514           Vector seqs = (Vector) seqRefs.get(accessionId);\r
515           for (int jj = 0; jj < seqs.size(); jj++)\r
516           {\r
517             sequence = (SequenceI) seqs.elementAt(jj);\r
518             if (!sequenceMatches.contains(sequence))\r
519             {\r
520               sequenceMatches.addElement(sequence);\r
521             }\r
522           }\r
523         }\r
524       }\r
525       if (sequenceMatches.size() == 0)\r
526       {\r
527         // failed to match directly on accessionId==query so just compare all\r
528         // sequences to entry\r
529         Enumeration e = seqRefs.keys();\r
530         while (e.hasMoreElements())\r
531         {\r
532           Vector sqs = (Vector) seqRefs.get(e.nextElement());\r
533           if (sqs != null && sqs.size() > 0)\r
534           {\r
535             Enumeration sqe = sqs.elements();\r
536             while (sqe.hasMoreElements())\r
537             {\r
538               sequenceMatches.addElement(sqe.nextElement());\r
539             }\r
540           }\r
541         }\r
542       }\r
543       // look for corresponding names\r
544       // this is uniprot specific ?\r
545       // could be useful to extend this so we try to find any 'significant'\r
546       // information in common between two sequence objects.\r
547       /*\r
548        * DBRefEntry[] entryRefs =\r
549        * jalview.util.DBRefUtils.selectRefs(entry.getDBRef(), new String[] {\r
550        * dbSource }); for (int j = 0; j < entry.getName().size(); j++) { String\r
551        * name = entry.getName().elementAt(j).toString(); if\r
552        * (seqRefs.containsKey(name)) { Vector seqs = (Vector) seqRefs.get(name);\r
553        * for (int jj = 0; jj < seqs.size(); jj++) { sequence = (SequenceI)\r
554        * seqs.elementAt(jj); if (!sequenceMatches.contains(sequence)) {\r
555        * sequenceMatches.addElement(sequence); } } } }\r
556        */\r
557       // sequenceMatches now contains the set of all sequences associated with\r
558       // the returned db record\r
559       String entrySeq = entry.getSequenceAsString().toUpperCase();\r
560       for (int m = 0; m < sequenceMatches.size(); m++)\r
561       {\r
562         sequence = (SequenceI) sequenceMatches.elementAt(m);\r
563         // only update start and end positions and shift features if there are\r
564         // no existing references\r
565         // TODO: test for legacy where uniprot or EMBL refs exist but no\r
566         // mappings are made (but content matches retrieved set)\r
567         boolean updateRefFrame = sequence.getDBRef() == null\r
568                 || sequence.getDBRef().length == 0;\r
569         // verify sequence against the entry sequence\r
570 \r
571         String nonGapped = AlignSeq.extractGaps("-. ",\r
572                 sequence.getSequenceAsString()).toUpperCase();\r
573 \r
574         int absStart = entrySeq.indexOf(nonGapped);\r
575         int mapStart = entry.getStart();\r
576         jalview.datamodel.Mapping mp;\r
577 \r
578         if (absStart == -1)\r
579         {\r
580           // Is local sequence contained in dataset sequence?\r
581           absStart = nonGapped.indexOf(entrySeq);\r
582           if (absStart == -1)\r
583           { // verification failed.\r
584             messages.append(sequence.getName()\r
585                     + " SEQUENCE NOT %100 MATCH \n");\r
586             continue;\r
587           }\r
588           transferred = true;\r
589           sbuffer.append(sequence.getName() + " HAS " + absStart\r
590                   + " PREFIXED RESIDUES COMPARED TO " + dbSource + "\n");\r
591           //\r
592           // + " - ANY SEQUENCE FEATURES"\r
593           // + " HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
594           // absStart = 0;\r
595           // create valid mapping between matching region of local sequence and\r
596           // the mapped sequence\r
597           mp = new Mapping(null, new int[]\r
598           { sequence.getStart() + absStart,\r
599               sequence.getStart() + absStart + entrySeq.length() - 1 },\r
600                   new int[]\r
601                   { entry.getStart(),\r
602                       entry.getStart() + entrySeq.length() - 1 }, 1, 1);\r
603           updateRefFrame = false; // mapping is based on current start/end so\r
604           // don't modify start and end\r
605         }\r
606         else\r
607         {\r
608           transferred = true;\r
609           // update start and end of local sequence to place it in entry's\r
610           // reference frame.\r
611           // apply identity map map from whole of local sequence to matching\r
612           // region of database\r
613           // sequence\r
614           mp = null; // Mapping.getIdentityMap();\r
615           // new Mapping(null,\r
616           // new int[] { absStart+sequence.getStart(),\r
617           // absStart+sequence.getStart()+entrySeq.length()-1},\r
618           // new int[] { entry.getStart(), entry.getEnd() }, 1, 1);\r
619           // relocate local features for updated start\r
620           if (updateRefFrame)\r
621           {\r
622             if (sequence.getSequenceFeatures() != null)\r
623             {\r
624               SequenceFeature[] sf = sequence.getSequenceFeatures();\r
625               int start = sequence.getStart();\r
626               int end = sequence.getEnd();\r
627               int startShift = 1 - absStart - start; // how much the features\r
628                                                      // are\r
629               // to be shifted by\r
630               for (int sfi = 0; sfi < sf.length; sfi++)\r
631               {\r
632                 if (sf[sfi].getBegin() >= start && sf[sfi].getEnd() <= end)\r
633                 {\r
634                   // shift feature along by absstart\r
635                   sf[sfi].setBegin(sf[sfi].getBegin() + startShift);\r
636                   sf[sfi].setEnd(sf[sfi].getEnd() + startShift);\r
637                 }\r
638               }\r
639             }\r
640           }\r
641         }\r
642 \r
643         System.out.println("Adding dbrefs to " + sequence.getName()\r
644                 + " from " + dbSource + " sequence : " + entry.getName());\r
645         sequence.transferAnnotation(entry, mp);\r
646         // unknownSequences.remove(sequence);\r
647         int absEnd = absStart + nonGapped.length();\r
648         absStart += 1;\r
649         if (updateRefFrame)\r
650         {\r
651           // finally, update local sequence reference frame if we're allowed\r
652           sequence.setStart(absStart);\r
653           sequence.setEnd(absEnd);\r
654           // search for alignment sequences to update coordinate frame for\r
655           for (int alsq = 0; alsq < alseqs.length; alsq++)\r
656           {\r
657             if (alseqs[alsq].getDatasetSequence() == sequence)\r
658             {\r
659               String ngAlsq = AlignSeq.extractGaps("-. ",\r
660                       alseqs[alsq].getSequenceAsString()).toUpperCase();\r
661               int oldstrt = alseqs[alsq].getStart();\r
662               alseqs[alsq].setStart(sequence.getSequenceAsString()\r
663                       .toUpperCase().indexOf(ngAlsq)\r
664                       + sequence.getStart());\r
665               if (oldstrt != alseqs[alsq].getStart())\r
666               {\r
667                 alseqs[alsq].setEnd(ngAlsq.length()\r
668                         + alseqs[alsq].getStart() - 1);\r
669               }\r
670             }\r
671           }\r
672           // TODO: search for all other references to this dataset sequence, and\r
673           // update start/end\r
674           // TODO: update all AlCodonMappings which involve this alignment\r
675           // sequence (e.g. Q30167 cdna translation from exon2 product (vamsas\r
676           // demo)\r
677         }\r
678         // and remove it from the rest\r
679         // TODO: decide if we should remove annotated sequence from set\r
680         sdataset.remove(sequence);\r
681         // TODO: should we make a note of sequences that have received new DB\r
682         // ids, so we can query all enabled DAS servers for them ?\r
683       }\r
684     }\r
685     if (!transferred)\r
686     {\r
687       // report the ID/sequence mismatches\r
688       sbuffer.append(messages);\r
689     }\r
690   }\r
691 \r
692   /**\r
693    * loop thru and collect additional sequences in Map.\r
694    * \r
695    * @param sequencesArray\r
696    * @return\r
697    */\r
698   private SequenceI[] recoverDbSequences(SequenceI[] sequencesArray)\r
699   {\r
700     Vector nseq = new Vector();\r
701     for (int i = 0; sequencesArray != null && i < sequencesArray.length; i++)\r
702     {\r
703       nseq.addElement(sequencesArray[i]);\r
704       DBRefEntry dbr[] = sequencesArray[i].getDBRef();\r
705       jalview.datamodel.Mapping map = null;\r
706       for (int r = 0; (dbr != null) && r < dbr.length; r++)\r
707       {\r
708         if ((map = dbr[r].getMap()) != null)\r
709         {\r
710           if (map.getTo() != null && !nseq.contains(map.getTo()))\r
711           {\r
712             nseq.addElement(map.getTo());\r
713           }\r
714         }\r
715       }\r
716     }\r
717     if (nseq.size() > 0)\r
718     {\r
719       sequencesArray = new SequenceI[nseq.size()];\r
720       nseq.toArray(sequencesArray);\r
721     }\r
722     return sequencesArray;\r
723   }\r
724 }\r