(JAL-972) jdas source retrieval and use of jdas structures for local sources
[jalview.git] / src / jalview / ws / DasSequenceFeatureFetcher.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
3  * Copyright (C) 2011 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 java.net.*;\r
21 import java.util.*;\r
22 \r
23 import javax.swing.*;\r
24 \r
25 import org.biodas.jdas.client.SourcesClient;\r
26 import org.biodas.jdas.schema.sources.SOURCE;\r
27 import org.biodas.jdas.schema.sources.SOURCES;\r
28 import org.biojava.dasobert.das.*;\r
29 import org.biojava.dasobert.das2.*;\r
30 import org.biojava.dasobert.das2.io.*;\r
31 import org.biojava.dasobert.dasregistry.*;\r
32 import org.biojava.dasobert.eventmodel.*;\r
33 import jalview.bin.Cache;\r
34 import jalview.datamodel.*;\r
35 import jalview.gui.*;\r
36 import jalview.util.UrlLink;\r
37 \r
38 /**\r
39  * DOCUMENT ME!\r
40  * \r
41  * @author $author$\r
42  * @version $Revision$\r
43  */\r
44 public class DasSequenceFeatureFetcher\r
45 {\r
46   SequenceI[] sequences;\r
47 \r
48   AlignFrame af;\r
49 \r
50   FeatureSettings fsettings;\r
51 \r
52   StringBuffer sbuffer = new StringBuffer();\r
53 \r
54   Vector selectedSources;\r
55 \r
56   boolean cancelled = false;\r
57 \r
58   private void debug(String mesg)\r
59   {\r
60     debug(mesg, null);\r
61   }\r
62 \r
63   private void debug(String mesg, Exception e)\r
64   {\r
65     if (Cache.log != null)\r
66     {\r
67       Cache.log.debug(mesg, e);\r
68     }\r
69     else\r
70     {\r
71       System.err.println(mesg);\r
72       if (e != null)\r
73       {\r
74         e.printStackTrace();\r
75       }\r
76     }\r
77   }\r
78 \r
79   long startTime;\r
80 \r
81   /**\r
82    * Creates a new SequenceFeatureFetcher object. Uses default\r
83    * \r
84    * @param align\r
85    *          DOCUMENT ME!\r
86    * @param ap\r
87    *          DOCUMENT ME!\r
88    */\r
89   public DasSequenceFeatureFetcher(SequenceI[] sequences,\r
90           FeatureSettings fsettings, Vector selectedSources)\r
91   {\r
92     this(sequences, fsettings, selectedSources, true, true);\r
93   }\r
94 \r
95   public DasSequenceFeatureFetcher(SequenceI[] oursequences,\r
96           FeatureSettings fsettings, Vector ourselectedSources,\r
97           boolean checkDbrefs, boolean promptFetchDbrefs)\r
98   {\r
99     this.selectedSources = new Vector();\r
100     Enumeration sources = ourselectedSources.elements();\r
101     // filter both sequences and sources to eliminate duplicates\r
102     while (sources.hasMoreElements())\r
103     {\r
104       Object src = sources.nextElement();\r
105       if (!selectedSources.contains(src))\r
106       {\r
107         selectedSources.addElement(src);\r
108       }\r
109       ;\r
110     }\r
111     Vector sqs = new Vector();\r
112     for (int i = 0; i < oursequences.length; i++)\r
113     {\r
114       if (!sqs.contains(oursequences[i]))\r
115       {\r
116         sqs.addElement(oursequences[i]);\r
117       }\r
118     }\r
119     sequences = new SequenceI[sqs.size()];\r
120     for (int i = 0; i < sequences.length; i++)\r
121     {\r
122       sequences[i] = (SequenceI) sqs.elementAt(i);\r
123     }\r
124     if (fsettings != null)\r
125     {\r
126       this.fsettings = fsettings;\r
127       this.af = fsettings.af;\r
128       af.setShowSeqFeatures(true);\r
129     }\r
130     int uniprotCount = 0;\r
131     for (int i = 0; i < selectedSources.size(); i++)\r
132     {\r
133       DasSource source = (DasSource) selectedSources.elementAt(i);\r
134       DasCoordinateSystem[] coords = source.getCoordinateSystem();\r
135       for (int c = 0; c < coords.length; c++)\r
136       {\r
137         // TODO: match UniProt coord system canonically (?) - does\r
138         // UniProt==uniprot==UNIPROT ?\r
139         if (coords[c].getName().indexOf("UniProt") > -1)\r
140         {\r
141           uniprotCount++;\r
142           break;\r
143         }\r
144       }\r
145     }\r
146 \r
147     int refCount = 0;\r
148     for (int i = 0; i < sequences.length; i++)\r
149     {\r
150       DBRefEntry[] dbref = sequences[i].getDBRef();\r
151       if (dbref != null)\r
152       {\r
153         for (int j = 0; j < dbref.length; j++)\r
154         {\r
155           if (dbref[j].getSource().equals(\r
156                   jalview.datamodel.DBRefSource.UNIPROT))\r
157           {\r
158             refCount++;\r
159             break;\r
160           }\r
161         }\r
162       }\r
163     }\r
164 \r
165     if (checkDbrefs && refCount < sequences.length && uniprotCount > 0)\r
166     {\r
167 \r
168       int reply = JOptionPane.YES_OPTION;\r
169       if (promptFetchDbrefs)\r
170       {\r
171         reply = JOptionPane\r
172                 .showInternalConfirmDialog(\r
173                         Desktop.desktop,\r
174                         "Do you want Jalview to find\n"\r
175                                 + "Uniprot Accession ids for given sequence names?",\r
176                         "Find Uniprot Accession Ids",\r
177                         JOptionPane.YES_NO_OPTION,\r
178                         JOptionPane.QUESTION_MESSAGE);\r
179       }\r
180 \r
181       if (reply == JOptionPane.YES_OPTION)\r
182       {\r
183         Thread thread = new Thread(new FetchDBRefs());\r
184         thread.start();\r
185       }\r
186       else\r
187       {\r
188         startFetching();\r
189       }\r
190     }\r
191     else\r
192     {\r
193       startFetching();\r
194     }\r
195 \r
196   }\r
197 \r
198   class FetchDBRefs implements Runnable\r
199   {\r
200     public void run()\r
201     {\r
202       new DBRefFetcher(sequences, af).fetchDBRefs(true);\r
203       startFetching();\r
204     }\r
205   }\r
206 \r
207   /**\r
208    * Spawns a number of dasobert Fetcher threads to add features to sequences in\r
209    * the dataset\r
210    */\r
211   void startFetching()\r
212   {\r
213     cancelled = false;\r
214     startTime = System.currentTimeMillis();\r
215     if (af != null)\r
216     {\r
217       af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
218     }\r
219 \r
220     if (selectedSources == null || selectedSources.size() == 0)\r
221     {\r
222       try\r
223       {\r
224         DasSource[] sources = new jalview.gui.DasSourceBrowser()\r
225                 .getDASSource();\r
226 \r
227         String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",\r
228                 "uniprot");\r
229         StringTokenizer st = new StringTokenizer(active, "\t");\r
230         selectedSources = new Vector();\r
231         String token;\r
232         while (st.hasMoreTokens())\r
233         {\r
234           token = st.nextToken();\r
235           for (int i = 0; i < sources.length; i++)\r
236           {\r
237             if (sources[i].getNickname().equals(token))\r
238             {\r
239               selectedSources.addElement(sources[i]);\r
240               break;\r
241             }\r
242           }\r
243         }\r
244       } catch (Exception ex)\r
245       {\r
246         debug("Exception whilst setting default feature sources from registry and local preferences.",\r
247                 ex);\r
248       }\r
249     }\r
250 \r
251     if (selectedSources == null || selectedSources.size() == 0)\r
252     {\r
253       System.out.println("No DAS Sources active");\r
254       cancelled = true;\r
255       setGuiNoDassourceActive();\r
256       return;\r
257     }\r
258 \r
259     sourcesRemaining = selectedSources.size();\r
260     // Now sending requests one at a time to each server\r
261     for (int sourceIndex = 0; sourceIndex < selectedSources.size()\r
262             && !cancelled; sourceIndex++)\r
263     {\r
264       DasSource dasSource = (DasSource) selectedSources\r
265               .elementAt(sourceIndex);\r
266 \r
267       nextSequence(dasSource, sequences[0]);\r
268     }\r
269   }\r
270 \r
271   private void setGuiNoDassourceActive()\r
272   {\r
273 \r
274     if (af != null)\r
275     {\r
276       af.setProgressBar("No DAS Sources Active", startTime);\r
277     }\r
278     if (getFeatSettings() != null)\r
279     {\r
280       fsettings.noDasSourceActive();\r
281     }\r
282   }\r
283 \r
284   /**\r
285    * Update our fsettings dialog reference if we didn't have one when we were\r
286    * first initialised.\r
287    * \r
288    * @return fsettings\r
289    */\r
290   private FeatureSettings getFeatSettings()\r
291   {\r
292     if (fsettings == null)\r
293     {\r
294       if (af != null)\r
295       {\r
296         fsettings = af.featureSettings;\r
297       }\r
298     }\r
299     return fsettings;\r
300   }\r
301 \r
302   public void cancel()\r
303   {\r
304     if (af != null)\r
305     {\r
306       af.setProgressBar("DAS Feature Fetching Cancelled", startTime);\r
307     }\r
308     cancelled = true;\r
309   }\r
310 \r
311   int sourcesRemaining = 0;\r
312 \r
313   void responseComplete(DasSource dasSource, SequenceI seq)\r
314   {\r
315     if (seq != null)\r
316     {\r
317       for (int seqIndex = 0; seqIndex < sequences.length - 1 && !cancelled; seqIndex++)\r
318       {\r
319         if (sequences[seqIndex] == seq)\r
320         {\r
321           nextSequence(dasSource, sequences[++seqIndex]);\r
322           return;\r
323         }\r
324       }\r
325     }\r
326 \r
327     sourcesRemaining--;\r
328 \r
329     if (sourcesRemaining == 0)\r
330     {\r
331       System.err.println("Fetching Complete.");\r
332       setGuiFetchComplete();\r
333     }\r
334 \r
335   }\r
336 \r
337   private void setGuiFetchComplete()\r
338   {\r
339 \r
340     if (!cancelled && af != null)\r
341     {\r
342       // only update the progress bar if we've completed the fetch normally\r
343       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
344     }\r
345 \r
346     if (af != null && af.featureSettings != null)\r
347     {\r
348       af.featureSettings.setTableData();\r
349     }\r
350 \r
351     if (getFeatSettings() != null)\r
352     {\r
353       fsettings.complete();\r
354     }\r
355   }\r
356 \r
357   void featuresAdded(SequenceI seq)\r
358   {\r
359     if (af == null)\r
360     {\r
361       // no gui to update with features.\r
362       return;\r
363     }\r
364     af.getFeatureRenderer().featuresAdded();\r
365 \r
366     int start = af.getViewport().getStartSeq();\r
367     int end = af.getViewport().getEndSeq();\r
368     int index;\r
369     for (index = start; index < end; index++)\r
370     {\r
371       if (seq == af.getViewport().getAlignment().getSequenceAt(index)\r
372               .getDatasetSequence())\r
373       {\r
374         af.alignPanel.paintAlignment(true);\r
375         break;\r
376       }\r
377     }\r
378   }\r
379 \r
380   void nextSequence(DasSource dasSource, SequenceI seq)\r
381   {\r
382     if (cancelled)\r
383       return;\r
384     DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(\r
385             seq.getDBRef(), new String[]\r
386             {\r
387             // jalview.datamodel.DBRefSource.PDB,\r
388             jalview.datamodel.DBRefSource.UNIPROT,\r
389             // jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord\r
390             // sys sources\r
391             });\r
392     // TODO: minimal list of DAS queries to make by querying with untyped ID if\r
393     // distinct from any typed IDs\r
394 \r
395     boolean dasCoordSysFound = false;\r
396 \r
397     if (uprefs != null)\r
398     {\r
399       // do any of these ids match the source's coordinate system ?\r
400       for (int j = 0; !dasCoordSysFound && j < uprefs.length; j++)\r
401       {\r
402         DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
403 \r
404         for (int csIndex = 0; csIndex < cs.length && !dasCoordSysFound; csIndex++)\r
405         {\r
406           if (cs.length > 0\r
407                   && jalview.util.DBRefUtils.isDasCoordinateSystem(\r
408                           cs[csIndex].getName(), uprefs[j]))\r
409           {\r
410             debug("Launched fetcher for coordinate system "\r
411                     + cs[0].getName());\r
412             // Will have to pass any mapping information to the fetcher\r
413             // - the start/end for the DBRefEntry may not be the same as the\r
414             // sequence's start/end\r
415 \r
416             System.out.println(seq.getName() + " "\r
417                     + (seq.getDatasetSequence() == null) + " "\r
418                     + dasSource.getUrl());\r
419 \r
420             dasCoordSysFound = true; // break's out of the loop\r
421             createFeatureFetcher(seq, dasSource, uprefs[j]);\r
422           }\r
423           else\r
424             System.out.println("IGNORE " + cs[csIndex].getName());\r
425         }\r
426       }\r
427     }\r
428 \r
429     if (!dasCoordSysFound)\r
430     {\r
431       String id = null;\r
432       // try and use the name as the sequence id\r
433       if (seq.getName().indexOf("|") > -1)\r
434       {\r
435         id = seq.getName().substring(seq.getName().lastIndexOf("|") + 1);\r
436         if (id.trim().length() < 4)\r
437         {\r
438           // hack - we regard a significant ID as being at least 4\r
439           // non-whitespace characters\r
440           id = seq.getName().substring(0, seq.getName().lastIndexOf("|"));\r
441           if (id.indexOf("|") > -1)\r
442           {\r
443             id = id.substring(id.lastIndexOf("|") + 1);\r
444           }\r
445         }\r
446       }\r
447       else\r
448       {\r
449         id = seq.getName();\r
450       }\r
451       if (id != null)\r
452       {\r
453         // Should try to call a general feature fetcher that\r
454         // queries many sources with name to discover applicable ID references\r
455         createFeatureFetcher(seq, dasSource, id);\r
456       }\r
457     }\r
458 \r
459   }\r
460 \r
461   /**\r
462    * fetch and add das features to a sequence using the given source URL and\r
463    * compatible DbRef id. new features are mapped using the DbRef mapping to the\r
464    * local coordinate system.\r
465    * \r
466    * @param seq\r
467    * @param SourceUrl\r
468    * @param dbref\r
469    */\r
470   protected void createFeatureFetcher(final SequenceI seq,\r
471           final DasSource dasSource, final DBRefEntry dbref)\r
472   {\r
473 \r
474     // ////////////\r
475     // / fetch DAS features\r
476     final Das1Source source = new Das1Source();\r
477     source.setUrl(dasSource.getUrl());\r
478     source.setNickname(dasSource.getNickname());\r
479     if (dbref == null || dbref.getAccessionId() == null\r
480             || dbref.getAccessionId().length() < 1)\r
481     {\r
482       responseComplete(dasSource, seq); // reduce thread count anyhow\r
483       return;\r
484     }\r
485     debug("new Das Feature Fetcher for " + dbref.getSource() + ":"\r
486             + dbref.getAccessionId() + " querying " + dasSource.getUrl());\r
487     FeatureThread fetcher = new FeatureThread(dbref.getAccessionId()\r
488     // + ":" + start + "," + end,\r
489             , source);\r
490 \r
491     fetcher.addFeatureListener(new FeatureListener()\r
492     {\r
493       public void comeBackLater(FeatureEvent e)\r
494       {\r
495         responseComplete(dasSource, seq);\r
496         debug("das source " + e.getSource().getNickname()\r
497                 + " asked us to come back in " + e.getComeBackLater()\r
498                 + " secs.");\r
499       }\r
500 \r
501       public void newFeatures(FeatureEvent e)\r
502       {\r
503 \r
504         Das1Source ds = e.getSource();\r
505 \r
506         Map[] features = e.getFeatures();\r
507         // add features to sequence\r
508         debug("das source " + ds.getUrl() + " returned " + features.length\r
509                 + " features");\r
510 \r
511         if (features.length > 0)\r
512         {\r
513           for (int i = 0; i < features.length; i++)\r
514           {\r
515             // standard DAS feature-> jalview sequence feature transformation\r
516             SequenceFeature f = newSequenceFeature(features[i],\r
517                     source.getNickname());\r
518             if (!parseSeqFeature(seq, f, features[i], source))\r
519             {\r
520               if (dbref.getMap() != null && f.getBegin() > 0\r
521                       && f.getEnd() > 0)\r
522               {\r
523                 debug("mapping from " + f.getBegin() + " - " + f.getEnd());\r
524                 SequenceFeature vf[] = null;\r
525 \r
526                 try\r
527                 {\r
528                   vf = dbref.getMap().locateFeature(f);\r
529                 } catch (Exception ex)\r
530                 {\r
531                   Cache.log\r
532                           .info("Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org.");\r
533                   Cache.log.info("Mapping feature from " + f.getBegin()\r
534                           + " to " + f.getEnd() + " in dbref "\r
535                           + dbref.getAccessionId() + " in "\r
536                           + dbref.getSource());\r
537                   Cache.log.info("using das Source " + ds.getUrl());\r
538                   Cache.log.info("Exception", ex);\r
539                 }\r
540 \r
541                 if (vf != null)\r
542                 {\r
543                   for (int v = 0; v < vf.length; v++)\r
544                   {\r
545                     debug("mapping to " + v + ": " + vf[v].getBegin()\r
546                             + " - " + vf[v].getEnd());\r
547                     seq.addSequenceFeature(vf[v]);\r
548                   }\r
549                 }\r
550               }\r
551               else\r
552               {\r
553                 seq.addSequenceFeature(f);\r
554               }\r
555             }\r
556           }\r
557           featuresAdded(seq);\r
558         }\r
559         else\r
560         {\r
561           // System.out.println("No features found for " + seq.getName()\r
562           // + " from: " + e.getDasSource().getNickname());\r
563         }\r
564         responseComplete(dasSource, seq);\r
565 \r
566       }\r
567     }\r
568 \r
569     );\r
570 \r
571     fetcher.start();\r
572   }\r
573 \r
574   protected void createFeatureFetcher(final SequenceI seq,\r
575           final DasSource dasSource, String id)\r
576   {\r
577     // ////////////\r
578     // / fetch DAS features\r
579     final Das1Source source = new Das1Source();\r
580     source.setUrl(dasSource.getUrl());\r
581     source.setNickname(dasSource.getNickname());\r
582 \r
583     if (id != null)\r
584     {\r
585       id = id.trim();\r
586     }\r
587     if (id != null && id.length() > 0)\r
588     {\r
589       debug("new Das Feature Fetcher for " + id + " querying "\r
590               + dasSource.getUrl());\r
591       FeatureThread fetcher = new FeatureThread(id\r
592       // + ":" + start + "," + end,\r
593               , source);\r
594 \r
595       fetcher.addFeatureListener(new FeatureListener()\r
596       {\r
597         public void comeBackLater(FeatureEvent e)\r
598         {\r
599           responseComplete(dasSource, seq);\r
600           debug("das source " + e.getSource().getNickname()\r
601                   + " asked us to come back in " + e.getComeBackLater()\r
602                   + " secs.");\r
603         }\r
604 \r
605         public void newFeatures(FeatureEvent e)\r
606         {\r
607 \r
608           Das1Source ds = e.getSource();\r
609 \r
610           Map[] features = e.getFeatures();\r
611           // add features to sequence\r
612           debug("das source " + ds.getUrl() + " returned "\r
613                   + features.length + " features");\r
614 \r
615           if (features.length > 0)\r
616           {\r
617             for (int i = 0; i < features.length; i++)\r
618             {\r
619               // standard DAS feature-> jalview sequence feature transformation\r
620               SequenceFeature f = newSequenceFeature(features[i],\r
621                       source.getNickname());\r
622               if (!parseSeqFeature(seq, f, features[i], source))\r
623               {\r
624                 // just add as a simple sequence feature\r
625                 seq.addSequenceFeature(f);\r
626               }\r
627             }\r
628 \r
629             featuresAdded(seq);\r
630           }\r
631           else\r
632           {\r
633             // System.out.println("No features found for " + seq.getName()\r
634             // + " from: " + e.getDasSource().getNickname());\r
635           }\r
636           responseComplete(dasSource, seq);\r
637 \r
638         }\r
639       }\r
640 \r
641       );\r
642 \r
643       fetcher.start();\r
644     }\r
645     else\r
646     {\r
647       // invalid fetch - indicate it is finished.\r
648       debug("Skipping empty ID for querying " + dasSource.getUrl());\r
649       responseComplete(dasSource, seq);\r
650     }\r
651   }\r
652 \r
653   /**\r
654    * examine the given sequence feature to determine if it should actually be\r
655    * turned into sequence annotation or database cross references rather than a\r
656    * simple sequence feature.\r
657    * \r
658    * @param seq\r
659    *          the sequence to annotate\r
660    * @param f\r
661    *          the jalview sequence feature generated from the DAS feature\r
662    * @param map\r
663    *          the sequence feature attributes\r
664    * @param source\r
665    *          the source that emitted the feature\r
666    * @return true if feature was consumed as another kind of annotation.\r
667    */\r
668   protected boolean parseSeqFeature(SequenceI seq, SequenceFeature f,\r
669           Map map, Das1Source source)\r
670   {\r
671     SequenceI mseq = seq;\r
672     while (seq.getDatasetSequence() != null)\r
673     {\r
674       seq = seq.getDatasetSequence();\r
675     }\r
676     if (f.getType() != null)\r
677     {\r
678       String type = f.getType();\r
679       if (type.equalsIgnoreCase("protein_name"))\r
680       {\r
681         // parse name onto the alignment sequence or the dataset sequence.\r
682         if (seq.getDescription() == null\r
683                 || seq.getDescription().trim().length() == 0)\r
684         {\r
685           // could look at the note series to pick out the first long name, for\r
686           // the moment just use the whole description string\r
687           seq.setDescription(f.getDescription());\r
688         }\r
689         if (mseq.getDescription() == null\r
690                 || mseq.getDescription().trim().length() == 0)\r
691         {\r
692           // could look at the note series to pick out the first long name, for\r
693           // the moment just use the whole description string\r
694           mseq.setDescription(f.getDescription());\r
695         }\r
696         return true;\r
697       }\r
698       // check if source has biosapiens or other sequence ontology label\r
699       if (type.equalsIgnoreCase("DBXREF") || type.equalsIgnoreCase("DBREF"))\r
700       {\r
701         // try to parse the accession out\r
702 \r
703         DBRefEntry dbr = new DBRefEntry();\r
704         dbr.setVersion(source.getNickname());\r
705         StringTokenizer st = new StringTokenizer(f.getDescription(), ":");\r
706         if (st.hasMoreTokens())\r
707         {\r
708           dbr.setSource(st.nextToken());\r
709         }\r
710         if (st.hasMoreTokens())\r
711         {\r
712           dbr.setAccessionId(st.nextToken());\r
713         }\r
714         seq.addDBRef(dbr);\r
715 \r
716         if (f.links != null && f.links.size() > 0)\r
717         {\r
718           // feature is also appended to enable links to be seen.\r
719           // TODO: consider extending dbrefs to have their own links ?\r
720           // TODO: new feature: extract dbref links from DAS servers and add the\r
721           // URL pattern to the list of DB name associated links in the user's\r
722           // preferences ?\r
723           // for the moment - just fix up the existing feature so it displays\r
724           // correctly.\r
725           // f.setType(dbr.getSource());\r
726           // f.setDescription();\r
727           f.setValue("linkonly", Boolean.TRUE);\r
728           // f.setDescription("");\r
729           Vector newlinks = new Vector();\r
730           Enumeration it = f.links.elements();\r
731           while (it.hasMoreElements())\r
732           {\r
733             String elm;\r
734             UrlLink urllink = new UrlLink(elm = (String) it.nextElement());\r
735             if (urllink.isValid())\r
736             {\r
737               urllink.setLabel(f.getDescription());\r
738               newlinks.addElement(urllink.toString());\r
739             }\r
740             else\r
741             {\r
742               // couldn't parse the link properly. Keep it anyway - just in\r
743               // case.\r
744               debug("couldn't parse link string - " + elm);\r
745               newlinks.addElement(elm);\r
746             }\r
747           }\r
748           f.links = newlinks;\r
749           seq.addSequenceFeature(f);\r
750         }\r
751         return true;\r
752       }\r
753     }\r
754     return false;\r
755   }\r
756 \r
757   /**\r
758    * creates a jalview sequence feature from a das feature document\r
759    * \r
760    * @param dasfeature\r
761    * @return sequence feature object created using dasfeature information\r
762    */\r
763   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
764   {\r
765     if (dasfeature == null)\r
766     {\r
767       return null;\r
768     }\r
769     try\r
770     {\r
771       /**\r
772        * Different qNames for a DAS Feature - are string keys to the HashMaps in\r
773        * features "METHOD") || qName.equals("TYPE") || qName.equals("START") ||\r
774        * qName.equals("END") || qName.equals("NOTE") || qName.equals("LINK") ||\r
775        * qName.equals("SCORE")\r
776        */\r
777       String desc = new String();\r
778       if (dasfeature.containsKey("NOTE"))\r
779       {\r
780         desc += (String) dasfeature.get("NOTE");\r
781       }\r
782 \r
783       int start = 0, end = 0;\r
784       float score = 0f;\r
785 \r
786       try\r
787       {\r
788         start = Integer.parseInt(dasfeature.get("START").toString());\r
789       } catch (Exception ex)\r
790       {\r
791       }\r
792       try\r
793       {\r
794         end = Integer.parseInt(dasfeature.get("END").toString());\r
795       } catch (Exception ex)\r
796       {\r
797       }\r
798       try\r
799       {\r
800         Object scr = dasfeature.get("SCORE");\r
801         if (scr != null)\r
802         {\r
803           score = (float) Double.parseDouble(scr.toString());\r
804 \r
805         }\r
806       } catch (Exception ex)\r
807       {\r
808       }\r
809 \r
810       SequenceFeature f = new SequenceFeature(\r
811               (String) dasfeature.get("TYPE"), desc, start, end, score,\r
812               nickname);\r
813 \r
814       if (dasfeature.containsKey("LINK"))\r
815       {\r
816         // Do not put feature extent in link text for non-positional features\r
817         if (f.begin == 0 && f.end == 0)\r
818         {\r
819           f.addLink(f.getType() + "|" + dasfeature.get("LINK"));\r
820         }\r
821         else\r
822         {\r
823           f.addLink(f.getType() + " " + f.begin + "_" + f.end + "|"\r
824                   + dasfeature.get("LINK"));\r
825         }\r
826       }\r
827 \r
828       return f;\r
829     } catch (Exception e)\r
830     {\r
831       System.out.println("ERRR " + e);\r
832       e.printStackTrace();\r
833       System.out.println("############");\r
834       debug("Failed to parse " + dasfeature.toString(), e);\r
835       return null;\r
836     }\r
837   }\r
838 \r
839   /**\r
840    * query the default DAS Source Registry for sources. Uses value of jalview\r
841    * property DAS_REGISTRY_URL and the DasSourceBrowser.DEFAULT_REGISTRY if that\r
842    * doesn't exist.\r
843    * \r
844    * @return list of sources\r
845    */\r
846   public static SOURCE[] getDASSources()\r
847   {\r
848 \r
849     String registryURL = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
850             DasSourceBrowser.DEFAULT_REGISTRY);\r
851     return getDASSources(registryURL);\r
852   }\r
853 \r
854   /**\r
855    * query the given URL for DasSources.\r
856    * \r
857    * @param registryURL\r
858    *          return sources from registryURL\r
859    */\r
860   public static SOURCE[] getDASSources(String registryURL)\r
861   {\r
862     \r
863     try\r
864     {\r
865       URL url = new URL(registryURL);\r
866       org.biodas.jdas.client.SourcesClientInterface client = new SourcesClient();\r
867       \r
868       SOURCES sources = client.fetchData(registryURL);\r
869 \r
870       List<SOURCE> dassources = sources.getSOURCE();\r
871 \r
872       return dassources.toArray(new SOURCE[dassources.size()]);\r
873     } catch (Exception ex)\r
874     {\r
875       System.err.println("Failed to contact DAS1 registry at "\r
876               + registryURL);\r
877       ex.printStackTrace();\r
878       return null;\r
879     }\r
880   }\r
881 \r
882 }\r