Merge branch 'develop' into update_212_Dec_merge_with_21125_chamges
[jalview.git] / src / jalview / ws / jws1 / SeqSearchWSClient.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.jws1;
22
23 import jalview.bin.Console;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.AlignmentView;
26 import jalview.gui.AlignFrame;
27 import jalview.gui.Desktop;
28 import jalview.gui.JvOptionPane;
29 import jalview.gui.WebserviceInfo;
30 import jalview.util.MessageManager;
31
32 import java.awt.Component;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.util.Enumeration;
36 import java.util.Hashtable;
37 import java.util.StringTokenizer;
38 import java.util.Vector;
39
40 import javax.swing.JMenu;
41 import javax.swing.JMenuItem;
42
43 import ext.vamsas.SeqSearchServiceLocator;
44 import ext.vamsas.SeqSearchServiceSoapBindingStub;
45 import ext.vamsas.ServiceHandle;
46
47 /**
48  * DOCUMENT ME!
49  * 
50  * @author $author$
51  * @version $Revision$
52  */
53 public class SeqSearchWSClient extends WS1Client
54 {
55   /**
56    * server is a WSDL2Java generated stub for an archetypal MsaWSI service.
57    */
58   ext.vamsas.SeqSearchI server;
59
60   /**
61    * Creates a new MsaWSClient object that uses a service given by an externally
62    * retrieved ServiceHandle
63    * 
64    * @param sh
65    *          service handle of type AbstractName(MsaWS)
66    * @param altitle
67    *          DOCUMENT ME!
68    * @param msa
69    *          DOCUMENT ME!
70    * @param submitGaps
71    *          DOCUMENT ME!
72    * @param preserveOrder
73    *          DOCUMENT ME!
74    */
75
76   public SeqSearchWSClient(ext.vamsas.ServiceHandle sh, String altitle,
77           jalview.datamodel.AlignmentView msa, String db,
78           AlignmentI seqdataset, AlignFrame _alignFrame)
79   {
80     super();
81     alignFrame = _alignFrame;
82     // can generalise the two errors below for metadata mapping from interface
83     // name to service client name
84     if (!sh.getAbstractName().equals(this.getServiceActionKey()))
85     {
86       JvOptionPane.showMessageDialog(Desktop.getDesktopPane(),
87               MessageManager.formatMessage(
88                       "label.service_called_is_not_seq_search_service",
89                       new String[]
90                       { sh.getName() }),
91               MessageManager.getString("label.internal_jalview_error"),
92               JvOptionPane.WARNING_MESSAGE);
93
94       return;
95     }
96
97     if ((wsInfo = setWebService(sh)) == null)
98     {
99       JvOptionPane.showMessageDialog(Desktop.getDesktopPane(),
100               MessageManager.formatMessage(
101                       "label.seq_search_service_is_unknown", new String[]
102                       { sh.getName() }),
103               MessageManager.getString("label.internal_jalview_error"),
104               JvOptionPane.WARNING_MESSAGE);
105
106       return;
107     }
108     startSeqSearchClient(altitle, msa, db, seqdataset);
109
110   }
111
112   /**
113    * non-process web service interaction - use this for calling HEADLESS
114    * synchronous service methods
115    * 
116    * @param sh
117    */
118   public SeqSearchWSClient(ServiceHandle sh)
119   {
120     setWebService(sh, true);
121   }
122
123   public SeqSearchWSClient()
124   {
125
126     super();
127     // add a class reference to the list
128   }
129
130   private void startSeqSearchClient(String altitle, AlignmentView msa,
131           String db, AlignmentI seqdataset)
132   {
133     if (!locateWebService())
134     {
135       return;
136     }
137     String visdb = (db == null || db == "") ? "default" : db; // need a visible
138     // name for a
139     // sequence db
140     boolean profileSearch = msa.getSequences().length > 2 ? true : false;
141     // single sequence or profile from alignment view
142     wsInfo.setProgressText("Searching " + visdb
143             + (!profileSearch
144                     ? " with sequence "
145                             + msa.getSequences()[0].getRefSeq().getName()
146                     : " with profile")
147             + " from " + altitle + "\nJob details\n");
148
149     String jobtitle = WebServiceName
150             + ((WebServiceName.indexOf("earch") > -1) ? " " : " search ")
151             + " of " + visdb
152             + (!profileSearch
153                     ? " with sequence "
154                             + msa.getSequences()[0].getRefSeq().getName()
155                     : " with profile")
156             + " from " + altitle;
157     SeqSearchWSThread ssthread = new SeqSearchWSThread(server, WsURL,
158             wsInfo, alignFrame, WebServiceName, jobtitle, msa, db,
159             seqdataset);
160     wsInfo.setthisService(ssthread);
161     ssthread.start();
162   }
163
164   /**
165    * Initializes the server field with a valid service implementation.
166    * 
167    * @return true if service was located.
168    */
169   private boolean locateWebService()
170   {
171     // this can be abstracted using reflection
172     // TODO: MuscleWS transmuted to generic MsaWS client
173     SeqSearchServiceLocator loc = new SeqSearchServiceLocator(); // Default
174
175     try
176     {
177       this.server = loc.getSeqSearchService(new java.net.URL(WsURL));
178       ((SeqSearchServiceSoapBindingStub) this.server).setTimeout(60000); // One
179       // minute
180       // timeout
181     } catch (Exception ex)
182     {
183       wsInfo.setProgressText("Serious! " + WebServiceName
184               + " Service location failed\nfor URL :" + WsURL + "\n"
185               + ex.getMessage());
186       wsInfo.setStatus(WebserviceInfo.ERROR);
187       ex.printStackTrace();
188
189       return false;
190     }
191
192     loc.getEngine().setOption("axis", "1");
193
194     return true;
195   }
196
197   protected String getServiceActionKey()
198   {
199     return "SeqSearch";
200   }
201
202   protected String getServiceActionDescription()
203   {
204     return "Sequence Database Search";
205   }
206
207   // simple caching of db parameters for each service endpoint
208   private static Hashtable dbParamsForEndpoint;
209   static
210   {
211     dbParamsForEndpoint = new Hashtable();
212   }
213
214   public String[] getSupportedDatabases() throws Exception
215   {
216
217     // check that we haven't already been to this service endpoint
218     if (dbParamsForEndpoint.containsKey(WsURL))
219     {
220       return (String[]) dbParamsForEndpoint.get(WsURL);
221     }
222     if (!locateWebService())
223     {
224       throw new Exception(MessageManager.formatMessage(
225               "exception.cannot_contact_service_endpoint_at", new String[]
226               { WsURL }));
227     }
228     String database = server.getDatabase();
229     if (database == null)
230     {
231       dbParamsForEndpoint.put(WsURL, new String[] {});
232       return null;
233     }
234     StringTokenizer en = new StringTokenizer(database.trim(), ",| ");
235     String[] dbs = new String[en.countTokens()];
236     for (int i = 0; i < dbs.length; i++)
237     {
238       dbs[i++] = en.nextToken().trim();
239     }
240     dbParamsForEndpoint.put(WsURL, dbs);
241     return dbs;
242   }
243
244   @Override
245   public void attachWSMenuEntry(JMenu wsmenu, final ServiceHandle sh,
246           final AlignFrame af)
247   {
248     // look for existing database service submenus on wsmenu
249     Hashtable dbsrchs = new Hashtable();
250     Vector newdbsrch = new Vector();
251     Component entries[] = wsmenu.getComponents();
252     for (int i = 0; entries != null && i < entries.length; i++)
253     {
254       if (entries[i] instanceof JMenu)
255       {
256         dbsrchs.put(entries[i].getName(), entries[i]);
257       }
258     }
259     JMenu defmenu = (JMenu) dbsrchs.get("Default Database");
260     if (defmenu == null)
261     {
262       dbsrchs.put("Default Database",
263               defmenu = new JMenu("Default Database"));
264       newdbsrch.addElement(defmenu);
265     }
266
267     String dbs[] = null;
268     try
269     {
270       dbs = new jalview.ws.jws1.SeqSearchWSClient(sh)
271               .getSupportedDatabases();
272     } catch (Exception e)
273     {
274       Console.warn(
275               "Database list request failed, so disabling SeqSearch Service client "
276                       + sh.getName() + " at " + sh.getEndpointURL(),
277               e);
278       return;
279     }
280     JMenuItem method;
281     // do default entry
282     defmenu.add(method = new JMenuItem(sh.getName()));
283     method.setToolTipText(sh.getEndpointURL());
284     method.addActionListener(new ActionListener()
285     {
286       @Override
287       public void actionPerformed(ActionEvent e)
288       {
289         // use same input gatherer as for secondary structure prediction
290         // we could actually parameterise the gatherer method here...
291         AlignmentView msa = af.gatherSeqOrMsaForSecStrPrediction();
292         new jalview.ws.jws1.SeqSearchWSClient(sh, af.getTitle(), msa, null,
293                 af.getViewport().getAlignment().getDataset(), af);
294       }
295     });
296     // add entry for each database the service supports
297     for (int db = 0; dbs != null && db < dbs.length; db++)
298     {
299       JMenu dbmenu = (JMenu) dbsrchs.get(dbs[db]);
300       if (dbmenu == null)
301       {
302         dbsrchs.put(dbs[db], dbmenu = new JMenu(dbs[db]));
303         newdbsrch.addElement(dbmenu);
304       }
305       // add the client handler code for this service
306       dbmenu.add(method = new JMenuItem(sh.getName()));
307       method.setToolTipText(sh.getEndpointURL());
308       final String searchdb = dbs[db];
309       method.addActionListener(new ActionListener()
310       {
311         @Override
312         public void actionPerformed(ActionEvent e)
313         {
314           AlignmentView msa = af.gatherSeqOrMsaForSecStrPrediction();
315           new jalview.ws.jws1.SeqSearchWSClient(sh, af.getTitle(), msa,
316                   searchdb, af.getViewport().getAlignment().getDataset(),
317                   af);
318         }
319       });
320     }
321     // add the databases onto the seqsearch menu
322     Enumeration e = newdbsrch.elements();
323     while (e.hasMoreElements())
324     {
325       Object el = e.nextElement();
326       if (el instanceof JMenu)
327       {
328         wsmenu.add((JMenu) el);
329       }
330       else
331       {
332         wsmenu.add((JMenuItem) el);
333       }
334     }
335
336   }
337 }