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      https://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.lang.reflect.Array;
022import java.util.ArrayList;
023import java.util.Iterator;
024import java.util.LinkedList;
025import java.util.List;
026import java.util.Objects;
027import java.util.Properties;
028import java.util.function.Consumer;
029import java.util.function.Supplier;
030
031/**
032 * Represents list of arguments parsed against a {@link Options} descriptor.
033 * <p>
034 * It allows querying of a boolean {@link #hasOption(String optionName)}, in addition to retrieving the
035 * {@link #getOptionValue(String optionName)} for options requiring arguments.
036 * </p>
037 * <p>
038 * Additionally, any left-over or unrecognized arguments, are available for further processing.
039 * </p>
040 */
041public class CommandLine implements Serializable {
042
043    /**
044     * A nested builder class to create {@code CommandLine} instance using descriptive methods.
045     *
046     * @since 1.4
047     */
048    public static final class Builder implements Supplier<CommandLine> {
049
050        /**
051         * Prints an Option to {@link System#out}.
052         */
053        static final Consumer<Option> DEPRECATED_HANDLER = o -> System.out.println(o.toDeprecatedString());
054
055        /** The unrecognized options/arguments */
056        private final List<String> args = new LinkedList<>();
057
058        /** The processed options */
059        private final List<Option> options = new ArrayList<>();
060
061        /**
062         * Deprecated Option handler.
063         */
064        private Consumer<Option> deprecatedHandler = DEPRECATED_HANDLER;
065
066        /**
067         * Constructs a new instance.
068         *
069         * @deprecated Use {@link #builder()}.
070         */
071        @Deprecated
072        public Builder() {
073            // empty
074        }
075
076        /**
077         * Adds left-over unrecognized option/argument.
078         *
079         * @param arg the unrecognized option/argument.
080         * @return this Builder instance for method chaining.
081         */
082        public Builder addArg(final String arg) {
083            if (arg != null) {
084                args.add(arg);
085            }
086            return this;
087        }
088
089        /**
090         * Adds an option to the command line. The values of the option are stored.
091         *
092         * @param option the processed option.
093         * @return this Builder instance for method chaining.
094         */
095        public Builder addOption(final Option option) {
096            if (option != null) {
097                options.add(option);
098            }
099            return this;
100        }
101
102        /**
103         * Creates a new instance.
104         *
105         * @return a new instance.
106         * @deprecated Use {@link #get()}.
107         */
108        @Deprecated
109        public CommandLine build() {
110            return get();
111        }
112
113        /**
114         * Creates a new instance.
115         *
116         * @return a new instance.
117         * @since 1.10.0
118         */
119        @Override
120        public CommandLine get() {
121            return new CommandLine(args, options, deprecatedHandler);
122        }
123
124        /**
125         * Sets the deprecated option handler.
126         *
127         * @param deprecatedHandler the deprecated option handler.
128         * @return {@code this} instance.
129         * @since 1.7.0
130         */
131        public Builder setDeprecatedHandler(final Consumer<Option> deprecatedHandler) {
132            this.deprecatedHandler = deprecatedHandler;
133            return this;
134        }
135    }
136
137    /** The serial version UID. */
138    private static final long serialVersionUID = 1L;
139
140    /**
141     * Creates a new builder.
142     *
143     * @return a new builder.
144     * @since 1.7.0
145     */
146    public static Builder builder() {
147        return new Builder();
148    }
149
150    /** The unrecognized options/arguments */
151    private final List<String> args;
152
153    /** The processed options */
154    private final List<Option> options;
155
156    /**
157     * The deprecated option handler.
158     * <p>
159     * If you want to serialize this field, use a serialization proxy.
160     * </p>
161     */
162    private final transient Consumer<Option> deprecatedHandler;
163
164    /**
165     * Creates a command line.
166     */
167    protected CommandLine() {
168        this(new LinkedList<>(), new ArrayList<>(), Builder.DEPRECATED_HANDLER);
169    }
170
171    /**
172     * Creates a command line.
173     */
174    private CommandLine(final List<String> args, final List<Option> options, final Consumer<Option> deprecatedHandler) {
175        this.args = Objects.requireNonNull(args, "args");
176        this.options = Objects.requireNonNull(options, "options");
177        this.deprecatedHandler = deprecatedHandler;
178    }
179
180    /**
181     * Adds left-over unrecognized option/argument.
182     *
183     * @param arg the unrecognized option/argument.
184     */
185    protected void addArg(final String arg) {
186        if (arg != null) {
187            args.add(arg);
188        }
189    }
190
191    /**
192     * Adds an option to the command line. The values of the option are stored.
193     *
194     * @param option the processed option.
195     */
196    protected void addOption(final Option option) {
197        if (option != null) {
198            options.add(option);
199        }
200    }
201
202    private <T> T get(final Supplier<T> supplier) {
203        return supplier == null ? null : supplier.get();
204    }
205
206    /**
207     * Gets any left-over non-recognized options and arguments
208     *
209     * @return remaining items passed in but not parsed as a {@code List}.
210     */
211    public List<String> getArgList() {
212        return args;
213    }
214
215    /**
216     * Gets any left-over non-recognized options and arguments
217     *
218     * @return remaining items passed in but not parsed as an array.
219     */
220    public String[] getArgs() {
221        return args.toArray(Util.EMPTY_STRING_ARRAY);
222    }
223
224    /**
225     * Gets the {@code Object} type of this {@code Option}.
226     *
227     * @deprecated due to System.err message. Instead use getParsedOptionValue(char)
228     * @param optionChar the name of the option.
229     * @return the type of opt.
230     */
231    @Deprecated
232    public Object getOptionObject(final char optionChar) {
233        return getOptionObject(String.valueOf(optionChar));
234    }
235
236    /**
237     * Gets the {@code Object} type of this {@code Option}.
238     *
239     * @param optionName the name of the option.
240     * @return the type of this {@code Option}.
241     * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
242     */
243    @Deprecated
244    public Object getOptionObject(final String optionName) {
245        try {
246            return getParsedOptionValue(optionName);
247        } catch (final ParseException pe) {
248            System.err.println("Exception found converting " + optionName + " to desired type: " + pe.getMessage());
249            return null;
250        }
251    }
252
253    /**
254     * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
255     * <code>-Dparam1=value1
256     * -Dparam2=value2</code>. All odd numbered values are property keys
257     * and even numbered values are property values.  If there are an odd number of values
258     * the last value is assumed to be a boolean flag and the value is "true".
259     *
260     * @param option name of the option.
261     * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
262     * @since 1.5.0
263     */
264    public Properties getOptionProperties(final Option option) {
265        final Properties props = new Properties();
266        for (final Option processedOption : options) {
267            if (processedOption.equals(option)) {
268                processPropertiesFromValues(props, processedOption.getValuesList());
269            }
270        }
271        return props;
272    }
273
274    /**
275     * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
276     * <code>-Dparam1=value1
277     * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option
278     * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}.
279     *
280     * @param optionName name of the option.
281     * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
282     * @since 1.2
283     */
284    public Properties getOptionProperties(final String optionName) {
285        final Properties props = new Properties();
286        for (final Option option : options) {
287            if (optionName.equals(option.getOpt()) || optionName.equals(option.getLongOpt())) {
288                processPropertiesFromValues(props, option.getValuesList());
289            }
290        }
291        return props;
292    }
293
294    /**
295     * Gets an array of the processed {@link Option}s.
296     *
297     * @return an array of the processed {@link Option}s.
298     */
299    public Option[] getOptions() {
300        return options.toArray(Option.EMPTY_ARRAY);
301    }
302
303    /**
304     * Gets the first argument, if any, of this option.
305     *
306     * @param optionChar the character name of the option.
307     * @return Value of the argument if option is set, and has an argument, otherwise null.
308     */
309    public String getOptionValue(final char optionChar) {
310        return getOptionValue(String.valueOf(optionChar));
311    }
312
313    /**
314     * Gets the argument, if any, of an option.
315     *
316     * @param optionChar character name of the option
317     * @param defaultValue is the default value to be returned if the option is not specified.
318     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
319     */
320    public String getOptionValue(final char optionChar, final String defaultValue) {
321        return getOptionValue(String.valueOf(optionChar), () -> defaultValue);
322    }
323
324    /**
325     * Gets the argument, if any, of an option.
326     *
327     * @param optionChar character name of the option
328     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
329     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
330     * @since 1.7.0
331     */
332    public String getOptionValue(final char optionChar, final Supplier<String> defaultValue) {
333        return getOptionValue(String.valueOf(optionChar), defaultValue);
334    }
335
336    /**
337     * Gets the first argument, if any, of this option.
338     *
339     * @param option the option.
340     * @return Value of the argument if option is set, and has an argument, otherwise null.
341     * @since 1.5.0
342     */
343    public String getOptionValue(final Option option) {
344        final String[] values = getOptionValues(option);
345        return values == null ? null : values[0];
346    }
347
348    /**
349     * Gets the first argument, if any, of an option.
350     *
351     * @param option the option.
352     * @param defaultValue is the default value to be returned if the option is not specified.
353     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
354     * @since 1.5.0
355     */
356    public String getOptionValue(final Option option, final String defaultValue) {
357        return getOptionValue(option, () -> defaultValue);
358    }
359
360    /**
361     * Gets the first argument, if any, of an option.
362     *
363     * @param option the option.
364     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
365     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
366     * @since 1.7.0
367     */
368    public String getOptionValue(final Option option, final Supplier<String> defaultValue) {
369        final String answer = getOptionValue(option);
370        return answer != null ? answer : get(defaultValue);
371    }
372
373    /**
374     * Gets the first argument, if any, of this option group.
375     *
376     * @param optionGroup the option group.
377     * @return Value of the argument if option group is selected, and has an argument, otherwise null.
378     * @since 1.9.0
379     */
380    public String getOptionValue(final OptionGroup optionGroup) {
381        final String[] values = getOptionValues(optionGroup);
382        return values == null ? null : values[0];
383    }
384
385    /**
386     * Gets the first argument, if any, of an option group.
387     *
388     * @param optionGroup the option group.
389     * @param defaultValue is the default value to be returned if the option group is not selected.
390     * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
391     * @since 1.9.0
392     */
393    public String getOptionValue(final OptionGroup optionGroup, final String defaultValue) {
394        return getOptionValue(optionGroup, () -> defaultValue);
395    }
396
397    /**
398     * Gets the first argument, if any, of an option group.
399     *
400     * @param optionGroup the option group.
401     * @param defaultValue is a supplier for the default value to be returned if the option group is not selected.
402     * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
403     * @since 1.9.0
404     */
405    public String getOptionValue(final OptionGroup optionGroup, final Supplier<String> defaultValue) {
406        final String answer = getOptionValue(optionGroup);
407        return answer != null ? answer : get(defaultValue);
408    }
409
410    /**
411     * Gets the first argument, if any, of this option.
412     *
413     * @param optionName the name of the option.
414     * @return Value of the argument if option is set, and has an argument, otherwise null.
415     */
416    public String getOptionValue(final String optionName) {
417        return getOptionValue(resolveOption(optionName));
418    }
419
420    /**
421     * Gets the first argument, if any, of an option.
422     *
423     * @param optionName name of the option.
424     * @param defaultValue is the default value to be returned if the option is not specified.
425     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
426     */
427    public String getOptionValue(final String optionName, final String defaultValue) {
428        return getOptionValue(resolveOption(optionName), () -> defaultValue);
429    }
430
431    /**
432     * Gets the first argument, if any, of an option.
433     *
434     * @param optionName name of the option.
435     * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
436     * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
437     * @since 1.7.0
438     */
439    public String getOptionValue(final String optionName, final Supplier<String> defaultValue) {
440        return getOptionValue(resolveOption(optionName), defaultValue);
441    }
442
443    /**
444     * Gets the array of values, if any, of an option.
445     *
446     * @param optionChar character name of the option.
447     * @return Values of the argument if option is set, and has an argument, otherwise null.
448     */
449    public String[] getOptionValues(final char optionChar) {
450        return getOptionValues(String.valueOf(optionChar));
451    }
452
453    /**
454     * Gets the array of values, if any, of an option.
455     *
456     * @param option the option.
457     * @return Values of the argument if option is set, and has an argument, otherwise null.
458     * @since 1.5.0
459     */
460    public String[] getOptionValues(final Option option) {
461        if (option == null) {
462            return null;
463        }
464        final List<String> values = new ArrayList<>();
465        for (final Option processedOption : options) {
466            if (processedOption.equals(option)) {
467                if (option.isDeprecated()) {
468                    handleDeprecated(option);
469                }
470                values.addAll(processedOption.getValuesList());
471            }
472        }
473        return values.isEmpty() ? null : values.toArray(Util.EMPTY_STRING_ARRAY);
474    }
475
476    /**
477     * Gets the array of values, if any, of an option group.
478     *
479     * @param optionGroup the option group.
480     * @return Values of the argument if option group is selected, and has an argument, otherwise null.
481     * @since 1.9.0
482     */
483    public String[] getOptionValues(final OptionGroup optionGroup) {
484        if (optionGroup == null || !optionGroup.isSelected()) {
485            return null;
486        }
487        return getOptionValues(optionGroup.getSelected());
488    }
489
490    /**
491     * Gets the array of values, if any, of an option.
492     *
493     * @param optionName string name of the option.
494     * @return Values of the argument if option is set, and has an argument, otherwise null.
495     */
496    public String[] getOptionValues(final String optionName) {
497        return getOptionValues(resolveOption(optionName));
498    }
499
500    /**
501     * Gets a version of this {@code Option} converted to a particular type.
502     *
503     * @param optionChar the name of the option.
504     * @param <T> The return type for the method.
505     * @return the value parsed into a particular object or null if the option is not set.
506     * @throws ParseException if there are problems turning the option value into the desired type
507     * @see PatternOptionBuilder
508     * @since 1.5.0
509     */
510    public <T> T getParsedOptionValue(final char optionChar) throws ParseException {
511        return getParsedOptionValue(String.valueOf(optionChar));
512    }
513
514    /**
515     * Gets a version of this {@code Option} converted to a particular type.
516     *
517     * @param optionChar the name of the option.
518     * @param defaultValue the default value to return if opt is not set.
519     * @param <T> The return type for the method.
520     * @return the value parsed into a particular object or the defaultValue if the option is not set.
521     * @throws ParseException if there are problems turning the option value into the desired type
522     * @see PatternOptionBuilder
523     * @since 1.7.0
524     */
525    public <T> T getParsedOptionValue(final char optionChar, final Supplier<T> defaultValue) throws ParseException {
526        return getParsedOptionValue(String.valueOf(optionChar), defaultValue);
527    }
528
529    /**
530     * Gets a version of this {@code Option} converted to a particular type.
531     *
532     * @param optionChar the name of the option.
533     * @param defaultValue the default value to return if opt is not set.
534     * @param <T> The return type for the method.
535     * @return the value parsed into a particular object or the defaultValue if the option is not set.
536     * @throws ParseException if there are problems turning the option value into the desired type
537     * @see PatternOptionBuilder
538     * @since 1.7.0
539     */
540    public <T> T getParsedOptionValue(final char optionChar, final T defaultValue) throws ParseException {
541        return getParsedOptionValue(String.valueOf(optionChar), defaultValue);
542    }
543
544    /**
545     * Gets a version of this {@code Option} converted to a particular type.
546     *
547     * @param option the option.
548     * @param <T> The return type for the method.
549     * @return the value parsed into a particular object or null if the option is not set.
550     * @throws ParseException if there are problems turning the option value into the desired type
551     * @see PatternOptionBuilder
552     * @since 1.5.0
553     */
554    public <T> T getParsedOptionValue(final Option option) throws ParseException {
555        return getParsedOptionValue(option, () -> null);
556    }
557
558    /**
559     * Gets a version of this {@code Option} converted to a particular type.
560     *
561     * @param option the option.
562     * @param defaultValue the default value to return if opt is not set.
563     * @param <T> The return type for the method.
564     * @return the value parsed into a particular object or the defaultValue if the option is not set.
565     * @throws ParseException if there are problems turning the option value into the desired type
566     * @see PatternOptionBuilder
567     * @since 1.7.0
568     */
569    @SuppressWarnings("unchecked")
570    public <T> T getParsedOptionValue(final Option option, final Supplier<T> defaultValue) throws ParseException {
571        if (option == null) {
572            return get(defaultValue);
573        }
574        final String res = getOptionValue(option);
575        try {
576            if (res == null) {
577                return get(defaultValue);
578            }
579            return (T) option.getConverter().apply(res);
580        } catch (final Exception e) {
581            throw ParseException.wrap(e);
582        }
583    }
584
585    /**
586     * Gets a version of this {@code Option} converted to a particular type.
587     *
588     * @param option the option.
589     * @param defaultValue the default value to return if opt is not set.
590     * @param <T> The return type for the method.
591     * @return the value parsed into a particular object or the defaultValue if the option is not set.
592     * @throws ParseException if there are problems turning the option value into the desired type
593     * @see PatternOptionBuilder
594     * @since 1.7.0
595     */
596    public <T> T getParsedOptionValue(final Option option, final T defaultValue) throws ParseException {
597        return getParsedOptionValue(option, () -> defaultValue);
598    }
599
600    /**
601     * Gets a version of this {@code OptionGroup} converted to a particular type.
602     *
603     * @param optionGroup the option group.
604     * @param <T> The return type for the method.
605     * @return the value parsed into a particular object or null if no option in the OptionGroup is set.
606     * @throws ParseException if there are problems turning the selected option value into the desired type
607     * @see PatternOptionBuilder
608     * @since 1.9.0
609     */
610    public <T> T getParsedOptionValue(final OptionGroup optionGroup) throws ParseException {
611        return getParsedOptionValue(optionGroup, () -> null);
612    }
613
614    /**
615     * Gets a version of this {@code OptionGroup} converted to a particular type.
616     *
617     * @param optionGroup the option group.
618     * @param defaultValue the default value to return if opt is not set.
619     * @param <T> The return type for the method.
620     * @return the value parsed into a particular object or the defaultValue if no option in the OptionGroup is set.
621     * @throws ParseException if there are problems turning the selected option value into the desired type
622     * @see PatternOptionBuilder
623     * @since 1.9.0
624     */
625    public <T> T getParsedOptionValue(final OptionGroup optionGroup, final Supplier<T> defaultValue) throws ParseException {
626        if (optionGroup == null || !optionGroup.isSelected()) {
627            return get(defaultValue);
628        }
629        return getParsedOptionValue(optionGroup.getSelected(), defaultValue);
630    }
631
632    /**
633     * Gets a version of this {@code OptionGroup} converted to a particular type.
634     *
635     * @param optionGroup the option group.
636     * @param defaultValue the default value to return if an option is not selected.
637     * @param <T> The return type for the method.
638     * @return the value parsed into a particular object or the defaultValue if no option in the OptionGroup is set.
639     * @throws ParseException if there are problems turning the option value into the desired type
640     * @see PatternOptionBuilder
641     * @since 1.9.0
642     */
643    public <T> T getParsedOptionValue(final OptionGroup optionGroup, final T defaultValue) throws ParseException {
644        return getParsedOptionValue(optionGroup, () -> defaultValue);
645    }
646
647    /**
648     * Gets a version of this {@code Option} converted to a particular type.
649     *
650     * @param optionName the name of the option.
651     * @param <T> The return type for the method.
652     * @return the value parsed into a particular object or null if the option is not set.
653     * @throws ParseException if there are problems turning the option value into the desired type
654     * @see PatternOptionBuilder
655     * @since 1.2
656     */
657    public <T> T getParsedOptionValue(final String optionName) throws ParseException {
658        return getParsedOptionValue(resolveOption(optionName));
659    }
660
661    /**
662     * Gets a version of this {@code Option} converted to a particular type.
663     *
664     * @param optionName the name of the option.
665     * @param defaultValue the default value to return if opt is not set.
666     * @param <T> The return type for the method.
667     * @return the value parsed into a particular object or the defaultValue if the option is not set.
668     * @throws ParseException if there are problems turning the option value into the desired type
669     * @see PatternOptionBuilder
670     * @since 1.7.0
671     */
672    public <T> T getParsedOptionValue(final String optionName, final Supplier<T> defaultValue) throws ParseException {
673        return getParsedOptionValue(resolveOption(optionName), defaultValue);
674    }
675
676    /**
677     * Gets a version of this {@code Option} converted to a particular type.
678     *
679     * @param optionName the name of the option.
680     * @param defaultValue the default value to return if opt is not set.
681     * @param <T> The return type for the method.
682     * @return the value parsed into a particular object or the defaultValue if the option is not set.
683     * @throws ParseException if there are problems turning the option value into the desired type
684     * @see PatternOptionBuilder
685     * @since 1.7.0
686     */
687    public <T> T getParsedOptionValue(final String optionName, final T defaultValue) throws ParseException {
688        return getParsedOptionValue(resolveOption(optionName), defaultValue);
689    }
690
691    /**
692     * Gets a version of this {@code Option} converted to an array of a particular type.
693     *
694     * @param optionChar the name of the option.
695     * @param <T> The array type for the return value.
696     * @return the values parsed into an array of objects or null if the option is not set.
697     * @throws ParseException if there are problems turning the option value into the desired type
698     * @see PatternOptionBuilder
699     * @since 1.10.0
700     */
701    public <T> T[] getParsedOptionValues(final char optionChar) throws ParseException {
702        return getParsedOptionValues(String.valueOf(optionChar));
703    }
704
705    /**
706     * Gets a version of this {@code Option} converted to an array of a particular type.
707     *
708     * @param optionChar the name of the option.
709     * @param defaultValue the default value to return if opt is not set.
710     * @param <T> The array type for the return value.
711     * @return the values parsed into an array of objects or the defaultValue if the option is not set.
712     * @throws ParseException if there are problems turning the option value into the desired type
713     * @see PatternOptionBuilder
714     * @since 1.10.0
715     */
716    public <T> T[] getParsedOptionValues(final char optionChar, final Supplier<T[]> defaultValue) throws ParseException {
717        return getParsedOptionValues(String.valueOf(optionChar), defaultValue);
718    }
719
720    /**
721     * Gets a version of this {@code Option} converted to an array of a particular type.
722     *
723     * @param optionChar the name of the option.
724     * @param defaultValue the default value to return if opt is not set.
725     * @param <T> The array type for the return value.
726     * @return the values parsed into an array of objects or the defaultValue if the option is not set.
727     * @throws ParseException if there are problems turning the option value into the desired type
728     * @see PatternOptionBuilder
729     * @since 1.10.0
730     */
731    public <T> T[] getParsedOptionValues(final char optionChar, final T[] defaultValue) throws ParseException {
732        return getParsedOptionValues(String.valueOf(optionChar), defaultValue);
733    }
734
735    /**
736     * Gets a version of this {@code Option} converted to an array of a particular type.
737     *
738     * @param option the option.
739     * @param <T> The array type for the return value.
740     * @return the values parsed into an array of objects or null if the option is not set.
741     * @throws ParseException if there are problems turning the option value into the desired type
742     * @see PatternOptionBuilder
743     * @since 1.10.0
744     */
745    public <T> T[] getParsedOptionValues(final Option option) throws ParseException {
746        return getParsedOptionValues(option, () -> null);
747    }
748
749    /**
750     * Gets a version of this {@code Option} converted to an array of a particular type.
751     *
752     * @param option the option.
753     * @param defaultValue the default value to return if opt is not set.
754     * @param <T> The array type for the return value.
755     * @return the values parsed into an array of objects or the defaultValue if the option is not set.
756     * @throws ParseException if there are problems turning the option value into the desired type
757     * @see PatternOptionBuilder
758     * @since 1.10.0
759     */
760    @SuppressWarnings("unchecked")
761    public <T> T[] getParsedOptionValues(final Option option, final Supplier<T[]> defaultValue) throws ParseException {
762        if (option == null) {
763            return get(defaultValue);
764        }
765        final Class<? extends T> clazz = (Class<? extends T>) option.getType();
766        final String[] values = getOptionValues(option);
767        if (values == null) {
768            return get(defaultValue);
769        }
770        final T[] result = (T[]) Array.newInstance(clazz, values.length);
771        try {
772            for (int i = 0; i < values.length; i++) {
773                result[i] = clazz.cast(option.getConverter().apply(values[i]));
774            }
775            return result;
776        } catch (final Exception t) {
777            throw ParseException.wrap(t);
778        }
779    }
780
781    /**
782     * Gets a version of this {@code Option} converted to an array of a particular type.
783     *
784     * @param option the option.
785     * @param defaultValue the default value to return if opt is not set.
786     * @param <T> The array type for the return value.
787     * @return the values parsed into an array of objects or the defaultValue if the option is not set.
788     * @throws ParseException if there are problems turning the option value into the desired type
789     * @see PatternOptionBuilder
790     * @since 1.10.0
791     */
792    public <T> T[] getParsedOptionValues(final Option option, final T[] defaultValue) throws ParseException {
793        return getParsedOptionValues(option, () -> defaultValue);
794    }
795
796    /**
797     * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
798     *
799     * @param optionGroup the option group.
800     * @param <T> The array type for the return value.
801     * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
802     * @throws ParseException if there are problems turning the selected option value into the desired type
803     * @see PatternOptionBuilder
804     * @since 1.10.0
805     */
806    public <T> T[] getParsedOptionValues(final OptionGroup optionGroup) throws ParseException {
807        return getParsedOptionValues(optionGroup, () -> null);
808    }
809
810    /**
811     * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
812     *
813     * @param optionGroup the option group.
814     * @param defaultValue the default value to return if opt is not set.
815     * @param <T> The array type for the return value.
816     * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
817     * @throws ParseException if there are problems turning the selected option value into the desired type
818     * @see PatternOptionBuilder
819     * @since 1.10.0
820     */
821    public <T> T[] getParsedOptionValues(final OptionGroup optionGroup, final Supplier<T[]> defaultValue) throws ParseException {
822        if (optionGroup == null || !optionGroup.isSelected()) {
823            return get(defaultValue);
824        }
825        return getParsedOptionValues(optionGroup.getSelected(), defaultValue);
826    }
827
828    /**
829     * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
830     *
831     * @param optionGroup the option group.
832     * @param defaultValue the default value to return if an option is not selected.
833     * @param <T> The array type for the return value.
834     * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
835     * @throws ParseException if there are problems turning the option value into the desired type
836     * @see PatternOptionBuilder
837     * @since 1.10.0
838     */
839    public <T> T[] getParsedOptionValues(final OptionGroup optionGroup, final T[] defaultValue) throws ParseException {
840        return getParsedOptionValues(optionGroup, () -> defaultValue);
841    }
842
843    /**
844     * Gets a version of this {@code Option} converted to an array of a particular type.
845     *
846     * @param optionName the name of the option.
847     * @param <T> The array type for the return value.
848     * @return the values parsed into an array of objects or null if the option is not set.
849     * @throws ParseException if there are problems turning the option value into the desired type
850     * @see PatternOptionBuilder
851     * @since 1.10.0
852     */
853    public <T> T[] getParsedOptionValues(final String optionName) throws ParseException {
854        return getParsedOptionValues(resolveOption(optionName));
855    }
856
857    /**
858     * Gets a version of this {@code Option} converted to an array of a particular type.
859     *
860     * @param optionName the name of the option.
861     * @param defaultValue the default value to return if opt is not set.
862     * @param <T> The array type for the return value.
863     * @return the values parsed into an array of objects or defaultValues if the option is not set.
864     * @throws ParseException if there are problems turning the option value into the desired type
865     * @see PatternOptionBuilder
866     * @since 1.10.0
867     */
868    public <T> T[] getParsedOptionValues(final String optionName, final Supplier<T[]> defaultValue) throws ParseException {
869        return getParsedOptionValues(resolveOption(optionName), defaultValue);
870    }
871
872    /**
873     * Gets a version of this {@code Option} converted to an array of a particular type.
874     *
875     * @param optionName the name of the option.
876     * @param defaultValue the default value to return if opt is not set.
877     * @param <T> The array type for the return value.
878     * @return the values parsed into an array of objects or defaultValues if the option is not set.
879     * @throws ParseException if there are problems turning the option value into the desired type
880     * @see PatternOptionBuilder
881     * @since 1.10.0
882     */
883    public <T> T[] getParsedOptionValues(final String optionName, final T[] defaultValue) throws ParseException {
884        return getParsedOptionValues(resolveOption(optionName), defaultValue);
885    }
886
887    /**
888     * Handles deprecated options.
889     *
890     * @param option a deprecated option.
891     */
892    private void handleDeprecated(final Option option) {
893        if (deprecatedHandler != null) {
894            deprecatedHandler.accept(option);
895        }
896    }
897
898    /**
899     * jkeyes - commented out until it is implemented properly
900     * <p>
901     * Dump state, suitable for debugging.
902     * </p>
903     *
904     * @return Stringified form of this object.
905     */
906
907    /*
908     * public String toString() { StringBuilder buf = new StringBuilder();
909     *
910     * buf.append("[ CommandLine: [ options: "); buf.append(options.toString()); buf.append(" ] [ args: ");
911     * buf.append(args.toString()); buf.append(" ] ]");
912     *
913     * return buf.toString(); }
914     */
915
916    /**
917     * Tests to see if an option has been set.
918     *
919     * @param optionChar character name of the option.
920     * @return true if set, false if not.
921     */
922    public boolean hasOption(final char optionChar) {
923        return hasOption(String.valueOf(optionChar));
924    }
925
926    /**
927     * Tests to see if an option has been set.
928     *
929     * @param option the option to check.
930     * @return true if set, false if not.
931     * @since 1.5.0
932     */
933    public boolean hasOption(final Option option) {
934        final boolean result = options.contains(option);
935        if (result && option.isDeprecated()) {
936            handleDeprecated(option);
937        }
938        return result;
939    }
940
941    /**
942     * Tests to see if an option has been set.
943     *
944     * @param optionGroup the option group to check.
945     * @return true if set, false if not.
946     * @since 1.9.0
947     */
948    public boolean hasOption(final OptionGroup optionGroup) {
949        if (optionGroup == null || !optionGroup.isSelected()) {
950            return false;
951        }
952        return hasOption(optionGroup.getSelected());
953    }
954
955    /**
956     * Tests to see if an option has been set.
957     *
958     * @param optionName Short name of the option.
959     * @return true if set, false if not.
960     */
961    public boolean hasOption(final String optionName) {
962        return hasOption(resolveOption(optionName));
963    }
964
965    /**
966     * Returns an iterator over the Option members of CommandLine.
967     *
968     * @return an {@code Iterator} over the processed {@link Option} members of this {@link CommandLine}.
969     */
970    public Iterator<Option> iterator() {
971        return options.iterator();
972    }
973
974    /**
975     * Parses a list of values as properties.  All odd numbered values are property keys
976     * and even numbered values are property values.  If there are an odd number of values
977     * the last value is assumed to be a boolean with a value of "true".
978     * @param props the properties to update.
979     * @param values the list of values to parse.
980     */
981    private void processPropertiesFromValues(final Properties props, final List<String> values) {
982        for (int i = 0; i < values.size(); i += 2) {
983            if (i + 1 < values.size()) {
984                props.put(values.get(i), values.get(i + 1));
985            } else {
986                props.put(values.get(i), "true");
987            }
988        }
989    }
990
991    /**
992     * Retrieves the option object given the long or short option as a String
993     *
994     * @param optionName short or long name of the option, may be null.
995     * @return Canonicalized option.
996     */
997    private Option resolveOption(final String optionName) {
998        final String actual = Util.stripLeadingHyphens(optionName);
999        if (actual != null) {
1000            for (final Option option : options) {
1001                if (actual.equals(option.getOpt()) || actual.equals(option.getLongOpt())) {
1002                    return option;
1003                }
1004            }
1005        }
1006        return null;
1007    }
1008}