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