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