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.metadata;
\r
21 import java.net.URL;
\r
22 import java.util.ArrayList;
\r
23 import java.util.HashSet;
\r
24 import java.util.List;
\r
25 import java.util.Set;
\r
26 import java.util.TreeSet;
\r
28 import javax.xml.bind.ValidationException;
\r
29 import javax.xml.bind.annotation.XmlAccessType;
\r
30 import javax.xml.bind.annotation.XmlAccessorType;
\r
31 import javax.xml.bind.annotation.XmlAttribute;
\r
32 import javax.xml.bind.annotation.XmlElement;
\r
34 import compbio.util.SysPrefs;
\r
35 import compbio.util.Util;
\r
38 * Command line option/flag or multiple exclusive options with no value. Example
\r
39 * -protein, -dna, -auto
\r
45 * type of executable
\r
47 @XmlAccessorType(XmlAccessType.FIELD)
\r
48 public class Option<T> implements Argument<T> {
\r
50 @XmlElement(required = true)
\r
51 protected String description;
\r
53 @XmlElement(required = true)
\r
54 Set<String> optionNames = new HashSet<String>();
\r
56 @XmlElement(required = true)
\r
57 protected String name;
\r
60 protected boolean isRequired;
\r
62 protected URL furtherDetails;
\r
64 protected String defaultValue;
\r
67 // Has to have no arg constructor for JAXB
\r
70 public Option(String name, String description) {
\r
72 this.description = description;
\r
76 * Human readable name of the option
\r
78 public String getName() {
\r
82 public void setName(String name) {
\r
87 * A long description of the Option
\r
89 public String getDescription() {
\r
93 public void setDescription(String description) {
\r
94 this.description = description;
\r
98 * The URL where further details about the option can be found
\r
100 public URL getFurtherDetails() {
\r
101 return furtherDetails;
\r
104 public void setFurtherDetails(URL furtherDetails) {
\r
105 this.furtherDetails = furtherDetails;
\r
109 * A default value of the option. Defaults to command line argument name
\r
112 public String getDefaultValue() {
\r
113 return defaultValue;
\r
117 * Sets one of the values defined in optionList as default. Attempting set
\r
118 * the value not listed there will result in WrongParameter exception
\r
120 * @param defaultVal
\r
121 * @throws WrongParameterException
\r
122 * is thrown if the defaultValue is not found in optionList
\r
124 public void setDefaultValue(String defaultVal)
\r
125 throws WrongParameterException {
\r
126 if (optionNames.isEmpty()) {
\r
127 throw new IllegalStateException("Please define optionNames first!");
\r
129 if (!valueExist(defaultVal, getOptionNames())) {
\r
130 throw new WrongParameterException(
\r
131 "Attempting to set illegal defaultValue '" + defaultVal
\r
132 + "' which is not defined optionNames for option: "
\r
135 this.defaultValue = defaultVal;
\r
138 static boolean valueExist(String testValue, List<String> values) {
\r
139 assert !Util.isEmpty(testValue);
\r
140 for (String val : values) {
\r
141 if (testValue.equalsIgnoreCase(val)) {
\r
149 * Flag that indicated that this option must be specified in the command
\r
150 * line for an executable to run
\r
152 * @return true is the option is required, false otherwise
\r
154 public boolean isRequired() {
\r
158 public void setRequired(boolean isRequired) {
\r
159 this.isRequired = isRequired;
\r
164 * @return List of option names
\r
166 public List<String> getOptionNames() {
\r
167 return new ArrayList<String>(optionNames);
\r
170 public void setOptionNames(Set<String> optionNames) {
\r
171 this.optionNames = new HashSet<String>(optionNames);
\r
175 * Adds an option to the optionName list
\r
178 * @return modified optionName list
\r
180 public Set<String> addOptionNames(String... value) {
\r
181 for (String v : value) {
\r
182 boolean added = this.optionNames.add(v);
\r
183 assert added : "Duplicated optionName is detected!";
\r
185 return this.optionNames;
\r
189 public String toString() {
\r
190 String value = "Option name: " + this.name + SysPrefs.newlinechar;
\r
191 value += "Description: " + this.description + SysPrefs.newlinechar;
\r
192 if (!Util.isEmpty(defaultValue)) {
\r
193 value += "Default value: " + this.defaultValue
\r
194 + SysPrefs.newlinechar;
\r
196 value += "URL: " + this.furtherDetails + SysPrefs.newlinechar;
\r
197 value += "Is required: " + this.isRequired + SysPrefs.newlinechar;
\r
198 if (!this.optionNames.isEmpty()) {
\r
199 Set<String> sortedPosval = new TreeSet<String>(this.optionNames);
\r
200 value += "Option Names: " + SysPrefs.newlinechar;
\r
201 for (String val : sortedPosval) {
\r
202 value += val + SysPrefs.newlinechar;
\r
209 * Convert the option to the command string.
\r
211 * @return If only one optionName is defined, than it is returned, if many
\r
212 * option names are defined, then the defaultValue is returned.
\r
213 * Option must have a default value if there are many optionNames to
\r
216 public String toCommand(String nameValueSeparator) {
\r
217 if (optionNames.size() == 1) {
\r
218 return optionNames.iterator().next();
\r
220 return getDefaultValue();
\r
224 public boolean equals(Object obj) {
\r
228 Option<?> objArg = null;
\r
229 if (obj instanceof Option<?>) {
\r
230 objArg = (Option<?>) obj;
\r
234 if (!Util.isEmpty(objArg.name) && !Util.isEmpty(name)) {
\r
235 if (!objArg.name.equals(this.name)) {
\r
239 if (!Util.isEmpty(objArg.description) && !Util.isEmpty(description)) {
\r
240 if (!objArg.description.equals(this.description)) {
\r
244 if (objArg.isRequired != this.isRequired) {
\r
247 if (!Util.isEmpty(objArg.defaultValue) && !Util.isEmpty(defaultValue)) {
\r
248 if (!objArg.defaultValue.equals(this.defaultValue)) {
\r
252 if (objArg.optionNames.size() != this.optionNames.size()) {
\r
255 int matchCount = 0;
\r
256 for (String oname : objArg.optionNames) {
\r
257 if (Util.isEmpty(oname)) {
\r
260 for (String thisoname : this.optionNames) {
\r
261 if (oname.equals(thisoname)) {
\r
267 if (matchCount != objArg.optionNames.size()) {
\r
274 public int hashCode() {
\r
275 int code = this.name.hashCode() * this.description.hashCode();
\r
276 if (this.isRequired) {
\r
277 code += this.furtherDetails.hashCode() * 3;
\r
279 if (defaultValue != null) {
\r
280 code += this.defaultValue.hashCode() * 2;
\r
283 if (this.description != null) {
\r
284 code += this.description.hashCode() * 4;
\r
291 * List of possible optionNames
\r
294 public List<String> getPossibleValues() {
\r
295 return new ArrayList<String>(optionNames);
\r
299 public void setValue(String dValue) throws WrongParameterException {
\r
300 this.setDefaultValue(dValue);
\r
304 * Validate the option
\r
306 * @throws ValidationException
\r
307 * is the option is invalid. This happens if option does not
\r
308 * have a default value but have multiple option names, or no
\r
309 * option names is defined
\r
311 void validate() throws ValidationException {
\r
312 if (optionNames == null) {
\r
313 throw new ValidationException(
\r
314 "Option names are not defined for option: " + this);
\r
316 if (optionNames.size() > 1 && Util.isEmpty(getDefaultValue())) {
\r
317 throw new ValidationException(
\r
318 "Default value is required as multiple optionNames are defined for option: "
\r
321 if (Util.isEmpty(name)) {
\r
322 throw new ValidationException("No name is defined for option: "
\r