JAL-1355 (basic i18n support)
[jalview.git] / src / jalview / ws / jws2 / SequenceAnnotationWSClient.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
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  */
18 package jalview.ws.jws2;
19
20 import jalview.api.AlignCalcWorkerI;
21 import jalview.bin.Cache;
22 import jalview.gui.AlignFrame;
23 import jalview.gui.Desktop;
24 import jalview.gui.JvSwingUtils;
25 import jalview.util.MessageManager;
26 import jalview.ws.jws2.dm.AAConSettings;
27 import jalview.ws.jws2.jabaws2.Jws2Instance;
28 import jalview.ws.params.WsParamSetI;
29 import jalview.ws.uimodel.AlignAnalysisUIText;
30
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.util.List;
34
35 import javax.swing.JCheckBoxMenuItem;
36 import javax.swing.JMenu;
37 import javax.swing.JMenuItem;
38 import javax.swing.JOptionPane;
39 import javax.swing.event.MenuEvent;
40 import javax.swing.event.MenuListener;
41
42 /**
43  * @author jprocter
44  * 
45  */
46 public class SequenceAnnotationWSClient extends Jws2Client
47 {
48   /**
49    * initialise a client so its attachWSMenuEntry method can be called.
50    */
51   public SequenceAnnotationWSClient()
52   {
53     // TODO Auto-generated constructor stub
54   }
55
56   public SequenceAnnotationWSClient(final Jws2Instance sh,
57           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
58   {
59     super(alignFrame, preset, null);
60     initSequenceAnnotationWSClient(sh, alignFrame, preset, editParams);
61   }
62
63   // dan think. Do I need to change this method to run RNAalifold through the GUI
64   
65   public void initSequenceAnnotationWSClient(final Jws2Instance sh,
66           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
67   {
68         // dan changed! dan test. comment out if conditional
69 //    if (alignFrame.getViewport().getAlignment().isNucleotide())
70 //    {
71 //      JOptionPane.showMessageDialog(Desktop.desktop, sh.serviceType
72 //              + " can only be used\nfor amino acid alignments.",
73 //              "Wrong type of sequences!", JOptionPane.WARNING_MESSAGE);
74 //      return;
75 //
76 //    }
77     AlignAnalysisUIText aaui = sh.getAlignAnalysisUI();
78     if (aaui!=null)
79     {
80       Class clientClass = aaui.getClient();
81       
82       // Build an AACon style client - take alignment, return annotation for
83       // columns
84
85       List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
86               .getCalcManager()
87               .getRegisteredWorkersOfClass(clientClass);
88       JabawsAlignCalcWorker worker;
89       if (clnts == null || clnts.size() == 0)
90       {
91         if (!processParams(sh, editParams))
92         {
93           return;
94         }
95         try {
96           worker = (JabawsAlignCalcWorker) (clientClass.getConstructor(
97                   new Class[] { Jws2Instance.class, 
98                           AlignFrame.class, WsParamSetI.class, 
99                           List.class }).newInstance(new Object[] { sh, alignFrame, this.preset, paramset}));
100         } catch (Exception x)
101         {
102           x.printStackTrace();
103           throw new Error("Implementation error",x);
104         }
105         alignFrame
106                 .getViewport()
107                 .getCalcManager()
108                 .registerWorker(
109                         worker);
110         alignFrame.getViewport().getCalcManager().startWorker(worker);
111
112       }
113       else
114       {
115         worker = (JabawsAlignCalcWorker) clnts.get(0);
116         if (editParams)
117         {
118           paramset = worker.getArguments();
119           preset = worker.getPreset();
120         }
121
122         if (!processParams(sh, editParams, true))
123         {
124           return;
125         }
126         // reinstate worker if it was blacklisted (might have happened due to
127         // invalid parameters)
128         alignFrame.getViewport().getCalcManager().workerMayRun(worker);
129         worker.updateParameters(this.preset, paramset);
130       }
131     }
132     if (sh.action.toLowerCase().contains("disorder"))
133     {
134       // build IUPred style client. take sequences, returns annotation per
135       // sequence.
136       if (!processParams(sh, editParams))
137       {
138         return;
139       }
140
141       alignFrame
142               .getViewport()
143               .getCalcManager()
144               .startWorker(
145                       new AADisorderClient(sh, alignFrame, preset, paramset));
146     }
147   }
148
149   public SequenceAnnotationWSClient(AAConSettings fave,
150           AlignFrame alignFrame, boolean b)
151   {
152     super(alignFrame, fave.getPreset(), fave.getJobArgset());
153     initSequenceAnnotationWSClient(fave.getService(), alignFrame,
154             fave.getPreset(), b);
155   }
156
157   /*
158    * (non-Javadoc)
159    * 
160    * @see jalview.ws.jws2.Jws2Client#attachWSMenuEntry(javax.swing.JMenu,
161    * jalview.ws.jws2.jabaws2.Jws2Instance, jalview.gui.AlignFrame)
162    */
163   public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
164           final AlignFrame alignFrame)
165   {
166     if (registerAAConWSInstance(wsmenu, service, alignFrame)) {
167       // Alignment dependent analysis calculation WS gui
168       return;
169     }
170     boolean hasparams = service.hasParameters();
171     // Assume name ends in WS
172     String calcName = service.serviceType.substring(0,
173             service.serviceType.length() - 2);
174
175     JMenuItem annotservice = new JMenuItem(MessageManager.formatMessage("label.calcname_with_default_settings", new String[]{calcName}));
176     annotservice.addActionListener(new ActionListener()
177     {
178
179       @Override
180       public void actionPerformed(ActionEvent e)
181       {
182         new SequenceAnnotationWSClient(service, alignFrame, null, false);
183       }
184     });
185     wsmenu.add(annotservice);
186     if (hasparams)
187     {
188       // only add these menu options if the service has user-modifiable
189       // arguments
190       annotservice = new JMenuItem(MessageManager.getString("label.edit_settings_and_run"));
191       annotservice
192               .setToolTipText(MessageManager.getString("label.view_and_change_parameters_before_running_calculation"));
193
194       annotservice.addActionListener(new ActionListener()
195       {
196         public void actionPerformed(ActionEvent e)
197         {
198           new SequenceAnnotationWSClient(service, alignFrame, null, true);
199         }
200       });
201       wsmenu.add(annotservice);
202       List<WsParamSetI> presets = service.getParamStore().getPresets();
203       if (presets != null && presets.size() > 0)
204       {
205         JMenu presetlist = new JMenu("Run " + calcName + "with preset");
206
207         for (final WsParamSetI preset : presets)
208         {
209           final JMenuItem methodR = new JMenuItem(preset.getName());
210           methodR.setToolTipText("<html><p>"
211                   + JvSwingUtils.wrapTooltip("<strong>"
212                           + (preset.isModifiable() ? "User Preset"
213                                   : "Service Preset") + "</strong><br/>"
214                           + preset.getDescription() + "</p>") + "</html>");
215           methodR.addActionListener(new ActionListener()
216           {
217             public void actionPerformed(ActionEvent e)
218             {
219               new SequenceAnnotationWSClient(service, alignFrame, preset,
220                       false);
221             }
222
223           });
224           presetlist.add(methodR);
225         }
226         wsmenu.add(presetlist);
227       }
228
229     }
230     else
231     {
232       annotservice = new JMenuItem(MessageManager.getString("label.view_documentation"));
233       if (service.docUrl != null)
234       {
235         annotservice.addActionListener(new ActionListener()
236         {
237
238           @Override
239           public void actionPerformed(ActionEvent arg0)
240           {
241             Desktop.instance.showUrl(service.docUrl);
242           }
243         });
244         annotservice.setToolTipText("<html>"
245                 + JvSwingUtils.wrapTooltip("View <a href=\""
246                         + service.docUrl + "\">" + service.docUrl + "</a>")
247                 + "</html>");
248         wsmenu.add(annotservice);
249       }
250     }
251   }
252
253   
254   private boolean registerAAConWSInstance(final JMenu wsmenu,
255           final Jws2Instance service, final AlignFrame alignFrame)
256   {
257     final AlignAnalysisUIText aaui = service.getAlignAnalysisUI(); // null ; // AlignAnalysisUIText.aaConGUI.get(service.serviceType.toString());
258     if (aaui==null)
259     {
260       // not an instantaneous calculation GUI type service
261       return false;
262     }
263     // create the instaneous calculation GUI bits and update state if existing GUI elements already present
264     
265     JCheckBoxMenuItem _aaConEnabled = null;
266     for (int i = 0; i < wsmenu.getItemCount(); i++)
267     {
268       JMenuItem item = wsmenu.getItem(i);
269       if (item instanceof JCheckBoxMenuItem
270               && item.getText().equals(aaui.getAAconToggle()))
271       {
272         _aaConEnabled = (JCheckBoxMenuItem) item;
273       }
274     }
275     // is there an aaCon worker already present - if so, set it to use the
276     // given service handle
277     {
278       List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
279               .getCalcManager()
280               .getRegisteredWorkersOfClass(aaui.getClient());
281       if (aaconClient != null && aaconClient.size() > 0)
282       {
283         JabawsAlignCalcWorker worker = (JabawsAlignCalcWorker) aaconClient.get(0);
284         if (!worker.service.hosturl.equals(service.hosturl))
285         {
286           // javax.swing.SwingUtilities.invokeLater(new Runnable()
287           {
288             // @Override
289             // public void run()
290             {
291               removeCurrentAAConWorkerFor(aaui, alignFrame);
292               buildCurrentAAConWorkerFor(aaui, alignFrame, service);
293             }
294           }// );
295         }
296       }
297     }
298
299     // is there a service already registered ? there shouldn't be if we are
300     // being called correctly
301     if (_aaConEnabled == null)
302     {
303       final JCheckBoxMenuItem aaConEnabled = new JCheckBoxMenuItem(
304               aaui.getAAconToggle());
305
306       aaConEnabled.setToolTipText("<html><p>"
307               + JvSwingUtils.wrapTooltip(aaui.getAAconToggleTooltip() + "</p>")
308               + "</html>");
309       aaConEnabled.addActionListener(new ActionListener()
310       {
311         @Override
312         public void actionPerformed(ActionEvent arg0)
313         {
314           List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
315                   .getCalcManager()
316                   .getRegisteredWorkersOfClass(aaui.getClient());
317           if (aaconClient != null && aaconClient.size() > 0)
318           {
319             removeCurrentAAConWorkerFor(aaui, alignFrame);
320           }
321           else
322           {
323             buildCurrentAAConWorkerFor(aaui, alignFrame);
324
325           }
326         }
327
328       });
329       wsmenu.add(aaConEnabled);
330       final JMenuItem modifyParams = new JMenuItem(aaui.getAAeditSettings());
331       modifyParams.setToolTipText("<html><p>"
332               + JvSwingUtils.wrapTooltip(aaui.getAAeditSettingsTooltip() + "</p>")
333               + "</html>");
334       modifyParams.addActionListener(new ActionListener()
335       {
336
337         @Override
338         public void actionPerformed(ActionEvent arg0)
339         {
340           showAAConAnnotationSettingsFor(aaui, alignFrame);
341         }
342       });
343       wsmenu.add(modifyParams);
344       wsmenu.addMenuListener(new MenuListener()
345       {
346
347         @Override
348         public void menuSelected(MenuEvent arg0)
349         {
350           // TODO: refactor to the implementing class.
351           if (alignFrame.getViewport().getAlignment()
352                   .isNucleotide() ? aaui.isNa() : aaui.isPr()) {
353             aaConEnabled.setEnabled(true);
354             modifyParams.setEnabled(true);
355           }
356           else {
357             aaConEnabled.setEnabled(false);
358             modifyParams.setEnabled(false);
359           }
360           List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
361                   .getCalcManager()
362                   .getRegisteredWorkersOfClass(aaui.getClient());
363           if (aaconClient != null && aaconClient.size() > 0)
364           {
365             aaConEnabled.setSelected(true);
366           }
367           else
368           {
369             aaConEnabled.setSelected(false);
370           }
371         }
372
373         @Override
374         public void menuDeselected(MenuEvent arg0)
375         {
376           // TODO Auto-generated method stub
377
378         }
379
380         @Override
381         public void menuCanceled(MenuEvent arg0)
382         {
383           // TODO Auto-generated method stub
384
385         }
386       });
387
388     }
389     return true;
390   }
391
392   private static void showAAConAnnotationSettingsFor(final AlignAnalysisUIText aaui, AlignFrame alignFrame)
393   {
394     /*
395      * preferred settings Whether AACon is automatically recalculated Which
396      * AACon server to use What parameters to use
397      */
398     // could actually do a class search for this too
399     AAConSettings fave = (AAConSettings) alignFrame.getViewport()
400             .getCalcIdSettingsFor(aaui.getCalcId());
401     if (fave == null)
402     {
403       fave = createDefaultAAConSettings(aaui);
404     }
405     new SequenceAnnotationWSClient(fave, alignFrame, true);
406
407   }
408
409   private static void buildCurrentAAConWorkerFor(final AlignAnalysisUIText aaui, AlignFrame alignFrame)
410   {
411     buildCurrentAAConWorkerFor(aaui, alignFrame, null);
412   }
413
414   private static void buildCurrentAAConWorkerFor(final AlignAnalysisUIText aaui, AlignFrame alignFrame,
415           Jws2Instance service)
416   {
417     /*
418      * preferred settings Whether AACon is automatically recalculated Which
419      * AACon server to use What parameters to use
420      */
421     AAConSettings fave = (AAConSettings) alignFrame.getViewport()
422             .getCalcIdSettingsFor(aaui.getCalcId());
423     if (fave == null)
424     {
425       fave = createDefaultAAConSettings(aaui, service);
426     }
427     else
428     {
429       if (service != null
430               && !fave.getService().hosturl.equals(service.hosturl))
431       {
432         Cache.log.debug("Changing AACon service to " + service.hosturl
433                 + " from " + fave.getService().hosturl);
434         fave.setService(service);
435       }
436     }
437     new SequenceAnnotationWSClient(fave, alignFrame, false);
438   }
439
440   private static AAConSettings createDefaultAAConSettings(AlignAnalysisUIText aaui)
441   {
442     return createDefaultAAConSettings(aaui, null);
443   }
444
445   private static AAConSettings createDefaultAAConSettings(AlignAnalysisUIText aaui,
446           Jws2Instance service)
447   {
448     if (service != null)
449     {
450       if (!service.serviceType.toString().equals(
451               compbio.ws.client.Services.AAConWS.toString()))
452       {
453         Cache.log
454                 .warn("Ignoring invalid preferred service for AACon calculations (service type was "
455                         + service.serviceType + ")");
456         service = null;
457       }
458       else
459       {
460         // check service is actually in the list of currently avaialable
461         // services
462         if (!Jws2Discoverer.getDiscoverer().getServices().contains(service))
463         {
464           // it isn't ..
465           service = null;
466         }
467       }
468     }
469     if (service == null)
470     {
471       // get the default service for AACon
472       service = Jws2Discoverer.getDiscoverer().getPreferredServiceFor(null,
473               aaui.getServiceType());
474     }
475     if (service == null)
476     {
477       // TODO raise dialog box explaining error, and/or open the JABA
478       // preferences menu.
479       throw new Error("No AACon service found.");
480     }
481     return new AAConSettings(true, service, null, null);
482   }
483
484   private static void removeCurrentAAConWorkerFor(AlignAnalysisUIText aaui, AlignFrame alignFrame)
485   {
486     alignFrame.getViewport().getCalcManager()
487             .removeRegisteredWorkersOfClass(aaui.getClient());
488   }
489 }