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