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