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