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