3fe638e7cfe03462be3c063788261cb1c0d1e569
[jabaws.git] / webservices / compbio / ws / client / AAConClient.java
1 /* Copyright (c) 2010 Peter Troshin\r
2  *  \r
3  *  Amino Acid Conservation Web Service client @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.IOException;\r
33 import java.io.PrintWriter;\r
34 import java.io.Writer;\r
35 import java.net.MalformedURLException;\r
36 import java.net.URL;\r
37 import java.util.List;\r
38 import java.util.logging.Level;\r
39 import java.util.logging.Logger;\r
40 \r
41 import javax.xml.namespace.QName;\r
42 import javax.xml.ws.Service;\r
43 import javax.xml.ws.WebServiceException;\r
44 \r
45 import compbio.data.msa.SequenceAnnotation;\r
46 import compbio.data.sequence.FastaSequence;\r
47 import compbio.data.sequence.ScoreManager;\r
48 import compbio.data.sequence.SequenceUtil;\r
49 import compbio.data.sequence.UnknownFileFormatException;\r
50 import compbio.metadata.JobSubmissionException;\r
51 import compbio.metadata.Option;\r
52 import compbio.metadata.Preset;\r
53 import compbio.metadata.ResultNotAvailableException;\r
54 import compbio.metadata.WrongParameterException;\r
55 import compbio.ws.server.AAConWS;\r
56 \r
57 /**\r
58  * A command line client for AACon web service\r
59  * \r
60  * @author pvtroshin\r
61  * @version 1.0\r
62  */\r
63 public class AAConClient {\r
64 \r
65         /*\r
66          * Use java.util.Logger instead of log4j logger to reduce the size of the\r
67          * client package\r
68          */\r
69         private static final Logger log = Logger.getLogger(AAConClient.class\r
70                         .getCanonicalName());\r
71 \r
72         /**\r
73          * The fully qualified web service namespace\r
74          */\r
75         static final String QUALIFIED_SERVICE_NAME = "http://msa.data.compbio/01/12/2010/";\r
76 \r
77         /**\r
78          * Web service host\r
79          */\r
80         static final String hostname = "http://www.compbio.dundee.ac.uk/aacon";\r
81         // static final String hostname = "http://localhost:8080/jabaws";\r
82 \r
83         /**\r
84          * Web service name\r
85          */\r
86         static final String serviceName = "AAConWS";\r
87 \r
88         /**\r
89          * Connects to the service and do the job as requested, if something goes\r
90          * wrong reports or/and prints usage help.\r
91          * \r
92          * @param cmd\r
93          *            command line options\r
94          * @throws IOException\r
95          *             if the system cannot read/write from/into the file system\r
96          */\r
97         @SuppressWarnings("unchecked")\r
98         AAConClient(String[] cmd) throws IOException {\r
99 \r
100                 File inputFile = IOHelper.getFile(cmd, inputkey, true);\r
101                 File outFile = IOHelper.getFile(cmd, outputkey, false);\r
102                 File parametersFile = IOHelper.getFile(cmd, paramFile, true);\r
103                 String presetName = CmdHelper.getPresetName(cmd);\r
104 \r
105                 SequenceAnnotation<AAConWS> msaws = connect();\r
106                 Preset<AAConWS> preset = null;\r
107                 if (presetName != null) {\r
108                         preset = MetadataHelper.getPreset(msaws, presetName);\r
109                 }\r
110                 List<Option<AAConWS>> customOptions = null;\r
111                 if (parametersFile != null) {\r
112                         List<String> prms = IOHelper.loadParameters(parametersFile);\r
113                         customOptions = MetadataHelper.processParameters(prms,\r
114                                         msaws.getRunnerOptions());\r
115                 }\r
116                 ScoreManager result = null;\r
117                 if (inputFile != null) {\r
118                         System.out.println("Calculating conservation...");\r
119                         result = analize(inputFile, msaws, preset, customOptions);\r
120                         Writer outStream = null;\r
121                         if (outFile != null) {\r
122                                 outStream = IOHelper.getWriter(outFile);\r
123                         } else {\r
124                                 // this stream is going to be closed later which is fine as\r
125                                 // std.out will not be\r
126                                 outStream = new PrintWriter(System.out, true);\r
127                         }\r
128                         writeOut(outStream, result);\r
129                         // stream is closed in the method no need to close it here\r
130                 }\r
131 \r
132                 boolean listParameters = CmdHelper.listParameters(cmd);\r
133                 if (listParameters) {\r
134                         System.out.println(MetadataHelper.getParametersList(msaws));\r
135                 }\r
136                 boolean listPreset = CmdHelper.listPresets(cmd);\r
137                 if (listPreset) {\r
138                         System.out.println(MetadataHelper.getPresetList(msaws));\r
139                 }\r
140                 boolean listLimits = CmdHelper.listLimits(cmd);\r
141                 if (listLimits) {\r
142                         System.out.println(MetadataHelper.getLimits(msaws));\r
143                 }\r
144                 log.fine("Disconnecting...");\r
145                 ((Closeable) msaws).close();\r
146                 log.fine("Disconnected successfully!");\r
147         }\r
148 \r
149         /**\r
150          * Outputs AAcon results into the file represented by the outStream\r
151          * \r
152          * @param outStream\r
153          * @param result\r
154          *            the AACon scores to output\r
155          */\r
156         static void writeOut(Writer writer, ScoreManager result) {\r
157                 try {\r
158                         result.writeOut(writer);\r
159                 } catch (IOException e) {\r
160                         System.err\r
161                                         .println("Problems writing output file! Stack trace is below: ");\r
162                         e.printStackTrace();\r
163                 } finally {\r
164                         if (writer != null) {\r
165                                 try {\r
166                                         writer.close();\r
167                                 } catch (IOException ignored) {\r
168                                         // e.printStackTrace();\r
169                                 }\r
170                         }\r
171                 }\r
172         }\r
173 \r
174         /**\r
175          * Connects to a AACon web service by the host and the service name\r
176          * \r
177          * \r
178          * @return {@link AlignmentAnnotation}\r
179          * @throws WebServiceException\r
180          *             if cannot connect to a web service\r
181          */\r
182         public static SequenceAnnotation<AAConWS> connect()\r
183                         throws WebServiceException {\r
184                 URL url = null;\r
185                 log.log(Level.FINE, "Attempting to connect...");\r
186                 try {\r
187                         url = new URL(hostname + "/" + "AAConWS" + "?wsdl");\r
188                 } catch (MalformedURLException e) {\r
189                         e.printStackTrace();\r
190                         // ignore as the host name is already verified\r
191                 }\r
192                 QName qname = new QName(QUALIFIED_SERVICE_NAME, "AAConWS");\r
193                 Service serv = Service.create(url, qname);\r
194                 QName portName = new QName(QUALIFIED_SERVICE_NAME, "AAConWS" + "Port");\r
195 \r
196                 @SuppressWarnings("unchecked")\r
197                 SequenceAnnotation<AAConWS> serviceIF = serv.getPort(portName,\r
198                                 SequenceAnnotation.class);\r
199 \r
200                 log.log(Level.FINE, "Connected successfully!");\r
201                 return serviceIF;\r
202         }\r
203 \r
204         /**\r
205          * Calculate conservation for sequences loaded from the file\r
206          * \r
207          * @param wsproxy\r
208          *            a web service proxy\r
209          * @param file\r
210          *            the file to read the results from\r
211          * @param preset\r
212          *            Preset to use optional\r
213          * @param customOptions\r
214          *            the list of options\r
215          * @return Set<Score> the conservation scores\r
216          * @throws UnknownFileFormatException\r
217          */\r
218         static ScoreManager analize(File file, SequenceAnnotation<AAConWS> wsproxy,\r
219                         Preset<AAConWS> preset, List<Option<AAConWS>> customOptions) {\r
220 \r
221                 List<FastaSequence> fastalist = null;\r
222                 ScoreManager scores = null;\r
223                 try {\r
224                         fastalist = SequenceUtil.openInputStream(file.getAbsolutePath());\r
225 \r
226                         String jobId = null;\r
227                         if (customOptions != null && preset != null) {\r
228                                 System.out\r
229                                                 .println("WARN: Parameters (-f) are defined together with a preset (-r) ignoring preset!");\r
230                         }\r
231                         if (customOptions != null) {\r
232                                 jobId = wsproxy.customAnalize(fastalist, customOptions);\r
233                         } else if (preset != null) {\r
234                                 jobId = wsproxy.presetAnalize(fastalist, preset);\r
235                         } else {\r
236                                 jobId = wsproxy.analize(fastalist);\r
237                         }\r
238                         Thread.sleep(1000);\r
239                         scores = wsproxy.getAnnotation(jobId);\r
240 \r
241                 } catch (IOException e) {\r
242                         System.err\r
243                                         .println("Exception while reading the input file. "\r
244                                                         + "Check that the input file contains a list of fasta formatted sequences! "\r
245                                                         + "Exception details are below:");\r
246                         e.printStackTrace();\r
247                 } catch (JobSubmissionException e) {\r
248                         System.err\r
249                                         .println("Exception while submitting job to a web server. "\r
250                                                         + "Exception details are below:");\r
251                         e.printStackTrace();\r
252                 } catch (ResultNotAvailableException e) {\r
253                         System.err.println("Exception while waiting for results. "\r
254                                         + "Exception details are below:");\r
255                         e.printStackTrace();\r
256                 } catch (InterruptedException ignored) {\r
257                         // ignore and propagate an interruption\r
258                         Thread.currentThread().interrupt();\r
259                 } catch (WrongParameterException e) {\r
260                         System.err\r
261                                         .println("Exception while parsing the web method input parameters. "\r
262                                                         + "Exception details are below:");\r
263                         e.printStackTrace();\r
264                 } catch (UnknownFileFormatException e) {\r
265                         System.err\r
266                                         .println("Exception while attempting to read the input file "\r
267                                                         + "Exception details are below:");\r
268                         System.out.println(e.getMessage());\r
269                         e.printStackTrace();\r
270                 }\r
271                 return scores;\r
272         }\r
273 \r
274         /**\r
275          * Prints AAConClient usage information to standard out\r
276          * \r
277          * @param exitStatus\r
278          */\r
279         static void printUsage(int exitStatus) {\r
280                 System.out.println();\r
281                 System.out.println("Usage: <Class or Jar file name> "\r
282                                 + " ACTION [OPTIONS] ");\r
283                 System.out.println();\r
284                 System.out.println("ACTIONS: ");\r
285                 System.out\r
286                                 .println(inputkey\r
287                                                 + pseparator\r
288                                                 + "<inputFile> - full path to fasta or Clustal formatted alignment file ");\r
289                 System.out.println(paramList\r
290                                 + " - lists parameters supported by web service");\r
291                 System.out.println(presetList\r
292                                 + " - lists presets supported by web service");\r
293                 System.out.println(limitList + " - lists web services limits");\r
294                 System.out\r
295                                 .println("Please note that if input file is specified other actions are ignored");\r
296 \r
297                 System.out.println();\r
298                 System.out.println("OPTIONS (only for use with -i action):");\r
299 \r
300                 System.out.println(presetkey + pseparator\r
301                                 + "<presetName> - name of the preset to use");\r
302                 System.out\r
303                                 .println(outputkey\r
304                                                 + pseparator\r
305                                                 + "<outputFile> - full path to the file where to write the result");\r
306                 System.out\r
307                                 .println("-f=<parameterInputFile> - the name of the file with the list of parameters to use.");\r
308                 System.out\r
309                                 .println("Please note that -r and -f options cannot be used together. "\r
310                                                 + "Conservation is calculated with either a preset or "\r
311                                                 + "the parameters from the file, but not both!");\r
312 \r
313                 System.exit(exitStatus);\r
314         }\r
315 \r
316         /**\r
317          * Starts command line client, if no parameters are supplied prints help.\r
318          * \r
319          * @param args\r
320          *            Usage: <Class or Jar file name> ACTION [OPTIONS]\r
321          * \r
322          *            -i=<inputFile> - full path to fasta or Clustal formatted\r
323          *            alignment file\r
324          * \r
325          *            -parameters - lists parameters supported by web service\r
326          * \r
327          *            -presets - lists presets supported by web service\r
328          * \r
329          *            -limits - lists web services limits. Please note that if input\r
330          *            file is specified other actions are ignored\r
331          * \r
332          *            OPTIONS: (only for use with -i action):\r
333          * \r
334          *            -r=<presetName> - name of the preset to use\r
335          * \r
336          *            -o=<outputFile> - full path to the file where to write results\r
337          *            -f=<parameterInputFile> - the name of the file with the list\r
338          *            of parameters to use. Please note that -r and -f options\r
339          *            cannot be used together. Conservation is calculated with\r
340          *            either a preset or parameters from the file, but not both!\r
341          * \r
342          */\r
343         public static void main(String[] args) {\r
344 \r
345                 if (args == null) {\r
346                         printUsage(1);\r
347                 }\r
348                 if (args.length < 1) {\r
349                         System.out.println("No options is specified! ");\r
350                         printUsage(1);\r
351                 }\r
352 \r
353                 try {\r
354                         new AAConClient(args);\r
355                 } catch (IOException e) {\r
356                         log.log(Level.SEVERE, "IOException in client! " + e.getMessage(),\r
357                                         e.getCause());\r
358                         System.err.println("Cannot write output file! Stack trace: ");\r
359                         e.printStackTrace();\r
360                 }\r
361         }\r
362 }\r