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