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