change over source attribute datamodel
[jalview.git] / src / jalview / gui / DasSourceBrowser.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.gui;\r
19 \r
20 import java.security.interfaces.DSAKey;\r
21 import java.text.ParseException;\r
22 import java.util.*;\r
23 import java.util.List;\r
24 \r
25 import java.awt.*;\r
26 import java.awt.event.*;\r
27 import javax.swing.*;\r
28 import javax.swing.event.*;\r
29 import javax.swing.table.*;\r
30 \r
31 import org.biodas.jdas.dassources.Capabilities;\r
32 import org.biodas.jdas.dassources.utils.DasTimeFormat;\r
33 import org.biodas.jdas.schema.sources.CAPABILITY;\r
34 import org.biodas.jdas.schema.sources.COORDINATES;\r
35 import org.biodas.jdas.schema.sources.MAINTAINER;\r
36 import org.biodas.jdas.schema.sources.PROP;\r
37 import org.biodas.jdas.schema.sources.SOURCE;\r
38 import org.biodas.jdas.schema.sources.SOURCES;\r
39 import org.biodas.jdas.schema.sources.VERSION;\r
40 \r
41 import jalview.jbgui.*;\r
42 import jalview.util.*;\r
43 \r
44 public class DasSourceBrowser extends GDasSourceBrowser implements\r
45         Runnable, ListSelectionListener\r
46 {\r
47   static org.biodas.jdas.schema.sources.SOURCE[] dasSources = null;\r
48 \r
49   Hashtable localSources = null;\r
50 \r
51   Vector selectedSources;\r
52 \r
53   public static String DEFAULT_REGISTRY = "http://www.dasregistry.org/das1/sources/";\r
54 \r
55   /**\r
56    * true if thread is running and we are talking to DAS registry service\r
57    */\r
58   public boolean loadingDasSources = false;\r
59 \r
60   protected static String getDasRegistryURL()\r
61   {\r
62     String registry = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
63             DEFAULT_REGISTRY);\r
64 \r
65     if (registry.indexOf("/registry/das1/sources/") > -1)\r
66     {\r
67       jalview.bin.Cache.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,\r
68               DEFAULT_REGISTRY);\r
69       registry = DEFAULT_REGISTRY;\r
70     }\r
71     return registry;\r
72   }\r
73 \r
74   public DasSourceBrowser(FeatureSettings featureSettings)\r
75   {\r
76     fs = featureSettings;\r
77     String registry = getDasRegistryURL();\r
78 \r
79     registryURL.setText(registry);\r
80 \r
81     setSelectedFromProperties();\r
82 \r
83     displayFullDetails(null);\r
84     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
85 \r
86     filter1.addListSelectionListener(this);\r
87     filter2.addListSelectionListener(this);\r
88     filter3.addListSelectionListener(this);\r
89 \r
90     // Ask to be notified of selection changes.\r
91     ListSelectionModel rowSM = table.getSelectionModel();\r
92     rowSM.addListSelectionListener(new ListSelectionListener()\r
93     {\r
94       public void valueChanged(ListSelectionEvent e)\r
95       {\r
96         ListSelectionModel lsm = (ListSelectionModel) e.getSource();\r
97         if (!lsm.isSelectionEmpty())\r
98         {\r
99           int selectedRow = lsm.getMinSelectionIndex();\r
100           displayFullDetails(table.getValueAt(selectedRow, 0).toString());\r
101         }\r
102       }\r
103     });\r
104 \r
105     table.addMouseListener(new MouseAdapter()\r
106     {\r
107       public void mouseClicked(MouseEvent evt)\r
108       {\r
109         if (evt.getClickCount() == 2\r
110                 || SwingUtilities.isRightMouseButton(evt))\r
111         {\r
112           editRemoveLocalSource(evt);\r
113         }\r
114       }\r
115     });\r
116 \r
117     if (dasSources != null)\r
118     {\r
119       init();\r
120     }\r
121   }\r
122 \r
123   FeatureSettings fs = null;\r
124 \r
125   public DasSourceBrowser()\r
126   {\r
127     this(null);\r
128   }\r
129 \r
130   public void paintComponent(java.awt.Graphics g)\r
131   {\r
132     if (dasSources == null && !loadingDasSources)\r
133     {\r
134       Thread worker = new Thread(this);\r
135       worker.start();\r
136     }\r
137   }\r
138 \r
139   void init()\r
140   {\r
141     int dSize = dasSources.length;\r
142     Object[][] data = new Object[dSize][2];\r
143     for (int i = 0; i < dSize; i++)\r
144     {\r
145       data[i][0] = dasSources[i].getTitle(); // what's equivalent of nickname\r
146       data[i][1] = new Boolean(selectedSources.contains(dasSources[i]\r
147               .getTitle()));\r
148     }\r
149 \r
150     refreshTableData(data);\r
151     setCapabilities(dasSources);\r
152 \r
153     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
154     {\r
155       public void run()\r
156       {\r
157         TableSorter sorter = (TableSorter) table.getModel();\r
158         sorter.setSortingStatus(1, TableSorter.DESCENDING);\r
159         sorter.setSortingStatus(1, TableSorter.NOT_SORTED);\r
160       }\r
161     });\r
162 \r
163     progressBar.setIndeterminate(false);\r
164     progressBar.setVisible(false);\r
165     addLocal.setVisible(true);\r
166     refresh.setVisible(true);\r
167   }\r
168 \r
169   public void refreshTableData(Object[][] data)\r
170   {\r
171     TableSorter sorter = new TableSorter(new DASTableModel(data));\r
172     sorter.setTableHeader(table.getTableHeader());\r
173     table.setModel(sorter);\r
174   }\r
175 \r
176   void displayFullDetails(String nickName)\r
177   {\r
178 \r
179     StringBuffer text = new StringBuffer(\r
180             "<HTML><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">");\r
181 \r
182     if (nickName == null)\r
183     {\r
184       fullDetails.setText(text + "Select a DAS service from the table"\r
185               + " to read a full description here.</font></html>");\r
186       return;\r
187     }\r
188 \r
189     int dSize = dasSources.length;\r
190     for (int i = 0; i < dSize; i++)\r
191     {\r
192       if (!dasSources[i].getTitle().equals(nickName))\r
193       {\r
194         continue;\r
195       }\r
196 \r
197       SOURCE ds = dasSources[i];\r
198       VERSION latest = getVersionFor(ds);\r
199       text.append("<font color=\"#0000FF\">Id:</font> "\r
200               + dasSources[i].getUri() + "<br>");\r
201       text.append("<font color=\"#0000FF\">Nickname:</font> "\r
202               + dasSources[i].getTitle() + "<br>");\r
203       text.append("<font color=\"#0000FF\">URL:</font> "\r
204               + latest.getUri() + "<br>");\r
205 \r
206       text.append("<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"\r
207               + ds.getMAINTAINER().getEmail()\r
208               + "\">"\r
209               + ds.getMAINTAINER().getEmail() + "</a>" + "<br>");\r
210 \r
211       text.append("<font color=\"#0000FF\">Registered at:</font> "\r
212               + latest.getCreated() + "<br>");\r
213 \r
214       // TODO: Identify last successful test date\r
215 //      text.append("<font color=\"#0000FF\">Last successful test:</font> "\r
216 //              + latest.dasSources[i].getLeaseDate() + "<br>");\r
217 \r
218       text.append("<font color=\"#0000FF\">Labels:</font> ");\r
219       for (int s = 0; s < latest.getPROP().length; s++)\r
220       {\r
221         text.append(dasSources[i].getLabels()[s]);\r
222         if (s < dasSources[i].getLabels().length - 1)\r
223         {\r
224           text.append(",");\r
225         }\r
226         text.append(" ");\r
227       }\r
228       text.append("<br>");\r
229 \r
230       text.append("<font color=\"#0000FF\">Capabilities:</font> ");\r
231       CAPABILITY[] scap = latest.getCAPABILITY().toArray(new CAPABILITY[0]);\r
232       for (int j = 0; j < scap.length; j++)\r
233       {\r
234         text.append(scap[j]);\r
235         if (j < scap.length - 1)\r
236         {\r
237           text.append(", ");\r
238         }\r
239       }\r
240       text.append("<br>");\r
241 \r
242       text.append("<font color=\"#0000FF\">Coordinates:</font> ");\r
243       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
244       for (int j = 0; j < dcs.length; j++)\r
245       {\r
246         text.append("(" + dcs[j].getUniqueId() + ") "\r
247                 + dcs[j].getCategory() + ", " + dcs[j].getName());\r
248         if (dcs[j].getNCBITaxId() != 0)\r
249         {\r
250           text.append(", " + dcs[j].getNCBITaxId());\r
251         }\r
252         if (dcs[j].getOrganismName().length() > 0)\r
253         {\r
254           text.append(", " + dcs[j].getOrganismName());\r
255         }\r
256 \r
257         text.append("<br>");\r
258       }\r
259 \r
260       text.append("<font color=\"#0000FF\">Description:</font> "\r
261               + dasSources[i].getDescription() + "<br>");\r
262 \r
263       if (dasSources[i].getHelperurl() != null\r
264               && dasSources[i].getHelperurl().length() > 0)\r
265       {\r
266         text.append("<font color=\"#0000FF\"><a href=\""\r
267                 + dasSources[i].getHelperurl()\r
268                 + "\">Go to site</a></font<br>");\r
269       }\r
270 \r
271       text.append("</font></html>");\r
272 \r
273       break;\r
274     }\r
275 \r
276     fullDetails.setText(text.toString());\r
277     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
278     {\r
279       public void run()\r
280       {\r
281         fullDetailsScrollpane.getVerticalScrollBar().setValue(0);\r
282       }\r
283     });\r
284   }\r
285 \r
286   public void run()\r
287   {\r
288     loadingDasSources = true;\r
289 \r
290     addLocal.setVisible(false);\r
291     refresh.setVisible(false);\r
292     progressBar.setVisible(true);\r
293     progressBar.setIndeterminate(true);\r
294     setParentGuiEnabled(false);\r
295     // Refresh the source list.\r
296     dasSources = null;\r
297     getDASSource();\r
298 \r
299     init();\r
300 \r
301     setParentGuiEnabled(true);\r
302     loadingDasSources = false;\r
303 \r
304   }\r
305 \r
306   private void setParentGuiEnabled(boolean b)\r
307   {\r
308     if (fs != null)\r
309     {\r
310       fs.fetchDAS.setEnabled(b);\r
311       fs.saveDAS.setEnabled(b);\r
312     }\r
313   }\r
314 \r
315   public Vector getSelectedSources()\r
316   {\r
317     // wait around if we're still loading.\r
318     while (dasSources == null)\r
319     {\r
320       if (!loadingDasSources)\r
321       {\r
322         new Thread(this).start();\r
323         try\r
324         {\r
325           Thread.sleep(5);\r
326         } catch (Exception e)\r
327         {\r
328         }\r
329         ;\r
330         while (loadingDasSources)\r
331         {\r
332           try\r
333           {\r
334             Thread.sleep(5);\r
335           } catch (Exception e)\r
336           {\r
337           }\r
338           ;\r
339         }\r
340         ;\r
341       }\r
342     }\r
343 \r
344     Vector selected = new Vector();\r
345     for (int r = 0; r < selectedSources.size(); r++)\r
346     {\r
347       for (int i = 0; i < dasSources.length; i++)\r
348       {\r
349         if (dasSources[i].getTitle()\r
350                 .equals(selectedSources.elementAt(r)))\r
351         {\r
352           selected.addElement(dasSources[i]);\r
353           break;\r
354         }\r
355       }\r
356     }\r
357 \r
358     return selected;\r
359   }\r
360 \r
361   /**\r
362    * retrieve das sources from registry and add local source list\r
363    * \r
364    * @return\r
365    */\r
366   public SOURCE[] getDASSource()\r
367   {\r
368     if (dasSources == null)\r
369     {\r
370       dasSources = jalview.ws.DasSequenceFeatureFetcher.getDASSources();\r
371       appendLocalSources();\r
372     }\r
373 \r
374     return dasSources;\r
375   }\r
376 \r
377   public void refresh_actionPerformed(ActionEvent e)\r
378   {\r
379     saveProperties(jalview.bin.Cache.applicationProperties);\r
380 \r
381     Thread worker = new Thread(this);\r
382     worker.start();\r
383   }\r
384 \r
385   private boolean isLaterThan(String ref, String newer)\r
386   {\r
387     Date refdate=null,newdate=null;\r
388     try {\r
389       refdate=DasTimeFormat.fromDASString(ref);\r
390       \r
391     }\r
392     catch (ParseException x)\r
393     {\r
394       return false;\r
395     }\r
396     try {\r
397       newdate = DasTimeFormat.fromDASString(newer);\r
398     }\r
399     catch (ParseException e) {\r
400       // TODO: handle exception\r
401     }\r
402     if (refdate!=null)\r
403     {\r
404       if (newdate!=null)\r
405       {\r
406         return refdate.before(newdate);\r
407       }\r
408       return false;\r
409     }\r
410     if (newdate!=null)\r
411     {\r
412       return true;\r
413     }\r
414     // assume first instance of source is newest in list. - TODO: check if natural ordering of source versions is newest first or oldest first\r
415     return false;\r
416   }\r
417   private VERSION getVersionFor(SOURCE ds)\r
418   {\r
419     VERSION latest=null;\r
420     for (VERSION v:ds.getVERSION()) {\r
421       if (latest==null || isLaterThan(latest.getCreated(),v.getCreated()))\r
422       {\r
423         // TODO: das 1.6 - should just get the first version - ignore other versions since not specified how to construct URL from version's URI + source URI\r
424         latest=v;\r
425       }\r
426     }\r
427     return latest;\r
428   }\r
429   private void setCapabilities(SOURCE[] sources)\r
430   {\r
431     Vector<String> authority = new Vector<String>();\r
432     Vector<String> type = new Vector<String>();\r
433     Vector<String> label = new Vector<String>();\r
434     Vector<String> taxIds=new Vector<String>();\r
435     authority.add("Any");\r
436     type.add("Any");\r
437     label.add("Any");\r
438     \r
439 \r
440     for (int i = 0; i < sources.length; i++)\r
441     {\r
442       SOURCE ds = sources[i];\r
443       VERSION latest=getVersionFor(ds);\r
444       \r
445       for (COORDINATES cs: latest.getCOORDINATES())\r
446       {\r
447         if (!type.contains(cs.getSource()))\r
448         {\r
449           type.add(cs.getSource()); // source==category\r
450         }\r
451 \r
452         if (!authority.contains(cs.getAuthority()))\r
453         {\r
454           authority.add(cs.getAuthority());\r
455         }\r
456       }\r
457 \r
458       for (PROP slabel:latest.getPROP())\r
459       {\r
460         if (slabel.getName().equalsIgnoreCase("LABEL") && !label.contains(slabel.getValue()))\r
461         {\r
462           label.add(slabel.getValue());\r
463         }\r
464       }\r
465 \r
466     }\r
467 \r
468     filter1.setListData(authority);\r
469     filter2.setListData(type);\r
470     filter3.setListData(label);\r
471     // filter4 taxIds\r
472 \r
473     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
474     {\r
475       public void run()\r
476       {\r
477         filter1.setSelectedIndex(0);\r
478         filter2.setSelectedIndex(0);\r
479         filter3.setSelectedIndex(0);\r
480       }\r
481     });\r
482   }\r
483 \r
484   public void amendLocal(boolean newSource)\r
485   {\r
486     String url = "http://localhost:8080/", nickname = "";\r
487     boolean seqsrc = false;\r
488     if (!newSource)\r
489     {\r
490       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
491       nickname = table.getValueAt(selectedRow, 0).toString();\r
492       url = ((SOURCE) localSources.get(nickname)).getUri();\r
493       seqsrc = ((SOURCE) localSources.get(nickname)).getVERSION().get(0).getCAPABILITY().contains(Capabilities.SEQUENCE);\r
494     }\r
495 \r
496     JTextField nametf = new JTextField(nickname, 40);\r
497     JTextField urltf = new JTextField(url, 40);\r
498     JCheckBox seqs = new JCheckBox("Sequence Source");\r
499     seqs.setSelected(seqsrc);\r
500     JPanel panel = new JPanel(new BorderLayout());\r
501     JPanel pane12 = new JPanel(new BorderLayout());\r
502     pane12.add(new JLabel("Nickname: "), BorderLayout.CENTER);\r
503     pane12.add(nametf, BorderLayout.EAST);\r
504     panel.add(pane12, BorderLayout.NORTH);\r
505     pane12 = new JPanel(new BorderLayout());\r
506     pane12.add(new JLabel("URL: "), BorderLayout.NORTH);\r
507     pane12.add(seqs, BorderLayout.SOUTH);\r
508     pane12.add(urltf, BorderLayout.EAST);\r
509     panel.add(pane12, BorderLayout.SOUTH);\r
510 \r
511     int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
512             panel, "Enter Nickname & URL of Local DAS Source",\r
513             JOptionPane.OK_CANCEL_OPTION);\r
514 \r
515     if (reply != JOptionPane.OK_OPTION)\r
516     {\r
517       return;\r
518     }\r
519 \r
520     if (!urltf.getText().endsWith("/"))\r
521     {\r
522       urltf.setText(urltf.getText() + "/");\r
523     }\r
524 \r
525     // build using pattern from test: sourcesclientImplTest\r
526     {\r
527       SOURCE source = new SOURCE();\r
528       String uri = "http://das.sanger.ac.uk/das/dummysource";\r
529       source.setUri("http://das.sanger.ac.uk/das/dummysource");\r
530       source.setDescription("Dummy Test Source, should not be in a working registry sources doc");\r
531       VERSION version = new VERSION();\r
532       version.setUri(uri);\r
533       COORDINATES coord = new COORDINATES();\r
534       coord.setAuthority("NCBI");\r
535       coord.setSource("Chromosome");\r
536       coord.setTaxid("9606");\r
537       coord.setVersion("35");\r
538       version.getCOORDINATES().add(coord);\r
539       CAPABILITY cap = new CAPABILITY();\r
540       cap.setQueryUri(uri + "features");\r
541       cap.setType("das1:" + Capabilities.FEATURES.getName());\r
542       version.getCAPABILITY().add(cap);\r
543       source.getVERSION().add(version);\r
544       MAINTAINER m = new MAINTAINER();\r
545       m.setEmail("jw12@sanger.ac.uk");\r
546       source.setMAINTAINER(m);\r
547       source.setTitle("dummy title");\r
548 \r
549     }\r
550     SOURCE local = new Das1Source();\r
551 \r
552     local.setUrl(urltf.getText());\r
553     local.setNickname(nametf.getText());\r
554     if (seqs.isSelected())\r
555     {\r
556       local.setCapabilities(new String[]\r
557       { "features", "sequence" });\r
558     }\r
559     if (localSources == null)\r
560     {\r
561       localSources = new Hashtable();\r
562     }\r
563 \r
564     localSources.put(local.getTitle(), local);\r
565 \r
566     if (!newSource && !nickname.equals(nametf.getText()))\r
567     {\r
568       localSources.remove(nickname);\r
569     }\r
570 \r
571     int size = dasSources.length;\r
572     int adjust = newSource ? 1 : 0;\r
573 \r
574     Object[][] data = new Object[size + adjust][2];\r
575     for (int i = 0; i < size; i++)\r
576     {\r
577       if (!newSource && dasSources[i].getTitle().equals(nickname))\r
578       {\r
579         ((DasSource) dasSources[i]).setNickname(local.getTitle());\r
580         ((DasSource) dasSources[i]).setUrl(local.getUrl());\r
581         data[i][0] = local.getTitle();\r
582         data[i][1] = new Boolean(true);\r
583       }\r
584       else\r
585       {\r
586         data[i][0] = dasSources[i].getTitle();\r
587         data[i][1] = new Boolean(selectedSources.contains(dasSources[i]\r
588                 .getTitle()));\r
589       }\r
590     }\r
591 \r
592     if (newSource)\r
593     {\r
594       data[size][0] = local.getTitle();\r
595       data[size][1] = new Boolean(true);\r
596       selectedSources.add(local.getTitle());\r
597     }\r
598 \r
599     DasSource[] tmp = new DasSource[size + adjust];\r
600 \r
601     System.arraycopy(dasSources, 0, tmp, 0, size);\r
602 \r
603     if (newSource)\r
604     {\r
605       tmp[size] = local;\r
606     }\r
607 \r
608     dasSources = tmp;\r
609 \r
610     refreshTableData(data);\r
611 \r
612     SwingUtilities.invokeLater(new Runnable()\r
613     {\r
614       public void run()\r
615       {\r
616         scrollPane.getVerticalScrollBar().setValue(\r
617                 scrollPane.getVerticalScrollBar().getMaximum());\r
618       }\r
619     });\r
620 \r
621     displayFullDetails(local.getTitle());\r
622   }\r
623 \r
624   public void editRemoveLocalSource(MouseEvent evt)\r
625   {\r
626     int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
627     if (selectedRow == -1)\r
628     {\r
629       return;\r
630     }\r
631 \r
632     String nickname = table.getValueAt(selectedRow, 0).toString();\r
633 \r
634     if (!localSources.containsKey(nickname))\r
635     {\r
636       JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
637               "You can only edit or remove local DAS Sources!",\r
638               "Public DAS source - not editable",\r
639               JOptionPane.WARNING_MESSAGE);\r
640       return;\r
641     }\r
642 \r
643     Object[] options =\r
644     { "Edit", "Remove", "Cancel" };\r
645     int choice = JOptionPane.showInternalOptionDialog(Desktop.desktop,\r
646             "Do you want to edit or remove " + nickname + "?",\r
647             "Edit / Remove Local DAS Source",\r
648             JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,\r
649             null, options, options[2]);\r
650 \r
651     switch (choice)\r
652     {\r
653     case 0:\r
654       amendLocal(false);\r
655       break;\r
656     case 1:\r
657       localSources.remove(nickname);\r
658       selectedSources.remove(nickname);\r
659       Object[][] data = new Object[dasSources.length - 1][2];\r
660       DasSource[] tmp = new DasSource[dasSources.length - 1];\r
661       int index = 0;\r
662       for (int i = 0; i < dasSources.length; i++)\r
663       {\r
664         if (dasSources[i].getTitle().equals(nickname))\r
665         {\r
666           continue;\r
667         }\r
668         else\r
669         {\r
670           tmp[index] = dasSources[i];\r
671           data[index][0] = dasSources[i].getTitle();\r
672           data[index][1] = new Boolean(\r
673                   selectedSources.contains(dasSources[i].getTitle()));\r
674           index++;\r
675         }\r
676       }\r
677       dasSources = tmp;\r
678       refreshTableData(data);\r
679       SwingUtilities.invokeLater(new Runnable()\r
680       {\r
681         public void run()\r
682         {\r
683           scrollPane.getVerticalScrollBar().setValue(\r
684                   scrollPane.getVerticalScrollBar().getMaximum());\r
685         }\r
686       });\r
687 \r
688       break;\r
689     }\r
690   }\r
691 \r
692   void appendLocalSources()\r
693   {\r
694     if (localSources == null)\r
695     {\r
696       return;\r
697     }\r
698     // note - we add all das sources to list so they can be filtered for the\r
699     // standard fetchDbRefs function\r
700     int size = dasSources != null ? dasSources.length : 0;\r
701     int lsize = localSources.size();\r
702 \r
703     Object[][] data = new Object[size + lsize][2];\r
704     for (int i = 0; i < size; i++)\r
705     {\r
706       data[i][0] = dasSources[i].getTitle();\r
707       data[i][1] = new Boolean(selectedSources.contains(dasSources[i]\r
708               .getTitle()));\r
709     }\r
710 \r
711     DasSource[] tmp = new DasSource[size + lsize];\r
712     if (dasSources != null)\r
713     {\r
714       System.arraycopy(dasSources, 0, tmp, 0, size);\r
715     }\r
716 \r
717     Enumeration en = localSources.keys();\r
718     int index = size;\r
719     while (en.hasMoreElements())\r
720     {\r
721       String key = en.nextElement().toString();\r
722       data[index][0] = key;\r
723       data[index][1] = new Boolean(false);\r
724       tmp[index] = new Das1Source();\r
725       tmp[index].setNickname(key);\r
726       tmp[index].setUrl(((DasSource) localSources.get(key)).getUrl());\r
727 \r
728       index++;\r
729     }\r
730 \r
731     dasSources = tmp;\r
732 \r
733     refreshTableData(data);\r
734   }\r
735 \r
736   public void valueChanged(ListSelectionEvent evt)\r
737   {\r
738     // Called when the MainTable selection changes\r
739     if (evt.getValueIsAdjusting())\r
740     {\r
741       return;\r
742     }\r
743 \r
744     displayFullDetails(null);\r
745 \r
746     // Filter the displayed data sources\r
747     int dSize = dasSources.length;\r
748 \r
749     ArrayList names = new ArrayList();\r
750     ArrayList selected = new ArrayList();\r
751     DasSource ds;\r
752 \r
753     // The features filter is not visible, but we must still\r
754     // filter the das source list here.\r
755     // July 2006 - only 6 sources fo not serve features\r
756     Object[] dummyFeatureList = new Object[]\r
757     { "features" };\r
758 \r
759     for (int i = 0; i < dSize; i++)\r
760     {\r
761       ds = dasSources[i];\r
762       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
763 \r
764       if (dcs.length == 0 && ds.getCapabilities().length == 0\r
765               && filter1.getSelectedIndex() == 0\r
766               && filter2.getSelectedIndex() == 0\r
767               && filter3.getSelectedIndex() == 0)\r
768       {\r
769         // THIS IS A FIX FOR LOCAL SOURCES WHICH DO NOT\r
770         // HAVE COORDINATE SYSTEMS, INFO WHICH AT PRESENT\r
771         // IS ADDED FROM THE REGISTRY\r
772         names.add(ds.getTitle());\r
773         selected.add(new Boolean(selectedSources.contains(ds.getTitle())));\r
774         continue;\r
775       }\r
776 \r
777       if (!selectedInList(dummyFeatureList, ds.getCapabilities())\r
778               || !selectedInList(filter3.getSelectedValues(),\r
779                       ds.getLabels()))\r
780       {\r
781         continue;\r
782       }\r
783 \r
784       for (int j = 0; j < dcs.length; j++)\r
785       {\r
786         if (selectedInList(filter1.getSelectedValues(), new String[]\r
787         { dcs[j].getName() })\r
788                 && selectedInList(filter2.getSelectedValues(), new String[]\r
789                 { dcs[j].getCategory() }))\r
790         {\r
791           names.add(ds.getTitle());\r
792           selected.add(new Boolean(selectedSources.contains(ds\r
793                   .getTitle())));\r
794           break;\r
795         }\r
796       }\r
797     }\r
798 \r
799     dSize = names.size();\r
800     Object[][] data = new Object[dSize][2];\r
801     for (int d = 0; d < dSize; d++)\r
802     {\r
803       data[d][0] = names.get(d);\r
804       data[d][1] = selected.get(d);\r
805     }\r
806 \r
807     refreshTableData(data);\r
808   }\r
809 \r
810   boolean selectedInList(Object[] selection, String[] items)\r
811   {\r
812     for (int i = 0; i < selection.length; i++)\r
813     {\r
814       if (selection[i].equals("Any"))\r
815       {\r
816         return true;\r
817       }\r
818 \r
819       for (int j = 0; j < items.length; j++)\r
820       {\r
821         if (selection[i].equals(items[j]))\r
822         {\r
823           return true;\r
824         }\r
825       }\r
826     }\r
827 \r
828     return false;\r
829   }\r
830 \r
831   void setSelectedFromProperties()\r
832   {\r
833     String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",\r
834             "uniprot");\r
835     StringTokenizer st = new StringTokenizer(active, "\t");\r
836     selectedSources = new Vector();\r
837     while (st.hasMoreTokens())\r
838     {\r
839       selectedSources.addElement(st.nextToken());\r
840     }\r
841 \r
842     Vector _localSources = jalview.bin.Cache.getLocalDasSources();\r
843     if (_localSources != null)\r
844     {\r
845       if (localSources == null)\r
846       {\r
847         localSources = new Hashtable();\r
848       }\r
849       Enumeration sources = _localSources.elements();\r
850       while (sources.hasMoreElements())\r
851       {\r
852         Das1Source source = (Das1Source) sources.nextElement();\r
853         localSources.put(source.getTitle(), source);\r
854       }\r
855     }\r
856   }\r
857 \r
858   public void reset_actionPerformed(ActionEvent e)\r
859   {\r
860     registryURL.setText(DEFAULT_REGISTRY);\r
861   }\r
862 \r
863   /**\r
864    * set the DAS source settings in the given jalview properties.\r
865    * \r
866    * @param properties\r
867    */\r
868   public void saveProperties(Properties properties)\r
869   {\r
870     if (registryURL.getText() == null || registryURL.getText().length() < 1)\r
871     {\r
872       properties.remove(jalview.bin.Cache.DAS_REGISTRY_URL);\r
873     }\r
874     else\r
875     {\r
876       properties.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,\r
877               registryURL.getText());\r
878     }\r
879 \r
880     StringBuffer sb = new StringBuffer();\r
881     for (int r = 0; r < table.getModel().getRowCount(); r++)\r
882     {\r
883       if (((Boolean) table.getValueAt(r, 1)).booleanValue())\r
884       {\r
885         sb.append(table.getValueAt(r, 0) + "\t");\r
886       }\r
887     }\r
888 \r
889     properties.setProperty(jalview.bin.Cache.DAS_ACTIVE_SOURCE,\r
890             sb.toString());\r
891 \r
892     if (localSources != null)\r
893     {\r
894       sb = new StringBuffer();\r
895       Enumeration en = localSources.keys();\r
896       while (en.hasMoreElements())\r
897       {\r
898         String token = en.nextElement().toString();\r
899         sb.append(token\r
900                 + "|"\r
901                 + (((DasSource) localSources.get(token))\r
902                         .hasCapability("sequence") ? "sequence:" : "")\r
903                 + ((DasSource) localSources.get(token)).getUrl() + "\t");\r
904       }\r
905 \r
906       properties.setProperty(jalview.bin.Cache.DAS_LOCAL_SOURCE,\r
907               sb.toString());\r
908     }\r
909 \r
910   }\r
911 \r
912   class DASTableModel extends AbstractTableModel\r
913   {\r
914 \r
915     public DASTableModel(Object[][] data)\r
916     {\r
917       this.data = data;\r
918     }\r
919 \r
920     private String[] columnNames = new String[]\r
921     { "Nickname", "Use Source" };\r
922 \r
923     private Object[][] data;\r
924 \r
925     public int getColumnCount()\r
926     {\r
927       return columnNames.length;\r
928     }\r
929 \r
930     public int getRowCount()\r
931     {\r
932       return data.length;\r
933     }\r
934 \r
935     public String getColumnName(int col)\r
936     {\r
937       return columnNames[col];\r
938     }\r
939 \r
940     public Object getValueAt(int row, int col)\r
941     {\r
942       return data[row][col];\r
943     }\r
944 \r
945     /*\r
946      * JTable uses this method to determine the default renderer/ editor for\r
947      * each cell. If we didn't implement this method, then the last column would\r
948      * contain text ("true"/"false"), rather than a check box.\r
949      */\r
950     public Class getColumnClass(int c)\r
951     {\r
952       return getValueAt(0, c).getClass();\r
953     }\r
954 \r
955     /*\r
956      * Don't need to implement this method unless your table's editable.\r
957      */\r
958     public boolean isCellEditable(int row, int col)\r
959     {\r
960       // Note that the data/cell address is constant,\r
961       // no matter where the cell appears onscreen.\r
962       return col == 1;\r
963 \r
964     }\r
965 \r
966     /*\r
967      * Don't need to implement this method unless your table's data can change.\r
968      */\r
969     public void setValueAt(Object value, int row, int col)\r
970     {\r
971       data[row][col] = value;\r
972       fireTableCellUpdated(row, col);\r
973 \r
974       String name = getValueAt(row, 0).toString();\r
975       boolean selected = ((Boolean) value).booleanValue();\r
976 \r
977       if (selectedSources.contains(name) && !selected)\r
978       {\r
979         selectedSources.remove(name);\r
980       }\r
981 \r
982       if (!selectedSources.contains(name) && selected)\r
983       {\r
984         selectedSources.add(name);\r
985       }\r
986     }\r
987   }\r
988 \r
989   public void initDasSources()\r
990   {\r
991 \r
992     Thread thr = new Thread(new Runnable()\r
993     {\r
994       public void run()\r
995       {\r
996         // this actually initialises the das source list\r
997         paintComponent(null); // yuk\r
998       }\r
999     });\r
1000     thr.start();\r
1001     while (loadingDasSources || dasSources == null)\r
1002     {\r
1003       try\r
1004       {\r
1005         Thread.sleep(10);\r
1006       } catch (Exception e)\r
1007       {\r
1008       }\r
1009       ;\r
1010     }\r
1011   }\r
1012 \r
1013   public Vector resolveSourceNicknames(Vector sources)\r
1014   {\r
1015 \r
1016     Vector resolved = new Vector();\r
1017     if (sources != null)\r
1018     {\r
1019       for (int i = 0; i < dasSources.length; i++)\r
1020       {\r
1021         if (sources.contains(dasSources[i].getTitle()))\r
1022         {\r
1023           if (!resolved.contains(dasSources[i]))\r
1024           {\r
1025             resolved.addElement(dasSources[i]);\r
1026           }\r
1027         }\r
1028       }\r
1029     }\r
1030     return resolved;\r
1031   }\r
1032 \r
1033   /**\r
1034    * disable or enable the buttons on the source browser\r
1035    * \r
1036    * @param b\r
1037    */\r
1038   public void setGuiEnabled(boolean b)\r
1039   {\r
1040     refresh.setEnabled(b);\r
1041     addLocal.setEnabled(b);\r
1042   }\r
1043 }\r