Merge branch 'develop' into update_212_Dec_merge_with_21125_chamges
[jalview.git] / src / jalview / ws / jws2 / MsaWSClient.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.datamodel.AlignmentI;
24 import jalview.datamodel.AlignmentView;
25 import jalview.gui.AlignFrame;
26 import jalview.gui.Desktop;
27 import jalview.gui.JvOptionPane;
28 import jalview.gui.JvSwingUtils;
29 import jalview.util.MessageManager;
30 import jalview.ws.WSMenuEntryProviderI;
31 import jalview.ws.api.JalviewServiceEndpointProviderI;
32 import jalview.ws.api.MultipleSequenceAlignmentI;
33 import jalview.ws.api.ServiceWithParameters;
34 import jalview.ws.gui.MsaWSThread;
35 import jalview.ws.params.ArgumentI;
36 import jalview.ws.params.WsParamSetI;
37
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.MouseAdapter;
41 import java.awt.event.MouseEvent;
42 import java.util.List;
43 import java.util.Locale;
44
45 import javax.swing.JMenu;
46 import javax.swing.JMenuItem;
47 import javax.swing.ToolTipManager;
48
49
50 /**
51  * MsaWSClient
52  * 
53  * Instantiates web service menu items for multiple alignment services, and
54  * holds logic for constructing a web service thread.
55  * 
56  * TODO remove dependency on Jws2Client methods for creating AACon service UI
57  * elements.
58  * 
59  * @author Jim Procter et al
60  * @version $Revision$
61  */
62 public class MsaWSClient extends Jws2Client implements WSMenuEntryProviderI
63 {
64   /**
65    * server is a proxy class implementing the core methods for submitting,
66    * monitoring and retrieving results from a multiple sequence alignment
67    * service
68    */
69   MultipleSequenceAlignmentI server;
70
71   public MsaWSClient(ServiceWithParameters sh, String altitle,
72           jalview.datamodel.AlignmentView msa, boolean submitGaps,
73           boolean preserveOrder, AlignmentI seqdataset,
74           AlignFrame _alignFrame)
75   {
76     this(sh, null, null, false, altitle, msa, submitGaps, preserveOrder,
77             seqdataset, _alignFrame);
78     // TODO Auto-generated constructor stub
79   }
80
81   public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
82           String altitle,
83           jalview.datamodel.AlignmentView msa, boolean submitGaps,
84           boolean preserveOrder, AlignmentI seqdataset,
85           AlignFrame _alignFrame)
86   {
87     this(sh, preset, null, false, altitle, msa, submitGaps, preserveOrder,
88             seqdataset, _alignFrame);
89     // TODO Auto-generated constructor stub
90   }
91
92   /**
93    * Creates a new MsaWSClient object that uses a service given by an externally
94    * retrieved ServiceHandle
95    * 
96    * @param sh
97    *          service handle of type AbstractName(MsaWS)
98    * @param altitle
99    *          DOCUMENT ME!
100    * @param msa
101    *          DOCUMENT ME!
102    * @param submitGaps
103    *          DOCUMENT ME!
104    * @param preserveOrder
105    *          DOCUMENT ME!
106    */
107
108   public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
109           List<ArgumentI> arguments, boolean editParams, String altitle,
110           jalview.datamodel.AlignmentView msa, boolean submitGaps,
111           boolean preserveOrder, AlignmentI seqdataset,
112           AlignFrame _alignFrame)
113   {
114     super(_alignFrame, preset, arguments);
115     processParams(sh, editParams).thenAccept((startJob) -> {
116       if (!startJob)
117         return;
118       
119       if (!(sh instanceof JalviewServiceEndpointProviderI
120               && ((JalviewServiceEndpointProviderI) sh)
121                       .getEndpoint() instanceof MultipleSequenceAlignmentI))
122       {
123         // redundant at mo - but may change
124         JvOptionPane.showMessageDialog(Desktop.getDesktopPane(),
125                 MessageManager.formatMessage(
126                         "label.service_called_is_not_msa_service",
127                         new String[]
128                         { sh.getName() }),
129                 MessageManager.getString("label.internal_jalview_error"),
130                 JvOptionPane.WARNING_MESSAGE);
131   
132         return;
133       }
134       serviceHandle = sh;
135       server = (MultipleSequenceAlignmentI) ((JalviewServiceEndpointProviderI) sh)
136               .getEndpoint();
137       if ((wsInfo = setWebService(sh, false)) == null)
138       {
139         JvOptionPane.showMessageDialog(Desktop.getDesktopPane(), MessageManager
140                 .formatMessage("label.msa_service_is_unknown", new String[]
141                 { sh.getName() }),
142                 MessageManager.getString("label.internal_jalview_error"),
143                 JvOptionPane.WARNING_MESSAGE);
144   
145         return;
146       }
147   
148       startMsaWSClient(altitle, msa, submitGaps, preserveOrder, seqdataset);
149     });
150
151   }
152
153   public MsaWSClient()
154   {
155     super();
156     // add a class reference to the list
157   }
158
159   private void startMsaWSClient(String altitle, AlignmentView msa,
160           boolean submitGaps, boolean preserveOrder, AlignmentI seqdataset)
161   {
162     // if (!locateWebService())
163     // {
164     // return;
165     // }
166
167     wsInfo.setProgressText(((submitGaps) ? "Re-alignment" : "Alignment")
168             + " of " + altitle + "\nJob details\n");
169     String jobtitle = WebServiceName.toLowerCase(Locale.ROOT);
170     if (jobtitle.endsWith("alignment"))
171     {
172       if (submitGaps && (!jobtitle.endsWith("realignment")
173               || jobtitle.indexOf("profile") == -1))
174       {
175         int pos = jobtitle.indexOf("alignment");
176         jobtitle = WebServiceName.substring(0, pos) + "re-alignment of "
177                 + altitle;
178       }
179       else
180       {
181         jobtitle = WebServiceName + " of " + altitle;
182       }
183     }
184     else
185     {
186       jobtitle = WebServiceName + (submitGaps ? " re" : " ")
187               + "alignment of " + altitle;
188     }
189
190     MsaWSThread msathread = new MsaWSThread(server, preset, paramset, WsURL,
191             wsInfo, alignFrame, WebServiceName, jobtitle, msa, submitGaps,
192             preserveOrder, seqdataset);
193     if (msathread.hasValidInput())
194     {
195       wsInfo.setthisService(msathread);
196       wsInfo.setVisible(true);
197       msathread.start();
198     }
199     else
200     {
201       wsInfo.setVisible(false);
202       JvOptionPane.showMessageDialog(alignFrame,
203               MessageManager.getString("info.invalid_msa_input_mininfo"),
204               MessageManager.getString("info.invalid_msa_notenough"),
205               JvOptionPane.INFORMATION_MESSAGE);
206     }
207   }
208
209   protected String getServiceActionKey()
210   {
211     return "MsaWS";
212   }
213
214   protected String getServiceActionDescription()
215   {
216     return "Multiple Sequence Alignment";
217   }
218
219   /**
220    * look at ourselves and work out if we are a service that can take a profile
221    * and align to it
222    * 
223    * @return true if we can send gapped sequences to the alignment service
224    */
225   private boolean canSubmitGaps()
226   {
227     // TODO: query service or extract service handle props to check if we can
228     // realign
229     return (WebServiceName.indexOf("lustal") > -1); // cheat!
230   }
231
232   @Override
233   public void attachWSMenuEntry(JMenu rmsawsmenu,
234           final ServiceWithParameters service, final AlignFrame alignFrame)
235   {
236     if (Jws2ClientFactory.registerAAConWSInstance(rmsawsmenu,
237                     service, alignFrame))
238     {
239             // Alignment dependent analysis calculation WS gui
240       return;
241     }
242     serviceHandle = service;
243     setWebService(service, true); // headless
244     attachWSMenuEntry(rmsawsmenu, alignFrame);
245   }
246
247   @Override
248   public void attachWSMenuEntry(JMenu wsmenu, AlignFrame alignFrame)
249   {
250     boolean finished = true, submitGaps = false;
251     /**
252      * temp variables holding msa service submenu or root service menu
253      */
254     JMenu msawsmenu = wsmenu;
255     JMenu rmsawsmenu = wsmenu;
256     String svcname = WebServiceName;
257     if (svcname.endsWith("WS"))
258     {
259       svcname = svcname.substring(0, svcname.length() - 2);
260     }
261     String calcName = svcname + " ";
262     if (canSubmitGaps())
263     {
264       msawsmenu = new JMenu(svcname);
265       rmsawsmenu.add(msawsmenu);
266       calcName = "";
267     }
268     boolean hasparams = serviceHandle.hasParameters();
269     ServiceWithParameters service = (ServiceWithParameters) serviceHandle;
270     do
271     {
272       String action = "Align ";
273       if (submitGaps == true)
274       {
275         action = "Realign ";
276         msawsmenu = new JMenu(MessageManager
277                 .formatMessage("label.realign_with_params", new String[]
278                 { svcname }));
279         msawsmenu.setToolTipText(MessageManager
280                 .getString("label.align_sequences_to_existing_alignment"));
281         rmsawsmenu.add(msawsmenu);
282       }
283       final boolean withGaps = submitGaps;
284
285       JMenuItem method = new JMenuItem(MessageManager.formatMessage(
286               "label.calcname_with_default_settings", new String[]
287               { calcName }));
288       method.setToolTipText(MessageManager.formatMessage(
289               "label.action_with_default_settings", new String[]
290               { action }));
291
292       method.addActionListener(new ActionListener()
293       {
294         @Override
295         public void actionPerformed(ActionEvent e)
296         {
297           AlignmentView msa = alignFrame.gatherSequencesForAlignment();
298
299           if (msa != null)
300           {
301             new MsaWSClient(service, alignFrame.getTitle(), msa, withGaps,
302                     true,
303                     alignFrame.getViewport().getAlignment().getDataset(),
304                     alignFrame);
305           }
306
307         }
308       });
309       msawsmenu.add(method);
310       if (hasparams)
311       {
312         // only add these menu options if the service has user-modifiable
313         // arguments
314         method = new JMenuItem(
315                 MessageManager.getString("label.edit_settings_and_run"));
316         method.setToolTipText(MessageManager.getString(
317                 "label.view_and_change_parameters_before_alignment"));
318
319         method.addActionListener(new ActionListener()
320         {
321           @Override
322           public void actionPerformed(ActionEvent e)
323           {
324             AlignmentView msa = alignFrame.gatherSequencesForAlignment();
325             if (msa != null)
326             {
327               new MsaWSClient(service, null, null, true,
328                       alignFrame.getTitle(), msa, withGaps, true,
329                       alignFrame.getViewport().getAlignment().getDataset(),
330                       alignFrame);
331             }
332
333           }
334         });
335         msawsmenu.add(method);
336         List<WsParamSetI> presets = service.getParamStore().getPresets();
337         if (presets != null && presets.size() > 0)
338         {
339           JMenu presetlist = new JMenu(MessageManager.formatMessage(
340                   "label.run_with_preset_params", new String[]
341                   { calcName }));
342
343           final int showToolTipFor = ToolTipManager.sharedInstance()
344                   .getDismissDelay();
345           for (final WsParamSetI preset : presets)
346           {
347             final JMenuItem methodR = new JMenuItem(preset.getName());
348             final int QUICK_TOOLTIP = 1500;
349             // JAL-1582 shorten tooltip display time in these menu items as
350             // they can obscure other options
351             methodR.addMouseListener(new MouseAdapter()
352             {
353               @Override
354               public void mouseEntered(MouseEvent e)
355               {
356                 ToolTipManager.sharedInstance()
357                         .setDismissDelay(QUICK_TOOLTIP);
358               }
359
360               @Override
361               public void mouseExited(MouseEvent e)
362               {
363                 ToolTipManager.sharedInstance()
364                         .setDismissDelay(showToolTipFor);
365               }
366
367             });
368             String tooltip = JvSwingUtils.wrapTooltip(true, "<strong>"
369                     + (preset.isModifiable()
370                             ? MessageManager.getString("label.user_preset")
371                             : MessageManager
372                                     .getString("label.service_preset"))
373                     + "</strong><br/>" + preset.getDescription());
374             methodR.setToolTipText(tooltip);
375             methodR.addActionListener(new ActionListener()
376             {
377               @Override
378               public void actionPerformed(ActionEvent e)
379               {
380                 AlignmentView msa = alignFrame
381                         .gatherSequencesForAlignment();
382
383                 if (msa != null)
384                 {
385                   MsaWSClient msac = new MsaWSClient(service, preset,
386                           alignFrame.getTitle(), msa, false, true,
387                           alignFrame.getViewport().getAlignment()
388                                   .getDataset(),
389                           alignFrame);
390                 }
391
392               }
393
394             });
395             presetlist.add(methodR);
396           }
397           msawsmenu.add(presetlist);
398         }
399       }
400       if (!submitGaps && canSubmitGaps())
401       {
402         submitGaps = true;
403         finished = false;
404       }
405       else
406       {
407         finished = true;
408       }
409     } while (!finished);
410   }
411 }