JAL-3253 jalview.bin.Instance handles all singleton instances -
[jalview.git] / src / jalview / gui / WsPreferences.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import jalview.bin.Cache;
24 import jalview.bin.Instance;
25 import jalview.jbgui.GWsPreferences;
26 import jalview.util.MessageManager;
27 import jalview.ws.jws2.Jws2Discoverer;
28 import jalview.ws.rest.RestServiceDescription;
29
30 import java.awt.BorderLayout;
31 import java.awt.Color;
32 import java.awt.Component;
33 import java.awt.Dimension;
34 import java.awt.event.ActionEvent;
35 import java.awt.event.ActionListener;
36 import java.net.URL;
37 import java.util.List;
38 import java.util.Vector;
39
40 import javax.swing.JLabel;
41 import javax.swing.JOptionPane;
42 import javax.swing.JPanel;
43 import javax.swing.JTable;
44 import javax.swing.JTextField;
45 import javax.swing.table.AbstractTableModel;
46 import javax.swing.table.TableCellRenderer;
47
48 public class WsPreferences extends GWsPreferences
49 {
50
51   public WsPreferences()
52   {
53     super();
54     initFromPreferences();
55   }
56
57   List<String> wsUrls;
58
59   Vector<String> oldUrls, rsbsUrls, oldRsbsUrls;
60
61   private boolean needWsMenuUpdate;
62
63   private boolean oldJws1, oldJws2, oldIndexByHost, oldIndexByType,
64           oldEnfin, oldWsWarning;
65
66   private void initFromPreferences()
67   {
68
69     wsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
70     if (!wsUrls.isEmpty())
71     {
72       oldUrls = new Vector<String>(wsUrls);
73     }
74     else
75     {
76       oldUrls = null;
77       wsUrls = new Vector<String>();
78     }
79     wsList.setDefaultRenderer(Integer.class, new JabaWSStatusRenderer());
80     wsList.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
81     updateList();
82     rsbsUrls = jalview.ws.rest.RestClient.getRsbsDescriptions();
83     if (rsbsUrls != null)
84     {
85       oldRsbsUrls = new Vector<String>(rsbsUrls);
86     }
87     else
88     {
89       oldRsbsUrls = null;
90       rsbsUrls = new Vector<String>();
91     }
92     updateRsbsList();
93     enableEnfinServices.setSelected(
94             oldEnfin = Cache.getDefault("SHOW_ENFIN_SERVICES", true));
95     enableEnfinServices.addActionListener(updateAction);
96     enableJws2Services.setSelected(
97             oldJws2 = Cache.getDefault("SHOW_JWS2_SERVICES", true));
98     enableJws2Services.addActionListener(updateAction);
99     indexByHost.setSelected(
100             oldIndexByHost = Cache.getDefault("WSMENU_BYHOST", false));
101     indexByHost.addActionListener(updateAction);
102     indexByType.setSelected(
103             oldIndexByType = Cache.getDefault("WSMENU_BYTYPE", false));
104     indexByType.addActionListener(updateAction);
105     displayWsWarning.setSelected(oldWsWarning = Cache
106             .getDefault("SHOW_WSDISCOVERY_ERRORS", true));
107   }
108
109   ActionListener updateAction = new ActionListener()
110   {
111
112     @Override
113     public void actionPerformed(ActionEvent e)
114     {
115       update++;
116     }
117
118   };
119
120   private void updateList()
121   {
122     Object tdat[][] = new Object[wsUrls.size()][2];
123     int r = 0;
124     for (String url : wsUrls)
125     {
126       int status = Jws2Discoverer.getDiscoverer().getServerStatusFor(url);
127       tdat[r][1] = new Integer(status);
128       tdat[r++][0] = url;
129     }
130
131     wsList.setModel(new WsUrlTableModel(tdat));
132     wsList.getColumn(MessageManager.getString("label.status"))
133             .setMinWidth(10);
134   }
135
136   private class JabaWSStatusRenderer extends JPanel
137           implements TableCellRenderer
138   {
139     public JabaWSStatusRenderer()
140     {
141       setOpaque(true);
142       setMinimumSize(new Dimension(10, 10));
143       // setText(" ");
144
145     }
146
147     /**
148      * render an Integer reflecting service status as a colour and symbol
149      */
150
151     @Override
152     public Component getTableCellRendererComponent(JTable arg0,
153             Object status, boolean isSelected, boolean hasFocus, int row,
154             int column)
155     {
156       Color c;
157       String t = new String("");
158       switch (((Integer) status).intValue())
159       {
160       case 1:
161         // cb.setSelected(true);
162         // cb.setBackground(
163         c = Color.green;
164         break;
165       case 0:
166         // cb.setSelected(true);
167         // cb.setBackground(
168         c = Color.lightGray;
169         break;
170       case -1:
171         // cb.setSelected(false);
172         // cb.setBackground(
173         c = Color.red;
174         break;
175       default:
176         // cb.setSelected(false);
177         // cb.setBackground(
178         c = Color.orange;
179       }
180       setBackground(c);
181       // setText(t);
182       return this;
183
184     }
185
186   }
187
188   private class WsUrlTableModel extends AbstractTableModel
189   {
190
191     private Object[][] data;
192
193     private String[] columnNames = new String[] {
194         MessageManager.getString("label.service_url"),
195         MessageManager.getString("label.status") };
196
197     public WsUrlTableModel(Object[][] tdat)
198     {
199       this.data = tdat;
200     }
201
202     @Override
203     public int getColumnCount()
204     {
205       return 2;
206     }
207
208     @Override
209     public String getColumnName(int column)
210     {
211       return columnNames[column];
212     }
213
214     @Override
215     public int getRowCount()
216     {
217       if (data == null)
218       {
219         return 0;
220       }
221       return data.length;
222     }
223
224     @Override
225     public java.lang.Class<?> getColumnClass(int columnIndex)
226     {
227       return getValueAt(0, columnIndex).getClass();
228     };
229
230     @Override
231     public Object getValueAt(int rowIndex, int columnIndex)
232     {
233       return data[rowIndex][columnIndex];
234     }
235
236   }
237
238   private void updateRsbsList()
239   {
240     sbrsList.setListData(rsbsUrls);
241   }
242
243   private void updateServiceList()
244   {
245     Jws2Discoverer.getDiscoverer().setServiceUrls(wsUrls);
246   }
247
248   private void updateRsbsServiceList()
249   {
250     jalview.ws.rest.RestClient.setRsbsServices(rsbsUrls);
251   }
252
253   /*
254    * (non-Javadoc)
255    * 
256    * @see
257    * jalview.jbgui.GWsPreferences#deleteWsUrl_actionPerformed(java.awt.event
258    * .ActionEvent)
259    */
260   @Override
261   protected void deleteWsUrl_actionPerformed(ActionEvent e)
262   {
263     int sel = wsList.getSelectedRow();
264     if (sel > -1)
265     {
266       wsUrls.remove(sel);
267       update++;
268       updateList();
269     }
270   }
271
272   /*
273    * (non-Javadoc)
274    * 
275    * @see jalview.jbgui.GWsPreferences#editWsUrl_actionPerformed(java.awt.event.
276    * ActionEvent)
277    */
278   @Override
279   protected void editWsUrl_actionPerformed(ActionEvent e)
280   {
281     int sel = wsList.getSelectedRow();
282     if (sel > -1)
283     {
284       String url = editUrl(wsUrls.get(sel),
285               MessageManager.getString("label.edit_jabaws_url"));
286       if (url != null)
287       {
288         int present = wsUrls.indexOf(url);
289         if (present == -1)
290         {
291           update++;
292           wsUrls.set(sel, url);
293           updateList();
294         }
295         else
296         {
297           if (present != sel)
298           {
299             wsUrls.remove(sel);
300             updateList();
301           }
302         }
303       }
304     }
305   }
306
307   @Override
308   protected void newSbrsUrl_actionPerformed(ActionEvent e)
309   {
310     RestServiceEditorPane rse = new RestServiceEditorPane();
311     rse.showDialog(MessageManager.getString("label.add_new_sbrs_service"));
312     String rservice = rse.getEditedRestService();
313     if (rservice != null && !rsbsUrls.contains(rservice))
314     {
315       rsbsUrls.add(rservice);
316       update++;
317       updateRsbsList();
318     }
319   }
320
321   @Override
322   protected void editSbrsUrl_actionPerformed(ActionEvent e)
323   {
324     int sel = sbrsList.getSelectedIndex();
325     if (sel > -1)
326     {
327       RestServiceEditorPane rse = new RestServiceEditorPane(
328               new RestServiceDescription(rsbsUrls.elementAt(sel)));
329       rse.showDialog(MessageManager.getString("label.edit_sbrs_entry"));
330       String rservice = rse.getEditedRestService();
331       if (rservice != null)
332       {
333         int present = rsbsUrls.indexOf(rservice);
334         if (present == -1)
335         {
336           update++;
337           rsbsUrls.setElementAt(rservice, sel);
338           updateRsbsList();
339         }
340         else
341         {
342           if (present != sel)
343           {
344             rsbsUrls.removeElementAt(sel);
345             update++;
346             updateRsbsList();
347           }
348         }
349       }
350     }
351   }
352
353   void updateWsMenuConfig(boolean old)
354   {
355     if (old)
356     {
357       if (oldUrls != wsUrls || (wsUrls != null && oldUrls != null
358               && !wsUrls.equals(oldUrls)))
359       {
360         update++;
361       }
362       wsUrls = (oldUrls == null) ? null : new Vector(oldUrls);
363       if (oldRsbsUrls != rsbsUrls || (rsbsUrls != null
364               && oldRsbsUrls != null && !oldRsbsUrls.equals(rsbsUrls)))
365       {
366         update++;
367       }
368       oldRsbsUrls = (oldRsbsUrls == null) ? null : new Vector(oldRsbsUrls);
369     }
370     else
371     {
372
373     }
374     Cache.setProperty("SHOW_ENFIN_SERVICES",
375             Boolean.valueOf(
376                     old ? oldEnfin : enableEnfinServices.isSelected())
377                     .toString());
378     Cache.setProperty("SHOW_JWS2_SERVICES",
379             Boolean.valueOf(old ? oldJws2 : enableJws2Services.isSelected())
380                     .toString());
381     Cache.setProperty("WSMENU_BYHOST",
382             Boolean.valueOf(old ? oldIndexByHost : indexByHost.isSelected())
383                     .toString());
384     Cache.setProperty("WSMENU_BYTYPE",
385             Boolean.valueOf(old ? oldIndexByType : indexByType.isSelected())
386                     .toString());
387
388     Cache.setProperty("SHOW_WSDISCOVERY_ERRORS",
389             Boolean.valueOf(
390                     old ? oldWsWarning : displayWsWarning.isSelected())
391                     .toString());
392     updateServiceList();
393     updateRsbsServiceList();
394   }
395
396   /*
397    * (non-Javadoc)
398    * 
399    * @see
400    * jalview.jbgui.GWsPreferences#moveWsUrlDown_actionPerformed(java.awt.event
401    * .ActionEvent)
402    */
403   @Override
404   protected void moveWsUrlDown_actionPerformed(ActionEvent e)
405   {
406     int p = wsList.getSelectedRow();
407     if (p > -1 && p < wsUrls.size() - 1)
408     {
409       String t = wsUrls.get(p + 1);
410       wsUrls.set(p + 1, wsUrls.get(p));
411       wsUrls.set(p, t);
412       updateList();
413       wsList.getSelectionModel().setSelectionInterval(p + 1, p + 1);
414       update++;
415     }
416   }
417
418   /*
419    * (non-Javadoc)
420    * 
421    * @see
422    * jalview.jbgui.GWsPreferences#moveWsUrlUp_actionPerformed(java.awt.event
423    * .ActionEvent)
424    */
425   @Override
426   protected void moveWsUrlUp_actionPerformed(ActionEvent e)
427   {
428     int p = wsList.getSelectedRow();
429     if (p > 0)
430     {
431       String t = wsUrls.get(p - 1);
432       wsUrls.set(p - 1, wsUrls.get(p));
433       wsUrls.set(p, t);
434       updateList();
435       wsList.getSelectionModel().setSelectionInterval(p - 1, p - 1);
436       update++;
437     }
438   }
439
440   private String editUrl(String initUrl, String title)
441   {
442     String url = initUrl;
443     URL foo = null;
444     if (url == null)
445     {
446       url = "";
447     }
448     JTextField urltf = new JTextField(url, 40);
449     JPanel panel = new JPanel(new BorderLayout());
450     JPanel pane12 = new JPanel(new BorderLayout());
451     pane12.add(new JLabel(MessageManager.getString("label.url:")),
452             BorderLayout.CENTER);
453     pane12.add(urltf, BorderLayout.EAST);
454     panel.add(pane12, BorderLayout.NORTH);
455     boolean valid = false;
456     int resp = JvOptionPane.CANCEL_OPTION;
457     while (!valid && (resp = JvOptionPane.showInternalConfirmDialog(
458             Desktop.getDesktopPane(), panel, title,
459             JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.OK_OPTION)
460     {
461       try
462       {
463         // TODO: do a better job of checking that the url is a valid discovery
464         // URL for web services.
465         String tx = urltf.getText().trim();
466         while (tx.length() > 0 && tx.lastIndexOf('/') == tx.length() - 1)
467         {
468           tx = tx.substring(0, tx.length() - 1);
469         }
470         foo = new URL(tx);
471         valid = true;
472         urltf.setText(tx);
473       } catch (Exception e)
474       {
475         valid = false;
476         JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
477                 MessageManager.getString("label.invalid_url"));
478       }
479     }
480     if (valid && resp == JvOptionPane.OK_OPTION)
481     {
482       int validate = JvOptionPane.showInternalConfirmDialog(Desktop.getDesktopPane(),
483               MessageManager.getString("info.validate_jabaws_server"),
484               MessageManager.getString("label.test_server"),
485               JvOptionPane.YES_NO_OPTION);
486
487       if (validate == JvOptionPane.OK_OPTION)
488       {
489         if (Jws2Discoverer.testServiceUrl(foo))
490         {
491           return foo.toString();
492         }
493         else
494         {
495           int opt = JvOptionPane.showInternalOptionDialog(Desktop.getDesktopPane(),
496                   "The Server  '" + foo.toString()
497                           + "' failed validation,\ndo you want to add it anyway? ",
498                   "Server Validation Failed", JvOptionPane.YES_NO_OPTION,
499                   JvOptionPane.INFORMATION_MESSAGE, null, null, null);
500           if (opt == JvOptionPane.YES_OPTION)
501           {
502             return foo.toString();
503           }
504           else
505           {
506             JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
507                     MessageManager.getString(
508                             "warn.server_didnt_pass_validation"));
509           }
510
511         }
512       }
513       else
514       {
515         // just return the URL anyway
516         return foo.toString();
517       }
518     }
519     return initUrl;
520   }
521
522   /*
523    * (non-Javadoc)
524    * 
525    * @see jalview.jbgui.GWsPreferences#newWsUrl_actionPerformed(java.awt.event.
526    * ActionEvent)
527    */
528   @Override
529   protected void newWsUrl_actionPerformed(ActionEvent e)
530   {
531     String url = editUrl(null,
532             MessageManager.getString("label.add_jabaws_url"));
533     if (url != null)
534     {
535       if (!wsUrls.contains(url))
536       {
537         int selind = wsList.getSelectedRow();
538         if (selind > -1)
539         {
540           wsUrls.add(selind, url);
541         }
542         else
543         {
544           wsUrls.add(url);
545         }
546         update++;
547         updateList();
548       }
549     }
550   }
551
552   /*
553    * (non-Javadoc)
554    * 
555    * @see jalview.jbgui.GWsPreferences#refreshWs_actionPerformed(java.awt.event.
556    * ActionEvent)
557    */
558   @Override
559   protected void refreshWs_actionPerformed(ActionEvent e)
560   {
561     new Thread(new Runnable()
562     {
563
564       @Override
565       public void run()
566       {
567         // force a refresh.
568         lastrefresh = update - 1;
569         updateWsMenuConfig(false);
570         refreshWsMenu(true);
571       }
572     }).start();
573
574   }
575
576   /**
577    * Refresh the web services menus - but only if there has been a change in the
578    * configuration (indicated by update!=lastrefresh)
579    * 
580    * @param showProgress
581    *          show progress in dialog or on desktop
582    */
583   protected void refreshWsMenu(boolean showProgress)
584   {
585     if (showProgress)
586     {
587       new Thread(new Runnable()
588       {
589
590         @Override
591         public void run()
592         {
593           progressBar.setVisible(true);
594           validate();
595           progressBar.setIndeterminate(true);
596           if (lastrefresh != update)
597           {
598             lastrefresh = update;
599             Instance.getDesktop().startServiceDiscovery(true); // wait around for all
600                                                           // threads to complete
601             updateList();
602
603           }
604           progressBar.setIndeterminate(false);
605           progressBar.setVisible(false);
606           validate();
607         }
608       }).start();
609
610     }
611     else
612     {
613       new Thread(new Runnable()
614       {
615
616         @Override
617         public void run()
618         {
619           long ct = System.currentTimeMillis();
620           Instance.getDesktop().setProgressBar(MessageManager
621                   .getString("status.refreshing_web_service_menus"), ct);
622           if (lastrefresh != update)
623           {
624             lastrefresh = update;
625             Instance.getDesktop().startServiceDiscovery(true);
626             updateList();
627           }
628           Instance.getDesktop().setProgressBar(null, ct);
629         }
630
631       }).start();
632     }
633   }
634
635   /**
636    * state counters for ensuring that updates only happen if config has changed.
637    */
638   private long update = 0, lastrefresh = 0;
639
640   /*
641    * (non-Javadoc)
642    * 
643    * @see
644    * jalview.jbgui.GWsPreferences#resetWs_actionPerformed(java.awt.event.ActionEvent
645    * )
646    */
647   @Override
648   protected void resetWs_actionPerformed(ActionEvent e)
649   {
650     Jws2Discoverer.getDiscoverer().setServiceUrls(null);
651     List<String> nwsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
652     if (!wsUrls.equals(nwsUrls))
653     {
654       update++;
655     }
656     wsUrls = nwsUrls;
657     updateList();
658
659     updateAndRefreshWsMenuConfig(true);
660   }
661
662   protected void ok_ActionPerformed(ActionEvent e)
663   {
664     // update everything regardless.
665     updateAndRefreshWsMenuConfig(false);
666   }
667
668   public void updateAndRefreshWsMenuConfig(
669           final boolean showProgressInDialog)
670   {
671     new Thread(new Runnable()
672     {
673
674       @Override
675       public void run()
676       {
677         updateWsMenuConfig(false);
678         refreshWsMenu(showProgressInDialog);
679       }
680     }).start();
681
682   }
683 }