1 /* Copyright (c) 2009 Peter Troshin
\r
3 * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0
\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
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
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
15 * Any republication or derived work distributed in source code form
\r
16 * must include this copyright and license notice.
\r
19 package compbio.engine.client;
\r
21 import java.util.ArrayList;
\r
22 import java.util.LinkedHashMap;
\r
23 import java.util.List;
\r
24 import java.util.Map;
\r
26 import javax.xml.bind.annotation.XmlAccessType;
\r
27 import javax.xml.bind.annotation.XmlAccessorType;
\r
28 import javax.xml.bind.annotation.XmlTransient;
\r
30 import org.apache.log4j.Logger;
\r
32 import compbio.metadata.Option;
\r
35 * Class to replace List<String> params in the SkeletalExecutable
\r
36 * So this must be included into executable
\r
38 * List<String> Executable.getParameter() - is OK, but
\r
39 * when RunConfiguration is loaded CommandBuilder must be recreated from the saved list!
\r
40 * It is safer to return CommandBuilder from getParameters and persist it but needs more work.
\r
41 * Benefits of doing it: delimiter is saved, key value pairs are explicitly known, no reliance on the order for
\r
42 * space delimited key value pairs, fully functional object
\r
44 * TODO complete and use
\r
46 @XmlAccessorType(XmlAccessType.FIELD)
\r
47 public class CommandBuilder<T> {
\r
49 private static final Logger log = Logger.getLogger(CommandBuilder.class);
\r
51 Map<String, Parameter> paramList;
\r
52 String nameValueSeparator;
\r
54 // Optionally accept order template with keys in order
\r
55 // List<String> orderTemplate
\r
56 // String keyPrefix;
\r
58 private CommandBuilder() {
\r
59 // JAXB default constructor
\r
62 public CommandBuilder(String nameValueSeparator) {
\r
63 this.paramList = new LinkedHashMap<String, Parameter>();
\r
64 this.nameValueSeparator = nameValueSeparator;
\r
67 public void addParams(List<String> params) {
\r
68 for (String param : params) {
\r
73 public void setParams(List<String> params) {
\r
78 Parameter newParameter(String param) {
\r
79 if (compbio.util.Util.isEmpty(param)) {
\r
80 throw new NullPointerException("Param must be provided!");
\r
82 if (isCombinedValue(param)) {
\r
83 return new Parameter(getName(param), getValue(param));
\r
85 return new Parameter(param);
\r
88 boolean isCombinedValue(String param) {
\r
89 return param.contains(nameValueSeparator);
\r
92 public boolean hasParam(String paramName) {
\r
93 return paramList.containsKey(paramName);
\r
96 String getName(String param) {
\r
97 assert param.indexOf(nameValueSeparator) >= 0 : "The value does not look like a combined value (key+value). Value:"
\r
99 return param.substring(0, param.indexOf(nameValueSeparator));
\r
102 String getValue(String param) {
\r
103 assert param.indexOf(nameValueSeparator) >= 0 : "The value does not look like a combined value (key+value). Value:"
\r
105 return param.substring(param.indexOf(nameValueSeparator) + 1);
\r
108 public boolean setFirst(String param) {
\r
109 Parameter p = newParameter(param);
\r
111 return setParam(p);
\r
114 public boolean setParam(String param) {
\r
115 return setParam(newParameter(param));
\r
118 boolean setParam(Parameter param) {
\r
119 boolean overriden = paramList.put(param.name, param) != null;
\r
121 log.warn("Key " + param.name
\r
122 + " in the command list has been overriden! ");
\r
127 public boolean setLast(String paramName) {
\r
128 Parameter p = newParameter(paramName);
\r
130 return setParam(p);
\r
133 public boolean setLast(String paramName, String paramValue) {
\r
134 if (compbio.util.Util.isEmpty(paramName)) {
\r
135 throw new NullPointerException("ParamName must be provided!");
\r
137 // paramName could contain separator character as long as there is no
\r
139 // e.g. paramName could be a path to the file with spaces
\r
140 if (paramValue != null && paramName.contains(nameValueSeparator)) {
\r
141 log.warn("WARN: paramName "
\r
143 + " contains nameValue separator. Removing the separator...");
\r
144 paramName = paramName.trim().substring(0, paramName.length() - 1);
\r
146 if (paramValue != null && paramName.contains(nameValueSeparator)) {
\r
147 throw new IllegalArgumentException("Parameter name '" + paramName
\r
148 + "' contains name value separator character '"
\r
149 + nameValueSeparator + "'!");
\r
151 Parameter p = new Parameter(paramName, paramValue);
\r
153 return setParam(p);
\r
156 public String getParamValue(String paramName) {
\r
157 Parameter p = paramList.get(paramName);
\r
158 return p == null ? null : p.value;
\r
161 public boolean removeParam(String paramName) {
\r
162 return paramList.remove(paramName) != null;
\r
165 public boolean setParam(String paramName, String paramValue) {
\r
166 return setParam(new Parameter(paramName, paramValue));
\r
169 public List<String> getCommands() {
\r
170 return parameterToString(getCommandList());
\r
173 public String getCommandString() {
\r
174 String command = "";
\r
175 for (Parameter p : getCommandList()) {
\r
176 command += p.toCommand(this.nameValueSeparator) + " ";
\r
181 List<String> parameterToString(List<Parameter> parameters) {
\r
182 List<String> commands = new ArrayList<String>();
\r
183 for (Parameter p : parameters) {
\r
184 if (isWhiteSpaceSeparator()) {
\r
185 commands.add(p.name);
\r
186 if (p.value != null) {
\r
187 commands.add(p.value);
\r
190 commands.add(p.toCommand(this.nameValueSeparator));
\r
197 * This produces the same result as getCommands method. The only difference
\r
198 * is that it accepts a List of Options as an input
\r
201 * @return the instance of the CommandBuilder
\r
203 public static <T> CommandBuilder<T> newCommandBuilder(
\r
204 List<? extends Option<T>> arguments, String nameValueSeparator) {
\r
205 CommandBuilder<T> cbuilder = new CommandBuilder<T>(nameValueSeparator);
\r
206 for (Option<T> option : arguments) {
\r
207 String comm = option.toCommand(nameValueSeparator);
\r
208 log.trace("Setting parameter " + comm);
\r
209 cbuilder.setParam(comm);
\r
214 public int size() {
\r
215 return paramList.size();
\r
218 boolean isWhiteSpaceSeparator() {
\r
219 return nameValueSeparator.trim().length() == 0;
\r
222 List<Parameter> getCommandList() {
\r
223 List<Parameter> commands = new ArrayList<Parameter>();
\r
224 Parameter first = null;
\r
225 Parameter last = null;
\r
226 for (Parameter param : paramList.values()) {
\r
227 if (param.isFirst()) {
\r
228 assert first == null : "Attempting to set more the one parameter as FIRST! "
\r
229 + "Parameter which has been set is: "
\r
231 + "\n Parameters to be set is " + param;
\r
233 commands.add(0, first);
\r
236 if (param.isLast()) {
\r
237 assert last == null : "Attempting to set more the one parameter as LAST! "
\r
238 + "Parameter which has been set is: "
\r
240 + "\n Parameters to be set is " + param;
\r
244 commands.add(param);
\r
246 if (last != null) {
\r
247 commands.add(last);
\r
253 public int hashCode() {
\r
254 final int prime = 31;
\r
258 + ((nameValueSeparator == null) ? 0 : nameValueSeparator
\r
260 result = prime * result
\r
261 + ((paramList == null) ? 0 : paramList.hashCode());
\r
266 public boolean equals(Object obj) {
\r
271 if (getClass() != obj.getClass())
\r
273 CommandBuilder<?> other = (CommandBuilder<?>) obj;
\r
274 if (nameValueSeparator == null) {
\r
275 if (other.nameValueSeparator != null)
\r
277 } else if (!nameValueSeparator.equals(other.nameValueSeparator))
\r
279 if (paramList == null) {
\r
280 if (other.paramList != null)
\r
283 if (other.paramList == null && paramList != null) {
\r
286 if (paramList.size() != other.paramList.size()) {
\r
290 * Order is important at runtime, but jaxb will not preserve the order
\r
291 * on marshalling This is to no concern here as the order is managed
\r
292 * internally using position
\r
294 for (Map.Entry<String, Parameter> param : paramList.entrySet()) {
\r
295 String key = param.getKey();
\r
296 Parameter p = other.paramList.get(key);
\r
300 if (!p.equals(param.getValue())) {
\r
308 public String toString() {
\r
309 String value = "NameValueSeparator: " + nameValueSeparator + "\n";
\r
310 for (Map.Entry<String, Parameter> entry : paramList.entrySet()) {
\r
311 value += "Key: " + entry.getKey() + "\n" + " Value: "
\r
312 + entry.getValue() + "\n";
\r
317 @XmlAccessorType(XmlAccessType.FIELD)
\r
318 static class Parameter {
\r
321 private static final int LAST = -100;
\r
323 private static final int FIRST = -200;
\r
325 // e.g. stick it at the beginning or the end or elsewhere
\r
326 private int position = -1;
\r
332 // JAXB default constructor
\r
335 Parameter(String name) {
\r
339 Parameter(String name, String value) {
\r
341 this.value = value;
\r
345 this.position = LAST;
\r
349 this.position = FIRST;
\r
352 void setAtPosition(int position) {
\r
353 throw new UnsupportedOperationException();
\r
354 // this.position = position;
\r
358 return position == LAST;
\r
361 boolean isFirst() {
\r
362 return position == FIRST;
\r
365 String toCommand(String separator) {
\r
366 if (value == null) {
\r
369 return name + separator + value;
\r
373 public String toString() {
\r
374 String value = "Name: " + name + "\n";
\r
375 if (value != null) {
\r
376 value += "Value: " + value + "\n";
\r
378 if (position == LAST) {
\r
379 value += "Position: LAST" + "\n";
\r
380 } else if (position == FIRST) {
\r
381 value += "Position: FIRST" + "\n";
\r
382 } else if (position != -1) {
\r
383 value += "Position:" + position + "\n";
\r
389 public int hashCode() {
\r
390 final int prime = 7;
\r
392 result = prime * result + ((name == null) ? 0 : name.hashCode());
\r
393 result = prime * result + position;
\r
394 result = prime * result + ((value == null) ? 0 : value.hashCode());
\r
399 public boolean equals(Object obj) {
\r
404 if (getClass() != obj.getClass())
\r
406 Parameter other = (Parameter) obj;
\r
407 if (name == null) {
\r
408 if (other.name != null)
\r
410 } else if (!name.equals(other.name))
\r
412 if (position != other.position)
\r
414 if (value == null) {
\r
415 if (other.value != null)
\r
417 } else if (!value.equals(other.value))
\r