| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.cli; |
| |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** <p>Describes a single command-line option. It maintains |
| * information regarding the short-name of the option, the long-name, |
| * if any exists, a flag indicating if an argument is required for |
| * this option, and a self-documenting description of the option.</p> |
| * |
| * <p>An Option is not created independantly, but is create through |
| * an instance of {@link Options}.<p> |
| * |
| * @see org.apache.commons.cli.Options |
| * @see org.apache.commons.cli.CommandLine |
| * |
| * @author bob mcwhirter (bob @ werken.com) |
| * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
| * @version $Revision$, $Date$ |
| */ |
| public class Option implements Cloneable, Serializable |
| { |
| private static final long serialVersionUID = 1L; |
| |
| /** constant that specifies the number of argument values has not been specified */ |
| public static final int UNINITIALIZED = -1; |
| |
| /** constant that specifies the number of argument values is infinite */ |
| public static final int UNLIMITED_VALUES = -2; |
| |
| /** the name of the option */ |
| private String opt; |
| |
| /** the long representation of the option */ |
| private String longOpt; |
| |
| /** the name of the argument for this option */ |
| private String argName = "arg"; |
| |
| /** description of the option */ |
| private String description; |
| |
| /** specifies whether this option is required to be present */ |
| private boolean required; |
| |
| /** specifies whether the argument value of this Option is optional */ |
| private boolean optionalArg; |
| |
| /** the number of argument values this option can have */ |
| private int numberOfArgs = UNINITIALIZED; |
| |
| /** the type of this Option */ |
| private Object type; |
| |
| /** the list of argument values **/ |
| private List values = new ArrayList(); |
| |
| /** the character that is the value separator */ |
| private char valuesep; |
| |
| /** |
| * Creates an Option using the specified parameters. |
| * |
| * @param opt short representation of the option |
| * @param description describes the function of the option |
| * |
| * @throws IllegalArgumentException if there are any non valid |
| * Option characters in <code>opt</code>. |
| */ |
| public Option(String opt, String description) throws IllegalArgumentException |
| { |
| this(opt, null, false, description); |
| } |
| |
| /** |
| * Creates an Option using the specified parameters. |
| * |
| * @param opt short representation of the option |
| * @param hasArg specifies whether the Option takes an argument or not |
| * @param description describes the function of the option |
| * |
| * @throws IllegalArgumentException if there are any non valid |
| * Option characters in <code>opt</code>. |
| */ |
| public Option(String opt, boolean hasArg, String description) throws IllegalArgumentException |
| { |
| this(opt, null, hasArg, description); |
| } |
| |
| /** |
| * Creates an Option using the specified parameters. |
| * |
| * @param opt short representation of the option |
| * @param longOpt the long representation of the option |
| * @param hasArg specifies whether the Option takes an argument or not |
| * @param description describes the function of the option |
| * |
| * @throws IllegalArgumentException if there are any non valid |
| * Option characters in <code>opt</code>. |
| */ |
| public Option(String opt, String longOpt, boolean hasArg, String description) |
| throws IllegalArgumentException |
| { |
| // ensure that the option is valid |
| OptionValidator.validateOption(opt); |
| |
| this.opt = opt; |
| this.longOpt = longOpt; |
| |
| // if hasArg is set then the number of arguments is 1 |
| if (hasArg) |
| { |
| this.numberOfArgs = 1; |
| } |
| |
| this.description = description; |
| } |
| |
| /** |
| * Returns the id of this Option. This is only set when the |
| * Option shortOpt is a single character. This is used for switch |
| * statements. |
| * |
| * @return the id of this Option |
| */ |
| public int getId() |
| { |
| return getKey().charAt(0); |
| } |
| |
| /** |
| * Returns the 'unique' Option identifier. |
| * |
| * @return the 'unique' Option identifier |
| */ |
| String getKey() |
| { |
| // if 'opt' is null, then it is a 'long' option |
| if (opt == null) |
| { |
| return longOpt; |
| } |
| |
| return opt; |
| } |
| |
| /** |
| * Retrieve the name of this Option. |
| * |
| * It is this String which can be used with |
| * {@link CommandLine#hasOption(String opt)} and |
| * {@link CommandLine#getOptionValue(String opt)} to check |
| * for existence and argument. |
| * |
| * @return The name of this option |
| */ |
| public String getOpt() |
| { |
| return opt; |
| } |
| |
| /** |
| * Retrieve the type of this Option. |
| * |
| * @return The type of this option |
| */ |
| public Object getType() |
| { |
| return type; |
| } |
| |
| /** |
| * Sets the type of this Option. |
| * |
| * @param type the type of this Option |
| */ |
| public void setType(Object type) |
| { |
| this.type = type; |
| } |
| |
| /** |
| * Retrieve the long name of this Option. |
| * |
| * @return Long name of this option, or null, if there is no long name |
| */ |
| public String getLongOpt() |
| { |
| return longOpt; |
| } |
| |
| /** |
| * Sets the long name of this Option. |
| * |
| * @param longOpt the long name of this Option |
| */ |
| public void setLongOpt(String longOpt) |
| { |
| this.longOpt = longOpt; |
| } |
| |
| /** |
| * Sets whether this Option can have an optional argument. |
| * |
| * @param optionalArg specifies whether the Option can have |
| * an optional argument. |
| */ |
| public void setOptionalArg(boolean optionalArg) |
| { |
| this.optionalArg = optionalArg; |
| } |
| |
| /** |
| * @return whether this Option can have an optional argument |
| */ |
| public boolean hasOptionalArg() |
| { |
| return optionalArg; |
| } |
| |
| /** |
| * Query to see if this Option has a long name |
| * |
| * @return boolean flag indicating existence of a long name |
| */ |
| public boolean hasLongOpt() |
| { |
| return longOpt != null; |
| } |
| |
| /** |
| * Query to see if this Option requires an argument |
| * |
| * @return boolean flag indicating if an argument is required |
| */ |
| public boolean hasArg() |
| { |
| return numberOfArgs > 0 || numberOfArgs == UNLIMITED_VALUES; |
| } |
| |
| /** |
| * Retrieve the self-documenting description of this Option |
| * |
| * @return The string description of this option |
| */ |
| public String getDescription() |
| { |
| return description; |
| } |
| |
| /** |
| * Sets the self-documenting description of this Option |
| * |
| * @param description The description of this option |
| * @since 1.1 |
| */ |
| public void setDescription(String description) |
| { |
| this.description = description; |
| } |
| |
| /** |
| * Query to see if this Option requires an argument |
| * |
| * @return boolean flag indicating if an argument is required |
| */ |
| public boolean isRequired() |
| { |
| return required; |
| } |
| |
| /** |
| * Sets whether this Option is mandatory. |
| * |
| * @param required specifies whether this Option is mandatory |
| */ |
| public void setRequired(boolean required) |
| { |
| this.required = required; |
| } |
| |
| /** |
| * Sets the display name for the argument value. |
| * |
| * @param argName the display name for the argument value. |
| */ |
| public void setArgName(String argName) |
| { |
| this.argName = argName; |
| } |
| |
| /** |
| * Gets the display name for the argument value. |
| * |
| * @return the display name for the argument value. |
| */ |
| public String getArgName() |
| { |
| return argName; |
| } |
| |
| /** |
| * Returns whether the display name for the argument value |
| * has been set. |
| * |
| * @return if the display name for the argument value has been |
| * set. |
| */ |
| public boolean hasArgName() |
| { |
| return argName != null && argName.length() > 0; |
| } |
| |
| /** |
| * Query to see if this Option can take many values. |
| * |
| * @return boolean flag indicating if multiple values are allowed |
| */ |
| public boolean hasArgs() |
| { |
| return numberOfArgs > 1 || numberOfArgs == UNLIMITED_VALUES; |
| } |
| |
| /** |
| * Sets the number of argument values this Option can take. |
| * |
| * @param num the number of argument values |
| */ |
| public void setArgs(int num) |
| { |
| this.numberOfArgs = num; |
| } |
| |
| /** |
| * Sets the value separator. For example if the argument value |
| * was a Java property, the value separator would be '='. |
| * |
| * @param sep The value separator. |
| */ |
| public void setValueSeparator(char sep) |
| { |
| this.valuesep = sep; |
| } |
| |
| /** |
| * Returns the value separator character. |
| * |
| * @return the value separator character. |
| */ |
| public char getValueSeparator() |
| { |
| return valuesep; |
| } |
| |
| /** |
| * Return whether this Option has specified a value separator. |
| * |
| * @return whether this Option has specified a value separator. |
| * @since 1.1 |
| */ |
| public boolean hasValueSeparator() |
| { |
| return valuesep > 0; |
| } |
| |
| /** |
| * Returns the number of argument values this Option can take. |
| * |
| * @return num the number of argument values |
| */ |
| public int getArgs() |
| { |
| return numberOfArgs; |
| } |
| |
| /** |
| * Adds the specified value to this Option. |
| * |
| * @param value is a/the value of this Option |
| */ |
| void addValueForProcessing(String value) |
| { |
| switch (numberOfArgs) |
| { |
| case UNINITIALIZED: |
| throw new RuntimeException("NO_ARGS_ALLOWED"); |
| |
| default: |
| processValue(value); |
| } |
| } |
| |
| /** |
| * Processes the value. If this Option has a value separator |
| * the value will have to be parsed into individual tokens. When |
| * n-1 tokens have been processed and there are more value separators |
| * in the value, parsing is ceased and the remaining characters are |
| * added as a single token. |
| * |
| * @param value The String to be processed. |
| * |
| * @since 1.0.1 |
| */ |
| private void processValue(String value) |
| { |
| // this Option has a separator character |
| if (hasValueSeparator()) |
| { |
| // get the separator character |
| char sep = getValueSeparator(); |
| |
| // store the index for the value separator |
| int index = value.indexOf(sep); |
| |
| // while there are more value separators |
| while (index != -1) |
| { |
| // next value to be added |
| if (values.size() == (numberOfArgs - 1)) |
| { |
| break; |
| } |
| |
| // store |
| add(value.substring(0, index)); |
| |
| // parse |
| value = value.substring(index + 1); |
| |
| // get new index |
| index = value.indexOf(sep); |
| } |
| } |
| |
| // store the actual value or the last value that has been parsed |
| add(value); |
| } |
| |
| /** |
| * Add the value to this Option. If the number of arguments |
| * is greater than zero and there is enough space in the list then |
| * add the value. Otherwise, throw a runtime exception. |
| * |
| * @param value The value to be added to this Option |
| * |
| * @since 1.0.1 |
| */ |
| private void add(String value) |
| { |
| if ((numberOfArgs > 0) && (values.size() > (numberOfArgs - 1))) |
| { |
| throw new RuntimeException("Cannot add value, list full."); |
| } |
| |
| // store value |
| values.add(value); |
| } |
| |
| /** |
| * Returns the specified value of this Option or |
| * <code>null</code> if there is no value. |
| * |
| * @return the value/first value of this Option or |
| * <code>null</code> if there is no value. |
| */ |
| public String getValue() |
| { |
| return hasNoValues() ? null : (String) values.get(0); |
| } |
| |
| /** |
| * Returns the specified value of this Option or |
| * <code>null</code> if there is no value. |
| * |
| * @param index The index of the value to be returned. |
| * |
| * @return the specified value of this Option or |
| * <code>null</code> if there is no value. |
| * |
| * @throws IndexOutOfBoundsException if index is less than 1 |
| * or greater than the number of the values for this Option. |
| */ |
| public String getValue(int index) throws IndexOutOfBoundsException |
| { |
| return hasNoValues() ? null : (String) values.get(index); |
| } |
| |
| /** |
| * Returns the value/first value of this Option or the |
| * <code>defaultValue</code> if there is no value. |
| * |
| * @param defaultValue The value to be returned if ther |
| * is no value. |
| * |
| * @return the value/first value of this Option or the |
| * <code>defaultValue</code> if there are no values. |
| */ |
| public String getValue(String defaultValue) |
| { |
| String value = getValue(); |
| |
| return (value != null) ? value : defaultValue; |
| } |
| |
| /** |
| * Return the values of this Option as a String array |
| * or null if there are no values |
| * |
| * @return the values of this Option as a String array |
| * or null if there are no values |
| */ |
| public String[] getValues() |
| { |
| return hasNoValues() ? null : (String[]) values.toArray(new String[values.size()]); |
| } |
| |
| /** |
| * @return the values of this Option as a List |
| * or null if there are no values |
| */ |
| public List getValuesList() |
| { |
| return values; |
| } |
| |
| /** |
| * Dump state, suitable for debugging. |
| * |
| * @return Stringified form of this object |
| */ |
| public String toString() |
| { |
| StringBuffer buf = new StringBuffer().append("[ option: "); |
| |
| buf.append(opt); |
| |
| if (longOpt != null) |
| { |
| buf.append(" ").append(longOpt); |
| } |
| |
| buf.append(" "); |
| |
| if (hasArgs()) |
| { |
| buf.append("[ARG...]"); |
| } |
| else if (hasArg()) |
| { |
| buf.append(" [ARG]"); |
| } |
| |
| buf.append(" :: ").append(description); |
| |
| if (type != null) |
| { |
| buf.append(" :: ").append(type); |
| } |
| |
| buf.append(" ]"); |
| |
| return buf.toString(); |
| } |
| |
| /** |
| * Returns whether this Option has any values. |
| * |
| * @return whether this Option has any values. |
| */ |
| private boolean hasNoValues() |
| { |
| return values.isEmpty(); |
| } |
| |
| public boolean equals(Object o) |
| { |
| if (this == o) |
| { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) |
| { |
| return false; |
| } |
| |
| Option option = (Option) o; |
| |
| |
| if (opt != null ? !opt.equals(option.opt) : option.opt != null) |
| { |
| return false; |
| } |
| if (longOpt != null ? !longOpt.equals(option.longOpt) : option.longOpt != null) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| public int hashCode() |
| { |
| int result; |
| result = (opt != null ? opt.hashCode() : 0); |
| result = 31 * result + (longOpt != null ? longOpt.hashCode() : 0); |
| return result; |
| } |
| |
| /** |
| * A rather odd clone method - due to incorrect code in 1.0 it is public |
| * and in 1.1 rather than throwing a CloneNotSupportedException it throws |
| * a RuntimeException so as to maintain backwards compat at the API level. |
| * |
| * After calling this method, it is very likely you will want to call |
| * clearValues(). |
| * |
| * @throws RuntimeException |
| */ |
| public Object clone() |
| { |
| try |
| { |
| Option option = (Option) super.clone(); |
| option.values = new ArrayList(values); |
| return option; |
| } |
| catch (CloneNotSupportedException cnse) |
| { |
| throw new RuntimeException("A CloneNotSupportedException was thrown: " + cnse.getMessage()); |
| } |
| } |
| |
| /** |
| * Clear the Option values. After a parse is complete, these are left with |
| * data in them and they need clearing if another parse is done. |
| * |
| * See: <a href="https://issues.apache.org/jira/browse/CLI-71">CLI-71</a> |
| */ |
| void clearValues() |
| { |
| values.clear(); |
| } |
| |
| /** |
| * This method is not intended to be used. It was a piece of internal |
| * API that was made public in 1.0. It currently throws an UnsupportedOperationException. |
| * @deprecated |
| * @throws UnsupportedOperationException |
| */ |
| public boolean addValue(String value) |
| { |
| throw new UnsupportedOperationException("The addValue method is not intended for client use. " |
| + "Subclasses should use the addValueForProcessing method instead. "); |
| } |
| |
| } |