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