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