dfa7598c9156662a6f57f7c9a72865779a8d0b0b
[jalview.git] / src / jalview / ws / jws2 / Jws2Client.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.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.gui.WebserviceInfo;
29 import jalview.gui.WsJobParameters;
30 import jalview.util.MessageManager;
31 import jalview.ws.api.UIinfo;
32 import jalview.ws.jws2.dm.AAConSettings;
33 import jalview.ws.jws2.dm.JabaWsParamSet;
34 import jalview.ws.jws2.jabaws2.Jws2Instance;
35 import jalview.ws.params.ArgumentI;
36 import jalview.ws.params.ParamDatastoreI;
37 import jalview.ws.params.WsParamSetI;
38 import jalview.ws.uimodel.AlignAnalysisUIText;
39
40 import java.awt.event.ActionEvent;
41 import java.awt.event.ActionListener;
42 import java.util.List;
43
44 import javax.swing.JCheckBoxMenuItem;
45 import javax.swing.JMenu;
46 import javax.swing.JMenuItem;
47 import javax.swing.event.MenuEvent;
48 import javax.swing.event.MenuListener;
49
50 import compbio.metadata.Argument;
51
52 /**
53  * provides metadata for a jabaws2 service instance - resolves names, etc.
54  * 
55  * @author JimP
56  * 
57  */
58 public abstract class Jws2Client extends jalview.ws.WSClient
59 {
60   protected AlignFrame alignFrame;
61
62   protected WsParamSetI preset;
63
64   protected List<Argument> paramset;
65
66   public Jws2Client(AlignFrame _alignFrame, WsParamSetI preset,
67           List<Argument> arguments)
68   {
69     alignFrame = _alignFrame;
70     this.preset = preset;
71     if (preset != null)
72     {
73       if (!((preset instanceof JabaPreset)
74               || preset instanceof JabaWsParamSet))
75       {
76         /*
77          * { this.preset = ((JabaPreset) preset).p; } else if (preset instanceof
78          * JabaWsParamSet) { List<Argument> newargs = new ArrayList<Argument>();
79          * JabaWsParamSet pset = ((JabaWsParamSet) preset); for (Option opt :
80          * pset.getjabaArguments()) { newargs.add(opt); } if (arguments != null
81          * && arguments.size() > 0) { // merge arguments with preset's own
82          * arguments. for (Argument opt : arguments) { newargs.add(opt); } }
83          * paramset = newargs; } else {
84          */
85         throw new Error(MessageManager.getString(
86                 "error.implementation_error_can_only_instantiate_jaba_param_sets"));
87       }
88     }
89     else
90     {
91       // just provided with a bunch of arguments
92       this.paramset = arguments;
93     }
94   }
95
96   boolean processParams(Jws2Instance sh, boolean editParams)
97   {
98     return processParams(sh, editParams, false);
99   }
100
101   protected boolean processParams(Jws2Instance sh, boolean editParams,
102           boolean adjustingExisting)
103   {
104
105     if (editParams)
106     {
107       if (sh.paramStore == null)
108       {
109         sh.paramStore = new JabaParamStore(sh,
110                 Desktop.getUserParameterStore());
111       }
112       WsJobParameters jobParams = (preset == null && paramset != null
113               && paramset.size() > 0)
114                       ? new WsJobParameters((ParamDatastoreI) null, sh,
115                               (WsParamSetI) null,
116                               JabaParamStore.getJwsArgsfromJaba(paramset))
117                       : new WsJobParameters((ParamDatastoreI) null, sh,
118                               preset,
119                               (List<ArgumentI>) null);
120       if (adjustingExisting)
121       {
122         jobParams.setName(MessageManager
123                 .getString("label.adjusting_parameters_for_calculation"));
124       }
125       if (!jobParams.showRunDialog())
126       {
127         return false; // dialog cancelled
128       }
129
130       WsParamSetI prset = jobParams.getPreset();
131       if (prset == null)
132       {
133         paramset = jobParams.isServiceDefaults() ? null
134                 : JabaParamStore
135                         .getJabafromJwsArgs(jobParams.getJobParams());
136         this.preset = null;
137       }
138       else
139       {
140         this.preset = prset; // ((JabaPreset) prset).p;
141         paramset = null; // no user supplied parameters.
142       }
143     }
144     return true;
145
146   }
147
148   public Jws2Client()
149   {
150     // anonymous constructor - used for headless method calls only
151   }
152
153   protected WebserviceInfo setWebService(UIinfo serv, boolean b)
154   {
155     // TODO pullup
156     WebServiceName = serv.getName();
157     WebServiceJobTitle = serv.getActionText();
158     WsURL = serv.getHostURL();
159     if (!b)
160     {
161       return new WebserviceInfo(WebServiceJobTitle,
162               WebServiceJobTitle + " using service hosted at "
163                       + WsURL + "\n"
164                       + (serv.getDescription() != null
165                               ? serv.getDescription()
166                               : ""),
167               false);
168     }
169     return null;
170   }
171
172   /*
173    * Jws2Instance serviceHandle; (non-Javadoc)
174    * 
175    * @see jalview.ws.WSMenuEntryProviderI#attachWSMenuEntry(javax.swing.JMenu,
176    * jalview.gui.AlignFrame)
177    * 
178    * @Override public void attachWSMenuEntry(JMenu wsmenu, AlignFrame
179    * alignFrame) { if (serviceHandle==null) { throw new
180    * Error("Implementation error: No service handle for this Jws2 service."); }
181    * attachWSMenuEntry(wsmenu, serviceHandle, alignFrame); }
182    */
183   /**
184    * add the menu item for a particular jws2 service instance
185    * 
186    * @param wsmenu
187    * @param service
188    * @param alignFrame
189    */
190   abstract void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
191           final AlignFrame alignFrame);
192
193   static boolean registerAAConWSInstance(final JMenu wsmenu,
194           final Jws2Instance service, final AlignFrame alignFrame)
195   {
196     final AlignAnalysisUIText aaui = service.getAlignAnalysisUI(); // null ; //
197                                                                    // AlignAnalysisUIText.aaConGUI.get(service.serviceType.toString());
198     if (aaui == null)
199     {
200       // not an instantaneous calculation GUI type service
201       return false;
202     }
203     // create the instaneous calculation GUI bits and update state if existing
204     // GUI elements already present
205
206     JCheckBoxMenuItem _aaConEnabled = null;
207     for (int i = 0; i < wsmenu.getItemCount(); i++)
208     {
209       JMenuItem item = wsmenu.getItem(i);
210       if (item instanceof JCheckBoxMenuItem
211               && item.getText().equals(aaui.getAAconToggle()))
212       {
213         _aaConEnabled = (JCheckBoxMenuItem) item;
214       }
215     }
216     // is there an aaCon worker already present - if so, set it to use the
217     // given service handle
218     {
219       List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
220               .getCalcManager()
221               .getRegisteredWorkersOfClass(aaui.getClient());
222       if (aaconClient != null && aaconClient.size() > 0)
223       {
224         AbstractJabaCalcWorker worker = (AbstractJabaCalcWorker) aaconClient
225                 .get(0);
226         if (!worker.service.getHostURL().equals(service.getHostURL()))
227         {
228           // javax.swing.SwingUtilities.invokeLater(new Runnable()
229           {
230             // @Override
231             // public void run()
232             {
233               removeCurrentAAConWorkerFor(aaui, alignFrame);
234               buildCurrentAAConWorkerFor(aaui, alignFrame, service);
235             }
236           } // );
237         }
238       }
239     }
240
241     // is there a service already registered ? there shouldn't be if we are
242     // being called correctly
243     if (_aaConEnabled == null)
244     {
245       final JCheckBoxMenuItem aaConEnabled = new JCheckBoxMenuItem(
246               aaui.getAAconToggle());
247
248       aaConEnabled.setToolTipText(
249               JvSwingUtils.wrapTooltip(true, aaui.getAAconToggleTooltip()));
250       aaConEnabled.addActionListener(new ActionListener()
251       {
252         @Override
253         public void actionPerformed(ActionEvent arg0)
254         {
255           List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
256                   .getCalcManager()
257                   .getRegisteredWorkersOfClass(aaui.getClient());
258           if (aaconClient != null && aaconClient.size() > 0)
259           {
260             removeCurrentAAConWorkerFor(aaui, alignFrame);
261           }
262           else
263           {
264             buildCurrentAAConWorkerFor(aaui, alignFrame);
265
266           }
267         }
268
269       });
270       wsmenu.add(aaConEnabled);
271       final JMenuItem modifyParams = new JMenuItem(
272               aaui.getAAeditSettings());
273       modifyParams.setToolTipText(JvSwingUtils.wrapTooltip(true,
274               aaui.getAAeditSettingsTooltip()));
275       modifyParams.addActionListener(new ActionListener()
276       {
277
278         @Override
279         public void actionPerformed(ActionEvent arg0)
280         {
281           showAAConAnnotationSettingsFor(aaui, alignFrame);
282         }
283       });
284       wsmenu.add(modifyParams);
285       wsmenu.addMenuListener(new MenuListener()
286       {
287
288         @Override
289         public void menuSelected(MenuEvent arg0)
290         {
291           // TODO: refactor to the implementing class.
292           if (alignFrame.getViewport().getAlignment().isNucleotide()
293                   ? aaui.isNa()
294                   : aaui.isPr())
295           {
296             aaConEnabled.setEnabled(true);
297             modifyParams.setEnabled(true);
298           }
299           else
300           {
301             aaConEnabled.setEnabled(false);
302             modifyParams.setEnabled(false);
303           }
304           List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
305                   .getCalcManager()
306                   .getRegisteredWorkersOfClass(aaui.getClient());
307           if (aaconClient != null && aaconClient.size() > 0)
308           {
309             aaConEnabled.setSelected(true);
310           }
311           else
312           {
313             aaConEnabled.setSelected(false);
314           }
315         }
316
317         @Override
318         public void menuDeselected(MenuEvent arg0)
319         {
320           // TODO Auto-generated method stub
321
322         }
323
324         @Override
325         public void menuCanceled(MenuEvent arg0)
326         {
327           // TODO Auto-generated method stub
328
329         }
330       });
331
332     }
333     return true;
334   }
335
336   private static void showAAConAnnotationSettingsFor(
337           final AlignAnalysisUIText aaui, AlignFrame alignFrame)
338   {
339     /*
340      * preferred settings Whether AACon is automatically recalculated Which
341      * AACon server to use What parameters to use
342      */
343     // could actually do a class search for this too
344     AAConSettings fave = (AAConSettings) alignFrame.getViewport()
345             .getCalcIdSettingsFor(aaui.getCalcId());
346     if (fave == null)
347     {
348       fave = createDefaultAAConSettings(aaui);
349     }
350     new SequenceAnnotationWSClient(fave, alignFrame, true);
351
352   }
353
354   private static void buildCurrentAAConWorkerFor(
355           final AlignAnalysisUIText aaui, AlignFrame alignFrame)
356   {
357     buildCurrentAAConWorkerFor(aaui, alignFrame, null);
358   }
359
360   private static void buildCurrentAAConWorkerFor(
361           final AlignAnalysisUIText aaui, AlignFrame alignFrame,
362           Jws2Instance service)
363   {
364     /*
365      * preferred settings Whether AACon is automatically recalculated Which
366      * AACon server to use What parameters to use
367      */
368     AAConSettings fave = (AAConSettings) alignFrame.getViewport()
369             .getCalcIdSettingsFor(aaui.getCalcId());
370     if (fave == null)
371     {
372       fave = createDefaultAAConSettings(aaui, service);
373     }
374     else
375     {
376       if (service != null
377               && !fave.getService().getHostURL()
378                       .equals(service.getHostURL()))
379       {
380         Cache.log.debug("Changing AACon service to " + service.getHostURL()
381                 + " from " + fave.getService().getHostURL());
382         fave.setService(service);
383       }
384     }
385     new SequenceAnnotationWSClient(fave, alignFrame, false);
386   }
387
388   private static AAConSettings createDefaultAAConSettings(
389           AlignAnalysisUIText aaui)
390   {
391     return createDefaultAAConSettings(aaui, null);
392   }
393
394   private static AAConSettings createDefaultAAConSettings(
395           AlignAnalysisUIText aaui, Jws2Instance service)
396   {
397     if (service != null)
398     {
399       if (!service.getServiceType()
400               .equals(compbio.ws.client.Services.AAConWS.toString()))
401       {
402         Cache.log.warn(
403                 "Ignoring invalid preferred service for AACon calculations (service type was "
404                         + service.getServiceType() + ")");
405         service = null;
406       }
407       else
408       {
409         // check service is actually in the list of currently avaialable
410         // services
411         if (!Jws2Discoverer.getDiscoverer().getServices().contains(service))
412         {
413           // it isn't ..
414           service = null;
415         }
416       }
417     }
418     if (service == null)
419     {
420       // get the default service for AACon
421       service = Jws2Discoverer.getDiscoverer().getPreferredServiceFor(null,
422               aaui.getServiceType());
423     }
424     if (service == null)
425     {
426       // TODO raise dialog box explaining error, and/or open the JABA
427       // preferences menu.
428       throw new Error(
429               MessageManager.getString("error.no_aacon_service_found"));
430     }
431     return new AAConSettings(true, service, null, null);
432   }
433
434   private static void removeCurrentAAConWorkerFor(AlignAnalysisUIText aaui,
435           AlignFrame alignFrame)
436   {
437     alignFrame.getViewport().getCalcManager()
438             .removeRegisteredWorkersOfClass(aaui.getClient());
439   }
440
441 }