Fix for local sources with no capabilities
[jalview.git] / src / jalview / gui / DasSourceBrowser.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 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.gui;\r
20 \r
21 import jalview.jbgui.*;\r
22 import javax.swing.table.AbstractTableModel;\r
23 import javax.swing.event.*;\r
24 import jalview.util.TableSorter;\r
25 import java.awt.event.*;\r
26 import javax.swing.*;\r
27 import java.util.*;\r
28 \r
29 \r
30 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
31 import org.biojava.dasobert.dasregistry.DasSource;\r
32 import org.biojava.dasobert.dasregistry.Das1Source;\r
33 import java.awt.BorderLayout;\r
34 \r
35 public class DasSourceBrowser extends GDasSourceBrowser\r
36     implements Runnable, ListSelectionListener\r
37 {\r
38   static DasSource[] dasSources = null;\r
39 \r
40   Hashtable localSources = null;\r
41 \r
42   Vector selectedSources;\r
43 \r
44 \r
45   public DasSourceBrowser()\r
46   {\r
47     registryURL.setText(jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
48         "http://das.sanger.ac.uk/registry/das1/sources/") );\r
49 \r
50     setSelectedFromProperties();\r
51 \r
52     displayFullDetails(null);\r
53     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
54 \r
55     filter1.addListSelectionListener(this);\r
56     filter2.addListSelectionListener(this);\r
57     filter3.addListSelectionListener(this);\r
58 \r
59     //Ask to be notified of selection changes.\r
60     ListSelectionModel rowSM = table.getSelectionModel();\r
61     rowSM.addListSelectionListener(new ListSelectionListener()\r
62     {\r
63       public void valueChanged(ListSelectionEvent e)\r
64       {\r
65         ListSelectionModel lsm = (ListSelectionModel) e.getSource();\r
66         if (!lsm.isSelectionEmpty())\r
67         {\r
68           int selectedRow = lsm.getMinSelectionIndex();\r
69           displayFullDetails(table.getValueAt(selectedRow, 0).toString());\r
70         }\r
71       }\r
72     });\r
73 \r
74     table.addMouseListener(new MouseAdapter()\r
75         {\r
76           public void mouseClicked(MouseEvent evt)\r
77           {\r
78             if(evt.getClickCount()==2\r
79                || SwingUtilities.isRightMouseButton(evt))\r
80               editRemoveLocalSource(evt);\r
81           }\r
82         });\r
83 \r
84     if(dasSources==null)\r
85     {\r
86     Thread worker = new Thread(this);\r
87     worker.start();\r
88     }\r
89     else\r
90      {\r
91        init();\r
92      }\r
93   }\r
94 \r
95   void init()\r
96   {\r
97     int dSize = dasSources.length;\r
98     Object[][] data = new Object[dSize][2];\r
99     for (int i = 0; i < dSize; i++)\r
100     {\r
101       data[i][0] = dasSources[i].getNickname();\r
102       data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
103           getNickname()));\r
104     }\r
105 \r
106     refreshTableData(data);\r
107     setCapabilities(dasSources);\r
108 \r
109     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
110         {\r
111           public void run()\r
112           {\r
113             TableSorter sorter = (TableSorter)table.getModel();\r
114             sorter.setSortingStatus(1, TableSorter.DESCENDING);\r
115             sorter.setSortingStatus(1, TableSorter.NOT_SORTED);\r
116           }\r
117         });\r
118 \r
119     progressBar.setIndeterminate(false);\r
120     progressBar.setVisible(false);\r
121     addLocal.setVisible(true);\r
122     refresh.setVisible(true);\r
123   }\r
124 \r
125 \r
126   public void refreshTableData(Object[][] data)\r
127   {\r
128     TableSorter sorter = new TableSorter(new DASTableModel(data));\r
129     sorter.setTableHeader(table.getTableHeader());\r
130     table.setModel(sorter);\r
131   }\r
132 \r
133   void displayFullDetails(String nickName)\r
134   {\r
135 \r
136     StringBuffer text = new StringBuffer(\r
137         "<HTML><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">");\r
138 \r
139     if (nickName == null)\r
140     {\r
141       fullDetails.setText(text +\r
142                           "Select a DAS service from the table"\r
143                           + " to read a full description here.</font></html>");\r
144       return;\r
145     }\r
146 \r
147     int dSize = dasSources.length;\r
148     for (int i = 0; i < dSize; i++)\r
149     {\r
150       if (!dasSources[i].getNickname().equals(nickName))\r
151         continue;\r
152 \r
153       DasSource ds = dasSources[i];\r
154 \r
155       text.append("<font color=\"#0000FF\">Id:</font> " + dasSources[i].getId() +\r
156                   "<br>");\r
157       text.append("<font color=\"#0000FF\">Nickname:</font> " +\r
158                   dasSources[i].getNickname() + "<br>");\r
159       text.append("<font color=\"#0000FF\">URL:</font> " + dasSources[i].getUrl() +\r
160                   "<br>");\r
161 \r
162       text.append("<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"\r
163                   +dasSources[i].getAdminemail()\r
164                   +"\">"+dasSources[i].getAdminemail()+"</a>" +\r
165                   "<br>");\r
166 \r
167 \r
168       text.append("<font color=\"#0000FF\">Registered at:</font> " + dasSources[i].getRegisterDate() +\r
169                         "<br>");\r
170 \r
171       text.append("<font color=\"#0000FF\">Last successful test:</font> " + dasSources[i].getLeaseDate() +\r
172                         "<br>");\r
173 \r
174       text.append("<font color=\"#0000FF\">Labels:</font> ");\r
175       for(int s=0; s<dasSources[i].getLabels().length; s++)\r
176       {\r
177         text.append( dasSources[i].getLabels()[s]);\r
178         if(s<dasSources[i].getLabels().length-1)\r
179           text.append(",");\r
180         text.append(" ");\r
181       }\r
182       text.append("<br>");\r
183 \r
184 \r
185 \r
186       text.append("<font color=\"#0000FF\">Capabilities:</font> ");\r
187       String[] scap = dasSources[i].getCapabilities();\r
188       for (int j = 0; j < scap.length; j++)\r
189       {\r
190         text.append(scap[j]);\r
191         if (j < scap.length - 1)\r
192           text.append(", ");\r
193       }\r
194       text.append("<br>");\r
195 \r
196       text.append("<font color=\"#0000FF\">Coordinates:</font> ");\r
197       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
198       for (int j = 0; j < dcs.length; j++)\r
199       {\r
200         text.append("(" + dcs[j].getUniqueId() + ") "\r
201                     + dcs[j].getCategory() + ", " + dcs[j].getName());\r
202         if (dcs[j].getNCBITaxId() != 0)\r
203           text.append(", " + dcs[j].getNCBITaxId());\r
204         if (dcs[j].getOrganismName().length() > 0)\r
205           text.append(", " + dcs[j].getOrganismName());\r
206 \r
207         text.append("<br>");\r
208       }\r
209 \r
210       text.append("<font color=\"#0000FF\">Description:</font> " +\r
211                   dasSources[i].getDescription() + "<br>");\r
212 \r
213 \r
214       if (dasSources[i].getHelperurl()!=null\r
215           && dasSources[i].getHelperurl().length() > 0)\r
216       {\r
217         text.append("<font color=\"#0000FF\"><a href=\"" +\r
218                     dasSources[i].getHelperurl()\r
219                     + "\">Go to site</a></font<br>");\r
220       }\r
221 \r
222       text.append("</font></html>");\r
223 \r
224       break;\r
225     }\r
226 \r
227     fullDetails.setText(text.toString());\r
228     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
229     {\r
230       public void run()\r
231       {\r
232         fullDetailsScrollpane.getVerticalScrollBar().setValue(0);\r
233       }\r
234     });\r
235   }\r
236 \r
237 \r
238   public void run()\r
239   {\r
240     addLocal.setVisible(false);\r
241     refresh.setVisible(false);\r
242     progressBar.setVisible(true);\r
243     progressBar.setIndeterminate(true);\r
244 \r
245     dasSources = jalview.io.DasSequenceFeatureFetcher.getDASSources();\r
246 \r
247     appendLocalSources();\r
248 \r
249     init();\r
250 \r
251   }\r
252 \r
253   public Vector getSelectedSources()\r
254   {\r
255     Vector selected = new Vector();\r
256     for (int r = 0; r < selectedSources.size(); r++)\r
257     {\r
258         for (int i = 0; i < dasSources.length; i++)\r
259         {\r
260           if (dasSources[i].getNickname().equals(\r
261               selectedSources.elementAt(r)))\r
262           {\r
263             selected.addElement(dasSources[i]);\r
264             break;\r
265           }\r
266         }\r
267     }\r
268 \r
269     return selected;\r
270   }\r
271 \r
272   public DasSource[] getDASSource()\r
273   {\r
274     if(dasSources==null)\r
275     {\r
276      dasSources = jalview.io.DasSequenceFeatureFetcher.getDASSources();\r
277      appendLocalSources();\r
278     }\r
279 \r
280     return dasSources;\r
281   }\r
282 \r
283   public void refresh_actionPerformed(ActionEvent e)\r
284   {\r
285     saveProperties(jalview.bin.Cache.applicationProperties);\r
286 \r
287     Thread worker = new Thread(this);\r
288     worker.start();\r
289   }\r
290 \r
291   private void setCapabilities(DasSource[] sources)\r
292   {\r
293     Vector authority = new Vector();\r
294     Vector type = new Vector();\r
295     Vector label = new Vector();\r
296 \r
297     authority.addElement("Any");\r
298     type.addElement("Any");\r
299     label.addElement("Any");\r
300 \r
301     for (int i = 0; i < sources.length; i++)\r
302     {\r
303       DasSource ds = sources[i];\r
304 \r
305       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
306 \r
307       for (int j = 0; j < dcs.length; j++)\r
308       {\r
309         if (!type.contains(dcs[j].getCategory()))\r
310           type.addElement(dcs[j].getCategory());\r
311 \r
312         if (!authority.contains(dcs[j].getName()))\r
313           authority.addElement(dcs[j].getName());\r
314       }\r
315 \r
316       String[] slabels = ds.getLabels();\r
317       for (int s = 0; s < slabels.length; s++)\r
318       {\r
319         if (!label.contains(slabels[s]))\r
320         {\r
321           label.addElement(slabels[s]);\r
322         }\r
323       }\r
324 \r
325     }\r
326 \r
327     filter1.setListData(authority);\r
328     filter2.setListData(type);\r
329     filter3.setListData(label);\r
330 \r
331     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
332     {\r
333       public void run()\r
334       {\r
335         filter1.setSelectedIndex(0);\r
336         filter2.setSelectedIndex(0);\r
337         filter3.setSelectedIndex(0);\r
338       }\r
339     });\r
340   }\r
341 \r
342   public void amendLocal(boolean newSource)\r
343   {\r
344     String url = "http://localhost:8080/", nickname = "";\r
345 \r
346     if(!newSource)\r
347     {\r
348       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
349       nickname = table.getValueAt(selectedRow, 0).toString();\r
350       url = ((DasSource)localSources.get(nickname)).getUrl();\r
351     }\r
352 \r
353     JTextField nametf = new JTextField(nickname, 40);\r
354     JTextField urltf = new JTextField(url, 40);\r
355 \r
356     JPanel panel = new JPanel(new BorderLayout());\r
357     JPanel pane12 = new JPanel(new BorderLayout());\r
358     pane12.add(new JLabel("Nickname: "), BorderLayout.CENTER);\r
359     pane12.add(nametf, BorderLayout.EAST);\r
360     panel.add(pane12, BorderLayout.NORTH);\r
361     pane12 = new JPanel(new BorderLayout());\r
362     pane12.add(new JLabel("URL: "), BorderLayout.CENTER);\r
363     pane12.add(urltf, BorderLayout.EAST);\r
364     panel.add(pane12, BorderLayout.SOUTH);\r
365 \r
366 \r
367     int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
368         panel, "Enter Nickname & URL of Local DAS Source",\r
369         JOptionPane.OK_CANCEL_OPTION);\r
370 \r
371        if (reply != JOptionPane.OK_OPTION )\r
372        {\r
373            return;\r
374        }\r
375 \r
376        if(!urltf.getText().endsWith("/"))\r
377          urltf.setText(urltf.getText()+"/");\r
378 \r
379        Das1Source local = new Das1Source();\r
380 \r
381        local.setUrl(urltf.getText());\r
382        local.setNickname(nametf.getText());\r
383 \r
384 \r
385        if(localSources==null)\r
386          localSources = new Hashtable();\r
387 \r
388        localSources.put(local.getNickname(), local);\r
389 \r
390        if(!newSource && !nickname.equals(nametf.getText()))\r
391        {\r
392          localSources.remove(nickname);\r
393        }\r
394 \r
395        int size = dasSources.length;\r
396        int adjust = newSource ? 1 : 0;\r
397 \r
398        Object[][] data = new Object[size+adjust][2];\r
399        for (int i = 0; i < size; i++)\r
400        {\r
401          if(!newSource && dasSources[i].getNickname().equals(nickname))\r
402          {\r
403            ((DasSource)dasSources[i]).setNickname(local.getNickname());\r
404            ((DasSource)dasSources[i]).setUrl(local.getUrl());\r
405            data[i][0] = local.getNickname();\r
406            data[i][1] = new Boolean(true);\r
407          }\r
408          else\r
409          {\r
410            data[i][0] = dasSources[i].getNickname();\r
411            data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
412                getNickname()));\r
413          }\r
414        }\r
415 \r
416        if(newSource)\r
417        {\r
418          data[size][0] = local.getNickname();\r
419          data[size][1] = new Boolean(true);\r
420          selectedSources.add(local.getNickname());\r
421        }\r
422 \r
423        DasSource [] tmp = new DasSource[size+adjust];\r
424 \r
425        System.arraycopy(dasSources, 0, tmp, 0, size);\r
426 \r
427        if(newSource)\r
428          tmp[size] = local;\r
429 \r
430        dasSources = tmp;\r
431 \r
432        refreshTableData(data);\r
433 \r
434        SwingUtilities.invokeLater(new Runnable()\r
435        {\r
436          public void run()\r
437          {\r
438            scrollPane.getVerticalScrollBar().setValue(\r
439                scrollPane.getVerticalScrollBar().getMaximum()\r
440                );\r
441          }\r
442        });\r
443 \r
444        displayFullDetails(local.getNickname());\r
445      }\r
446 \r
447     public void editRemoveLocalSource(MouseEvent evt)\r
448     {\r
449       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
450       if(selectedRow==-1)\r
451         return;\r
452 \r
453       String nickname = table.getValueAt(selectedRow, 0).toString();\r
454 \r
455       if (!localSources.containsKey(nickname))\r
456       {\r
457         JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
458         "You can only edit or remove local DAS Sources!",\r
459          "Public DAS source - not editable",\r
460          JOptionPane.WARNING_MESSAGE);\r
461         return;\r
462       }\r
463 \r
464 \r
465       Object[] options = {"Edit", "Remove", "Cancel"};\r
466       int choice = JOptionPane.showInternalOptionDialog(Desktop.desktop,\r
467     "Do you want to edit or remove "+nickname+"?",\r
468     "Edit / Remove Local DAS Source",\r
469     JOptionPane.YES_NO_CANCEL_OPTION,\r
470     JOptionPane.QUESTION_MESSAGE,\r
471     null,\r
472     options,\r
473     options[2]);\r
474 \r
475       switch(choice)\r
476       {\r
477         case 0: amendLocal(false);   break;\r
478         case 1:\r
479           localSources.remove(nickname);\r
480           selectedSources.remove(nickname);\r
481           Object[][] data = new Object[dasSources.length-1][2];\r
482           DasSource [] tmp = new DasSource[dasSources.length-1];\r
483           int index = 0;\r
484           for (int i = 0; i < dasSources.length; i++)\r
485           {\r
486             if (dasSources[i].getNickname().equals(nickname))\r
487             {\r
488               continue;\r
489             }\r
490             else\r
491             {\r
492               tmp[index] = dasSources[i];\r
493               data[index][0] = dasSources[i].getNickname();\r
494               data[index][1] = new Boolean(selectedSources.contains(dasSources[i].\r
495                   getNickname()));\r
496               index++;\r
497             }\r
498           }\r
499            dasSources = tmp;\r
500            refreshTableData(data);\r
501            SwingUtilities.invokeLater(new Runnable()\r
502            {\r
503              public void run()\r
504              {\r
505                scrollPane.getVerticalScrollBar().setValue(\r
506                    scrollPane.getVerticalScrollBar().getMaximum()\r
507                    );\r
508              }\r
509            });\r
510 \r
511           break;\r
512       }\r
513     }\r
514 \r
515     void appendLocalSources()\r
516     {\r
517       if(localSources==null)\r
518         return;\r
519 \r
520       int size = dasSources!=null ? dasSources.length : 0;\r
521       int lsize = localSources.size();\r
522 \r
523       Object[][] data = new Object[size+lsize][2];\r
524       for (int i = 0; i < size; i++)\r
525       {\r
526         data[i][0] = dasSources[i].getNickname();\r
527         data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
528             getNickname()));\r
529       }\r
530 \r
531       DasSource [] tmp = new DasSource[size+lsize];\r
532       if(dasSources!=null)\r
533         System.arraycopy(dasSources, 0, tmp, 0, size);\r
534 \r
535       Enumeration en = localSources.keys();\r
536       int index = size;\r
537       while(en.hasMoreElements())\r
538       {\r
539         String key = en.nextElement().toString();\r
540         data[index][0] = key;\r
541         data[index][1] = new Boolean(false);\r
542         tmp[index] = new Das1Source();\r
543         tmp[index].setNickname(key);\r
544         tmp[index].setUrl( ((DasSource)localSources.get(key)).getUrl() );\r
545 \r
546         index++;\r
547       }\r
548 \r
549       dasSources = tmp;\r
550 \r
551       refreshTableData(data);\r
552   }\r
553 \r
554   public void valueChanged(ListSelectionEvent evt)\r
555   {\r
556     //Called when the MainTable selection changes\r
557     if (evt.getValueIsAdjusting() )\r
558     {\r
559       return;\r
560     }\r
561 \r
562 \r
563     displayFullDetails(null);\r
564 \r
565     // Filter the displayed data sources\r
566     int dSize = dasSources.length;\r
567 \r
568 \r
569     ArrayList names = new ArrayList();\r
570     ArrayList selected = new ArrayList();\r
571     DasSource ds;\r
572 \r
573     //The features filter is not visible, but we must still\r
574     //filter the das source list here.\r
575     //July 2006 - only 6 sources fo not serve features\r
576     Object [] dummyFeatureList = new Object[]{"features"};\r
577 \r
578     for (int i = 0; i < dSize; i++)\r
579     {\r
580       ds = dasSources[i];\r
581       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
582 \r
583       if (dcs.length == 0 && ds.getCapabilities().length == 0\r
584           && filter1.getSelectedIndex() == 0\r
585           && filter2.getSelectedIndex() == 0\r
586           && filter3.getSelectedIndex() == 0)\r
587       {\r
588         //THIS IS A FIX FOR LOCAL SOURCES WHICH DO NOT\r
589         //HAVE COORDINATE SYSTEMS, INFO WHICH AT PRESENT\r
590         //IS ADDED FROM THE REGISTRY\r
591         names.add(ds.getNickname());\r
592         selected.add(new Boolean(\r
593               selectedSources.contains(ds.getNickname())));\r
594         continue;\r
595       }\r
596 \r
597 \r
598       if (!selectedInList(dummyFeatureList, ds.getCapabilities())\r
599       ||  !selectedInList(filter3.getSelectedValues(),\r
600                           ds.getLabels()))\r
601       {\r
602         continue;\r
603       }\r
604 \r
605       for (int j = 0; j < dcs.length; j++)\r
606       {\r
607         if (   selectedInList(filter1.getSelectedValues(),\r
608                            new String[]\r
609                            {dcs[j].getName()})\r
610             && selectedInList(filter2.getSelectedValues(),\r
611                               new String[]\r
612                               {dcs[j].getCategory()}))\r
613         {\r
614           names.add(ds.getNickname());\r
615           selected.add(new Boolean(\r
616               selectedSources.contains(ds.getNickname())));\r
617           break;\r
618         }\r
619       }\r
620     }\r
621 \r
622     dSize = names.size();\r
623     Object[][] data = new Object[dSize][2];\r
624     for (int d = 0; d < dSize; d++)\r
625     {\r
626       data[d][0] = names.get(d);\r
627       data[d][1] = selected.get(d);\r
628     }\r
629 \r
630     refreshTableData(data);\r
631   }\r
632 \r
633   boolean selectedInList(Object [] selection, String[] items)\r
634   {\r
635     for (int i = 0; i < selection.length; i++)\r
636     {\r
637       if (selection[i].equals("Any") )\r
638         return true;\r
639 \r
640       for (int j = 0; j < items.length; j++)\r
641       {\r
642         if (selection[i].equals(items[j]))\r
643           return true;\r
644       }\r
645     }\r
646 \r
647     return false;\r
648   }\r
649 \r
650   void setSelectedFromProperties()\r
651   {\r
652      String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
653      StringTokenizer st = new StringTokenizer(active, "\t");\r
654      selectedSources = new Vector();\r
655      while(st.hasMoreTokens())\r
656      {\r
657        selectedSources.addElement(st.nextToken());\r
658      }\r
659 \r
660      String local = jalview.bin.Cache.getProperty("DAS_LOCAL_SOURCE");\r
661      if(local!=null)\r
662      {\r
663        if(localSources == null)\r
664          localSources = new Hashtable();\r
665 \r
666        st = new StringTokenizer(local, "\t");\r
667        while(st.hasMoreTokens())\r
668        {\r
669          String token = st.nextToken();\r
670          int bar = token.indexOf("|");\r
671          Das1Source source = new Das1Source();\r
672 \r
673          source.setUrl(token.substring(bar + 1));\r
674          source.setNickname(token.substring(0, bar));\r
675 \r
676          localSources.put(source.getNickname(), source);\r
677        }\r
678      }\r
679   }\r
680 \r
681   public void saveProperties(Properties properties)\r
682   {\r
683     if (registryURL.getText() == null || registryURL.getText().length() < 1)\r
684       properties.remove("DAS_REGISTRY_URL");\r
685     else\r
686       properties.setProperty("DAS_REGISTRY_URL", registryURL.getText());\r
687 \r
688     StringBuffer sb = new StringBuffer();\r
689     for(int r=0; r<table.getModel().getRowCount(); r++)\r
690     {\r
691       if( ((Boolean)table.getValueAt(r,1)).booleanValue())\r
692       {\r
693         sb.append(table.getValueAt(r,0)+"\t");\r
694       }\r
695     }\r
696 \r
697     properties.setProperty("DAS_ACTIVE_SOURCE", sb.toString() );\r
698 \r
699     if(localSources!=null)\r
700     {\r
701       sb = new StringBuffer();\r
702       Enumeration en = localSources.keys();\r
703       while(en.hasMoreElements())\r
704       {\r
705         String token = en.nextElement().toString();\r
706         sb.append(token+"|"\r
707                   + ((DasSource)localSources.get(token)).getUrl()\r
708                   +"\t");\r
709       }\r
710 \r
711       properties.setProperty("DAS_LOCAL_SOURCE", sb.toString());\r
712     }\r
713 \r
714   }\r
715 \r
716   class DASTableModel\r
717       extends AbstractTableModel\r
718   {\r
719 \r
720     public DASTableModel(Object[][] data)\r
721     {\r
722       this.data = data;\r
723     }\r
724 \r
725     private String[] columnNames = new String[]  {"Nickname", "Use Source"};\r
726 \r
727     private Object[][] data;\r
728 \r
729     public int getColumnCount()\r
730     {\r
731       return columnNames.length;\r
732     }\r
733 \r
734     public int getRowCount()\r
735     {\r
736       return data.length;\r
737     }\r
738 \r
739     public String getColumnName(int col)\r
740     {\r
741       return columnNames[col];\r
742     }\r
743 \r
744     public Object getValueAt(int row, int col)\r
745     {\r
746       return data[row][col];\r
747     }\r
748 \r
749     /*\r
750      * JTable uses this method to determine the default renderer/\r
751      * editor for each cell.  If we didn't implement this method,\r
752      * then the last column would contain text ("true"/"false"),\r
753      * rather than a check box.\r
754      */\r
755     public Class getColumnClass(int c)\r
756     {\r
757       return getValueAt(0, c).getClass();\r
758     }\r
759 \r
760     /*\r
761      * Don't need to implement this method unless your table's\r
762      * editable.\r
763      */\r
764     public boolean isCellEditable(int row, int col)\r
765     {\r
766       //Note that the data/cell address is constant,\r
767       //no matter where the cell appears onscreen.\r
768       return col == 1;\r
769 \r
770     }\r
771 \r
772     /*\r
773      * Don't need to implement this method unless your table's\r
774      * data can change.\r
775      */\r
776     public void setValueAt(Object value, int row, int col)\r
777     {\r
778       data[row][col] = value;\r
779       fireTableCellUpdated(row, col);\r
780 \r
781       String name = getValueAt(row,0).toString();\r
782       boolean selected = ((Boolean)value).booleanValue();\r
783 \r
784       if(selectedSources.contains(name) && !selected)\r
785         selectedSources.remove(name);\r
786 \r
787       if(!selectedSources.contains(name) && selected)\r
788         selectedSources.add(name);\r
789     }\r
790   }\r
791 }\r
792 \r
793 \r