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