/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. */ package org.opends.sdk.tools; import static com.sun.opends.sdk.util.Messages.*; import static org.opends.sdk.util.StaticUtils.*; import java.util.Iterator; import java.util.LinkedList; import com.sun.opends.sdk.util.Message; import com.sun.opends.sdk.util.MessageBuilder; /** * This class defines a generic argument that may be used in the * argument list for an application. This is an abstract class that must * be subclassed in order to provide specific functionality. */ abstract class Argument { // Indicates whether this argument should be hidden in the usage // information. private boolean isHidden; // Indicates whether this argument may be specified more than once for // multiple values. private boolean isMultiValued; // Indicates whether this argument was provided in the set of // command-line // arguments. private boolean isPresent; // Indicates whether this argument is required to have a value. private boolean isRequired; // Indicates whether this argument requires a value. private boolean needsValue; // The single-character identifier for this argument. private Character shortIdentifier; // The unique ID of the description for this argument. private Message description; // The set of values for this argument. private LinkedList values; // The default value for the argument if none other is provided. private String defaultValue; // The long identifier for this argument. private String longIdentifier; // The generic name that will be used to refer to this argument. private String name; // The name of the property that can be used to set the default value. private String propertyName; // The value placeholder for this argument, which will be used in // usage // information. private Message valuePlaceholder; // Indicates whether this argument was provided in the set of // properties // found is a properties file. private boolean isValueSetByProperty; /** * Creates a new argument with the provided information. * * @param name * The generic name that should be used to refer to this * argument. * @param shortIdentifier * The single-character identifier for this argument, or * null if there is none. * @param longIdentifier * The long identifier for this argument, or * null if there is none. * @param isRequired * Indicates whether this argument must be specified on the * command line. * @param isMultiValued * Indicates whether this argument may be specified more than * once to provide multiple values. * @param needsValue * Indicates whether this argument requires a value. * @param valuePlaceholder * The placeholder for the argument value that will be * displayed in usage information, or null if * this argument does not require a value. * @param defaultValue * The default value that should be used for this argument if * none is provided in a properties file or on the command * line. This may be null if there is no generic * default. * @param propertyName * The name of the property in a property file that may be * used to override the default value but will be overridden * by a command-line argument. * @param description * Message for the description of this argument. * @throws ArgumentException * If there is a problem with any of the parameters used to * create this argument. */ protected Argument(String name, Character shortIdentifier, String longIdentifier, boolean isRequired, boolean isMultiValued, boolean needsValue, Message valuePlaceholder, String defaultValue, String propertyName, Message description) throws ArgumentException { this.name = name; this.shortIdentifier = shortIdentifier; this.longIdentifier = longIdentifier; this.isRequired = isRequired; this.isMultiValued = isMultiValued; this.needsValue = needsValue; this.valuePlaceholder = valuePlaceholder; this.defaultValue = defaultValue; this.propertyName = propertyName; this.description = description; this.isValueSetByProperty = false; if ((shortIdentifier == null) && (longIdentifier == null)) { Message message = ERR_ARG_NO_IDENTIFIER.get(name); throw new ArgumentException(message); } if (needsValue && (valuePlaceholder == null)) { Message message = ERR_ARG_NO_VALUE_PLACEHOLDER.get(name); throw new ArgumentException(message); } values = new LinkedList(); isPresent = false; isHidden = false; } /** * Retrieves the generic name that will be used to refer to this * argument. * * @return The generic name that will be used to refer to this * argument. */ public String getName() { return name; } /** * Retrieves the single-character identifier that may be used to * specify the value of this argument. * * @return The single-character identifier that may be used to specify * the value of this argument, or null if there * is none. */ public Character getShortIdentifier() { return shortIdentifier; } /** * Retrieves the long (multi-character) identifier that may be used to * specify the value of this argument. * * @return The long (multi-character) identifier that may be used to * specify the value of this argument. */ public String getLongIdentifier() { return longIdentifier; } /** * Indicates whether this argument is required to have at least one * value. * * @return true if this argument is required to have at * least one value, or false if it does not need * to have a value. */ public boolean isRequired() { return isRequired; } /** * Specifies whether this argument is required to have at least one * value. * * @param isRequired * Indicates whether this argument is required to have at * least one value. */ public void setRequired(boolean isRequired) { this.isRequired = isRequired; } /** * Indicates whether this argument is present in the parsed set of * command-line arguments. * * @return true if this argument is present in the parsed * set of command-line arguments, or false if * not. */ public boolean isPresent() { return isPresent; } /** * Specifies whether this argument is present in the parsed set of * command-line arguments. * * @param isPresent * Indicates whether this argument is present in the set of * command-line arguments. */ public void setPresent(boolean isPresent) { this.isPresent = isPresent; } /** * Indicates whether this argument should be hidden from the usage * information. * * @return true if this argument should be hidden from * the usage information, or false if not. */ public boolean isHidden() { return isHidden; } /** * Specifies whether this argument should be hidden from the usage * information. * * @param isHidden * Indicates whether this argument should be hidden from the * usage information. */ public void setHidden(boolean isHidden) { this.isHidden = isHidden; } /** * Indicates whether this argument may be provided more than once on * the command line to specify multiple values. * * @return true if this argument may be provided more * than once on the command line to specify multiple values, * or false if it may have at most one value. */ public boolean isMultiValued() { return isMultiValued; } /** * Specifies whether this argument may be provided more than once on * the command line to specify multiple values. * * @param isMultiValued * Indicates whether this argument may be provided more than * once on the command line to specify multiple values. */ public void setMultiValued(boolean isMultiValued) { this.isMultiValued = isMultiValued; } /** * Indicates whether a value must be provided with this argument if it * is present. * * @return true if a value must be provided with the * argument if it is present, or false if the * argument does not take a value and the presence of the * argument identifier itself is sufficient to convey the * necessary information. */ public boolean needsValue() { return needsValue; } /** * Specifies whether a value must be provided with this argument if it * is present. If this is changed from false to * true, then a value placeholder must also be provided. * * @param needsValue * Indicates whether a value must be provided with this * argument if it is present. */ public void setNeedsValue(boolean needsValue) { this.needsValue = needsValue; } /** * Retrieves the value placeholder that will be displayed for this * argument in the generated usage information. * * @return The value placeholder that will be displayed for this * argument in the generated usage information, or * null if there is none. */ public Message getValuePlaceholder() { return valuePlaceholder; } /** * Specifies the value placeholder that will be displayed for this * argument in the generated usage information. It may be * null only if needsValue() returns * false. * * @param valuePlaceholder * The value placeholder that will be displayed for this * argument in the generated usage information. */ public void setValuePlaceholder(Message valuePlaceholder) { this.valuePlaceholder = valuePlaceholder; } /** * Retrieves the default value that will be used for this argument if * it is not specified on the command line and it is not set from a * properties file. * * @return The default value that will be used for this argument if it * is not specified on the command line and it is not set from * a properties file, or null if there is no * default value. */ public String getDefaultValue() { return defaultValue; } /** * Specifies the default value that will be used for this argument if * it is not specified on the command line and it is not set from a * properties file. * * @param defaultValue * The default value that will be used for this argument if * it is not specified on the command line and it is not set * from a properties file. */ public void setDefaultValue(String defaultValue) { this.defaultValue = defaultValue; } /** * Retrieves the name of a property in a properties file that may be * used to set the default value for this argument if it is present. A * value read from a properties file will override the default value * returned from the getDefaultValue, but the properties * file value will be overridden by a value supplied on the command * line. * * @return The name of a property in a properties file that may be * used to set the default value for this argument if it is * present. */ public String getPropertyName() { return propertyName; } /** * Specifies the name of a property in a properties file that may be * used to set the default value for this argument if it is present. * * @param propertyName * The name of a property in a properties file that may be * used to set the default value for this argument if it is * present. */ public void setPropertyName(String propertyName) { this.propertyName = propertyName; } /** * Indicates whether this argument was provided in the set of * properties found is a properties file. * * @return true if this argument was provided in the set * of properties found is a properties file, or * false if not. */ public boolean isValueSetByProperty() { return isValueSetByProperty; } /** * Specifies whether this argument was provided in the set of * properties found is a properties file. * * @param isValueSetByProperty * Specify whether this argument was provided in the set of * properties found is a properties file. */ public void setValueSetByProperty(boolean isValueSetByProperty) { this.isValueSetByProperty = isValueSetByProperty; } /** * Retrieves the human-readable description for this argument. * * @return The human-readable description for this argument. */ public Message getDescription() { return description != null ? description : Message.EMPTY; } /** * Indicates whether this argument has at least one value. * * @return true if this argument has at least one value, * or false if it does not have any values. */ public boolean hasValue() { return (!values.isEmpty()); } /** * Retrieves the string vale for this argument. If it has multiple * values, then the first will be returned. If it does not have any * values, then the default value will be returned. * * @return The string value for this argument, or null if * there are no values and no default value has been given. */ public String getValue() { if (values.isEmpty()) { return defaultValue; } return values.getFirst(); } /** * Retrieves the set of string values for this argument. * * @return The set of string values for this argument. */ public LinkedList getValues() { return values; } /** * Retrieves the value of this argument as an integer. * * @return The value of this argument as an integer. * @throws ArgumentException * If there are multiple values, or the value cannot be * parsed as an integer. */ public int getIntValue() throws ArgumentException { if (values.isEmpty()) { Message message = ERR_ARG_NO_INT_VALUE.get(name); throw new ArgumentException(message); } Iterator iterator = values.iterator(); String valueString = iterator.next(); int intValue; try { intValue = Integer.parseInt(valueString); } catch (Exception e) { Message message = ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name); throw new ArgumentException(message, e); } if (iterator.hasNext()) { Message message = ERR_ARG_INT_MULTIPLE_VALUES.get(name); throw new ArgumentException(message); } else { return intValue; } } /** * Retrieves the set of values for this argument as a list of * integers. * * @return A list of the integer representations of the values for * this argument. * @throws ArgumentException * If any of the values cannot be parsed as an integer. */ public LinkedList getIntValues() throws ArgumentException { LinkedList intList = new LinkedList(); Iterator iterator = values.iterator(); while (iterator.hasNext()) { String valueString = iterator.next(); try { intList.add(Integer.valueOf(valueString)); } catch (Exception e) { Message message = ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name); throw new ArgumentException(message, e); } } return intList; } /** * Retrieves the value of this argument as an integer. * * @return The value of this argument as an integer. * @throws ArgumentException * If there are multiple values, or the value cannot be * parsed as an integer. */ public double getDoubleValue() throws ArgumentException { if (values.isEmpty()) { Message message = ERR_ARG_NO_INT_VALUE.get(name); throw new ArgumentException(message); } Iterator iterator = values.iterator(); String valueString = iterator.next(); double intValue; try { intValue = Double.parseDouble(valueString); } catch (Exception e) { Message message = ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name); throw new ArgumentException(message, e); } if (iterator.hasNext()) { Message message = ERR_ARG_INT_MULTIPLE_VALUES.get(name); throw new ArgumentException(message); } else { return intValue; } } /** * Retrieves the set of values for this argument as a list of * integers. * * @return A list of the integer representations of the values for * this argument. * @throws ArgumentException * If any of the values cannot be parsed as an integer. */ public LinkedList getDoubleValues() throws ArgumentException { LinkedList intList = new LinkedList(); Iterator iterator = values.iterator(); while (iterator.hasNext()) { String valueString = iterator.next(); try { intList.add(Double.valueOf(valueString)); } catch (Exception e) { Message message = ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name); throw new ArgumentException(message, e); } } return intList; } /** * Retrieves the value of this argument as a Boolean. * * @return The value of this argument as a Boolean. * @throws ArgumentException * If this argument cannot be interpreted as a Boolean * value. */ public boolean getBooleanValue() throws ArgumentException { if (values.isEmpty()) { Message message = ERR_ARG_NO_BOOLEAN_VALUE.get(name); throw new ArgumentException(message); } Iterator iterator = values.iterator(); String valueString = toLowerCase(iterator.next()); boolean booleanValue; if (valueString.equals("true") || valueString.equals("yes") || valueString.equals("on") || valueString.equals("1")) { booleanValue = true; } else if (valueString.equals("false") || valueString.equals("no") || valueString.equals("off") || valueString.equals("0")) { booleanValue = false; } else { Message message = ERR_ARG_CANNOT_DECODE_AS_BOOLEAN.get(valueString, name); throw new ArgumentException(message); } if (iterator.hasNext()) { Message message = ERR_ARG_BOOLEAN_MULTIPLE_VALUES.get(name); throw new ArgumentException(message); } else { return booleanValue; } } /** * Indicates whether the provided value is acceptable for use in this * argument. * * @param valueString * The value for which to make the determination. * @param invalidReason * A buffer into which the invalid reason may be written if * the value is not acceptable. * @return true if the value is acceptable, or * false if it is not. */ public abstract boolean valueIsAcceptable(String valueString, MessageBuilder invalidReason); /** * Adds a value to the set of values for this argument. This should * only be called if the value is allowed by the * valueIsAcceptable method. * * @param valueString * The string representation of the value to add to this * argument. */ public void addValue(String valueString) { values.add(valueString); } /** * Clears the set of values assigned to this argument. */ public void clearValues() { values.clear(); } }