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