Merge branch 'JAL-3878_ws-overhaul-3' into with_ws_overhaul-3
[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
24 import java.awt.BorderLayout;
25 import java.awt.Color;
26 import java.awt.Component;
27 import java.awt.Dimension;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.net.URL;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Vector;
34
35 import javax.swing.JLabel;
36 import javax.swing.JPanel;
37 import javax.swing.JTable;
38 import javax.swing.JTextField;
39 import javax.swing.table.AbstractTableModel;
40 import javax.swing.table.TableCellRenderer;
41 import jalview.bin.Cache;
42 import jalview.jbgui.GWsPreferences;
43 import jalview.util.MessageManager;
44 import jalview.ws.WSDiscovererI;
45 import jalview.ws.jws2.Jws2Discoverer;
46 import jalview.ws.rest.RestServiceDescription;
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.getInstance().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.getInstance().getServerStatusFor(url);
127       tdat[r][1] = Integer.valueOf(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 WSDiscovererI.STATUS_OK:
161         // cb.setSelected(true);
162         // cb.setBackground(
163         c = Color.green;
164         break;
165       case WSDiscovererI.STATUS_NO_SERVICES:
166         // cb.setSelected(true);
167         // cb.setBackground(
168         c = Color.lightGray;
169         break;
170       case WSDiscovererI.STATUS_INVALID:
171         // cb.setSelected(false);
172         // cb.setBackground(
173         c = Color.red;
174         break;
175       case WSDiscovererI.STATUS_UNKNOWN:
176       default:
177         // cb.setSelected(false);
178         // cb.setBackground(
179         c = Color.orange;
180       }
181       setBackground(c);
182       // setText(t);
183       return this;
184
185     }
186
187   }
188
189   private class WsUrlTableModel extends AbstractTableModel
190   {
191
192     private Object[][] data;
193
194     private String[] columnNames = new String[] {
195         MessageManager.getString("label.service_url"),
196         MessageManager.getString("label.status") };
197
198     public WsUrlTableModel(Object[][] tdat)
199     {
200       this.data = tdat;
201     }
202
203     @Override
204     public int getColumnCount()
205     {
206       return 2;
207     }
208
209     @Override
210     public String getColumnName(int column)
211     {
212       return columnNames[column];
213     }
214
215     @Override
216     public int getRowCount()
217     {
218       if (data == null)
219       {
220         return 0;
221       }
222       return data.length;
223     }
224
225     @Override
226     public java.lang.Class<?> getColumnClass(int columnIndex)
227     {
228       return getValueAt(0, columnIndex).getClass();
229     };
230
231     @Override
232     public Object getValueAt(int rowIndex, int columnIndex)
233     {
234       return data[rowIndex][columnIndex];
235     }
236
237   }
238
239   private void updateRsbsList()
240   {
241     sbrsList.setListData(rsbsUrls);
242   }
243
244   private void updateServiceList()
245   {
246     Jws2Discoverer.getInstance().setServiceUrls(wsUrls);
247   }
248
249   private void updateRsbsServiceList()
250   {
251     jalview.ws.rest.RestClient.setRsbsServices(rsbsUrls);
252   }
253
254   /*
255    * (non-Javadoc)
256    * 
257    * @see
258    * jalview.jbgui.GWsPreferences#deleteWsUrl_actionPerformed(java.awt.event
259    * .ActionEvent)
260    */
261   @Override
262   protected void deleteWsUrl_actionPerformed(ActionEvent e)
263   {
264     int sel = wsList.getSelectedRow();
265     if (sel > -1)
266     {
267       wsUrls.remove(sel);
268       update++;
269       updateList();
270     }
271   }
272
273   /*
274    * (non-Javadoc)
275    * 
276    * @see jalview.jbgui.GWsPreferences#editWsUrl_actionPerformed(java.awt.event.
277    * ActionEvent)
278    */
279   @Override
280   protected void editWsUrl_actionPerformed(ActionEvent e)
281   {
282     int sel = wsList.getSelectedRow();
283     if (sel > -1)
284     {
285       String url = editUrl(wsUrls.get(sel),
286               MessageManager.getString("label.edit_jabaws_url"));
287       if (url != null)
288       {
289         int present = wsUrls.indexOf(url);
290         if (present == -1)
291         {
292           update++;
293           wsUrls.set(sel, url);
294           updateList();
295         }
296         else
297         {
298           if (present != sel)
299           {
300             wsUrls.remove(sel);
301             updateList();
302           }
303         }
304       }
305     }
306   }
307
308   @Override
309   protected void newSbrsUrl_actionPerformed(ActionEvent e)
310   {
311     RestServiceEditorPane rse = new RestServiceEditorPane();
312     rse.showDialog(MessageManager.getString("label.add_new_sbrs_service"));
313     String rservice = rse.getEditedRestService();
314     if (rservice != null && !rsbsUrls.contains(rservice))
315     {
316       rsbsUrls.add(rservice);
317       update++;
318       updateRsbsList();
319     }
320   }
321
322   @Override
323   protected void editSbrsUrl_actionPerformed(ActionEvent e)
324   {
325     int sel = sbrsList.getSelectedIndex();
326     if (sel > -1)
327     {
328       RestServiceEditorPane rse = new RestServiceEditorPane(
329               new RestServiceDescription(rsbsUrls.elementAt(sel)));
330       rse.showDialog(MessageManager.getString("label.edit_sbrs_entry"));
331       String rservice = rse.getEditedRestService();
332       if (rservice != null)
333       {
334         int present = rsbsUrls.indexOf(rservice);
335         if (present == -1)
336         {
337           update++;
338           rsbsUrls.setElementAt(rservice, sel);
339           updateRsbsList();
340         }
341         else
342         {
343           if (present != sel)
344           {
345             rsbsUrls.removeElementAt(sel);
346             update++;
347             updateRsbsList();
348           }
349         }
350       }
351     }
352   }
353
354   void updateWsMenuConfig(boolean old)
355   {
356     if (old)
357     {
358       if (oldUrls != wsUrls || (wsUrls != null && oldUrls != null
359               && !wsUrls.equals(oldUrls)))
360       {
361         update++;
362       }
363       wsUrls = (oldUrls == null) ? null : new Vector(oldUrls);
364       if (oldRsbsUrls != rsbsUrls || (rsbsUrls != null
365               && oldRsbsUrls != null && !oldRsbsUrls.equals(rsbsUrls)))
366       {
367         update++;
368       }
369       oldRsbsUrls = (oldRsbsUrls == null) ? null : new Vector(oldRsbsUrls);
370     }
371     else
372     {
373
374     }
375     Cache.setProperty("SHOW_ENFIN_SERVICES",
376             Boolean.valueOf(
377                     old ? oldEnfin : enableEnfinServices.isSelected())
378                     .toString());
379     Cache.setProperty("SHOW_JWS2_SERVICES",
380             Boolean.valueOf(old ? oldJws2 : enableJws2Services.isSelected())
381                     .toString());
382     Cache.setProperty("WSMENU_BYHOST",
383             Boolean.valueOf(old ? oldIndexByHost : indexByHost.isSelected())
384                     .toString());
385     Cache.setProperty("WSMENU_BYTYPE",
386             Boolean.valueOf(old ? oldIndexByType : indexByType.isSelected())
387                     .toString());
388
389     Cache.setProperty("SHOW_WSDISCOVERY_ERRORS",
390             Boolean.valueOf(
391                     old ? oldWsWarning : displayWsWarning.isSelected())
392                     .toString());
393     updateServiceList();
394     updateRsbsServiceList();
395   }
396
397   /*
398    * (non-Javadoc)
399    * 
400    * @see
401    * jalview.jbgui.GWsPreferences#moveWsUrlDown_actionPerformed(java.awt.event
402    * .ActionEvent)
403    */
404   @Override
405   protected void moveWsUrlDown_actionPerformed(ActionEvent e)
406   {
407     int p = wsList.getSelectedRow();
408     if (p > -1 && p < wsUrls.size() - 1)
409     {
410       String t = wsUrls.get(p + 1);
411       wsUrls.set(p + 1, wsUrls.get(p));
412       wsUrls.set(p, t);
413       updateList();
414       wsList.getSelectionModel().setSelectionInterval(p + 1, p + 1);
415       update++;
416     }
417   }
418
419   /*
420    * (non-Javadoc)
421    * 
422    * @see
423    * jalview.jbgui.GWsPreferences#moveWsUrlUp_actionPerformed(java.awt.event
424    * .ActionEvent)
425    */
426   @Override
427   protected void moveWsUrlUp_actionPerformed(ActionEvent e)
428   {
429     int p = wsList.getSelectedRow();
430     if (p > 0)
431     {
432       String t = wsUrls.get(p - 1);
433       wsUrls.set(p - 1, wsUrls.get(p));
434       wsUrls.set(p, t);
435       updateList();
436       wsList.getSelectionModel().setSelectionInterval(p - 1, p - 1);
437       update++;
438     }
439   }
440
441   private String editUrl(String initUrl, String title)
442   {
443     String url = initUrl;
444     URL foo = null;
445     if (url == null)
446     {
447       url = "";
448     }
449     JTextField urltf = new JTextField(url, 40);
450     JPanel panel = new JPanel(new BorderLayout());
451     JPanel pane12 = new JPanel(new BorderLayout());
452     pane12.add(new JLabel(MessageManager.getString("label.url:")),
453             BorderLayout.CENTER);
454     pane12.add(urltf, BorderLayout.EAST);
455     panel.add(pane12, BorderLayout.NORTH);
456     boolean valid = false;
457     int resp = JvOptionPane.CANCEL_OPTION;
458     while (!valid && (resp = JvOptionPane.showInternalConfirmDialog(
459             Desktop.getDesktopPane(), panel, title,
460             JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.OK_OPTION)
461     {
462       try
463       {
464         // TODO: do a better job of checking that the url is a valid discovery
465         // URL for web services.
466         String tx = urltf.getText().trim();
467         while (tx.length() > 0 && tx.lastIndexOf('/') == tx.length() - 1)
468         {
469           tx = tx.substring(0, tx.length() - 1);
470         }
471         foo = new URL(tx);
472         valid = true;
473         urltf.setText(tx);
474       } catch (Exception e)
475       {
476         valid = false;
477         JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
478                 MessageManager.getString("label.invalid_url"));
479       }
480     }
481     if (valid && resp == JvOptionPane.OK_OPTION)
482     {
483       int validate = JvOptionPane.showInternalConfirmDialog(Desktop.getDesktopPane(),
484               MessageManager.getString("info.validate_jabaws_server"),
485               MessageManager.getString("label.test_server"),
486               JvOptionPane.YES_NO_OPTION);
487
488       if (validate == JvOptionPane.OK_OPTION)
489       {
490         if (Jws2Discoverer.getInstance().testServiceUrl(foo))
491         {
492           return foo.toString();
493         }
494         else
495         {
496           int opt = JvOptionPane.showInternalOptionDialog(Desktop.getDesktopPane(),
497                   "The Server  '" + foo.toString()
498                           + "' failed validation,\ndo you want to add it anyway? ",
499                   "Server Validation Failed", JvOptionPane.YES_NO_OPTION,
500                   JvOptionPane.INFORMATION_MESSAGE, null, null, null);
501           if (opt == JvOptionPane.YES_OPTION)
502           {
503             return foo.toString();
504           }
505           else
506           {
507             JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
508                     MessageManager.getString(
509                             "warn.server_didnt_pass_validation"));
510           }
511
512         }
513       }
514       else
515       {
516         // just return the URL anyway
517         return foo.toString();
518       }
519     }
520     return initUrl;
521   }
522
523   /*
524    * (non-Javadoc)
525    * 
526    * @see jalview.jbgui.GWsPreferences#newWsUrl_actionPerformed(java.awt.event.
527    * ActionEvent)
528    */
529   @Override
530   protected void newWsUrl_actionPerformed(ActionEvent e)
531   {
532     String url = editUrl(null,
533             MessageManager.getString("label.add_jabaws_url"));
534     if (url != null)
535     {
536       if (!wsUrls.contains(url))
537       {
538         int selind = wsList.getSelectedRow();
539         if (selind > -1)
540         {
541           wsUrls.add(selind, url);
542         }
543         else
544         {
545           wsUrls.add(url);
546         }
547         update++;
548         updateList();
549       }
550     }
551   }
552
553   /*
554    * (non-Javadoc)
555    * 
556    * @see jalview.jbgui.GWsPreferences#refreshWs_actionPerformed(java.awt.event.
557    * ActionEvent)
558    */
559   @Override
560   protected void refreshWs_actionPerformed(ActionEvent e)
561   {
562     new Thread(new Runnable()
563     {
564
565       @Override
566       public void run()
567       {
568         // force a refresh.
569         lastrefresh = update - 1;
570         updateWsMenuConfig(false);
571         refreshWsMenu(true);
572       }
573     }).start();
574
575   }
576
577   /**
578    * Refresh the web services menus - but only if there has been a change in the
579    * configuration (indicated by update!=lastrefresh)
580    * 
581    * @param showProgress
582    *          show progress in dialog or on desktop
583    */
584   protected void refreshWsMenu(boolean showProgress)
585   {
586     if (showProgress)
587     {
588       new Thread(new Runnable()
589       {
590
591         @Override
592         public void run()
593         {
594           progressBar.setVisible(true);
595           validate();
596           progressBar.setIndeterminate(true);
597           if (lastrefresh != update)
598           {
599             lastrefresh = update;
600             Desktop.getInstance().startServiceDiscovery(true); // wait around for all
601                                                           // threads to complete
602             updateList();
603
604           }
605           progressBar.setIndeterminate(false);
606           progressBar.setVisible(false);
607           validate();
608         }
609       }).start();
610
611     }
612     else
613     {
614       new Thread(new Runnable()
615       {
616
617         @Override
618         public void run()
619         {
620           long ct = System.currentTimeMillis();
621           Desktop.getInstance().setProgressBar(MessageManager
622                   .getString("status.refreshing_web_service_menus"), ct);
623           if (lastrefresh != update)
624           {
625             lastrefresh = update;
626             Desktop.getInstance().startServiceDiscovery(true);
627             updateList();
628           }
629           Desktop.getInstance().setProgressBar(null, ct);
630         }
631
632       }).start();
633     }
634   }
635
636   /**
637    * state counters for ensuring that updates only happen if config has changed.
638    */
639   private long update = 0, lastrefresh = 0;
640
641   /*
642    * (non-Javadoc)
643    * 
644    * @see
645    * jalview.jbgui.GWsPreferences#resetWs_actionPerformed(java.awt.event.ActionEvent
646    * )
647    */
648   @Override
649   protected void resetWs_actionPerformed(ActionEvent e)
650   {
651     Jws2Discoverer.getInstance().setServiceUrls(null);
652     List<String> nwsUrls = Jws2Discoverer.getInstance().getServiceUrls();
653     if (!wsUrls.equals(nwsUrls))
654     {
655       update++;
656     }
657     wsUrls = nwsUrls;
658     updateList();
659
660     updateAndRefreshWsMenuConfig(true);
661   }
662
663   protected void ok_ActionPerformed(ActionEvent e)
664   {
665     // update everything regardless.
666     updateAndRefreshWsMenuConfig(false);
667   }
668
669   public void updateAndRefreshWsMenuConfig(
670           final boolean showProgressInDialog)
671   {
672     new Thread(new Runnable()
673     {
674
675       @Override
676       public void run()
677       {
678         updateWsMenuConfig(false);
679         refreshWsMenu(showProgressInDialog);
680       }
681     }).start();
682
683   }
684 }