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