4b7c07e6d1b0dcd72ab01909a98a0c732fdd0a39
[jalview.git] / src / jalview / ws / DBRefFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)\r
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  * \r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  * \r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  * \r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.ws;\r
20 \r
21 import jalview.analysis.AlignSeq;\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    * picr client instance\r
64    */\r
65   uk.ac.ebi.www.picr.AccessionMappingService.AccessionMapperInterface picrClient = null;\r
66 \r
67   // /This will be a collection of Vectors of sequenceI refs.\r
68   // The key will be the seq name or accession id of the seq\r
69   Hashtable seqRefs;\r
70 \r
71   String[] dbSources;\r
72 \r
73   SequenceFetcher sfetcher;\r
74 \r
75   public DBRefFetcher()\r
76   {\r
77   }\r
78 \r
79   /**\r
80    * Creates a new SequenceFeatureFetcher object and fetches from the\r
81    * currently selected set of databases.\r
82    * \r
83    * @param seqs\r
84    *                fetch references for these sequences\r
85    * @param af\r
86    *                the parent alignframe for progress bar monitoring.\r
87    */\r
88   public DBRefFetcher(SequenceI[] seqs, AlignFrame af)\r
89   {\r
90     this(seqs, af, null);\r
91   }\r
92   /**\r
93    * Creates a new SequenceFeatureFetcher object and fetches from the\r
94    * currently selected set of databases.\r
95    * \r
96    * @param seqs\r
97    *                fetch references for these sequences\r
98    * @param af\r
99    *                the parent alignframe for progress bar monitoring.\r
100    * @param sources array of database source strings to query references from\r
101    */\r
102   public DBRefFetcher(SequenceI[] seqs, AlignFrame af, String[] sources)\r
103   {\r
104     this.af = af;\r
105     SequenceI[] ds = new SequenceI[seqs.length];\r
106     for (int i = 0; i < seqs.length; i++)\r
107     {\r
108       if (seqs[i].getDatasetSequence() != null)\r
109         ds[i] = seqs[i].getDatasetSequence();\r
110       else\r
111         ds[i] = seqs[i];\r
112     }\r
113     this.dataset = ds;\r
114     // TODO Jalview 2.5 lots of this code should be in the gui package!\r
115     sfetcher = jalview.gui.SequenceFetcher.getSequenceFetcherSingleton(af);\r
116     if (sources==null)\r
117     {\r
118       // af.featureSettings_actionPerformed(null);\r
119       String[] defdb=null,otherdb = sfetcher.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class);\r
120       Vector selsources = new Vector(), dasselsrc= (af.featureSettings!=null) ? af.featureSettings.getSelectedSources()\r
121               : new jalview.gui.DasSourceBrowser().getSelectedSources();\r
122       Enumeration en = dasselsrc.elements();\r
123       while (en.hasMoreElements())\r
124       {\r
125         DasSource src = (DasSource) en.nextElement();\r
126         selsources.addElement(src.getNickname());\r
127       }\r
128       int osel = 0;\r
129       for (int o=0;otherdb!=null && o<otherdb.length;o++)\r
130       {\r
131         if (!selsources.contains(otherdb[o]))\r
132         {\r
133           otherdb[o] = null;\r
134         } else {\r
135           osel++;\r
136         }\r
137       }\r
138       // select appropriate databases based on alignFrame context.\r
139       if (af.getViewport().getAlignment().isNucleotide())\r
140       {\r
141         defdb = DBRefSource.DNACODINGDBS;\r
142       }\r
143       else\r
144       {\r
145         defdb = DBRefSource.PROTEINDBS;\r
146       }\r
147       // append the selected sequence sources to the default dbs \r
148       dbSources = new String[defdb.length+osel];\r
149       System.arraycopy(defdb, 0, dbSources, 0, defdb.length);\r
150       for (int o=0,op=defdb.length; otherdb!=null && o<otherdb.length; o++)\r
151       {\r
152         if (otherdb[o]!=null)\r
153         {\r
154           dbSources[op++] = otherdb[o];\r
155         }\r
156       }\r
157     } else {\r
158       // we assume the caller knows what they're doing and ensured that all the db source names are valid\r
159       dbSources = sources;\r
160     }\r
161   }\r
162   /**\r
163    * retrieve all the das sequence sources and add them to the list of db sources to retrieve from \r
164    */\r
165   public void appendAllDasSources()\r
166   {\r
167     if (dbSources == null)\r
168     {\r
169       dbSources = new String[] {};\r
170     }\r
171     // append additional sources\r
172     String[] otherdb = sfetcher.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class);\r
173     if (otherdb!=null && otherdb.length>0)\r
174     {\r
175       String[] newsrc = new String[dbSources.length+otherdb.length];\r
176       System.arraycopy(dbSources, 0, newsrc,0,dbSources.length);\r
177       System.arraycopy(otherdb, 0, newsrc,dbSources.length, otherdb.length);\r
178       dbSources = newsrc;\r
179     }\r
180   }\r
181   /**\r
182    * start the fetcher thread\r
183    * \r
184    * @param waitTillFinished\r
185    *                true to block until the fetcher has finished\r
186    */\r
187   public void fetchDBRefs(boolean waitTillFinished)\r
188   {\r
189     Thread thread = new Thread(this);\r
190     thread.start();\r
191     running = true;\r
192 \r
193     if (waitTillFinished)\r
194     {\r
195       while (running)\r
196       {\r
197         try\r
198         {\r
199           Thread.sleep(500);\r
200         } catch (Exception ex)\r
201         {\r
202         }\r
203       }\r
204     }\r
205   }\r
206 \r
207   /**\r
208    * The sequence will be added to a vector of sequences belonging to key which\r
209    * could be either seq name or dbref id\r
210    * \r
211    * @param seq\r
212    *                SequenceI\r
213    * @param key\r
214    *                String\r
215    */\r
216   void addSeqId(SequenceI seq, String key)\r
217   {\r
218     key = key.toUpperCase();\r
219 \r
220     Vector seqs;\r
221     if (seqRefs.containsKey(key))\r
222     {\r
223       seqs = (Vector) seqRefs.get(key);\r
224 \r
225       if (seqs != null && !seqs.contains(seq))\r
226       {\r
227         seqs.addElement(seq);\r
228       }\r
229       else if (seqs == null)\r
230       {\r
231         seqs = new Vector();\r
232         seqs.addElement(seq);\r
233       }\r
234 \r
235     }\r
236     else\r
237     {\r
238       seqs = new Vector();\r
239       seqs.addElement(seq);\r
240     }\r
241 \r
242     seqRefs.put(key, seqs);\r
243   }\r
244 \r
245   /**\r
246    * DOCUMENT ME!\r
247    */\r
248   public void run()\r
249   {\r
250     if (dbSources == null)\r
251     {\r
252       throw new Error("Implementation error. Must initialise dbSources");\r
253     }\r
254     running = true;\r
255     long startTime = System.currentTimeMillis();\r
256     af.setProgressBar("Fetching db refs", startTime);\r
257     try {\r
258       picrClient = new uk.ac.ebi.www.picr.AccessionMappingService.AccessionMapperServiceLocator().getAccessionMapperPort(); \r
259     } catch (Exception e)\r
260     {\r
261       System.err.println("Couldn't locate PICR service instance.\n");\r
262       e.printStackTrace();\r
263     }\r
264     int db = 0;\r
265     Vector sdataset = new Vector();\r
266     for (int s = 0; s < dataset.length; s++)\r
267     {\r
268       sdataset.addElement(dataset[s]);\r
269     }\r
270     while (sdataset.size() > 0 && db < dbSources.length)\r
271     {\r
272       int maxqlen = 1; // default number of queries made to at one time\r
273       System.err.println("Verifying against " + dbSources[db]);\r
274       jalview.ws.seqfetcher.DbSourceProxy dbsource = sfetcher\r
275               .getSourceProxy(dbSources[db]);\r
276       if (dbsource == null)\r
277       {\r
278         System.err.println("No proxy for " + dbSources[db]);\r
279         db++;\r
280         continue;\r
281       }\r
282       if (dbsource.getDbSourceProperties()\r
283               .containsKey(DBRefSource.MULTIACC))\r
284       {\r
285         maxqlen = ((Integer) dbsource.getDbSourceProperties().get(\r
286                 DBRefSource.MULTIACC)).intValue();\r
287       }\r
288       else\r
289       {\r
290         maxqlen = 1;\r
291       }\r
292       // iterate through db for each remaining un-verified sequence\r
293       SequenceI[] currSeqs = new SequenceI[sdataset.size()];\r
294       sdataset.copyInto(currSeqs);// seqs that are to be validated against\r
295       // dbSources[db]\r
296       Vector queries = new Vector(); // generated queries curSeq\r
297       seqRefs = new Hashtable();\r
298 \r
299       int seqIndex = 0;\r
300 \r
301       while (queries.size() > 0 || seqIndex < currSeqs.length)\r
302       {\r
303         if (queries.size() > 0)\r
304         {\r
305           // Still queries to make for current seqIndex\r
306           StringBuffer queryString = new StringBuffer("");\r
307           int numq=0,nqSize = (maxqlen > queries.size()) ? queries.size()\r
308                   : maxqlen;\r
309           \r
310           while (queries.size()>0 && numq < nqSize)\r
311           {\r
312             String query = (String) queries.elementAt(0);\r
313             if (dbsource.isValidReference(query))\r
314             {\r
315               queryString.append((numq == 0) ? "" : dbsource\r
316                       .getAccessionSeparator());\r
317               queryString.append(query);\r
318               numq++;\r
319             }\r
320             // remove the extracted query string\r
321             queries.removeElementAt(0);\r
322           }\r
323           // make the queries and process the response\r
324           AlignmentI retrieved = null;\r
325           try\r
326           {\r
327             if (jalview.bin.Cache.log.isDebugEnabled())\r
328             {\r
329               jalview.bin.Cache.log.debug("Querying "+dbsource.getDbName()+" with : '"+queryString.toString()+"'");\r
330             }\r
331             retrieved = dbsource.getSequenceRecords(queryString.toString());\r
332           } catch (Exception ex)\r
333           {\r
334             ex.printStackTrace();\r
335           } catch (OutOfMemoryError err)\r
336           {\r
337             new OOMWarning("retrieving database references ("\r
338                     + queryString.toString() + ")", err);\r
339           }\r
340           if (retrieved != null)\r
341           {\r
342             transferReferences(sdataset, dbSources[db], retrieved);\r
343           }\r
344         }\r
345         else\r
346         {\r
347           // make some more strings for use as queries\r
348           for (int i = 0; (seqIndex < dataset.length) && (i < 50); seqIndex++, i++)\r
349           {\r
350             SequenceI sequence = dataset[seqIndex];\r
351             DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(\r
352                     sequence.getDBRef(), new String[]\r
353                     { dbSources[db] }); // jalview.datamodel.DBRefSource.UNIPROT\r
354             // });\r
355             // check for existing dbrefs to use\r
356             if (uprefs != null && uprefs.length>0)\r
357             {\r
358               for (int j = 0; j < uprefs.length; j++)\r
359               {\r
360                 addSeqId(sequence, uprefs[j].getAccessionId());\r
361                 queries\r
362                         .addElement(uprefs[j].getAccessionId()\r
363                                 .toUpperCase());\r
364               }\r
365             }\r
366             else\r
367             {\r
368               // generate queries from sequence ID string\r
369               StringTokenizer st = new StringTokenizer(sequence.getName(),\r
370                       "|");\r
371               while (st.hasMoreTokens())\r
372               {\r
373                 String token = st.nextToken();\r
374                 UPEntry[] presp = null;\r
375                 try {\r
376                   presp=picrClient.getUPIForAccession(token, null, picrClient.getMappedDatabaseNames(), null, true);\r
377                 } catch (Exception e) {\r
378                   System.err.println("Exception with Picr for '"+token+"'\n");\r
379                   e.printStackTrace();\r
380                 }\r
381                 if (presp!=null && presp.length>0)\r
382                 {\r
383                   for (int id=0;id<presp.length; id++)\r
384                   {\r
385                     // construct sequences from response if sequences are present, and do a transferReferences\r
386                     // otherwise transfer non sequence x-references directly.\r
387                   }\r
388                   System.out.println("Validated ID against PICR... (for what its worth):"+token);\r
389                   addSeqId(sequence, token);\r
390                   queries.addElement(token.toUpperCase());\r
391                 } else {\r
392                   //if ()\r
393                   //System.out.println("Not querying source with token="+token+"\n");\r
394                   addSeqId(sequence, token);\r
395                   queries.addElement(token.toUpperCase());\r
396                 }\r
397               }\r
398             }\r
399           }\r
400         }\r
401       }\r
402       // advance to next database\r
403       db++;\r
404     } // all databases have been queries.\r
405     if (sbuffer.length() > 0)\r
406     {\r
407       output\r
408               .setText("Your sequences have been verified against known sequence databases. Some of the ids have been\n"\r
409                       + "altered, most likely the start/end residue will have been updated.\n"\r
410                       + "Save your alignment to maintain the updated id.\n\n"\r
411                       + sbuffer.toString());\r
412       Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);\r
413       // The above is the dataset, we must now find out the index\r
414       // of the viewed sequence\r
415 \r
416     }\r
417 \r
418     af.setProgressBar("DBRef search completed", startTime);\r
419     // promptBeforeBlast();\r
420 \r
421     running = false;\r
422 \r
423   }\r
424 \r
425   /**\r
426    * Verify local sequences in seqRefs against the retrieved sequence database\r
427    * records.\r
428    * \r
429    */\r
430   void transferReferences(Vector sdataset, String dbSource,\r
431           AlignmentI retrievedAl) // File\r
432   // file)\r
433   {\r
434 \r
435     if (retrievedAl == null || retrievedAl.getHeight() == 0)\r
436     {\r
437       return;\r
438     }\r
439     SequenceI[] retrieved = recoverDbSequences(retrievedAl.getSequencesArray());\r
440     SequenceI sequence = null;\r
441 \r
442     // Vector entries = new Uniprot().getUniprotEntries(file);\r
443 \r
444     int i, iSize = retrieved.length; // entries == null ? 0 : entries.size();\r
445     // UniprotEntry entry;\r
446     for (i = 0; i < iSize; i++)\r
447     {\r
448       SequenceI entry = retrieved[i]; // (UniprotEntry) entries.elementAt(i);\r
449 \r
450       // Work out which sequences this sequence matches,\r
451       // taking into account all accessionIds and names in the file\r
452       Vector sequenceMatches = new Vector();\r
453       // look for corresponding accession ids\r
454       DBRefEntry[] entryRefs = jalview.util.DBRefUtils.selectRefs(entry\r
455               .getDBRef(), new String[]\r
456       { dbSource });\r
457       for (int j = 0; j < entryRefs.length; j++)\r
458       {\r
459         String accessionId = entryRefs[j].getAccessionId(); // .getAccession().elementAt(j).toString();\r
460         // match up on accessionId\r
461         if (seqRefs.containsKey(accessionId.toUpperCase()))\r
462         {\r
463           Vector seqs = (Vector) seqRefs.get(accessionId);\r
464           for (int jj = 0; jj < seqs.size(); jj++)\r
465           {\r
466             sequence = (SequenceI) seqs.elementAt(jj);\r
467             if (!sequenceMatches.contains(sequence))\r
468             {\r
469               sequenceMatches.addElement(sequence);\r
470             }\r
471           }\r
472         }\r
473       }\r
474       if (sequenceMatches.size() == 0)\r
475       {\r
476         // failed to match directly on accessionId==query so just compare all\r
477         // sequences to entry\r
478         Enumeration e = seqRefs.keys();\r
479         while (e.hasMoreElements())\r
480         {\r
481           Vector sqs = (Vector) seqRefs.get(e.nextElement());\r
482           if (sqs != null && sqs.size() > 0)\r
483           {\r
484             Enumeration sqe = sqs.elements();\r
485             while (sqe.hasMoreElements())\r
486             {\r
487               sequenceMatches.addElement(sqe.nextElement());\r
488             }\r
489           }\r
490         }\r
491       }\r
492       // look for corresponding names\r
493       // this is uniprot specific ?\r
494       // could be useful to extend this so we try to find any 'significant'\r
495       // information in common between two sequence objects.\r
496       /*\r
497        * DBRefEntry[] entryRefs =\r
498        * jalview.util.DBRefUtils.selectRefs(entry.getDBRef(), new String[] {\r
499        * dbSource }); for (int j = 0; j < entry.getName().size(); j++) { String\r
500        * name = entry.getName().elementAt(j).toString(); if\r
501        * (seqRefs.containsKey(name)) { Vector seqs = (Vector) seqRefs.get(name);\r
502        * for (int jj = 0; jj < seqs.size(); jj++) { sequence = (SequenceI)\r
503        * seqs.elementAt(jj); if (!sequenceMatches.contains(sequence)) {\r
504        * sequenceMatches.addElement(sequence); } } } }\r
505        */\r
506       // sequenceMatches now contains the set of all sequences associated with\r
507       // the returned db record\r
508       String entrySeq = entry.getSequenceAsString().toUpperCase();\r
509       for (int m = 0; m < sequenceMatches.size(); m++)\r
510       {\r
511         sequence = (SequenceI) sequenceMatches.elementAt(m);\r
512         // only update start and end positions and shift features if there are\r
513         // no existing references\r
514         // TODO: test for legacy where uniprot or EMBL refs exist but no\r
515         // mappings are made (but content matches retrieved set)\r
516         boolean updateRefFrame = sequence.getDBRef() == null\r
517                 || sequence.getDBRef().length == 0;\r
518         // verify sequence against the entry sequence\r
519 \r
520         String nonGapped = AlignSeq.extractGaps("-. ",\r
521                 sequence.getSequenceAsString()).toUpperCase();\r
522 \r
523         int absStart = entrySeq.indexOf(nonGapped);\r
524         int mapStart = entry.getStart();\r
525         jalview.datamodel.Mapping mp;\r
526 \r
527         if (absStart == -1)\r
528         {\r
529           // Is local sequence contained in dataset sequence?\r
530           absStart = nonGapped.indexOf(entrySeq);\r
531           if (absStart == -1)\r
532           { // verification failed.\r
533             sbuffer.append(sequence.getName()\r
534                     + " SEQUENCE NOT %100 MATCH \n");\r
535             continue;\r
536           }\r
537 \r
538           sbuffer.append(sequence.getName() + " HAS " + absStart\r
539                   + " PREFIXED RESIDUES COMPARED TO " + dbSource + "\n");\r
540           //\r
541           // + " - ANY SEQUENCE FEATURES"\r
542           // + " HAVE BEEN ADJUSTED ACCORDINGLY \n");\r
543           // absStart = 0;\r
544           // create valid mapping between matching region of local sequence and\r
545           // the mapped sequence\r
546           mp = new Mapping(null, new int[]\r
547           { sequence.getStart() + absStart,\r
548               sequence.getStart() + absStart + entrySeq.length() - 1 },\r
549                   new int[]\r
550                   { entry.getStart(),\r
551                       entry.getStart() + entrySeq.length() - 1 }, 1, 1);\r
552           updateRefFrame = false; // mapping is based on current start/end so\r
553           // don't modify start and end\r
554         }\r
555         else\r
556         {\r
557           // update start and end of local sequence to place it in entry's\r
558           // reference frame.\r
559           // apply identity map map from whole of local sequence to matching\r
560           // region of database\r
561           // sequence\r
562           mp = null; // Mapping.getIdentityMap();\r
563           // new Mapping(null,\r
564           // new int[] { absStart+sequence.getStart(),\r
565           // absStart+sequence.getStart()+entrySeq.length()-1},\r
566           // new int[] { entry.getStart(), entry.getEnd() }, 1, 1);\r
567           // relocate local features for updated start\r
568           if (updateRefFrame && sequence.getSequenceFeatures() != null)\r
569           {\r
570             SequenceFeature[] sf = sequence.getSequenceFeatures();\r
571             int start = sequence.getStart();\r
572             int end = sequence.getEnd();\r
573             int startShift = 1 - absStart - start; // how much the features are\r
574             // to be shifted by\r
575             for (int sfi = 0; sfi < sf.length; sfi++)\r
576             {\r
577               if (sf[sfi].getBegin() >= start && sf[sfi].getEnd() <= end)\r
578               {\r
579                 // shift feature along by absstart\r
580                 sf[sfi].setBegin(sf[sfi].getBegin() + startShift);\r
581                 sf[sfi].setEnd(sf[sfi].getEnd() + startShift);\r
582               }\r
583             }\r
584           }\r
585         }\r
586 \r
587         System.out.println("Adding dbrefs to " + sequence.getName()\r
588                 + " from " + dbSource + " sequence : " + entry.getName());\r
589         sequence.transferAnnotation(entry, mp);\r
590         // unknownSequences.remove(sequence);\r
591         int absEnd = absStart + nonGapped.length();\r
592         absStart += 1;\r
593         if (updateRefFrame)\r
594         {\r
595           // finally, update local sequence reference frame if we're allowed\r
596           sequence.setStart(absStart);\r
597           sequence.setEnd(absEnd);\r
598         }\r
599         // and remove it from the rest\r
600         // TODO: decide if we should remove annotated sequence from set\r
601         sdataset.remove(sequence);\r
602         // TODO: should we make a note of sequences that have received new DB ids, so we can query all enabled DAS servers for them ?\r
603       }\r
604     }\r
605   }\r
606 \r
607   /**\r
608    * loop thru and collect additional sequences in Map.\r
609    * @param sequencesArray\r
610    * @return\r
611    */\r
612   private SequenceI[] recoverDbSequences(SequenceI[] sequencesArray)\r
613   {\r
614     Vector nseq = new Vector();\r
615     for (int i=0;sequencesArray!=null && i<sequencesArray.length;i++)\r
616     {\r
617       nseq.addElement(sequencesArray[i]);\r
618       DBRefEntry dbr[] = sequencesArray[i].getDBRef();\r
619       jalview.datamodel.Mapping map = null;\r
620       for (int r=0;(dbr!=null) && r<dbr.length; r++) {\r
621         if ((map=dbr[r].getMap())!=null)\r
622         {\r
623           if (!nseq.contains(map.getTo()))\r
624           {\r
625             nseq.addElement(map.getTo());\r
626           }\r
627         }\r
628       }\r
629     }\r
630     if (nseq.size()>0) {\r
631       sequencesArray = new SequenceI[nseq.size()];\r
632       nseq.toArray(sequencesArray);\r
633     }\r
634     return sequencesArray;\r
635   }\r
636 }\r