这里说明一下Option类及其如何设置一个Option类的实例。
在buildGeneralOptions()方法接收Options opts然后又返回了opts,在这个过程中已经改变了opts的值。如下所示:
/** opts.addOption(fs);
* Specify properties of each generic option
*/
@SuppressWarnings("static-access")
private Options buildGeneralOptions(Options opts) {
Option fs = OptionBuilder.withArgName("local|namenode:port")
.hasArg()
.withDescription("specify a namenode")
.create("fs");
Option jt = OptionBuilder.withArgName("local|jobtracker:port")
.hasArg()
.withDescription("specify a job tracker")
.create("jt");
Option oconf = OptionBuilder.withArgName("configuration file")
.hasArg()
.withDescription("specify an application configuration file")
.create("conf");
Option property = OptionBuilder.withArgName("property=value")
.hasArgs()
.withArgPattern("=", 1)
.withDescription("use value for given property")
.create('D');
opts.addOption(jt);
opts.addOption(oconf);
opts.addOption(property);
return opts;
}
开始传进来一个opts,它并没有任何内容(是指Option类的对象,即一个选项),因为从开始实例化就没有配置过Options opts。但是,在上面代码的后面部分,已经为opts设置内容了,其实就是设置添加Option类的对象到Options中去。
看看具体都添加了一些什么信息。拿出一项来看看:
Option fs = OptionBuilder.withArgName("local|namenode:port") opts.addOption(fs);
.hasArg()
.withDescription("specify a namenode")
.create("fs");
Option代表了一个命令行,我们看一下Option类的定义:
package org.apache.commons.cli; import java.util.ArrayList; public class Option { // 参数值没有被指定时,用-1表示 // 参数值为无穷时使用-2表示 // 标识一个Option的字符串名称 // Option使用长名称表示 // 表明一个Option是否有一个相关的参数 // 表明一个Option的参数的名称 // 一个Option的描述信息 // 一个Option是否是必须指定的 // 是否一个Option的参数值是可选的 // 一个Option可以具有参数值的个数 // 一个Option的类型 // 参数值列表 // 指定用作分隔符的字符 // 参数样式及其它出现的次数 /** // 另一种构造方法 // 还是构造一个Option this.opt = opt; // if hasArg is set then the number of arguments is 1 this.hasArg = hasArg; // 返回Option的ID /** return this.opt; /** /** /** /** /** /** /** /** /** // 设置一个Option的描述信息 // 是否一个Option需要指定一个参数 // 设置一个Option的参数是否必需 // 设置这个参数值的显示名称 // 返回这个参数值的显示名称 // 是否这个参数值的显示名称已经被设置了 // 是否一个Option可以具有多个参数值 // 设置一个Option具有的参数值的个数 // 设置值的分隔符字符 // 返回值的分隔符字符 // 是否一个Option指定了值的分隔符字符 // 一个Option是否指定多了参数的样式 public void setArgPattern( String argPattern, int limit ) // 返回一个Option具有参数的个数 // 设置一个Option的值 default: // 检查参数样式 // 处理一个Option的值 // store the index for the value separator // while there are more value separators // 向一个Option添加值,如果参数的个数大于0并且有足够的列表的时候才可以添加 // 返回Option的值 // 返回指定的Option的值 // 返回一个Option的值,或者第一个值,如果它没有值就返回一个默认值 return (value != null) ? value : defaultValue; // 以一个字符串数组的形式返回一个Option的所有值 // 以列表的形式返回一个Option的所有值 // 用于调试使用的 buf.append(this.opt); if (this.longOpt != null) buf.append(" "); if (hasArg) buf.append(" :: ").append(this.description); if (this.type != null) buf.append(" ]"); return buf.toString(); // 一个Option是否可以是任意值
import java.util.regex.Pattern;
public static final int UNINITIALIZED = -1;
public static final int UNLIMITED_VALUES = -2;
private String opt;
private String longOpt;
private boolean hasArg;
private String argName = "arg";
private String description;
private boolean required;
private boolean optionalArg;
private int numberOfArgs = UNINITIALIZED;
private Object type;
private ArrayList values = new ArrayList();
private char valuesep;
private Pattern argPattern;
private int limit;
* 构造一个Option.
*
* @param opt 标识一个Option的名称
* @param description 一个Option的描述信息
*/
public Option(String opt, String description)
throws IllegalArgumentException
{
this(opt, null, false, description); // 调用其他构造方法
}
public Option(String opt, boolean hasArg, String description)
throws IllegalArgumentException
{
this(opt, null, hasArg, description);
}
public Option(String opt, String longOpt, boolean hasArg,
String description)
throws IllegalArgumentException
{
// 验证一个Option是合法的
OptionValidator.validateOption(opt);
this.longOpt = longOpt;
if (hasArg)
{
this.numberOfArgs = 1;
}
this.description = description;
}
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 this.longOpt;
}
}
* 返回一个Option的name
*/
public String getOpt()
{
return this.opt;
}
* 返回一个Option的类型
*/
public Object getType()
{
return this.type;
}
* 设置一个Option的类型
*/
public void setType(Object type)
{
this.type = type;
}
* 返回一个Option的长名称
*/
public String getLongOpt()
{
return this.longOpt;
}
* 设置一个Option的长名称
*/
public void setLongOpt(String longOpt)
{
this.longOpt = longOpt;
}
* 设置一个Option是否具有一个可选的参数
*/
public void setOptionalArg(boolean optionalArg)
{
this.optionalArg = optionalArg;
}
* 返回一个Option的是否具有可选的参数
*/
public boolean hasOptionalArg()
{
return this.optionalArg;
}
* 是否Option具有一个长名称
*/
public boolean hasLongOpt()
{
return (this.longOpt != null);
}
* 是否一个Option有一个必需的参数
*/
public boolean hasArg()
{
return (this.numberOfArgs > 0) || (numberOfArgs == UNLIMITED_VALUES);
}
// 返回一个Option的描述信息
public String getDescription()
{
return this.description;
}
public void setDescription(String description)
{
this.description = description;
}
public boolean isRequired()
{
return this.required;
}
public void setRequired(boolean required)
{
this.required = required;
}
public void setArgName(String argName)
{
this.argName = argName;
}
public String getArgName()
{
return this.argName;
}
public boolean hasArgName()
{
return (this.argName != null && this.argName.length() > 0);
}
public boolean hasArgs()
{
return (this.numberOfArgs > 1)
|| (this.numberOfArgs == UNLIMITED_VALUES);
}
public void setArgs(int num)
{
this.numberOfArgs = num;
}
public void setValueSeparator(char sep)
{
this.valuesep = sep;
}
public char getValueSeparator()
{
return this.valuesep;
}
public boolean hasValueSeparator()
{
return (this.valuesep > 0);
}
public boolean hasArgPattern()
{
return (limit!=0&&argPattern!=null);
}
{
if(argPattern==null || argPattern.length()==0 || limit==0 )
return;
this.argPattern = Pattern.compile(argPattern);
this.limit = limit;
}
public int getArgs()
{
return this.numberOfArgs;
}
void addValue(String value)
{
switch (numberOfArgs)
{
case UNINITIALIZED:
throw new RuntimeException("NO_ARGS_ALLOWED");
processValue(value);
}
}
private void checkArgPattern( String arg ) {
if(!hasArgPattern()) {
add(arg);
} else {
String [] tokens = argPattern.split(arg, -1);
if(tokens.length != limit+1)
throw new RuntimeException("ARG_PATTERN_NOT_MATCH");
for(int i=0; i<= limit; i++) {
add(tokens[i]);
}
}
}
private void processValue(String value)
{
// this Option has a separator character
if (hasValueSeparator())
{
// get the separator character
char sep = getValueSeparator();
int index = value.indexOf(sep);
while (index != -1)
{
// next value to be added
if (values.size()/(limit+1) == (numberOfArgs - 1))
{
break;
}
// store
checkArgPattern(value.substring(0, index));
// parse
value = value.substring(index + 1);
// get new index
index = value.indexOf(sep);
}
}
// check if the argment matches specified pattern; if yes,
// store the actual value or the last value that has been parsed
checkArgPattern(value);
}
private void add(String value)
{
if ((numberOfArgs > 0) && (values.size() > (numberOfArgs - 1)))
{
throw new RuntimeException("Cannot add value, list full.");
}
this.values.add(value);
}
public String getValue()
{
return hasNoValues() ? null : (String) this.values.get(0);
}
public String getValue(int index)
throws IndexOutOfBoundsException
{
return hasNoValues() ? null : (String) this.values.get(index);
}
public String getValue(String defaultValue)
{
String value = getValue();
}
public String[] getValues()
{
return hasNoValues()
? null : (String[]) this.values.toArray(new String[] { });
}
public java.util.List getValuesList()
{
return this.values;
}
public String toString()
{
StringBuffer buf = new StringBuffer().append("[ option: ");
{
buf.append(" ").append(this.longOpt);
}
{
buf.append("+ARG");
}
{
buf.append(" :: ").append(this.type);
}
}
private boolean hasNoValues()
{
return this.values.size() == 0;
}
}
可以看出,一个Option所具有的信息很多:长名称(longOpt)、短名称(name)、类型(type)、样式(pattern)、参数个数(numberOfArgs)、参数值的字符分隔符、ID,描述等等。
只有设置好了这些Option的信息,调用private Options buildGeneralOptions(Options opts) 方法时候返回的Options可以被后面进行解析使用。