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