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