/*
 The MIT License

 Copyright (c) 2004-2015 Paul R. Holser, Jr.

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package joptsimple;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;

import joptsimple.internal.AbbreviationMap;
import joptsimple.internal.SimpleOptionNameMap;
import joptsimple.internal.OptionNameMap;
import joptsimple.util.KeyValuePair;

import static java.util.Collections.*;
import static joptsimple.OptionException.*;
import static joptsimple.OptionParserState.*;
import static joptsimple.ParserRules.*;

/**
 * <p>Parses command line arguments, using a syntax that attempts to take from the best of POSIX {@code getopt()}
 * and GNU {@code getopt_long()}.</p>
 *
 * <p>This parser supports short options and long options.</p>
 *
 * <ul>
 *   <li><dfn>Short options</dfn> begin with a single hyphen ("{@code -}") followed by a single letter or digit,
 *   or question mark ("{@code ?}"), or dot ("{@code .}"), or underscore ("{@code _}").</li>
 *
 *   <li>Short options can accept single arguments. The argument can be made required or optional. The option's
 *   argument can occur:
 *     <ul>
 *       <li>in the slot after the option, as in {@code -d /tmp}</li>
 *       <li>right up against the option, as in {@code -d/tmp}</li>
 *       <li>right up against the option separated by an equals sign ({@code "="}), as in {@code -d=/tmp}</li>
 *     </ul>
 *   To specify <em>n</em> arguments for an option, specify the option <em>n</em> times, once for each argument,
 *   as in {@code -d /tmp -d /var -d /opt}; or, when using the
 *   {@linkplain ArgumentAcceptingOptionSpec#withValuesSeparatedBy(char) "separated values"} clause of the "fluent
 *   interface" (see below), give multiple values separated by a given character as a single argument to the
 *   option.</li>
 *
 *   <li>Short options can be clustered, so that {@code -abc} is treated as {@code -a -b -c}. If a short option
 *   in the cluster can accept an argument, the remaining characters are interpreted as the argument for that
 *   option.</li>
 *
 *   <li>An argument consisting only of two hyphens ({@code "--"}) signals that the remaining arguments are to be
 *   treated as non-options.</li>
 *
 *   <li>An argument consisting only of a single hyphen is considered a non-option argument (though it can be an
 *   argument of an option). Many Unix programs treat single hyphens as stand-ins for the standard input or standard
 *   output streams.</li>
 *
 *   <li><dfn>Long options</dfn> begin with two hyphens ({@code "--"}), followed by multiple letters, digits,
 *   hyphens, question marks, or dots. A hyphen cannot be the first character of a long option specification when
 *   configuring the parser.</li>
 *
 *   <li>You can abbreviate long options, so long as the abbreviation is unique. Suppress this behavior if
 *   you wish using {@linkplain OptionParser#OptionParser(boolean) this constructor}.</li>
 *
 *   <li>Long options can accept single arguments.  The argument can be made required or optional.  The option's
 *   argument can occur:
 *     <ul>
 *       <li>in the slot after the option, as in {@code --directory /tmp}</li>
 *       <li>right up against the option separated by an equals sign ({@code "="}), as in
 *       {@code --directory=/tmp}
 *     </ul>
 *   Specify multiple arguments for a long option in the same manner as for short options (see above).</li>
 *
 *   <li>You can use a single hyphen ({@code "-"}) instead of a double hyphen ({@code "--"}) for a long
 *   option.</li>
 *
 *   <li>The option {@code -W} is reserved.  If you tell the parser to {@linkplain
 *   #recognizeAlternativeLongOptions(boolean) recognize alternative long options}, then it will treat, for example,
 *   {@code -W foo=bar} as the long option {@code foo} with argument {@code bar}, as though you had written
 *   {@code --foo=bar}.</li>
 *
 *   <li>You can specify {@code -W} as a valid short option, or use it as an abbreviation for a long option, but
 *   {@linkplain #recognizeAlternativeLongOptions(boolean) recognizing alternative long options} will always supersede
 *   this behavior.</li>
 *
 *   <li>You can specify a given short or long option multiple times on a single command line. The parser collects
 *   any arguments specified for those options as a list.</li>
 *
 *   <li>If the parser detects an option whose argument is optional, and the next argument "looks like" an option,
 *   that argument is not treated as the argument to the option, but as a potentially valid option. If, on the other
 *   hand, the optional argument is typed as a derivative of {@link Number}, then that argument is treated as the
 *   negative number argument of the option, even if the parser recognizes the corresponding numeric option.
 *   For example:
 *   <pre><code>
 *     OptionParser parser = new OptionParser();
 *     parser.accepts( "a" ).withOptionalArg().ofType( Integer.class );
 *     parser.accepts( "2" );
 *     OptionSet options = parser.parse( "-a", "-2" );
 *   </code></pre>
 *   In this case, the option set contains {@code "a"} with argument {@code -2}, not both {@code "a"} and
 *   {@code "2"}. Swapping the elements in the <em>args</em> array gives the latter.</li>
 * </ul>
 *
 * <p>There are two ways to tell the parser what options to recognize:</p>
 *
 * <ol>
 *   <li>A "fluent interface"-style API for specifying options, available since version 2. Sentences in this fluent
 *   interface language begin with a call to {@link #accepts(String) accepts} or {@link #acceptsAll(List)
 *   acceptsAll} methods; calls on the ensuing chain of objects describe whether the options can take an argument,
 *   whether the argument is required or optional, to what type arguments of the options should be converted if any,
 *   etc. Since version 3, these calls return an instance of {@link OptionSpec}, which can subsequently be used to
 *   retrieve the arguments of the associated option in a type-safe manner.</li>
 *
 *   <li>Since version 1, a more concise way of specifying short options has been to use the special {@linkplain
 *   #OptionParser(String) constructor}. Arguments of options specified in this manner will be of type {@link String}.
 *   Here are the rules for the format of the specification strings this constructor accepts:
 *
 *     <ul>
 *       <li>Any letter or digit is treated as an option character.</li>
 *
 *       <li>An option character can be immediately followed by an asterisk ({@code *)} to indicate that
 *       the option is a "help" option.</li>
 *
 *       <li>If an option character (with possible trailing asterisk) is followed by a single colon ({@code ":"}),
 *       then the option requires an argument.</li>
 *
 *       <li>If an option character (with possible trailing asterisk) is followed by two colons ({@code "::"}),
 *       then the option accepts an optional argument.</li>
 *
 *       <li>Otherwise, the option character accepts no argument.</li>
 *
 *       <li>If the option specification string begins with a plus sign ({@code "+" }), the parser will behave
 *       "POSIX-ly correct".</li>
 *
 *       <li>If the option specification string contains the sequence {@code "W;"} (capital W followed by a
 *       semicolon), the parser will recognize the alternative form of long options.</li>
 *     </ul>
 *   </li>
 * </ol>
 *
 * <p>Each of the options in a list of options given to {@link #acceptsAll(List) acceptsAll} is treated as a
 * synonym of the others.  For example:</p>
 *   <pre>
 *     <code>
 *     OptionParser parser = new OptionParser();
 *     parser.acceptsAll( asList( "w", "interactive", "confirmation" ) );
 *     OptionSet options = parser.parse( "-w" );
 *     </code>
 *   </pre>
 * <p>In this case, <code>options.{@link OptionSet#has(String) has}</code> would answer {@code true} when given arguments
 * {@code "w"}, {@code "interactive"}, and {@code "confirmation"}. The {@link OptionSet} would give the same
 * responses to these arguments for its other methods as well.</p>
 *
 * <p>By default, as with GNU {@code getopt()}, the parser allows intermixing of options and non-options. If, however,
 * the parser has been created to be "POSIX-ly correct", then the first argument that does not look lexically like an
 * option, and is not a required argument of a preceding option, signals the end of options. You can still bind
 * optional arguments to their options using the abutting (for short options) or {@code =} syntax.</p>
 *
 * <p>Unlike GNU {@code getopt()}, this parser does not honor the environment variable {@code POSIXLY_CORRECT}.
 * "POSIX-ly correct" parsers are configured by either:</p>
 *
 * <ol>
 *   <li>using the method {@link #posixlyCorrect(boolean)}, or</li>
 *
 *   <li>using the {@linkplain #OptionParser(String) constructor} with an argument whose first character is a plus sign
 *   ({@code "+"})</li>
 * </ol>
 *
 * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
 * @see <a href="http://www.gnu.org/software/libc/manual">The GNU C Library</a>
 */
