    001/*
    002  Licensed to the Apache Software Foundation (ASF) under one or more
    003  contributor license agreements.  See the NOTICE file distributed with
    004  this work for additional information regarding copyright ownership.
    005  The ASF licenses this file to You under the Apache License, Version 2.0
    006  (the "License"); you may not use this file except in compliance with
    007  the License.  You may obtain a copy of the License at
    008
    009      http://www.apache.org/licenses/LICENSE-2.0
    010
    011  Unless required by applicable law or agreed to in writing, software
    012  distributed under the License is distributed on an "AS IS" BASIS,
    013  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014  See the License for the specific language governing permissions and
    015  limitations under the License.
    016 */
    017
    018package org.apache.commons.cli;
    019
    020import java.io.Serializable;
    021import java.util.ArrayList;
    022import java.util.Iterator;
    023import java.util.LinkedList;
    024import java.util.List;
    025import java.util.Objects;
    026import java.util.Properties;
    027import java.util.function.Consumer;
    028import java.util.function.Supplier;
    029
    030/**
    031 * Represents list of arguments parsed against a {@link Options} descriptor.
    032 * <p>
    033 * It allows querying of a boolean {@link #hasOption(String opt)}, in addition to retrieving the
    034 * {@link #getOptionValue(String opt)} for options requiring arguments.
    035 * </p>
    036 * <p>
    037 * Additionally, any left-over or unrecognized arguments, are available for further processing.
    038 * </p>
    039 */
    040public class CommandLine implements Serializable {
    041
    042    /**
    043     * A nested builder class to create {@code CommandLine} instance using descriptive methods.
    044     *
    045     * @since 1.4
    046     */
    047    public static final class Builder {
    048
    049        /**
    050         * Prints an Option to {@link System#out}.
    051         */
    052        static final Consumer<Option> DEPRECATED_HANDLER = o -> System.out.println(o.toDeprecatedString());
    053
    054        /** The unrecognized options/arguments */
    055        private final List<String> args = new LinkedList<>();
    056
    057        /** The processed options */
    058        private final List<Option> options = new ArrayList<>();
    059
    060        /**
    061         * Deprecated Option handler.
    062         */
    063        private Consumer<Option> deprecatedHandler = DEPRECATED_HANDLER;
    064
    065        /**
    066         * Adds left-over unrecognized option/argument.
    067         *
    068         * @param arg the unrecognized option/argument.
    069         *
    070         * @return this Builder instance for method chaining.
    071         */
    072        public Builder addArg(final String arg) {
    073            if (arg != null) {
    074                args.add(arg);
    075            }
    076            return this;
    077        }
    078
    079        /**
    080         * Adds an option to the command line. The values of the option are stored.
    081         *
    082         * @param opt the processed option.
    083         *
    084         * @return this Builder instance for method chaining.
    085         */
    086        public Builder addOption(final Option opt) {
    087            if (opt != null) {
    088                options.add(opt);
    089            }
    090            return this;
    091        }
    092
    093        /**
    094         * Creates the new instance.
    095         *
    096         * @return the new instance.
    097         */
    098        public CommandLine build() {
    099            return new CommandLine(args, options, deprecatedHandler);
    100        }
    101
    102        /**
    103         * Sets the deprecated option handler.
    104         *
    105         * @param deprecatedHandler the deprecated option handler.
    106         * @return {@code this} instance.
    107         * @since 1.7.0
    108         */
    109        public Builder setDeprecatedHandler(final Consumer<Option> deprecatedHandler) {
    110            this.deprecatedHandler = deprecatedHandler;
    111            return this;
    112        }
    113    }
    114
    115    /** The serial version UID. */
    116    private static final long serialVersionUID = 1L;
    117
    118    /**
    119     * Creates a new builder.
    120     *
    121     * @return a new builder.
    122     * @since 1.7.0
    123     */
    124    public static Builder builder() {
    125        return new Builder();
    126    }
    127
    128    /** The unrecognized options/arguments */
    129    private final List<String> args;
    130
    131    /** The processed options */
    132    private final List<Option> options;
    133
    134    /**
    135     * The deprecated option handler.
    136     * <p>
    137     * If you want to serialize this field, use a serialization proxy.
    138     * </p>
    139     */
    140    private final transient Consumer<Option> deprecatedHandler;
    141
    142    /**
    143     * Creates a command line.
    144     */
    145    protected CommandLine() {
    146        this(new LinkedList<>(), new ArrayList<>(), Builder.DEPRECATED_HANDLER);
    147    }
    148
    149    /**
    150     * Creates a command line.
    151     */
    152    private CommandLine(final List<String> args, final List<Option> options, final Consumer<Option> deprecatedHandler) {
    153        this.args = Objects.requireNonNull(args, "args");
    154        this.options = Objects.requireNonNull(options, "options");
    155        this.deprecatedHandler = deprecatedHandler;
    156    }
    157
    158    /**
    159     * Adds left-over unrecognized option/argument.
    160     *
    161     * @param arg the unrecognized option/argument.
    162     */
    163    protected void addArg(final String arg) {
    164        if (arg != null) {
    165            args.add(arg);
    166        }
    167    }
    168
    169    /**
    170     * Adds an option to the command line. The values of the option are stored.
    171     *
    172     * @param opt the processed option.
    173     */
    174    protected void addOption(final Option opt) {
    175        if (opt != null) {
    176            options.add(opt);
    177        }
    178    }
    179
    180    private <T> T get(final Supplier<T> supplier) {
    181        return supplier == null ? null : supplier.get();
    182    }
    183
    184    /**
    185     * Gets any left-over non-recognized options and arguments
    186     *
    187     * @return remaining items passed in but not parsed as a {@code List}.
    188     */
    189    public List<String> getArgList() {
    190        return args;
    191    }
    192
    193    /**
    194     * Gets any left-over non-recognized options and arguments
    195     *
    196     * @return remaining items passed in but not parsed as an array.
    197     */
    198    public String[] getArgs() {
    199        return args.toArray(Util.EMPTY_STRING_ARRAY);
    200    }
    201
    202    /**
    203     * Gets the {@code Object} type of this {@code Option}.
    204     *
    205     * @deprecated due to System.err message. Instead use getParsedOptionValue(char)
    206     * @param opt the name of the option.
    207     * @return the type of opt.
    208     */
    209    @Deprecated
    210    public Object getOptionObject(final char opt) {
    211        return getOptionObject(String.valueOf(opt));
    212    }
    213
    214    /**
    215     * Gets the {@code Object} type of this {@code Option}.
    216     *
    217     * @param opt the name of the option.
    218     * @return the type of this {@code Option}.
    219     * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
    220     */
    221    @Deprecated
    222    public Object getOptionObject(final String opt) {
    223        try {
    224            return getParsedOptionValue(opt);
    225        } catch (final ParseException pe) {
    226            System.err.println("Exception found converting " + opt + " to desired type: " + pe.getMessage());
    227            return null;
    228        }
    229    }
    230
    231    /**
    232     * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
    233     * <code>-Dparam1=value1
    234     * -Dparam2=value2</code>. All odd numbered values are property keys
    235     * and even numbered values are property values.  If there are an odd number of values
    236     * the last value is assumed to be a boolean flag and the value is "true".
    237     *
    238     * @param option name of the option.
    239     * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
    240     * @since 1.5.0
    241     */
    242    public Properties getOptionProperties(final Option option) {
    243        final Properties props = new Properties();
    244        for (final Option processedOption : options) {
    245            if (processedOption.equals(option)) {
    246                processPropertiesFromValues(props, processedOption.getValuesList());
    247            }
    248        }
    249        return props;
    250    }
    251
    252    /**
    253     * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
    254     * <code>-Dparam1=value1
    255     * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option
    256     * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}.
    257     *
    258     * @param opt name of the option.
    259     * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
    260     * @since 1.2
    261     */
    262    public Properties getOptionProperties(final String opt) {
    263        final Properties props = new Properties();
    264        for (final Option option : options) {
    265            if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt())) {
    266                processPropertiesFromValues(props, option.getValuesList());
    267            }
    268        }
    269        return props;
    270    }
    271
    272    /**
    273     * Gets an array of the processed {@link Option}s.
    274     *
    275     * @return an array of the processed {@link Option}s.
    276     */
    277    public Option[] getOptions() {
    278        return options.toArray(Option.EMPTY_ARRAY);
    279    }
    280
    281    /**
    282     * Gets the first argument, if any, of this option.
    283     *
    284     * @param opt the character name of the option.
    285     * @return Value of the argument if option is set, and has an argument, otherwise null.
    286     */
    287    public String getOptionValue(final char opt) {
    288        return getOptionValue(String.valueOf(opt));
    289    }
    290
    291    /**
    292     * Gets the argument, if any, of an option.
    293     *
    294     * @param opt character name of the option
    295     * @param defaultValue is the default value to be returned if the option is not specified.
    296     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    297     */
    298    public String getOptionValue(final char opt, final String defaultValue) {
    299        return getOptionValue(String.valueOf(opt), () -> defaultValue);
    300    }
    301
    302    /**
    303     * Gets the argument, if any, of an option.
    304     *
    305     * @param opt character name of the option
    306     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
    307     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    308     * @since 1.7.0
    309     */
    310    public String getOptionValue(final char opt, final Supplier<String> defaultValue) {
    311        return getOptionValue(String.valueOf(opt), defaultValue);
    312    }
    313
    314    /**
    315     * Gets the first argument, if any, of this option.
    316     *
    317     * @param option the option.
    318     * @return Value of the argument if option is set, and has an argument, otherwise null.
    319     * @since 1.5.0
    320     */
    321    public String getOptionValue(final Option option) {
    322        final String[] values = getOptionValues(option);
    323        return values == null ? null : values[0];
    324    }
    325
    326    /**
    327     * Gets the first argument, if any, of an option.
    328     *
    329     * @param option the option.
    330     * @param defaultValue is the default value to be returned if the option is not specified.
    331     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    332     * @since 1.5.0
    333     */
    334    public String getOptionValue(final Option option, final String defaultValue) {
    335        return getOptionValue(option, () -> defaultValue);
    336    }
    337
    338    /**
    339     * Gets the first argument, if any, of an option.
    340     *
    341     * @param option the option.
    342     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
    343     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    344     * @since 1.7.0
    345     */
    346    public String getOptionValue(final Option option, final Supplier<String> defaultValue) {
    347        final String answer = getOptionValue(option);
    348        return answer != null ? answer : get(defaultValue);
    349    }
    350
    351    /**
    352     * Gets the first argument, if any, of this option group.
    353     *
    354     * @param optionGroup the option group.
    355     * @return Value of the argument if option group is selected, and has an argument, otherwise null.
    356     * @since 1.9.0
    357     */
    358    public String getOptionValue(final OptionGroup optionGroup) {
    359        final String[] values = getOptionValues(optionGroup);
    360        return values == null ? null : values[0];
    361    }
    362
    363    /**
    364     * Gets the first argument, if any, of an option group.
    365     *
    366     * @param optionGroup the option group.
    367     * @param defaultValue is the default value to be returned if the option group is not selected.
    368     * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
    369     * @since 1.9.0
    370     */
    371    public String getOptionValue(final OptionGroup optionGroup, final String defaultValue) {
    372        return getOptionValue(optionGroup, () -> defaultValue);
    373    }
    374
    375    /**
    376     * Gets the first argument, if any, of an option group.
    377     *
    378     * @param optionGroup the option group..
    379     * @param defaultValue is a supplier for the default value to be returned if the option group is not selected.
    380     * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
    381     * @since 1.9.0
    382     */
    383    public String getOptionValue(final OptionGroup optionGroup, final Supplier<String> defaultValue) {
    384        final String answer = getOptionValue(optionGroup);
    385        return answer != null ? answer : get(defaultValue);
    386    }
    387
    388
    389    /**
    390     * Gets the first argument, if any, of this option.
    391     *
    392     * @param opt the name of the option.
    393     * @return Value of the argument if option is set, and has an argument, otherwise null.
    394     */
    395    public String getOptionValue(final String opt) {
    396        return getOptionValue(resolveOption(opt));
    397    }
    398
    399    /**
    400     * Gets the first argument, if any, of an option.
    401     *
    402     * @param opt name of the option.
    403     * @param defaultValue is the default value to be returned if the option is not specified.
    404     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    405     */
    406    public String getOptionValue(final String opt, final String defaultValue) {
    407        return getOptionValue(resolveOption(opt), () -> defaultValue);
    408    }
    409
    410    /**
    411     * Gets the first argument, if any, of an option.
    412     *
    413     * @param opt name of the option.
    414     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
    415     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
    416     * @since 1.7.0
    417     */
    418    public String getOptionValue(final String opt, final Supplier<String> defaultValue) {
    419        return getOptionValue(resolveOption(opt), defaultValue);
    420    }
    421
    422
    423    /**
    424     * Gets the array of values, if any, of an option.
    425     *
    426     * @param opt character name of the option.
    427     * @return Values of the argument if option is set, and has an argument, otherwise null.
    428     */
    429    public String[] getOptionValues(final char opt) {
    430        return getOptionValues(String.valueOf(opt));
    431    }
    432
    433    /**
    434     * Gets the array of values, if any, of an option.
    435     *
    436     * @param option the option.
    437     * @return Values of the argument if option is set, and has an argument, otherwise null.
    438     * @since 1.5.0
    439     */
    440    public String[] getOptionValues(final Option option) {
    441        if (option == null) {
    442            return null;
    443        }
    444        final List<String> values = new ArrayList<>();
    445        for (final Option processedOption : options) {
    446            if (processedOption.equals(option)) {
    447                if (option.isDeprecated()) {
    448                    handleDeprecated(option);
    449                }
    450                values.addAll(processedOption.getValuesList());
    451            }
    452        }
    453        return values.isEmpty() ? null : values.toArray(Util.EMPTY_STRING_ARRAY);
    454    }
    455
    456    /**
    457     * Gets the array of values, if any, of an option group.
    458     *
    459     * @param optionGroup the option group.
    460     * @return Values of the argument if option group is selected, and has an argument, otherwise null.
    461     * @since 1.9.0
    462     */
    463    public String[] getOptionValues(final OptionGroup optionGroup) {
    464        if (optionGroup == null || !optionGroup.isSelected()) {
    465            return null;
    466        }
    467        return getOptionValues(optionGroup.getSelected());
    468    }
    469
    470    /**
    471     * Gets the array of values, if any, of an option.
    472     *
    473     * @param opt string name of the option.
    474     * @return Values of the argument if option is set, and has an argument, otherwise null.
    475     */
    476    public String[] getOptionValues(final String opt) {
    477        return getOptionValues(resolveOption(opt));
    478    }
    479
    480    /**
    481     * Gets a version of this {@code Option} converted to a particular type.
    482     *
    483     * @param opt the name of the option.
    484     * @param <T> The return type for the method.
    485     * @return the value parsed into a particular object.
    486     * @throws ParseException if there are problems turning the option value into the desired type
    487     * @see PatternOptionBuilder
    488     * @since 1.5.0
    489     */
    490    public <T> T getParsedOptionValue(final char opt) throws ParseException {
    491        return getParsedOptionValue(String.valueOf(opt));
    492    }
    493
    494    /**
    495     * Gets a version of this {@code Option} converted to a particular type.
    496     *
    497     * @param opt the name of the option.
    498     * @param defaultValue the default value to return if opt is not set.
    499     * @param <T> The return type for the method.
    500     * @return the value parsed into a particular object.
    501     * @throws ParseException if there are problems turning the option value into the desired type
    502     * @see PatternOptionBuilder
    503     * @since 1.7.0
    504     */
    505    public <T> T getParsedOptionValue(final char opt, final Supplier<T> defaultValue) throws ParseException {
    506        return getParsedOptionValue(String.valueOf(opt), defaultValue);
    507    }
    508
    509    /**
    510     * Gets a version of this {@code Option} converted to a particular type.
    511     *
    512     * @param opt the name of the option.
    513     * @param defaultValue the default value to return if opt is not set.
    514     * @param <T> The return type for the method.
    515     * @return the value parsed into a particular object.
    516     * @throws ParseException if there are problems turning the option value into the desired type
    517     * @see PatternOptionBuilder
    518     * @since 1.7.0
    519     */
    520    public <T> T getParsedOptionValue(final char opt, final T defaultValue) throws ParseException {
    521        return getParsedOptionValue(String.valueOf(opt), defaultValue);
    522    }
    523
    524    /**
    525     * Gets a version of this {@code Option} converted to a particular type.
    526     *
    527     * @param option the option.
    528     * @param <T> The return type for the method.
    529     * @return the value parsed into a particular object.
    530     * @throws ParseException if there are problems turning the option value into the desired type
    531     * @see PatternOptionBuilder
    532     * @since 1.5.0
    533     */
    534    public <T> T getParsedOptionValue(final Option option) throws ParseException {
    535        return getParsedOptionValue(option, () -> null);
    536    }
    537
    538    /**
    539     * Gets a version of this {@code Option} converted to a particular type.
    540     *
    541     * @param option the option.
    542     * @param defaultValue the default value to return if opt is not set.
    543     * @param <T> The return type for the method.
    544     * @return the value parsed into a particular object.
    545     * @throws ParseException if there are problems turning the option value into the desired type
    546     * @see PatternOptionBuilder
    547     * @since 1.7.0
    548     */
    549    @SuppressWarnings("unchecked")
    550    public <T> T getParsedOptionValue(final Option option, final Supplier<T> defaultValue) throws ParseException {
    551        if (option == null) {
    552            return get(defaultValue);
    553        }
    554        final String res = getOptionValue(option);
    555        try {
    556            if (res == null) {
    557                return get(defaultValue);
    558            }
    559            return (T) option.getConverter().apply(res);
    560        } catch (final Throwable e) {
    561            throw ParseException.wrap(e);
    562        }
    563    }
    564
    565    /**
    566     * Gets a version of this {@code Option} converted to a particular type.
    567     *
    568     * @param option the option.
    569     * @param defaultValue the default value to return if opt is not set.
    570     * @param <T> The return type for the method.
    571     * @return the value parsed into a particular object.
    572     * @throws ParseException if there are problems turning the option value into the desired type
    573     * @see PatternOptionBuilder
    574     * @since 1.7.0
    575     */
    576    public <T> T getParsedOptionValue(final Option option, final T defaultValue) throws ParseException {
    577        return getParsedOptionValue(option, () -> defaultValue);
    578    }
    579
    580    /**
    581     * Gets a version of this {@code OptionGroup} converted to a particular type.
    582     *
    583     * @param optionGroup the option group.
    584     * @param <T> The return type for the method.
    585     * @return the value parsed into a particular object.
    586     * @throws ParseException if there are problems turning the selected option value into the desired type
    587     * @see PatternOptionBuilder
    588     * @since 1.9.0
    589     */
    590    public <T> T getParsedOptionValue(final OptionGroup optionGroup) throws ParseException {
    591        return getParsedOptionValue(optionGroup, () -> null);
    592    }
    593
    594    /**
    595     * Gets a version of this {@code OptionGroup} converted to a particular type.
    596     *
    597     * @param optionGroup the option group.
    598     * @param defaultValue the default value to return if opt is not set.
    599     * @param <T> The return type for the method.
    600     * @return the value parsed into a particular object.
    601     * @throws ParseException if there are problems turning the selected option value into the desired type
    602     * @see PatternOptionBuilder
    603     * @since 1.9.0
    604     */
    605    public <T> T getParsedOptionValue(final OptionGroup optionGroup, final Supplier<T> defaultValue) throws ParseException {
    606        if (optionGroup == null || !optionGroup.isSelected()) {
    607            return get(defaultValue);
    608        }
    609        return getParsedOptionValue(optionGroup.getSelected(), defaultValue);
    610    }
    611
    612    /**
    613     * Gets a version of this {@code OptionGroup} converted to a particular type.
    614     *
    615     * @param optionGroup the option group.
    616     * @param defaultValue the default value to return if an option is not selected.
    617     * @param <T> The return type for the method.
    618     * @return the value parsed into a particular object.
    619     * @throws ParseException if there are problems turning the option value into the desired type
    620     * @see PatternOptionBuilder
    621     * @since 1.9.0
    622     */
    623    public <T> T getParsedOptionValue(final OptionGroup optionGroup, final T defaultValue) throws ParseException {
    624        return getParsedOptionValue(optionGroup, () -> defaultValue);
    625    }
    626
    627    /**
    628     * Gets a version of this {@code Option} converted to a particular type.
    629     *
    630     * @param opt the name of the option.
    631     * @param <T> The return type for the method.
    632     * @return the value parsed into a particular object.
    633     * @throws ParseException if there are problems turning the option value into the desired type
    634     * @see PatternOptionBuilder
    635     * @since 1.2
    636     */
    637    public <T> T getParsedOptionValue(final String opt) throws ParseException {
    638        return getParsedOptionValue(resolveOption(opt));
    639    }
    640
    641    /**
    642     * Gets a version of this {@code Option} converted to a particular type.
    643     *
    644     * @param opt the name of the option.
    645     * @param defaultValue the default value to return if opt is not set.
    646     * @param <T> The return type for the method.
    647     * @return the value parsed into a particular object.
    648     * @throws ParseException if there are problems turning the option value into the desired type
    649     * @see PatternOptionBuilder
    650     * @since 1.7.0
    651     */
    652    public <T> T getParsedOptionValue(final String opt, final Supplier<T> defaultValue) throws ParseException {
    653        return getParsedOptionValue(resolveOption(opt), defaultValue);
    654    }
    655
    656    /**
    657     * Gets a version of this {@code Option} converted to a particular type.
    658     *
    659     * @param opt the name of the option.
    660     * @param defaultValue the default value to return if opt is not set.
    661     * @param <T> The return type for the method.
    662     * @return the value parsed into a particular object.
    663     * @throws ParseException if there are problems turning the option value into the desired type
    664     * @see PatternOptionBuilder
    665     * @since 1.7.0
    666     */
    667    public <T> T getParsedOptionValue(final String opt, final T defaultValue) throws ParseException {
    668        return getParsedOptionValue(resolveOption(opt), defaultValue);
    669    }
    670
    671    /**
    672     * Handles deprecated options.
    673     *
    674     * @param option a deprecated option.
    675     */
    676    private void handleDeprecated(final Option option) {
    677        if (deprecatedHandler != null) {
    678            deprecatedHandler.accept(option);
    679        }
    680    }
    681
    682    /**
    683     * jkeyes - commented out until it is implemented properly
    684     * <p>
    685     * Dump state, suitable for debugging.
    686     * </p>
    687     *
    688     * @return Stringified form of this object.
    689     */
    690
    691    /*
    692     * public String toString() { StringBuilder buf = new StringBuilder();
    693     *
    694     * buf.append("[ CommandLine: [ options: "); buf.append(options.toString()); buf.append(" ] [ args: ");
    695     * buf.append(args.toString()); buf.append(" ] ]");
    696     *
    697     * return buf.toString(); }
    698     */
    699
    700    /**
    701     * Tests to see if an option has been set.
    702     *
    703     * @param opt character name of the option.
    704     * @return true if set, false if not.
    705     */
    706    public boolean hasOption(final char opt) {
    707        return hasOption(String.valueOf(opt));
    708    }
    709
    710    /**
    711     * Tests to see if an option has been set.
    712     *
    713     * @param opt the option to check.
    714     * @return true if set, false if not.
    715     * @since 1.5.0
    716     */
    717    public boolean hasOption(final Option opt) {
    718        final boolean result = options.contains(opt);
    719        if (result && opt.isDeprecated()) {
    720            handleDeprecated(opt);
    721        }
    722        return result;
    723    }
    724
    725    /**
    726     * Tests to see if an option has been set.
    727     *
    728     * @param optionGroup the option group to check.
    729     * @return true if set, false if not.
    730     * @since 1.9.0
    731     */
    732    public boolean hasOption(final OptionGroup optionGroup) {
    733        if (optionGroup == null || !optionGroup.isSelected()) {
    734            return false;
    735        }
    736        return hasOption(optionGroup.getSelected());
    737    }
    738
    739    /**
    740     * Tests to see if an option has been set.
    741     *
    742     * @param opt Short name of the option.
    743     * @return true if set, false if not.
    744     */
    745    public boolean hasOption(final String opt) {
    746        return hasOption(resolveOption(opt));
    747    }
    748
    749    /**
    750     * Returns an iterator over the Option members of CommandLine.
    751     *
    752     * @return an {@code Iterator} over the processed {@link Option} members of this {@link CommandLine}.
    753     */
    754    public Iterator<Option> iterator() {
    755        return options.iterator();
    756    }
    757
    758    /**
    759     * Parses a list of values as properties.  All odd numbered values are property keys
    760     * and even numbered values are property values.  If there are an odd number of values
    761     * the last value is assumed to be a boolean with a value of "true".
    762     * @param props the properties to update.
    763     * @param values the list of values to parse.
    764     */
    765    private void processPropertiesFromValues(final Properties props, final List<String> values) {
    766        for (int i = 0; i < values.size(); i += 2) {
    767            if (i + 1 < values.size()) {
    768                props.put(values.get(i), values.get(i + 1));
    769            } else {
    770                props.put(values.get(i), "true");
    771            }
    772        }
    773    }
    774
    775    /**
    776     * Retrieves the option object given the long or short option as a String
    777     *
    778     * @param opt short or long name of the option, may be null.
    779     * @return Canonicalized option.
    780     */
    781    private Option resolveOption(final String opt) {
    782        final String actual = Util.stripLeadingHyphens(opt);
    783        if (actual != null) {
    784            for (final Option option : options) {
    785                if (actual.equals(option.getOpt()) || actual.equals(option.getLongOpt())) {
    786                    return option;
    787                }
    788            }
    789        }
    790        return null;
    791    }
    792}