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