View Javadoc
1   /*
2     Licensed to the Apache Software Foundation (ASF) under one or more
3     contributor license agreements.  See the NOTICE file distributed with
4     this work for additional information regarding copyright ownership.
5     The ASF licenses this file to You under the Apache License, Version 2.0
6     (the "License"); you may not use this file except in compliance with
7     the License.  You may obtain a copy of the License at
8   
9         https://www.apache.org/licenses/LICENSE-2.0
10  
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16   */
17  
18  package org.apache.commons.cli;
19  
20  import java.io.Serializable;
21  import java.lang.reflect.Array;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Objects;
27  import java.util.Properties;
28  import java.util.function.Consumer;
29  import java.util.function.Supplier;
30  
31  /**
32   * Represents list of arguments parsed against a {@link Options} descriptor.
33   * <p>
34   * It allows querying of a boolean {@link #hasOption(String optionName)}, in addition to retrieving the
35   * {@link #getOptionValue(String optionName)} for options requiring arguments.
36   * </p>
37   * <p>
38   * Additionally, any left-over or unrecognized arguments, are available for further processing.
39   * </p>
40   */
41  public class CommandLine implements Serializable {
42  
43      /**
44       * A nested builder class to create {@code CommandLine} instance using descriptive methods.
45       *
46       * @since 1.4
47       */
48      public static final class Builder implements Supplier<CommandLine> {
49  
50          /**
51           * Prints an Option to {@link System#out}.
52           */
53          static final Consumer<Option> DEPRECATED_HANDLER = o -> System.out.println(o.toDeprecatedString());
54  
55          /** The unrecognized options/arguments */
56          private final List<String> args = new LinkedList<>();
57  
58          /** The processed options */
59          private final List<Option> options = new ArrayList<>();
60  
61          /**
62           * Deprecated Option handler.
63           */
64          private Consumer<Option> deprecatedHandler = DEPRECATED_HANDLER;
65  
66          /**
67           * Constructs a new instance.
68           *
69           * @deprecated Use {@link #builder()}.
70           */
71          @Deprecated
72          public Builder() {
73              // empty
74          }
75  
76          /**
77           * Adds left-over unrecognized option/argument.
78           *
79           * @param arg the unrecognized option/argument.
80           * @return this Builder instance for method chaining.
81           */
82          public Builder addArg(final String arg) {
83              if (arg != null) {
84                  args.add(arg);
85              }
86              return this;
87          }
88  
89          /**
90           * Adds an option to the command line. The values of the option are stored.
91           *
92           * @param option the processed option.
93           * @return this Builder instance for method chaining.
94           */
95          public Builder addOption(final Option option) {
96              if (option != null) {
97                  options.add(option);
98              }
99              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 }