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