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