public class OptionParser implements OptionDeclarer {
    private final OptionNameMap<AbstractOptionSpec<?>> recognizedOptions;
    private final ArrayList<AbstractOptionSpec<?>> trainingOrder;
    private final Map<List<String>, Set<OptionSpec<?>>> requiredIf;
    private final Map<List<String>, Set<OptionSpec<?>>> requiredUnless;
    private final Map<List<String>, Set<OptionSpec<?>>> availableIf;
    private final Map<List<String>, Set<OptionSpec<?>>> availableUnless;

    private OptionParserState state;
    private boolean posixlyCorrect;
    private boolean allowsUnrecognizedOptions;
    private HelpFormatter helpFormatter = new BuiltinHelpFormatter();

    /**
     * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct"
     * behavior.
     */
    public OptionParser() {
        this(true);
    }

    /**
     * Creates an option parser that initially recognizes no options, and does not exhibit "POSIX-ly correct"
     * behavior.
     *
     * @param allowAbbreviations whether unambiguous abbreviations of long options should be recognized
     * by the parser
     */
    public OptionParser( boolean allowAbbreviations ) {
        trainingOrder = new ArrayList<>();
        requiredIf = new HashMap<>();
        requiredUnless = new HashMap<>();
        availableIf = new HashMap<>();
        availableUnless = new HashMap<>();
        state = moreOptions( false );

        recognizedOptions = allowAbbreviations
            ? new AbbreviationMap<AbstractOptionSpec<?>>()
            : new SimpleOptionNameMap<AbstractOptionSpec<?>>();

        recognize( new NonOptionArgumentSpec<String>() );
    }

