JAL-2069 ensure threshline instantiated to avoid NPE
[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 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(
93             oldEnfin = Cache.getDefault("SHOW_ENFIN_SERVICES", true));
94     enableEnfinServices.addActionListener(updateAction);
95     enableJws2Services.setSelected(
96             oldJws2 = Cache.getDefault("SHOW_JWS2_SERVICES", true));
97     enableJws2Services.addActionListener(updateAction);
98     indexByHost.setSelected(
99             oldIndexByHost = Cache.getDefault("WSMENU_BYHOST", false));
100     indexByHost.addActionListener(updateAction);
101     indexByType.setSelected(
102             oldIndexByType = Cache.getDefault("WSMENU_BYTYPE", false));
103     indexByType.addActionListener(updateAction);
104     displayWsWarning.setSelected(oldWsWarning = Cache
105             .getDefault("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"))
132             .setMinWidth(10);
133   }
134
135   private class JabaWSStatusRenderer extends JPanel
136           implements 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 || (wsUrls != null && oldUrls != null
357               && !wsUrls.equals(oldUrls)))
358       {
359         update++;
360       }
361       wsUrls = (oldUrls == null) ? null : new Vector(oldUrls);
362       if (oldRsbsUrls != rsbsUrls || (rsbsUrls != null
363               && oldRsbsUrls != null && !oldRsbsUrls.equals(rsbsUrls)))
364       {
365         update++;
366       }
367       oldRsbsUrls = (oldRsbsUrls == null) ? null : new Vector(oldRsbsUrls);
368     }
369     else
370     {
371
372     }
373     Cache.setProperty("SHOW_ENFIN_SERVICES",
374             Boolean.valueOf(
375                     old ? oldEnfin : enableEnfinServices.isSelected())
376                     .toString());
377     Cache.setProperty("SHOW_JWS2_SERVICES",
378             Boolean.valueOf(old ? oldJws2 : enableJws2Services.isSelected())
379                     .toString());
380     Cache.setProperty("WSMENU_BYHOST",
381             Boolean.valueOf(old ? oldIndexByHost : indexByHost.isSelected())
382                     .toString());
383     Cache.setProperty("WSMENU_BYTYPE",
384             Boolean.valueOf(old ? oldIndexByType : indexByType.isSelected())
385                     .toString());
386
387     Cache.setProperty("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.set(p + 1, wsUrls.get(p));
410       wsUrls.set(p, t);
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.set(p - 1, wsUrls.get(p));
432       wsUrls.set(p, t);
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:")),
451             BorderLayout.CENTER);
452     pane12.add(urltf, BorderLayout.EAST);
453     panel.add(pane12, BorderLayout.NORTH);
454     boolean valid = false;
455     int resp = JvOptionPane.CANCEL_OPTION;
456     while (!valid && (resp = JvOptionPane.showInternalConfirmDialog(
457             Desktop.desktop, panel, title,
458             JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.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         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
476                 MessageManager.getString("label.invalid_url"));
477       }
478     }
479     if (valid && resp == JvOptionPane.OK_OPTION)
480     {
481       int validate = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
482               MessageManager.getString("info.validate_jabaws_server"),
483               MessageManager.getString("label.test_server"),
484               JvOptionPane.YES_NO_OPTION);
485
486       if (validate == JvOptionPane.OK_OPTION)
487       {
488         if (Jws2Discoverer.testServiceUrl(foo))
489         {
490           return foo.toString();
491         }
492         else
493         {
494           int opt = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
495                   "The Server  '" + foo.toString()
496                           + "' failed validation,\ndo you want to add it anyway? ",
497                   "Server Validation Failed", JvOptionPane.YES_NO_OPTION,
498                   JvOptionPane.INFORMATION_MESSAGE, null, null, null);
499           if (opt == JvOptionPane.YES_OPTION)
500           {
501             return foo.toString();
502           }
503           else
504           {
505             JvOptionPane.showInternalMessageDialog(Desktop.desktop,
506                     MessageManager.getString(
507                             "warn.server_didnt_pass_validation"));
508           }
509
510         }
511       }
512       else
513       {
514         // just return the URL anyway
515         return foo.toString();
516       }
517     }
518     return initUrl;
519   }
520
521   /*
522    * (non-Javadoc)
523    * 
524    * @see jalview.jbgui.GWsPreferences#newWsUrl_actionPerformed(java.awt.event.
525    * ActionEvent)
526    */
527   @Override
528   protected void newWsUrl_actionPerformed(ActionEvent e)
529   {
530     String url = editUrl(null,
531             MessageManager.getString("label.add_jabaws_url"));
532     if (url != null)
533     {
534       if (!wsUrls.contains(url))
535       {
536         int selind = wsList.getSelectedRow();
537         if (selind > -1)
538         {
539           wsUrls.add(selind, url);
540         }
541         else
542         {
543           wsUrls.add(url);
544         }
545         update++;
546         updateList();
547       }
548     }
549   }
550
551   /*
552    * (non-Javadoc)
553    * 
554    * @see jalview.jbgui.GWsPreferences#refreshWs_actionPerformed(java.awt.event.
555    * ActionEvent)
556    */
557   @Override
558   protected void refreshWs_actionPerformed(ActionEvent e)
559   {
560     new Thread(new Runnable()
561     {
562
563       @Override
564       public void run()
565       {
566         // force a refresh.
567         lastrefresh = update - 1;
568         updateWsMenuConfig(false);
569         refreshWsMenu(true);
570       }
571     }).start();
572
573   }
574
575   /**
576    * Refresh the web services menus - but only if there has been a change in the
577    * configuration (indicated by update!=lastrefresh)
578    * 
579    * @param showProgress
580    *          show progress in dialog or on desktop
581    */
582   protected void refreshWsMenu(boolean showProgress)
583   {
584     if (showProgress)
585     {
586       new Thread(new Runnable()
587       {
588
589         @Override
590         public void run()
591         {
592           progressBar.setVisible(true);
593           validate();
594           progressBar.setIndeterminate(true);
595           if (lastrefresh != update)
596           {
597             lastrefresh = update;
598             Desktop.instance.startServiceDiscovery(true); // wait around for all
599                                                           // threads to complete
600             updateList();
601
602           }
603           progressBar.setIndeterminate(false);
604           progressBar.setVisible(false);
605           validate();
606         }
607       }).start();
608
609     }
610     else
611     {
612       new Thread(new Runnable()
613       {
614
615         @Override
616         public void run()
617         {
618           long ct = System.currentTimeMillis();
619           Desktop.instance.setProgressBar(MessageManager
620                   .getString("status.refreshing_web_service_menus"), ct);
621           if (lastrefresh != update)
622           {
623             lastrefresh = update;
624             Desktop.instance.startServiceDiscovery(true);
625             updateList();
626           }
627           Desktop.instance.setProgressBar(null, ct);
628         }
629
630       }).start();
631     }
632   }
633
634   /**
635    * state counters for ensuring that updates only happen if config has changed.
636    */
637   private long update = 0, lastrefresh = 0;
638
639   /*
640    * (non-Javadoc)
641    * 
642    * @see
643    * jalview.jbgui.GWsPreferences#resetWs_actionPerformed(java.awt.event.ActionEvent
644    * )
645    */
646   @Override
647   protected void resetWs_actionPerformed(ActionEvent e)
648   {
649     Jws2Discoverer.getDiscoverer().setServiceUrls(null);
650     List<String> nwsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
651     if (!wsUrls.equals(nwsUrls))
652     {
653       update++;
654     }
655     wsUrls = nwsUrls;
656     updateList();
657
658     updateAndRefreshWsMenuConfig(true);
659   }
660
661   protected void ok_ActionPerformed(ActionEvent e)
662   {
663     // update everything regardless.
664     updateAndRefreshWsMenuConfig(false);
665   }
666
667   public void updateAndRefreshWsMenuConfig(
668           final boolean showProgressInDialog)
669   {
670     new Thread(new Runnable()
671     {
672
673       @Override
674       public void run()
675       {
676         updateWsMenuConfig(false);
677         refreshWsMenu(showProgressInDialog);
678       }
679     }).start();
680
681   }
682 }