5fa373d08f3df3ded3b38bb57998c3090386a4fc
[jabaws.git] / webservices / compbio / ws / client / AAConClient.java
1 /* Copyright (c) 2009 Peter Troshin\r
2  *  \r
3  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0     \r
4  * \r
5  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
6  *  Apache License version 2 as published by the Apache Software Foundation\r
7  * \r
8  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
9  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
10  *  License for more details.\r
11  * \r
12  *  A copy of the license is in apache_license.txt. It is also available here:\r
13  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
14  * \r
15  * Any republication or derived work distributed in source code form\r
16  * must include this copyright and license notice.\r
17  */\r
18 \r
19 package compbio.ws.client;\r
20 \r
21 import static compbio.ws.client.Constraints.inputkey;\r
22 import static compbio.ws.client.Constraints.limitList;\r
23 import static compbio.ws.client.Constraints.outputkey;\r
24 import static compbio.ws.client.Constraints.paramFile;\r
25 import static compbio.ws.client.Constraints.paramList;\r
26 import static compbio.ws.client.Constraints.presetList;\r
27 import static compbio.ws.client.Constraints.presetkey;\r
28 import static compbio.ws.client.Constraints.pseparator;\r
29 \r
30 import java.io.Closeable;\r
31 import java.io.File;\r
32 import java.io.FileInputStream;\r
33 import java.io.IOException;\r
34 import java.io.OutputStream;\r
35 import java.net.MalformedURLException;\r
36 import java.net.URL;\r
37 import java.util.Arrays;\r
38 import java.util.List;\r
39 import java.util.Set;\r
40 import java.util.logging.Level;\r
41 import java.util.logging.Logger;\r
42 \r
43 import javax.xml.namespace.QName;\r
44 import javax.xml.ws.Service;\r
45 import javax.xml.ws.WebServiceException;\r
46 \r
47 import compbio.data.msa.Annotation;\r
48 import compbio.data.sequence.FastaSequence;\r
49 import compbio.data.sequence.Score;\r
50 import compbio.data.sequence.SequenceUtil;\r
51 import compbio.metadata.JobSubmissionException;\r
52 import compbio.metadata.Option;\r
53 import compbio.metadata.Preset;\r
54 import compbio.metadata.ResultNotAvailableException;\r
55 import compbio.metadata.WrongParameterException;\r
56 import compbio.ws.server.AAConWS;\r
57 \r
58 /**\r
59  * A command line client for AACon web service\r
60  * \r
61  * @author pvtroshin\r
62  * @version 1.0\r
63  */\r
64 public class AAConClient {\r
65 \r
66         /*\r
67          * Use java.util.Logger instead of log4j logger to reduce the size of the\r
68          * client package\r
69          */\r
70         private static final Logger log = Logger.getLogger(AAConClient.class\r
71                         .getCanonicalName());\r
72 \r
73         static final String QUALIFIED_SERVICE_NAME = "http://msa.data.compbio/01/12/2010/";\r
74 \r
75         // static final String hostname = "http://www.compbio.dundee.ac.uk/aacon";\r
76         static final String hostname = "http://localhost:8080/jabaws";\r
77 \r
78         static final String serviceName = "AAConWS";\r
79 \r
80         /**\r
81          * Attempt to construct the URL object from the string\r
82          * \r
83          * @param urlstr\r
84          * @return true if it succeed false otherwise\r
85          */\r
86         public static boolean validURL(String urlstr) {\r
87                 try {\r
88                         if (urlstr == null || urlstr.trim().length() == 0) {\r
89                                 return false;\r
90                         }\r
91                         new URL(urlstr);\r
92                 } catch (MalformedURLException e) {\r
93                         return false;\r
94                 }\r
95                 return true;\r
96         }\r
97 \r
98         /**\r
99          * Connects to the service and do the job as requested, if something goes\r
100          * wrong reports or/and prints usage help.\r
101          * \r
102          * @param <AAConWS>\r
103          *            web service type\r
104          * @param cmd\r
105          *            command line options\r
106          * @throws IOException\r
107          */\r
108         @SuppressWarnings("unchecked")\r
109         AAConClient(String[] cmd) throws IOException {\r
110 \r
111                 Services service = Services.getService(serviceName);\r
112                 if (service == null) {\r
113                         System.out.println("Service " + serviceName\r
114                                         + " is no supported! Valid values are: "\r
115                                         + Arrays.toString(Services.values()));\r
116                         printUsage(1);\r
117                 }\r
118                 File inputFile = IOHelper.getFile(cmd, inputkey, true);\r
119                 File outFile = IOHelper.getFile(cmd, outputkey, false);\r
120                 File parametersFile = IOHelper.getFile(cmd, paramFile, true);\r
121                 String presetName = CmdHelper.getPresetName(cmd);\r
122 \r
123                 Annotation<AAConWS> msaws = connect(hostname, service);\r
124                 Preset<AAConWS> preset = null;\r
125                 if (presetName != null) {\r
126                         preset = MetadataHelper.getPreset(msaws, presetName);\r
127                 }\r
128                 List<Option<AAConWS>> customOptions = null;\r
129                 if (parametersFile != null) {\r
130                         List<String> prms = IOHelper.loadParameters(parametersFile);\r
131                         customOptions = MetadataHelper.processParameters(prms,\r
132                                         msaws.getRunnerOptions());\r
133                 }\r
134                 Set<Score> result = null;\r
135                 if (inputFile != null) {\r
136                         System.out.println("calc conserv!");\r
137                         result = analize(inputFile, msaws, preset, customOptions);\r
138                         OutputStream outStream = null;\r
139                         if (outFile != null) {\r
140                                 outStream = IOHelper.getOutStream(outFile);\r
141                         } else {\r
142                                 // this stream is going to be closed later which is fine as\r
143                                 // std.out will not be\r
144                                 outStream = System.out;\r
145                         }\r
146                         writeOut(outStream, result);\r
147                         // stream is closed in the method no need to close it here\r
148                 }\r
149 \r
150                 boolean listParameters = CmdHelper.listParameters(cmd);\r
151                 if (listParameters) {\r
152                         System.out.println(MetadataHelper.getParametersList(msaws));\r
153                 }\r
154                 boolean listPreset = CmdHelper.listPresets(cmd);\r
155                 if (listPreset) {\r
156                         System.out.println(MetadataHelper.getPresetList(msaws));\r
157                 }\r
158                 boolean listLimits = CmdHelper.listLimits(cmd);\r
159                 if (listLimits) {\r
160                         System.out.println(MetadataHelper.getLimits(msaws));\r
161                 }\r
162                 log.fine("Disconnecting...");\r
163                 ((Closeable) msaws).close();\r
164                 log.fine("Disconnected successfully!");\r
165         }\r
166 \r
167         /**\r
168          * Outputs clustal formatted alignment into the file represented by the\r
169          * outStream\r
170          * \r
171          * @param outStream\r
172          * @param align\r
173          *            the alignment to output\r
174          */\r
175         static void writeOut(OutputStream outStream, Set<Score> result) {\r
176                 try {\r
177                         Score.write(result, outStream);\r
178                 } catch (IOException e) {\r
179                         System.err\r
180                                         .println("Problems writing output file! Stack trace is below: ");\r
181                         e.printStackTrace();\r
182                 } finally {\r
183                         if (outStream != null) {\r
184                                 try {\r
185                                         outStream.close();\r
186                                 } catch (IOException ignored) {\r
187                                         // e.printStackTrace();\r
188                                 }\r
189                         }\r
190                 }\r
191         }\r
192 \r
193         /**\r
194          * Connects to a web service by the host and the service name\r
195          * \r
196          * @param T\r
197          *            web service type\r
198          * @param host\r
199          * @param service\r
200          * @return MsaWS<T>\r
201          * @throws WebServiceException\r
202          */\r
203         public static Annotation<AAConWS> connect(String host, Services service)\r
204                         throws WebServiceException {\r
205                 URL url = null;\r
206                 log.log(Level.FINE, "Attempting to connect...");\r
207                 try {\r
208                         url = new URL(host + "/" + service.toString() + "?wsdl");\r
209                 } catch (MalformedURLException e) {\r
210                         e.printStackTrace();\r
211                         // ignore as the host name is already verified\r
212                 }\r
213                 Service serv = service.getService(url, QUALIFIED_SERVICE_NAME);\r
214                 @SuppressWarnings("unchecked")\r
215                 QName portName = new QName(QUALIFIED_SERVICE_NAME, "AAConWS" + "Port");\r
216 \r
217                 Annotation<AAConWS> serviceIF = serv\r
218                                 .getPort(portName, Annotation.class);\r
219 \r
220                 log.log(Level.FINE, "Connected successfully!");\r
221                 return serviceIF;\r
222         }\r
223 \r
224         /**\r
225          * Align sequences from the file using MsaWS\r
226          * \r
227          * @param <T>\r
228          *            web service type e.g. Clustal\r
229          * @param file\r
230          *            to write the resulting alignment to\r
231          * @param wsproxy\r
232          *            MsaWS required\r
233          * @param preset\r
234          *            Preset to use optional\r
235          * @param customOptions\r
236          *            file which contains new line separated list of options\r
237          * @return Alignment\r
238          */\r
239         static <AAConWS> Set<Score> analize(File file, Annotation<AAConWS> wsproxy,\r
240                         Preset<AAConWS> preset, List<Option<AAConWS>> customOptions) {\r
241                 FileInputStream instream = null;\r
242                 List<FastaSequence> fastalist = null;\r
243                 Set<Score> scores = null;\r
244                 try {\r
245                         instream = new FileInputStream(file);\r
246                         fastalist = SequenceUtil.readFasta(instream);\r
247                         instream.close();\r
248                         String jobId = null;\r
249                         if (customOptions != null && preset != null) {\r
250                                 System.out\r
251                                                 .println("WARN: Parameters (-f) are defined together with a preset (-r) ignoring preset!");\r
252                         }\r
253                         if (customOptions != null) {\r
254                                 jobId = wsproxy.customAnalize(fastalist, customOptions);\r
255                         } else if (preset != null) {\r
256                                 jobId = wsproxy.presetAnalize(fastalist, preset);\r
257                         } else {\r
258                                 jobId = wsproxy.analize(fastalist);\r
259                         }\r
260                         Thread.sleep(1000);\r
261                         scores = wsproxy.getAnnotation(jobId);\r
262 \r
263                 } catch (IOException e) {\r
264                         System.err\r
265                                         .println("Exception while reading the input file. "\r
266                                                         + "Check that the input file contains a list of fasta formatted sequences! "\r
267                                                         + "Exception details are below:");\r
268                         e.printStackTrace();\r
269                 } catch (JobSubmissionException e) {\r
270                         System.err\r
271                                         .println("Exception while submitting job to a web server. "\r
272                                                         + "Exception details are below:");\r
273                         e.printStackTrace();\r
274                 } catch (ResultNotAvailableException e) {\r
275                         System.err.println("Exception while waiting for results. "\r
276                                         + "Exception details are below:");\r
277                         e.printStackTrace();\r
278                 } catch (InterruptedException ignored) {\r
279                         // ignore and propagate an interruption\r
280                         Thread.currentThread().interrupt();\r
281                 } catch (WrongParameterException e) {\r
282                         e.printStackTrace();\r
283                 } finally {\r
284                         if (instream != null) {\r
285                                 try {\r
286                                         instream.close();\r
287                                 } catch (IOException ignored) {\r
288                                         // ignore\r
289                                 }\r
290                         }\r
291                 }\r
292                 return scores;\r
293         }\r
294 \r
295         /**\r
296          * Prints Jws2Client usage information to standard out\r
297          * \r
298          * @param exitStatus\r
299          */\r
300         static void printUsage(int exitStatus) {\r
301                 System.out.println();\r
302                 System.out.println("Usage: <Class or Jar file name> "\r
303                                 + " ACTION [OPTIONS] ");\r
304                 System.out.println();\r
305                 System.out.println("ACTIONS: ");\r
306                 System.out\r
307                                 .println(inputkey\r
308                                                 + pseparator\r
309                                                 + "<inputFile> - full path to fasta or Clustal formatted alignment file ");\r
310                 System.out.println(paramList\r
311                                 + " - lists parameters supported by web service");\r
312                 System.out.println(presetList\r
313                                 + " - lists presets supported by web service");\r
314                 System.out.println(limitList + " - lists web services limits");\r
315                 System.out\r
316                                 .println("Please note that if input file is specified other actions are ignored");\r
317 \r
318                 System.out.println();\r
319                 System.out.println("OPTIONS (only for use with -i action):");\r
320 \r
321                 System.out.println(presetkey + pseparator\r
322                                 + "<presetName> - name of the preset to use");\r
323                 System.out\r
324                                 .println(outputkey\r
325                                                 + pseparator\r
326                                                 + "<outputFile> - full path to the file where to write the result");\r
327                 System.out\r
328                                 .println("-f=<parameterInputFile> - the name of the file with the list of parameters to use.");\r
329                 System.out\r
330                                 .println("Please note that -r and -f options cannot be used together. "\r
331                                                 + "Conservation is calculated with either a preset or "\r
332                                                 + "the parameters from the file, but not both!");\r
333 \r
334                 System.exit(exitStatus);\r
335         }\r
336 \r
337         /**\r
338          * Starts command line client, if no parameter are supported print help. Two\r
339          * parameters are required for successfull call the JWS2 host name and a\r
340          * service name.\r
341          * \r
342          * @param args\r
343          *            Usage: <Class or Jar file name> ACTION [OPTIONS]\r
344          * \r
345          *            -i=<inputFile> - full path to fasta or Clustal formatted\r
346          *            alignment file\r
347          * \r
348          *            -parameters - lists parameters supported by web service\r
349          * \r
350          *            -presets - lists presets supported by web service\r
351          * \r
352          *            -limits - lists web services limits. Please note that if input\r
353          *            file is specified other actions are ignored\r
354          * \r
355          *            OPTIONS: (only for use with -i action):\r
356          * \r
357          *            -r=<presetName> - name of the preset to use\r
358          * \r
359          *            -o=<outputFile> - full path to the file where to write results\r
360          *            -f=<parameterInputFile> - the name of the file with the list\r
361          *            of parameters to use. Please note that -r and -f options\r
362          *            cannot be used together. Conservation is calculated with\r
363          *            either a preset or parameters from the file, but not both!\r
364          * \r
365          */\r
366         public static void main(String[] args) {\r
367 \r
368                 if (args == null) {\r
369                         printUsage(1);\r
370                 }\r
371                 if (args.length < 1) {\r
372                         System.out.println("No options is specified! ");\r
373                         printUsage(1);\r
374                 }\r
375 \r
376                 try {\r
377                         new AAConClient(args);\r
378                 } catch (IOException e) {\r
379                         log.log(Level.SEVERE, "IOException in client! " + e.getMessage(),\r
380                                         e.getCause());\r
381                         System.err.println("Cannot write output file! Stack trace: ");\r
382                         e.printStackTrace();\r
383                 }\r
384         }\r
385 }\r