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