| // 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(); |
| } |
| } |