    /**
     * Creates an option parser and configures it to recognize the short options specified in the given string.
     *
     * Arguments of options specified this way will be of type {@link String}.
     *
     * @param optionSpecification an option specification
     * @throws NullPointerException if {@code optionSpecification} is {@code null}
     * @throws OptionException if the option specification contains illegal characters or otherwise cannot be
     * recognized
     */
    public OptionParser( String optionSpecification ) {
        this();

        new OptionSpecTokenizer( optionSpecification ).configure( this );
    }

    public OptionSpecBuilder accepts( String option ) {
        return acceptsAll( singletonList( option ) );
    }

    public OptionSpecBuilder accepts( String option, String description ) {
        return acceptsAll( singletonList( option ), description );
    }

    public OptionSpecBuilder acceptsAll( List<String> options ) {
        return acceptsAll( options, "" );
    }

    public OptionSpecBuilder acceptsAll( List<String> options, String description ) {
        if ( options.isEmpty() )
            throw new IllegalArgumentException( "need at least one option" );

        ensureLegalOptions( options );

        return new OptionSpecBuilder( this, options, description );
    }

    public NonOptionArgumentSpec<String> nonOptions() {
        NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>();

        recognize( spec );

        return spec;
    }

    public NonOptionArgumentSpec<String> nonOptions( String description ) {
        NonOptionArgumentSpec<String> spec = new NonOptionArgumentSpec<>( description );

        recognize( spec );

        return spec;
    }

    public void posixlyCorrect( boolean setting ) {
        posixlyCorrect = setting;
        state = moreOptions( setting );
    }

    boolean posixlyCorrect() {
        return posixlyCorrect;
    }

    public void allowsUnrecognizedOptions() {
        allowsUnrecognizedOptions = true;
    }

