| /* |
| * 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. |
| * |
| * A simple command line parser. This parser allows the caller to register a set of |
| * valid arguments. Each argument can have both a long and short format (e.g. -h and |
| * -hod). Note that -- (double dashes) is not required for long options as in |
| * standard GNU, though it is accepted. |
| * |
| * The caller then calls getNextOpt(). This returns a character, matching the short |
| * form of the argument. The caller can then obtain the value by calling one of the |
| * getVal functions. |
| * |
| * Author: Alan F. Gates (gates@) |
| * $Header:$ |
| */ |
| |
| package org.apache.pig.tools.cmdline; |
| |
| import java.text.ParseException; |
| import java.util.HashMap; |
| import java.lang.AssertionError; |
| |
| public class CmdLineParser |
| { |
| |
| public enum ValueExpected {REQUIRED, OPTIONAL, NOT_ACCEPTED}; |
| public static final char EndOfOpts = '-'; |
| |
| /** |
| * @param args String array of arguments passed to the program. |
| */ |
| public CmdLineParser(String[] args) |
| { |
| mArgs = args; |
| mArgNum = 0; |
| mShort = new HashMap<Character, ValueExpected>(); |
| mLong = new HashMap<String, Character>(); |
| } |
| |
| /** |
| * Register a command line option. |
| * @param c Single character designator for this option. It cannot be '-'. |
| * @param s Full word designator for this option. This can be null, in which case |
| * no long designator will exist for this option. |
| * @param valueExpected If REQUIRED, a value will be expected with this option. If |
| * OPTIONAL a value will be accepted if it is seen. |
| * @throws AssertionError if there is no short option, or if this option has already been |
| * used. |
| */ |
| public void registerOpt(char c, String s, ValueExpected ve) |
| { |
| if (c == '-') { |
| throw new AssertionError("CmdLineParser: '-' is not a legal single character designator."); |
| } |
| |
| Character cc = new Character(c); |
| if (mShort.put(cc, ve) != null) { |
| throw new AssertionError("CmdLineParser: You have already registered option " + cc.toString()); |
| } |
| |
| if (mLong != null) { |
| if (mLong.put(s, cc) != null) { |
| throw new AssertionError("CmdLineParser: You have already registered option " + s); |
| } |
| } |
| } |
| |
| /** |
| * Get the next option. |
| * @return The short designator for the next argument. If there are no more arguments |
| * than the special designator CmdLineParser.EndOfOpts will be returned. |
| * @throws ParseException if an unknown option is found or an option that |
| * expects a value does not have one or a value that does not expect a value does have |
| * one. |
| */ |
| public char getNextOpt() throws ParseException |
| { |
| if (mArgNum >= mArgs.length) return EndOfOpts; |
| |
| int offset = 1; |
| mVal = null; |
| try { |
| String arg = mArgs[mArgNum]; |
| // If it doesn't start with a dash, we'll assume we've reached the end of the |
| // arguments. We need to decrement mArgNum because the finally at the end is |
| // going to increment it. |
| if (arg.charAt(0) != '-') { |
| mArgNum--; |
| return EndOfOpts; |
| } |
| |
| // Strip any dashes off of the beginning |
| for (int i = 1; i < arg.length() && arg.charAt(i) == '-'; i++) offset++; |
| |
| // If they passed us a - or -- then quit |
| if (offset == arg.length()) return EndOfOpts; |
| |
| Character cc = null; |
| if (arg.substring(offset).length() == 1) { |
| cc = new Character(arg.substring(offset).charAt(0)); |
| } else { |
| cc = mLong.get(arg.substring(offset)); |
| if (cc == null) { |
| Integer ii = new Integer(mArgNum + 1); |
| StringBuilder errMsg = new StringBuilder(); |
| errMsg.append("Found unknown option ("); |
| errMsg.append(arg); |
| errMsg.append(") at position "); |
| errMsg.append(ii.toString()); |
| throw new ParseException(errMsg.toString(), mArgNum); |
| } |
| } |
| |
| ValueExpected ve = mShort.get(cc); |
| if (ve == null) { |
| Integer ii = new Integer(mArgNum + 1); |
| StringBuilder errMsg = new StringBuilder(); |
| errMsg.append("Found unknown option ("); |
| errMsg.append(arg); |
| errMsg.append(") at position "); |
| errMsg.append(ii.toString()); |
| throw new ParseException(errMsg.toString(), mArgNum); |
| } |
| |
| switch (ve) { |
| case NOT_ACCEPTED: |
| return cc.charValue(); |
| |
| case REQUIRED: |
| // If it requires an option, make sure there is one. |
| if (mArgNum + 1 >= mArgs.length || mArgs[mArgNum + 1].charAt(0) == '-') { |
| String errMsg = "Option " + arg + |
| " requires a value but you did not provide one."; |
| throw new ParseException(errMsg, mArgNum); |
| } |
| mVal = new String(mArgs[++mArgNum]); |
| return cc.charValue(); |
| |
| case OPTIONAL: |
| if (mArgNum + 1 < mArgs.length && mArgs[mArgNum + 1].charAt(0) != '-') { |
| mVal = new String(mArgs[++mArgNum]); |
| } |
| return cc.charValue(); |
| |
| default: |
| throw new AssertionError("Unknown valueExpected state"); |
| |
| } |
| |
| } finally { |
| mArgNum++; |
| } |
| } |
| |
| /** |
| * Get any remaining arguments. |
| * @return In general this function will null. |
| * Only if the caller passed a '-' or '--' followed by other arguments. In that case |
| * the remainder of the args array will be returned. |
| */ |
| public String[] getRemainingArgs() |
| { |
| if (mArgNum == mArgs.length) return null; |
| |
| String[] remainders = new String[mArgs.length - mArgNum]; |
| System.arraycopy(mArgs, mArgNum, remainders, 0, remainders.length); |
| return remainders; |
| } |
| |
| /** |
| * Get the value, as a string. |
| * @return The value associated with the current option. If there is no value, |
| * then null will be returned. |
| */ |
| public String getValStr() |
| { |
| return mVal; |
| } |
| |
| /** |
| * Get the value, as an Integer. |
| * @return The value associated with the current option. If there is not value, then |
| * null will be returned. |
| * @throws NumberFormatException if the value cannot be converted to an integer. |
| */ |
| public Integer getValInt() throws NumberFormatException |
| { |
| if (mVal == null) return null; |
| else return new Integer(mVal); |
| } |
| |
| private String[] mArgs; |
| private HashMap<Character, ValueExpected> mShort; |
| private HashMap<String, Character> mLong; |
| private int mArgNum; |
| private String mVal; |
| |
| } |
| |