First patch for * JAL-493
[jalview.git] / src / jalview / ws / SeqSearchWSClient.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)\r
3  * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle\r
4  * \r
5  * This file is part of Jalview.\r
6  * \r
7  * Jalview is free software: you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License \r
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
10  * \r
11  * Jalview is distributed in the hope that it will be useful, but \r
12  * WITHOUT ANY WARRANTY; without even the implied warranty \r
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
14  * PURPOSE.  See the GNU General Public License for more details.\r
15  * \r
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package jalview.ws;\r
19 \r
20 import java.awt.Component;\r
21 import java.awt.event.ActionEvent;\r
22 import java.awt.event.ActionListener;\r
23 import java.util.Enumeration;\r
24 import java.util.Hashtable;\r
25 import java.util.StringTokenizer;\r
26 import java.util.Vector;\r
27 \r
28 import javax.swing.*;\r
29 \r
30 import ext.vamsas.*;\r
31 import jalview.datamodel.*;\r
32 import jalview.gui.*;\r
33 \r
34 /**\r
35  * DOCUMENT ME!\r
36  * \r
37  * @author $author$\r
38  * @version $Revision$\r
39  */\r
40 public class SeqSearchWSClient extends WS1Client\r
41 {\r
42   /**\r
43    * server is a WSDL2Java generated stub for an archetypal MsaWSI service.\r
44    */\r
45   ext.vamsas.SeqSearchI server;\r
46 \r
47   AlignFrame alignFrame;\r
48 \r
49   /**\r
50    * Creates a new MsaWSClient object that uses a service given by an externally\r
51    * retrieved ServiceHandle\r
52    * \r
53    * @param sh\r
54    *          service handle of type AbstractName(MsaWS)\r
55    * @param altitle\r
56    *          DOCUMENT ME!\r
57    * @param msa\r
58    *          DOCUMENT ME!\r
59    * @param submitGaps\r
60    *          DOCUMENT ME!\r
61    * @param preserveOrder\r
62    *          DOCUMENT ME!\r
63    */\r
64 \r
65   public SeqSearchWSClient(ext.vamsas.ServiceHandle sh, String altitle,\r
66           jalview.datamodel.AlignmentView msa, String db,\r
67           Alignment seqdataset, AlignFrame _alignFrame)\r
68   {\r
69     super();\r
70     alignFrame = _alignFrame;\r
71     // can generalise the two errors below for metadata mapping from interface\r
72     // name to service client name\r
73     if (!sh.getAbstractName().equals(this.getServiceActionKey()))\r
74     {\r
75       JOptionPane.showMessageDialog(Desktop.desktop,\r
76               "The Service called \n" + sh.getName()\r
77                       + "\nis not a \nSequence Search Service !",\r
78               "Internal Jalview Error", JOptionPane.WARNING_MESSAGE);\r
79 \r
80       return;\r
81     }\r
82 \r
83     if ((wsInfo = setWebService(sh)) == null)\r
84     {\r
85       JOptionPane.showMessageDialog(Desktop.desktop,\r
86               "The Sequence Search Service named " + sh.getName()\r
87                       + " is unknown", "Internal Jalview Error",\r
88               JOptionPane.WARNING_MESSAGE);\r
89 \r
90       return;\r
91     }\r
92     startSeqSearchClient(altitle, msa, db, seqdataset);\r
93 \r
94   }\r
95 \r
96   /**\r
97    * non-process web service interaction - use this for calling HEADLESS\r
98    * synchronous service methods\r
99    * \r
100    * @param sh\r
101    */\r
102   public SeqSearchWSClient(ServiceHandle sh)\r
103   {\r
104     setWebService(sh, true);\r
105   }\r
106 \r
107   public SeqSearchWSClient()\r
108   {\r
109 \r
110     super();\r
111     // add a class reference to the list\r
112   }\r
113 \r
114   private void startSeqSearchClient(String altitle, AlignmentView msa,\r
115           String db, Alignment seqdataset)\r
116   {\r
117     if (!locateWebService())\r
118     {\r
119       return;\r
120     }\r
121     String visdb = (db == null || db == "") ? "default" : db; // need a visible\r
122     // name for a\r
123     // sequence db\r
124     boolean profileSearch = msa.getSequences().length > 2 ? true : false;\r
125     // single sequence or profile from alignment view\r
126     wsInfo.setProgressText("Searching "\r
127             + visdb\r
128             + (!profileSearch ? " with sequence "\r
129                     + msa.getSequences()[0].getRefSeq().getName()\r
130                     : " with profile") + " from " + altitle\r
131             + "\nJob details\n");\r
132 \r
133     String jobtitle = WebServiceName\r
134             + ((WebServiceName.indexOf("earch") > -1) ? " " : " search ")\r
135             + " of "\r
136             + visdb\r
137             + (!profileSearch ? " with sequence "\r
138                     + msa.getSequences()[0].getRefSeq().getName()\r
139                     : " with profile") + " from " + altitle;\r
140     SeqSearchWSThread ssthread = new SeqSearchWSThread(server, WsURL,\r
141             wsInfo, alignFrame, WebServiceName, jobtitle, msa, db,\r
142             seqdataset);\r
143     wsInfo.setthisService(ssthread);\r
144     ssthread.start();\r
145   }\r
146 \r
147   /**\r
148    * Initializes the server field with a valid service implementation.\r
149    * \r
150    * @return true if service was located.\r
151    */\r
152   private boolean locateWebService()\r
153   {\r
154     // this can be abstracted using reflection\r
155     // TODO: MuscleWS transmuted to generic MsaWS client\r
156     SeqSearchServiceLocator loc = new SeqSearchServiceLocator(); // Default\r
157 \r
158     try\r
159     {\r
160       this.server = (SeqSearchI) loc.getSeqSearchService(new java.net.URL(\r
161               WsURL));\r
162       ((SeqSearchServiceSoapBindingStub) this.server).setTimeout(60000); // One\r
163       // minute\r
164       // timeout\r
165     } catch (Exception ex)\r
166     {\r
167       wsInfo.setProgressText("Serious! " + WebServiceName\r
168               + " Service location failed\nfor URL :" + WsURL + "\n"\r
169               + ex.getMessage());\r
170       wsInfo.setStatus(WebserviceInfo.ERROR);\r
171       ex.printStackTrace();\r
172 \r
173       return false;\r
174     }\r
175 \r
176     loc.getEngine().setOption("axis", "1");\r
177 \r
178     return true;\r
179   }\r
180 \r
181   protected String getServiceActionKey()\r
182   {\r
183     return "SeqSearch";\r
184   }\r
185 \r
186   protected String getServiceActionDescription()\r
187   {\r
188     return "Sequence Database Search";\r
189   }\r
190 \r
191   // simple caching of db parameters for each service endpoint\r
192   private static Hashtable dbParamsForEndpoint;\r
193   static\r
194   {\r
195     dbParamsForEndpoint = new Hashtable();\r
196   }\r
197 \r
198   public String[] getSupportedDatabases() throws Exception\r
199   {\r
200 \r
201     // check that we haven't already been to this service endpoint\r
202     if (dbParamsForEndpoint.containsKey(WsURL))\r
203     {\r
204       return (String[]) dbParamsForEndpoint.get(WsURL);\r
205     }\r
206     if (!locateWebService())\r
207     {\r
208       throw new Exception("Cannot contact service endpoint at " + WsURL);\r
209     }\r
210     String database = server.getDatabase();\r
211     if (database == null)\r
212     {\r
213       dbParamsForEndpoint.put(WsURL, new String[]\r
214       {});\r
215       return null;\r
216     }\r
217     StringTokenizer en = new StringTokenizer(database.trim(), ",| ");\r
218     String[] dbs = new String[en.countTokens()];\r
219     for (int i = 0; i < dbs.length; i++)\r
220     {\r
221       dbs[i++] = en.nextToken().trim();\r
222     }\r
223     dbParamsForEndpoint.put(WsURL, dbs);\r
224     return dbs;\r
225   }\r
226 \r
227   public void attachWSMenuEntry(JMenu wsmenu, final ServiceHandle sh,\r
228           final AlignFrame af)\r
229   {\r
230     // look for existing database service submenus on wsmenu\r
231     Hashtable dbsrchs = new Hashtable();\r
232     Vector newdbsrch = new Vector();\r
233     Component entries[] = wsmenu.getComponents();\r
234     for (int i = 0; entries != null && i < entries.length; i++)\r
235     {\r
236       if (entries[i] instanceof JMenu)\r
237       {\r
238         dbsrchs.put(entries[i].getName(), entries[i]);\r
239       }\r
240     }\r
241     JMenu defmenu = (JMenu) dbsrchs.get("Default Database");\r
242     if (defmenu == null)\r
243     {\r
244       dbsrchs.put("Default Database", defmenu = new JMenu(\r
245               "Default Database"));\r
246       newdbsrch.addElement(defmenu);\r
247     }\r
248 \r
249     String dbs[] = null;\r
250     try\r
251     {\r
252       dbs = new jalview.ws.SeqSearchWSClient(sh).getSupportedDatabases();\r
253     } catch (Exception e)\r
254     {\r
255       jalview.bin.Cache.log.warn(\r
256               "Database list request failed, so disabling SeqSearch Service client "\r
257                       + sh.getName() + " at " + sh.getEndpointURL(), e);\r
258       return;\r
259     }\r
260     JMenuItem method;\r
261     // do default entry\r
262     defmenu.add(method = new JMenuItem(sh.getName()));\r
263     method.setToolTipText(sh.getEndpointURL());\r
264     method.addActionListener(new ActionListener()\r
265     {\r
266       public void actionPerformed(ActionEvent e)\r
267       {\r
268         // use same input gatherer as for secondary structure prediction\r
269         // we could actually parameterise the gatherer method here...\r
270         AlignmentView msa = af.gatherSeqOrMsaForSecStrPrediction();\r
271         new jalview.ws.SeqSearchWSClient(sh, af.getTitle(), msa, null, af\r
272                 .getViewport().getAlignment().getDataset(), af);\r
273       }\r
274     });\r
275     // add entry for each database the service supports\r
276     for (int db = 0; dbs != null && db < dbs.length; db++)\r
277     {\r
278       JMenu dbmenu = (JMenu) dbsrchs.get(dbs[db]);\r
279       if (dbmenu == null)\r
280       {\r
281         dbsrchs.put(dbs[db], dbmenu = new JMenu(dbs[db]));\r
282         newdbsrch.addElement(dbmenu);\r
283       }\r
284       // add the client handler code for this service\r
285       dbmenu.add(method = new JMenuItem(sh.getName()));\r
286       method.setToolTipText(sh.getEndpointURL());\r
287       final String searchdb = dbs[db];\r
288       method.addActionListener(new ActionListener()\r
289       {\r
290         public void actionPerformed(ActionEvent e)\r
291         {\r
292           AlignmentView msa = af.gatherSeqOrMsaForSecStrPrediction();\r
293           new jalview.ws.SeqSearchWSClient(sh, af.getTitle(), msa,\r
294                   searchdb, af.getViewport().getAlignment().getDataset(),\r
295                   af);\r
296         }\r
297       });\r
298     }\r
299     // add the databases onto the seqsearch menu\r
300     Enumeration e = newdbsrch.elements();\r
301     while (e.hasMoreElements())\r
302     {\r
303       Object el = e.nextElement();\r
304       if (el instanceof JMenu)\r
305       {\r
306         wsmenu.add((JMenu) el);\r
307       }\r
308       else\r
309       {\r
310         wsmenu.add((JMenuItem) el);\r
311       }\r
312     }\r
313 \r
314   }\r
315 }\r