    boolean doesAllowsUnrecognizedOptions() {
        return allowsUnrecognizedOptions;
    }

    public void recognizeAlternativeLongOptions( boolean recognize ) {
        if ( recognize )
            recognize( new AlternativeLongOptionSpec() );
        else
            recognizedOptions.remove( String.valueOf( RESERVED_FOR_EXTENSIONS ) );
    }

    void recognize( AbstractOptionSpec<?> spec ) {
        recognizedOptions.putAll( spec.options(), spec );
        trainingOrder.add( spec );
    }

    /**
     * Writes information about the options this parser recognizes to the given output sink.
     *
     * The output sink is flushed, but not closed.
     *
     * @param sink the sink to write information to
     * @throws IOException if there is a problem writing to the sink
     * @throws NullPointerException if {@code sink} is {@code null}
     * @see #printHelpOn(Writer)
     */
    public void printHelpOn( OutputStream sink ) throws IOException {
        printHelpOn( new OutputStreamWriter( sink ) );
    }

    /**
     * Writes information about the options this parser recognizes to the given output sink.
     *
     * The output sink is flushed, but not closed.
     *
     * @param sink the sink to write information to
     * @throws IOException if there is a problem writing to the sink
     * @throws NullPointerException if {@code sink} is {@code null}
     * @see #printHelpOn(OutputStream)
     */
    public void printHelpOn( Writer sink ) throws IOException {
        sink.write( helpFormatter.format( _recognizedOptions() ) );
        sink.flush();
    }

    /**
     * Tells the parser to use the given formatter when asked to {@linkplain #printHelpOn(java.io.Writer) print help}.
     *
     * @param formatter the formatter to use for printing help
     * @throws NullPointerException if the formatter is {@code null}
     */
    public void formatHelpWith( HelpFormatter formatter ) {
        if ( formatter == null )
            throw new NullPointerException();

        helpFormatter = formatter;
    }

    /**
     * Retrieves all options-spec pairings which have been configured for the parser in the same order as declared
     * during training. Option flags for specs are alphabetized by {@link OptionSpec#options()}; only the order of the
     * specs is preserved.
     *
     * (Note: prior to 4.7 the order was alphabetical across all options regardless of spec.)
     *
     * @return a map containing all the configured options and their corresponding {@link OptionSpec}
     * @since 4.6
     */
    public Map<String, OptionSpec<?>> recognizedOptions() {
        return new LinkedHashMap<String, OptionSpec<?>>( _recognizedOptions() );
    }

    private Map<String, AbstractOptionSpec<?>> _recognizedOptions() {
        Map<String, AbstractOptionSpec<?>> options = new LinkedHashMap<>();
        for ( AbstractOptionSpec<?> spec : trainingOrder ) {
            for ( String option : spec.options() )
                options.put( option, spec );
        }
        return options;
    }

   /**
     * Parses the given command line arguments according to the option specifications given to the parser.
     *
     * @param arguments arguments to parse
     * @return an {@link OptionSet} describing the parsed options, their arguments, and any non-option arguments found
     * @throws OptionException if problems are detected while parsing
     * @throws NullPointerException if the argument list is {@code null}
     */
    public OptionSet parse( String... arguments ) {
        ArgumentList argumentList = new ArgumentList( arguments );
        OptionSet detected = new OptionSet( recognizedOptions.toJavaUtilMap() );
        detected.add( recognizedOptions.get( NonOptionArgumentSpec.NAME ) );

        while ( argumentList.hasMore() )
            state.handleArgument( this, argumentList, detected );

        reset();

        ensureRequiredOptions( detected );
        ensureAllowedOptions( detected );

        return detected;
    }

    /**
     * Mandates mutual exclusiveness for the options built by the specified builders.
     *
     * @param specs descriptors for options that should be mutually exclusive on a command line.
     * @throws NullPointerException if {@code specs} is {@code null}
     */
    public void mutuallyExclusive( OptionSpecBuilder... specs ) {
        for ( int i = 0; i < specs.length; i++ ) {
            for ( int j = 0; j < specs.length; j++ ) {
                if ( i != j )
                    specs[i].availableUnless( specs[j] );
            }
        }
    }

