Next version of JABA
[jabaws.git] / engine / compbio / engine / client / SkeletalExecutable.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.engine.client;\r
20 \r
21 import java.io.File;\r
22 import java.util.Arrays;\r
23 import java.util.List;\r
24 \r
25 import org.apache.log4j.Logger;\r
26 \r
27 import compbio.engine.client.CommandBuilder.Parameter;\r
28 import compbio.engine.conf.PropertyHelperManager;\r
29 import compbio.util.PropertyHelper;\r
30 import compbio.util.Util;\r
31 \r
32 public abstract class SkeletalExecutable<T> implements Executable<T> {\r
33 \r
34         private static final PropertyHelper ph = PropertyHelperManager\r
35                         .getPropertyHelper();\r
36 \r
37         private static Logger log = Logger.getLogger(SkeletalExecutable.class);\r
38 \r
39         protected String inputFile = "input.txt";\r
40         protected String outputFile = "output.txt";\r
41         protected String errorFile = "error.txt";\r
42 \r
43         private boolean isInputSet = false;\r
44         private boolean isOutputSet = false;\r
45         private boolean isErrorSet = false;\r
46 \r
47         /**\r
48          * This has to allow duplicate parameters as different options may have the\r
49          * same value e.g. Muscle -weight1 clustalw -weight2 clustalw\r
50          */\r
51         protected CommandBuilder<T> cbuilder;\r
52 \r
53         public SkeletalExecutable() {\r
54                 cbuilder = new CommandBuilder<T>(" ");\r
55         }\r
56 \r
57         public SkeletalExecutable(String parameterKeyValueDelimiter) {\r
58                 assert parameterKeyValueDelimiter != null;\r
59                 cbuilder = new CommandBuilder<T>(parameterKeyValueDelimiter);\r
60         }\r
61 \r
62         public SkeletalExecutable<T> setInput(String inFile) {\r
63                 if (compbio.util.Util.isEmpty(inFile)) {\r
64                         throw new IllegalArgumentException("Input file must not be NULL");\r
65                 }\r
66                 this.inputFile = inFile;\r
67                 this.isInputSet = true;\r
68                 return this;\r
69         }\r
70 \r
71         public SkeletalExecutable<T> setOutput(String outFile) {\r
72                 if (compbio.util.Util.isEmpty(outFile)\r
73                                 || PathValidator.isAbsolutePath(outFile)) {\r
74                         throw new IllegalArgumentException(\r
75                                         "Output file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
76                                                         + outFile);\r
77                 }\r
78                 this.outputFile = outFile;\r
79                 this.isOutputSet = true;\r
80                 return this;\r
81         }\r
82 \r
83         public SkeletalExecutable<T> setError(String errFile) {\r
84                 if (compbio.util.Util.isEmpty(errFile)\r
85                                 || PathValidator.isAbsolutePath(errFile)) {\r
86                         throw new IllegalArgumentException(\r
87                                         "Error file must not be NULL and Absolute path could not be used! Please provide the filename only. Value provided: "\r
88                                                         + errFile);\r
89                 }\r
90                 this.errorFile = errFile;\r
91                 this.isErrorSet = true;\r
92                 return this;\r
93         }\r
94 \r
95         @Override\r
96         public CommandBuilder<T> getParameters(ExecProvider provider) {\r
97                 /*\r
98                  * Prevent modification of the parameters unintentionally. This is\r
99                  * important to preserve executable parameters intact as engine could\r
100                  * add things into the array as it see fit. For instance\r
101                  * ExecutableWrapper (part of local engines) add command line as the\r
102                  * first element of an array.\r
103                  */\r
104                 paramValueUpdater();\r
105                 return cbuilder;\r
106         }\r
107 \r
108         @Override\r
109         public Executable<T> addParameters(List<String> parameters) {\r
110                 cbuilder.addParams(parameters);\r
111                 return this;\r
112         }\r
113 \r
114         public Executable<T> setParameter(String parameter) {\r
115                 cbuilder.setParam(parameter);\r
116                 return this;\r
117         }\r
118 \r
119         /**\r
120          * This is a generic method of changing values of the parameters with\r
121          * properties\r
122          * \r
123          * This method iterates via commands for an executable finding matches from\r
124          * the Executable.properties file and replacing values in CommandBuilder\r
125          * with a combination of value from CommandBuilder to merge path from\r
126          * properties\r
127          */\r
128         void paramValueUpdater() {\r
129                 for (Parameter command : cbuilder.getCommandList()) {\r
130                         if (command.value == null) {\r
131                                 continue;\r
132                         }\r
133                         String propertyPath = compbio.engine.client.Util.getExecProperty(\r
134                                         command.name + ".path", getType());\r
135                         if (Util.isEmpty(propertyPath)) {\r
136                                 continue;\r
137                         }\r
138                         if (new File(command.value).isAbsolute()) {\r
139                                 // Matrix can be found so no actions necessary\r
140                                 // This method has been called already and the matrix name\r
141                                 // is modified to contain full path // no further actions is\r
142                                 // necessary\r
143                                 continue;\r
144                         }\r
145                         String absMatrixPath = compbio.engine.client.Util\r
146                                         .convertToAbsolute(propertyPath);\r
147                         command.value = absMatrixPath + File.separator + command.value;\r
148                         cbuilder.setParam(command);\r
149                 }\r
150         }\r
151 \r
152         /**\r
153          * This method cannot really tell whether the files has actually been\r
154          * created or not. It must be overridden as required.\r
155          * \r
156          * @see compbio.engine.client.Executable#getCreatedFiles()\r
157          */\r
158         @Override\r
159         public List<String> getCreatedFiles() {\r
160                 return Arrays.asList(getOutput(), getError());\r
161         }\r
162 \r
163         @Override\r
164         public String getInput() {\r
165                 return inputFile;\r
166         }\r
167 \r
168         protected boolean isInputSet() {\r
169                 return isInputSet;\r
170         }\r
171 \r
172         protected boolean isOutputSet() {\r
173                 return isOutputSet;\r
174         }\r
175 \r
176         protected boolean isErrorSet() {\r
177                 return isErrorSet;\r
178         }\r
179 \r
180         @Override\r
181         public String getOutput() {\r
182                 return outputFile;\r
183         }\r
184 \r
185         @Override\r
186         public String getError() {\r
187                 return errorFile;\r
188         }\r
189 \r
190         @Override\r
191         public String toString() {\r
192                 String value = "Input: " + this.getInput() + "\n";\r
193                 value += "Output: " + this.getOutput() + "\n";\r
194                 value += "Error: " + this.getError() + "\n";\r
195                 value += "Class: " + this.getClass() + "\n";\r
196                 value += "Params: " + cbuilder + "\n";\r
197                 return value;\r
198         }\r
199 \r
200         @Override\r
201         public Executable<?> loadRunConfiguration(RunConfiguration rconfig) {\r
202                 if (!compbio.util.Util.isEmpty(rconfig.getOutput())) {\r
203                         setOutput(rconfig.getOutput());\r
204                 }\r
205                 if (!compbio.util.Util.isEmpty(rconfig.getError())) {\r
206                         setError(rconfig.getError());\r
207                 }\r
208                 if (!compbio.util.Util.isEmpty(rconfig.getInput())) {\r
209                         setInput(rconfig.getInput());\r
210                 }\r
211                 this.cbuilder = (CommandBuilder<T>) rconfig.getParameters();\r
212                 return this;\r
213         }\r
214 \r
215         @Override\r
216         public boolean equals(Object obj) {\r
217                 if (obj == null) {\r
218                         return false;\r
219                 }\r
220                 if (!(obj instanceof SkeletalExecutable<?>)) {\r
221                         return false;\r
222                 }\r
223                 SkeletalExecutable<?> exec = (SkeletalExecutable<?>) obj;\r
224                 if (!Util.isEmpty(this.inputFile) && !Util.isEmpty(exec.inputFile)) {\r
225                         if (!this.inputFile.equals(exec.inputFile)) {\r
226                                 return false;\r
227                         }\r
228                 }\r
229                 if (!Util.isEmpty(this.outputFile) && !Util.isEmpty(exec.outputFile)) {\r
230                         if (!this.outputFile.equals(exec.outputFile)) {\r
231                                 return false;\r
232                         }\r
233                 }\r
234                 if (!Util.isEmpty(this.errorFile) && !Util.isEmpty(exec.errorFile)) {\r
235                         if (!this.errorFile.equals(exec.errorFile)) {\r
236                                 return false;\r
237                         }\r
238                 }\r
239                 if (!this.cbuilder.equals(exec.cbuilder)) {\r
240                         return false;\r
241                 }\r
242                 return true;\r
243         }\r
244 \r
245         @Override\r
246         public int hashCode() {\r
247                 int code = inputFile.hashCode();\r
248                 code += outputFile.hashCode();\r
249                 code += errorFile.hashCode();\r
250                 code *= this.cbuilder.hashCode();\r
251                 return code;\r
252         }\r
253 \r
254         public String getClusterSettings() {\r
255                 String settings = ph.getProperty(getType().getSimpleName()\r
256                                 .toLowerCase()\r
257                                 + ".cluster.settings");\r
258                 return settings == null ? "" : settings;\r
259         }\r
260 \r
261         public abstract Class<? extends Executable<?>> getType();\r
262 \r
263 }\r