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