    private void ensureRequiredOptions( OptionSet options ) {
        List<AbstractOptionSpec<?>> missingRequiredOptions = missingRequiredOptions(options);
        boolean helpOptionPresent = isHelpOptionPresent( options );

        if ( !missingRequiredOptions.isEmpty() && !helpOptionPresent )
            throw new MissingRequiredOptionsException( missingRequiredOptions );
    }

    private void ensureAllowedOptions( OptionSet options ) {
        List<AbstractOptionSpec<?>> forbiddenOptions = unavailableOptions( options );
        boolean helpOptionPresent = isHelpOptionPresent( options );

        if ( !forbiddenOptions.isEmpty() && !helpOptionPresent )
            throw new UnavailableOptionException( forbiddenOptions );
    }

    private List<AbstractOptionSpec<?>> missingRequiredOptions( OptionSet options ) {
        List<AbstractOptionSpec<?>> missingRequiredOptions = new ArrayList<>();

        for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
            if ( each.isRequired() && !options.has( each ) )
                missingRequiredOptions.add(each);
        }

        for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredIf.entrySet() ) {
            AbstractOptionSpec<?> required = specFor( each.getKey().iterator().next() );

            if ( optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) )
                missingRequiredOptions.add( required );
        }

        for ( Map.Entry<List<String>, Set<OptionSpec<?>>> each : requiredUnless.entrySet() ) {
            AbstractOptionSpec<?> required = specFor(each.getKey().iterator().next());

            if ( !optionsHasAnyOf( options, each.getValue() ) && !options.has( required ) )
                missingRequiredOptions.add( required );
        }

        return missingRequiredOptions;
    }

    private List<AbstractOptionSpec<?>> unavailableOptions(OptionSet options) {
        List<AbstractOptionSpec<?>> unavailableOptions = new ArrayList<>();

        for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableIf.entrySet() ) {
            AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() );

            if ( !optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) {
                unavailableOptions.add(forbidden);
            }
        }

        for ( Map.Entry<List<String>, Set<OptionSpec<?>>> eachEntry : availableUnless.entrySet() ) {
            AbstractOptionSpec<?> forbidden = specFor( eachEntry.getKey().iterator().next() );

            if ( optionsHasAnyOf( options, eachEntry.getValue() ) && options.has( forbidden ) ) {
                unavailableOptions.add(forbidden);
            }
        }

        return unavailableOptions;
    }

    private boolean optionsHasAnyOf( OptionSet options, Collection<OptionSpec<?>> specs ) {
        for ( OptionSpec<?> each : specs ) {
            if ( options.has( each ) )
                return true;
        }

        return false;
    }

    private boolean isHelpOptionPresent( OptionSet options ) {
        boolean helpOptionPresent = false;

        for ( AbstractOptionSpec<?> each : recognizedOptions.toJavaUtilMap().values() ) {
            if ( each.isForHelp() && options.has( each ) ) {
                helpOptionPresent = true;
                break;
            }
        }

        return helpOptionPresent;
    }

    void handleLongOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
        KeyValuePair optionAndArgument = parseLongOptionWithArgument( candidate );

        if ( !isRecognized( optionAndArgument.key ) )
            throw unrecognizedOption( optionAndArgument.key );

        AbstractOptionSpec<?> optionSpec = specFor( optionAndArgument.key );
        optionSpec.handleOption( this, arguments, detected, optionAndArgument.value );
    }

    void handleShortOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
        KeyValuePair optionAndArgument = parseShortOptionWithArgument( candidate );

        if ( isRecognized( optionAndArgument.key ) ) {
            specFor( optionAndArgument.key ).handleOption( this, arguments, detected, optionAndArgument.value );
        }
        else
            handleShortOptionCluster( candidate, arguments, detected );
    }

    private void handleShortOptionCluster( String candidate, ArgumentList arguments, OptionSet detected ) {
        char[] options = extractShortOptionsFrom( candidate );
        validateOptionCharacters( options );

        for ( int i = 0; i < options.length; i++ ) {
            AbstractOptionSpec<?> optionSpec = specFor( options[ i ] );

            if ( optionSpec.acceptsArguments() && options.length > i + 1 ) {
                String detectedArgument = String.valueOf( options, i + 1, options.length - 1 - i );
                optionSpec.handleOption( this, arguments, detected, detectedArgument );
                break;
            }

            optionSpec.handleOption( this, arguments, detected, null );
        }
    }

    void handleNonOptionArgument( String candidate, ArgumentList arguments, OptionSet detectedOptions ) {
        specFor( NonOptionArgumentSpec.NAME ).handleOption( this, arguments, detectedOptions, candidate );
    }

    void noMoreOptions() {
        state = OptionParserState.noMoreOptions();
    }

    boolean looksLikeAnOption( String argument ) {
        return isShortOptionToken( argument ) || isLongOptionToken( argument );
    }

    boolean isRecognized( String option ) {
        return recognizedOptions.contains( option );
    }

    void requiredIf( List<String> precedentSynonyms, String required ) {
        requiredIf( precedentSynonyms, specFor( required ) );
    }

    void requiredIf( List<String> precedentSynonyms, OptionSpec<?> required ) {
        putDependentOption( precedentSynonyms, required, requiredIf );
    }

    void requiredUnless( List<String> precedentSynonyms, String required ) {
        requiredUnless( precedentSynonyms, specFor( required ) );
    }

    void requiredUnless( List<String> precedentSynonyms, OptionSpec<?> required ) {
        putDependentOption( precedentSynonyms, required, requiredUnless );
    }

    void availableIf( List<String> precedentSynonyms, String available ) {
        availableIf( precedentSynonyms, specFor( available ) );
    }

    void availableIf( List<String> precedentSynonyms, OptionSpec<?> available) {
        putDependentOption( precedentSynonyms, available, availableIf );
    }

    void availableUnless( List<String> precedentSynonyms, String available ) {
        availableUnless( precedentSynonyms, specFor( available ) );
    }

    void availableUnless( List<String> precedentSynonyms, OptionSpec<?> available ) {
        putDependentOption( precedentSynonyms, available, availableUnless );
    }

    private void putDependentOption( List<String> precedentSynonyms, OptionSpec<?> required,
        Map<List<String>, Set<OptionSpec<?>>> target ) {

        for ( String each : precedentSynonyms ) {
            AbstractOptionSpec<?> spec = specFor( each );
            if ( spec == null )
                throw new UnconfiguredOptionException( precedentSynonyms );
        }

        Set<OptionSpec<?>> associated = target.get( precedentSynonyms );
        if ( associated == null ) {
            associated = new HashSet<>();
            target.put( precedentSynonyms, associated );
        }

        associated.add( required );
    }

    private AbstractOptionSpec<?> specFor( char option ) {
        return specFor( String.valueOf( option ) );
    }

    private AbstractOptionSpec<?> specFor( String option ) {
        return recognizedOptions.get( option );
    }

    private void reset() {
        state = moreOptions( posixlyCorrect );
    }

    private static char[] extractShortOptionsFrom( String argument ) {
        char[] options = new char[ argument.length() - 1 ];
        argument.getChars( 1, argument.length(), options, 0 );

        return options;
    }

    private void validateOptionCharacters( char[] options ) {
        for ( char each : options ) {
            String option = String.valueOf( each );

            if ( !isRecognized( option ) )
                throw unrecognizedOption( option );

            if ( specFor( option ).acceptsArguments() )
                return;
        }
    }

    private static KeyValuePair parseLongOptionWithArgument( String argument ) {
        return KeyValuePair.valueOf( argument.substring( 2 ) );
    }

    private static KeyValuePair parseShortOptionWithArgument( String argument ) {
        return KeyValuePair.valueOf( argument.substring( 1 ) );
    }
}
