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