JAL-2416 order score models by order of addition rather than name
[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(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 = JvOptionPane.CANCEL_OPTION;
463     while (!valid
464             && (resp = JvOptionPane.showInternalConfirmDialog(
465                     Desktop.desktop, panel, title,
466                     JvOptionPane.OK_CANCEL_OPTION)) == JvOptionPane.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         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
484                 MessageManager.getString("label.invalid_url"));
485       }
486     }
487     if (valid && resp == JvOptionPane.OK_OPTION)
488     {
489       int validate = JvOptionPane.showInternalConfirmDialog(Desktop.desktop,
490               MessageManager.getString("info.validate_jabaws_server"),
491               MessageManager.getString("label.test_server"),
492               JvOptionPane.YES_NO_OPTION);
493
494       if (validate == JvOptionPane.OK_OPTION)
495       {
496         if (Jws2Discoverer.testServiceUrl(foo))
497         {
498           return foo.toString();
499         }
500         else
501         {
502           int opt = JvOptionPane
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                           JvOptionPane.YES_NO_OPTION,
510                           JvOptionPane.INFORMATION_MESSAGE, null, null, null);
511           if (opt == JvOptionPane.YES_OPTION)
512           {
513             return foo.toString();
514           }
515           else
516           {
517             JvOptionPane
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       @Override
578       public void run()
579       {
580         // force a refresh.
581         lastrefresh = update - 1;
582         updateWsMenuConfig(false);
583         refreshWsMenu(true);
584       }
585     }).start();
586
587   }
588
589   /**
590    * Refresh the web services menus - but only if there has been a change in the
591    * configuration (indicated by update!=lastrefresh)
592    * 
593    * @param showProgress
594    *          show progress in dialog or on desktop
595    */
596   protected void refreshWsMenu(boolean showProgress)
597   {
598     if (showProgress)
599     {
600       new Thread(new Runnable()
601       {
602
603         @Override
604         public void run()
605         {
606           progressBar.setVisible(true);
607           validate();
608           progressBar.setIndeterminate(true);
609           if (lastrefresh != update)
610           {
611             lastrefresh = update;
612             Desktop.instance.startServiceDiscovery(true); // wait around for all
613                                                           // threads to complete
614             updateList();
615
616           }
617           progressBar.setIndeterminate(false);
618           progressBar.setVisible(false);
619           validate();
620         }
621       }).start();
622
623     }
624     else
625     {
626       new Thread(new Runnable()
627       {
628
629         @Override
630         public void run()
631         {
632           long ct = System.currentTimeMillis();
633           Desktop.instance.setProgressBar(MessageManager
634                   .getString("status.refreshing_web_service_menus"), ct);
635           if (lastrefresh != update)
636           {
637             lastrefresh = update;
638             Desktop.instance.startServiceDiscovery(true);
639             updateList();
640           }
641           Desktop.instance.setProgressBar(null, ct);
642         }
643
644       }).start();
645     }
646   }
647
648   /**
649    * state counters for ensuring that updates only happen if config has changed.
650    */
651   private long update = 0, lastrefresh = 0;
652
653   /*
654    * (non-Javadoc)
655    * 
656    * @see
657    * jalview.jbgui.GWsPreferences#resetWs_actionPerformed(java.awt.event.ActionEvent
658    * )
659    */
660   @Override
661   protected void resetWs_actionPerformed(ActionEvent e)
662   {
663     Jws2Discoverer.getDiscoverer().setServiceUrls(null);
664     List<String> nwsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
665     if (!wsUrls.equals(nwsUrls))
666     {
667       update++;
668     }
669     wsUrls = nwsUrls;
670     updateList();
671
672     updateAndRefreshWsMenuConfig(true);
673   }
674
675   protected void ok_ActionPerformed(ActionEvent e)
676   {
677     // update everything regardless.
678     updateAndRefreshWsMenuConfig(false);
679   }
680
681   public void updateAndRefreshWsMenuConfig(
682           final boolean showProgressInDialog)
683   {
684     new Thread(new Runnable()
685     {
686
687       @Override
688       public void run()
689       {
690         updateWsMenuConfig(false);
691         refreshWsMenu(showProgressInDialog);
692       }
693     }).start();
694
695   }
696 }