blob: 11c42fec6c677e7b69f7fa6b97cdd98634e41838 [file] [log] [blame]
// 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 common.opt;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Simple parser of GNU-like options.
*/
public class OptionParser {
public static Option helpOption() {
return new Option() {
{
name = "--help";
alias = "-h";
}
};
}
/**
* Parse options, capture values and return rest of arguments.
*
* @param args
* command line arguments to parse
* @param startFrom
* number of first argument to start parsing from
* @param options
* options to fill with values
* @return rest of command line after first non-option or "--" separator
*/
public static String[] parseOptions(String args[], int startFrom, Option options[]) {
// Convert array of options into map, where key is option name or alias
Map<String, Option> optionMap = new HashMap<String, Option>(options.length);
for (Option option : options) {
optionMap.put(option.name, option);
if (option.alias != null)
optionMap.put(option.alias, option);
if (option.aliases != null) {
for (String alias : option.aliases)
optionMap.put(alias, option);
}
}
// Parse arguments
int position = startFrom;
while (position < args.length) {
// Double dash means end of options
String optionName = args[position];
if (optionName.equals("--")) {
position++;
break;
}
Option option = optionMap.get(optionName);
// If option is not found, then this is argument, unless is starts with
// dash
if (option == null)
if (!optionName.startsWith("-"))
break;
else
throw new UnknownOptionException("Option \"" + optionName
+ "\" is unknown. If this is not an option, then use \"--\" to separate options and arguments. Known options: " + optionMap.keySet().toString());
position += option.parse(position, args);
}
// Check is required options are used on command line
for (Option option : options) {
if (option.required && !option.used)
throw new OptionRequiredException("Option \"" + option.name + "\" is required.");
}
// Return rest of arguments, which are left after options
return (position < args.length) ? Arrays.copyOfRange(args, position, args.length) : new String[] {};
}
/* Example. */
public static void main(String args[]) {
if (args.length == 0)
args = new String[] {"--help", "--foo", "fooval", "--bar", "123", "-v", "--verbose", "-v", "-a", "a1", "-aa", "a2", "-aaa", "a3", "rest", "of",
"arguments"};
StringOption foo = new StringOption() {
{
name = "--foo";
alias = "-f";
value = "fooDefault";
}
};
IntOption bar = new IntOption() {
{
name = "--bar";
alias = "-b";
value = 123;
}
};
IncrementalOption verbose = new IncrementalOption() {
{
name = "--verbose";
alias = "-v";
}
};
StringArrayOption array = new StringArrayOption() {
{
name = "--array";
alias = "-a";
aliases = new String[] {"-aa", "-aaa"};
}
};
String arguments[] = OptionParser.parseOptions(args, 0, new Option[] {helpOption(), foo, bar, verbose, array});
assertTrue(foo.value.equals("fooval"));
assertTrue(bar.value == 123);
assertTrue(verbose.value == 3);
assertTrue(Arrays.equals(array.value, new String[] {"a1", "a2", "a3"}));
assertTrue(Arrays.equals(arguments, new String[] {"rest", "of", "arguments"}));
}
public static void assertTrue(boolean result) {
if (!result)
throw new AssertionError();
}
}