34fc751a2f915414bb68da74f09bc772d62774fa
[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.OutputStream;\r
34 import java.net.MalformedURLException;\r
35 import java.net.URL;\r
36 import java.util.List;\r
37 import java.util.Set;\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.Annotation;\r
46 import compbio.data.sequence.FastaSequence;\r
47 import compbio.data.sequence.Score;\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                 Annotation<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                 Set<Score> result = null;\r
117                 if (inputFile != null) {\r
118                         System.out.println("Calculating conservation...");\r
119                         result = analize(inputFile, msaws, preset, customOptions);\r
120                         OutputStream outStream = null;\r
121                         if (outFile != null) {\r
122                                 outStream = IOHelper.getOutStream(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 = System.out;\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(OutputStream outStream, Set<Score> result) {\r
157                 try {\r
158                         Score.write(result, outStream);\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 (outStream != null) {\r
165                                 try {\r
166                                         outStream.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 Annotation}\r
179          * @throws WebServiceException\r
180          *             if cannot connect to a web service\r
181          */\r
182         public static Annotation<AAConWS> connect() throws WebServiceException {\r
183                 URL url = null;\r
184                 log.log(Level.FINE, "Attempting to connect...");\r
185                 try {\r
186                         url = new URL(hostname + "/" + "AAConWS" + "?wsdl");\r
187                 } catch (MalformedURLException e) {\r
188                         e.printStackTrace();\r
189                         // ignore as the host name is already verified\r
190                 }\r
191                 QName qname = new QName(QUALIFIED_SERVICE_NAME, "AAConWS");\r
192                 Service serv = Service.create(url, qname);\r
193                 QName portName = new QName(QUALIFIED_SERVICE_NAME, "AAConWS" + "Port");\r
194 \r
195                 @SuppressWarnings("unchecked")\r
196                 Annotation<AAConWS> serviceIF = serv\r
197                                 .getPort(portName, Annotation.class);\r
198 \r
199                 log.log(Level.FINE, "Connected successfully!");\r
200                 return serviceIF;\r
201         }\r
202 \r
203         /**\r
204          * Calculate conservation for sequences loaded from the file\r
205          * \r
206          * @param wsproxy\r
207          *            a web service proxy\r
208          * @param file\r
209          *            the file to read the results from\r
210          * @param preset\r
211          *            Preset to use optional\r
212          * @param customOptions\r
213          *            the list of options\r
214          * @return Set<Score> the conservation scores\r
215          * @throws UnknownFileFormatException\r
216          */\r
217         static Set<Score> analize(File file, Annotation<AAConWS> wsproxy,\r
218                         Preset<AAConWS> preset, List<Option<AAConWS>> customOptions) {\r
219 \r
220                 List<FastaSequence> fastalist = null;\r
221                 Set<Score> scores = null;\r
222                 try {\r
223                         fastalist = SequenceUtil.openInputStream(file.getAbsolutePath());\r
224 \r
225                         String jobId = null;\r
226                         if (customOptions != null && preset != null) {\r
227                                 System.out\r
228                                                 .println("WARN: Parameters (-f) are defined together with a preset (-r) ignoring preset!");\r
229                         }\r
230                         if (customOptions != null) {\r
231                                 jobId = wsproxy.customAnalize(fastalist, customOptions);\r
232                         } else if (preset != null) {\r
233                                 jobId = wsproxy.presetAnalize(fastalist, preset);\r
234                         } else {\r
235                                 jobId = wsproxy.analize(fastalist);\r
236                         }\r
237                         Thread.sleep(1000);\r
238                         scores = wsproxy.getAnnotation(jobId);\r
239 \r
240                 } catch (IOException e) {\r
241                         System.err\r
242                                         .println("Exception while reading the input file. "\r
243                                                         + "Check that the input file contains a list of fasta formatted sequences! "\r
244                                                         + "Exception details are below:");\r
245                         e.printStackTrace();\r
246                 } catch (JobSubmissionException e) {\r
247                         System.err\r
248                                         .println("Exception while submitting job to a web server. "\r
249                                                         + "Exception details are below:");\r
250                         e.printStackTrace();\r
251                 } catch (ResultNotAvailableException e) {\r
252                         System.err.println("Exception while waiting for results. "\r
253                                         + "Exception details are below:");\r
254                         e.printStackTrace();\r
255                 } catch (InterruptedException ignored) {\r
256                         // ignore and propagate an interruption\r
257                         Thread.currentThread().interrupt();\r
258                 } catch (WrongParameterException e) {\r
259                         System.err\r
260                                         .println("Exception while parsing the web method input parameters. "\r
261                                                         + "Exception details are below:");\r
262                         e.printStackTrace();\r
263                 } catch (UnknownFileFormatException e) {\r
264                         System.err\r
265                                         .println("Exception while attempting to read the input file "\r
266                                                         + "Exception details are below:");\r
267                         System.out.println(e.getMessage());\r
268                         e.printStackTrace();\r
269                 }\r
270                 return scores;\r
271         }\r
272 \r
273         /**\r
274          * Prints AAConClient usage information to standard out\r
275          * \r
276          * @param exitStatus\r
277          */\r
278         static void printUsage(int exitStatus) {\r
279                 System.out.println();\r
280                 System.out.println("Usage: <Class or Jar file name> "\r
281                                 + " ACTION [OPTIONS] ");\r
282                 System.out.println();\r
283                 System.out.println("ACTIONS: ");\r
284                 System.out\r
285                                 .println(inputkey\r
286                                                 + pseparator\r
287                                                 + "<inputFile> - full path to fasta or Clustal formatted alignment file ");\r
288                 System.out.println(paramList\r
289                                 + " - lists parameters supported by web service");\r
290                 System.out.println(presetList\r
291                                 + " - lists presets supported by web service");\r
292                 System.out.println(limitList + " - lists web services limits");\r
293                 System.out\r
294                                 .println("Please note that if input file is specified other actions are ignored");\r
295 \r
296                 System.out.println();\r
297                 System.out.println("OPTIONS (only for use with -i action):");\r
298 \r
299                 System.out.println(presetkey + pseparator\r
300                                 + "<presetName> - name of the preset to use");\r
301                 System.out\r
302                                 .println(outputkey\r
303                                                 + pseparator\r
304                                                 + "<outputFile> - full path to the file where to write the result");\r
305                 System.out\r
306                                 .println("-f=<parameterInputFile> - the name of the file with the list of parameters to use.");\r
307                 System.out\r
308                                 .println("Please note that -r and -f options cannot be used together. "\r
309                                                 + "Conservation is calculated with either a preset or "\r
310                                                 + "the parameters from the file, but not both!");\r
311 \r
312                 System.exit(exitStatus);\r
313         }\r
314 \r
315         /**\r
316          * Starts command line client, if no parameters are supplied prints help.\r
317          * \r
318          * @param args\r
319          *            Usage: <Class or Jar file name> ACTION [OPTIONS]\r
320          * \r
321          *            -i=<inputFile> - full path to fasta or Clustal formatted\r
322          *            alignment file\r
323          * \r
324          *            -parameters - lists parameters supported by web service\r
325          * \r
326          *            -presets - lists presets supported by web service\r
327          * \r
328          *            -limits - lists web services limits. Please note that if input\r
329          *            file is specified other actions are ignored\r
330          * \r
331          *            OPTIONS: (only for use with -i action):\r
332          * \r
333          *            -r=<presetName> - name of the preset to use\r
334          * \r
335          *            -o=<outputFile> - full path to the file where to write results\r
336          *            -f=<parameterInputFile> - the name of the file with the list\r
337          *            of parameters to use. Please note that -r and -f options\r
338          *            cannot be used together. Conservation is calculated with\r
339          *            either a preset or parameters from the file, but not both!\r
340          * \r
341          */\r
342         public static void main(String[] args) {\r
343 \r
344                 if (args == null) {\r
345                         printUsage(1);\r
346                 }\r
347                 if (args.length < 1) {\r
348                         System.out.println("No options is specified! ");\r
349                         printUsage(1);\r
350                 }\r
351 \r
352                 try {\r
353                         new AAConClient(args);\r
354                 } catch (IOException e) {\r
355                         log.log(Level.SEVERE, "IOException in client! " + e.getMessage(),\r
356                                         e.getCause());\r
357                         System.err.println("Cannot write output file! Stack trace: ");\r
358                         e.printStackTrace();\r
359                 }\r
360         }\r
361 }\r