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     /**
203      * Gets the first element or null if values is null.
204      *
205      * @param values the array to query.
206      * @return the first element or null if values is null.
207      */
208     private String first(final String[] values) {
209         return values == null ? null : values[0];
210     }
211 
212     private <T> T get(final Supplier<T> supplier) {
213         return supplier == null ? null : supplier.get();
214     }
215 
216     /**
217      * Gets any left-over non-recognized options and arguments.
218      *
219      * @return remaining items passed in but not parsed as a {@code List}.
220      */
221     public List<String> getArgList() {
222         return args;
223     }
224 
225     /**
226      * Gets any left-over non-recognized options and arguments.
227      *
228      * @return remaining items passed in but not parsed as an array.
229      */
230     public String[] getArgs() {
231         return args.toArray(Util.EMPTY_STRING_ARRAY);
232     }
233 
234     /**
235      * Gets the number of times this option appears in the command line
236      *
237      * @param optionChar the character name of the option.
238      * @return Number of times the option is present.
239      * @since 1.11.0
240      */
241     public int getOptionCount(final char optionChar) {
242         return getOptionCount(String.valueOf(optionChar));
243     }
244 
245     /**
246      * Gets the number of times this option appears in the command line.
247      *
248      * @param option the option.
249      * @return Number of times the option is present.
250      * @since 1.11.0
251      */
252     public int getOptionCount(final Option option) {
253         return (int) options.stream().filter(opt -> Objects.equals(opt, option)).count();
254     }
255 
256     /**
257      * Gets the number of times this option appears in the command line
258      *
259      * @param optionName the name of the option.
260      * @return Number of times the option is present.
261      * @since 1.11.0
262      */
263     public int getOptionCount(final String optionName) {
264         return getOptionCount(resolveOption(optionName));
265     }
266 
267     /**
268      * Gets the {@code Object} type of this {@code Option}.
269      *
270      * @deprecated due to System.err message; use {@link #getParsedOptionValue(char)} instead.
271      * @param optionChar the name of the option.
272      * @return the type of opt.
273      */
274     @Deprecated
275     public Object getOptionObject(final char optionChar) {
276         return getOptionObject(String.valueOf(optionChar));
277     }
278 
279     /**
280      * Gets the {@code Object} type of this {@code Option}.
281      *
282      * @param optionName the name of the option.
283      * @return the type of this {@code Option}.
284      * @deprecated due to System.err message; use {@link #getParsedOptionValue(String)} instead.
285      */
286     @Deprecated
287     public Object getOptionObject(final String optionName) {
288         try {
289             return getParsedOptionValue(optionName);
290         } catch (final ParseException pe) {
291             System.err.println("Exception found converting " + optionName + " to desired type: " + pe.getMessage());
292             return null;
293         }
294     }
295 
296     /**
297      * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
298      * <code>-Dparam1=value1
299      * -Dparam2=value2</code>. All odd numbered values are property keys
300      * and even numbered values are property values.  If there are an odd number of values
301      * the last value is assumed to be a boolean flag and the value is "true".
302      *
303      * @param option name of the option.
304      * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
305      * @since 1.5.0
306      */
307     public Properties getOptionProperties(final Option option) {
308         final Properties props = new Properties();
309         options.forEach(processedOption -> {
310             if (processedOption.equals(option)) {
311                 processPropertiesFromValues(props, processedOption.getValuesList());
312             }
313         });
314         return props;
315     }
316 
317     /**
318      * Gets the map of values associated to the option. This is convenient for options specifying Java properties like
319      * <code>-Dparam1=value1
320      * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option
321      * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}.
322      *
323      * @param optionName name of the option.
324      * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists.
325      * @since 1.2
326      */
327     public Properties getOptionProperties(final String optionName) {
328         final Properties props = new Properties();
329         options.forEach(option -> {
330             if (optionName.equals(option.getOpt()) || optionName.equals(option.getLongOpt())) {
331                 processPropertiesFromValues(props, option.getValuesList());
332             }
333         });
334         return props;
335     }
336 
337     /**
338      * Gets an array of the processed {@link Option}s.
339      *
340      * @return an array of the processed {@link Option}s.
341      */
342     public Option[] getOptions() {
343         return options.toArray(Option.EMPTY_ARRAY);
344     }
345 
346     /**
347      * Gets the first argument, if any, of this option.
348      *
349      * @param optionChar the character name of the option.
350      * @return Value of the argument if option is set, and has an argument, otherwise null.
351      */
352     public String getOptionValue(final char optionChar) {
353         return getOptionValue(String.valueOf(optionChar));
354     }
355 
356     /**
357      * Gets the argument, if any, of an option.
358      *
359      * @param optionChar character name of the option
360      * @param defaultValue is the default value to be returned if the option is not specified.
361      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
362      */
363     public String getOptionValue(final char optionChar, final String defaultValue) {
364         return getOptionValue(String.valueOf(optionChar), () -> defaultValue);
365     }
366 
367     /**
368      * Gets the argument, if any, of an option.
369      *
370      * @param optionChar character name of the option.
371      * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
372      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
373      * @since 1.7.0
374      */
375     public String getOptionValue(final char optionChar, final Supplier<String> defaultValue) {
376         return getOptionValue(String.valueOf(optionChar), defaultValue);
377     }
378 
379     /**
380      * Gets the first argument, if any, of this option.
381      *
382      * @param option the option.
383      * @return Value of the argument if option is set, and has an argument, otherwise null.
384      * @since 1.5.0
385      */
386     public String getOptionValue(final Option option) {
387         return first(getOptionValues(option));
388     }
389 
390     /**
391      * Gets the first argument, if any, of an option.
392      *
393      * @param option the option.
394      * @param defaultValue is the default value to be returned if the option is not specified.
395      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
396      * @since 1.5.0
397      */
398     public String getOptionValue(final Option option, final String defaultValue) {
399         return getOptionValue(option, () -> defaultValue);
400     }
401 
402     /**
403      * Gets the first argument, if any, of an option.
404      *
405      * @param option the option.
406      * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
407      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
408      * @since 1.7.0
409      */
410     public String getOptionValue(final Option option, final Supplier<String> defaultValue) {
411         final String answer = getOptionValue(option);
412         return answer != null ? answer : get(defaultValue);
413     }
414 
415     /**
416      * Gets the first argument, if any, of this option group.
417      *
418      * @param optionGroup the option group.
419      * @return Value of the argument if option group is selected, and has an argument, otherwise null.
420      * @since 1.9.0
421      */
422     public String getOptionValue(final OptionGroup optionGroup) {
423         return first(getOptionValues(optionGroup));
424     }
425 
426     /**
427      * Gets the first argument, if any, of an option group.
428      *
429      * @param optionGroup the option group.
430      * @param defaultValue is the default value to be returned if the option group is not selected.
431      * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
432      * @since 1.9.0
433      */
434     public String getOptionValue(final OptionGroup optionGroup, final String defaultValue) {
435         return getOptionValue(optionGroup, () -> defaultValue);
436     }
437 
438     /**
439      * Gets the first argument, if any, of an option group.
440      *
441      * @param optionGroup the option group.
442      * @param defaultValue is a supplier for the default value to be returned if the option group is not selected.
443      * @return Value of the argument if option group is selected, and has an argument, otherwise {@code defaultValue}.
444      * @since 1.9.0
445      */
446     public String getOptionValue(final OptionGroup optionGroup, final Supplier<String> defaultValue) {
447         final String answer = getOptionValue(optionGroup);
448         return answer != null ? answer : get(defaultValue);
449     }
450 
451     /**
452      * Gets the first argument, if any, of this option.
453      *
454      * @param optionName the name of the option.
455      * @return Value of the argument if option is set, and has an argument, otherwise null.
456      */
457     public String getOptionValue(final String optionName) {
458         return getOptionValue(resolveOption(optionName));
459     }
460 
461     /**
462      * Gets the first argument, if any, of an option.
463      *
464      * @param optionName name of the option.
465      * @param defaultValue is the default value to be returned if the option is not specified.
466      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
467      */
468     public String getOptionValue(final String optionName, final String defaultValue) {
469         return getOptionValue(resolveOption(optionName), () -> defaultValue);
470     }
471 
472     /**
473      * Gets the first argument, if any, of an option.
474      *
475      * @param optionName name of the option.
476      * @param defaultValue is a supplier for the default value to be returned if the option is not specified.
477      * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}.
478      * @since 1.7.0
479      */
480     public String getOptionValue(final String optionName, final Supplier<String> defaultValue) {
481         return getOptionValue(resolveOption(optionName), defaultValue);
482     }
483 
484     /**
485      * Gets the array of values, if any, of an option.
486      *
487      * @param optionChar character name of the option.
488      * @return Values of the argument if option is set, and has an argument, otherwise null.
489      */
490     public String[] getOptionValues(final char optionChar) {
491         return getOptionValues(String.valueOf(optionChar));
492     }
493 
494     /**
495      * Gets the array of values, if any, of an option.
496      *
497      * @param option the option.
498      * @return Values of the argument if option is set, and has an argument, otherwise null.
499      * @since 1.5.0
500      */
501     public String[] getOptionValues(final Option option) {
502         if (option == null) {
503             return null;
504         }
505         final List<String> values = new ArrayList<>();
506         options.forEach(processedOption -> {
507             if (processedOption.equals(option)) {
508                 if (option.isDeprecated()) {
509                     handleDeprecated(option);
510                 }
511                 values.addAll(processedOption.getValuesList());
512             }
513         });
514         return values.isEmpty() ? null : values.toArray(Util.EMPTY_STRING_ARRAY);
515     }
516 
517     /**
518      * Gets the array of values, if any, of an option group.
519      *
520      * @param optionGroup the option group.
521      * @return Values of the argument if option group is selected, and has an argument, otherwise null.
522      * @since 1.9.0
523      */
524     public String[] getOptionValues(final OptionGroup optionGroup) {
525         if (optionGroup == null || !optionGroup.isSelected()) {
526             return null;
527         }
528         return getOptionValues(optionGroup.getSelected());
529     }
530 
531     /**
532      * Gets the array of values, if any, of an option.
533      *
534      * @param optionName string name of the option.
535      * @return Values of the argument if option is set, and has an argument, otherwise null.
536      */
537     public String[] getOptionValues(final String optionName) {
538         return getOptionValues(resolveOption(optionName));
539     }
540 
541     /**
542      * Gets a version of this {@code Option} converted to a particular type.
543      *
544      * @param optionChar the name of the option.
545      * @param <T> The return type for the method.
546      * @return the value parsed into a particular object or null if the option is not set.
547      * @throws ParseException if there are problems turning the option value into the desired type.
548      * @see PatternOptionBuilder
549      * @since 1.5.0
550      */
551     public <T> T getParsedOptionValue(final char optionChar) throws ParseException {
552         return getParsedOptionValue(String.valueOf(optionChar));
553     }
554 
555     /**
556      * Gets a version of this {@code Option} converted to a particular type.
557      *
558      * @param optionChar the name of the option.
559      * @param defaultValue the default value to return if opt is not set.
560      * @param <T> The return type for the method.
561      * @return the value parsed into a particular object or the defaultValue if the option is not set.
562      * @throws ParseException if there are problems turning the option value into the desired type.
563      * @see PatternOptionBuilder
564      * @since 1.7.0
565      */
566     public <T> T getParsedOptionValue(final char optionChar, final Supplier<T> defaultValue) throws ParseException {
567         return getParsedOptionValue(String.valueOf(optionChar), defaultValue);
568     }
569 
570     /**
571      * Gets a version of this {@code Option} converted to a particular type.
572      *
573      * @param optionChar the name of the option.
574      * @param defaultValue the default value to return if opt is not set.
575      * @param <T> The return type for the method.
576      * @return the value parsed into a particular object or the defaultValue if the option is not set.
577      * @throws ParseException if there are problems turning the option value into the desired type.
578      * @see PatternOptionBuilder
579      * @since 1.7.0
580      */
581     public <T> T getParsedOptionValue(final char optionChar, final T defaultValue) throws ParseException {
582         return getParsedOptionValue(String.valueOf(optionChar), defaultValue);
583     }
584 
585     /**
586      * Gets a version of this {@code Option} converted to a particular type.
587      *
588      * @param option the option.
589      * @param <T> The return type for the method.
590      * @return the value parsed into a particular object or null if the option is not set.
591      * @throws ParseException if there are problems turning the option value into the desired type.
592      * @see PatternOptionBuilder
593      * @since 1.5.0
594      */
595     public <T> T getParsedOptionValue(final Option option) throws ParseException {
596         return getParsedOptionValue(option, () -> null);
597     }
598 
599     /**
600      * Gets a version of this {@code Option} converted to a particular type.
601      *
602      * @param option the option.
603      * @param defaultValue the default value to return if opt is not set.
604      * @param <T> The return type for the method.
605      * @return the value parsed into a particular object or the defaultValue if the option is not set.
606      * @throws ParseException if there are problems turning the option value into the desired type.
607      * @see PatternOptionBuilder
608      * @since 1.7.0
609      */
610     @SuppressWarnings("unchecked")
611     public <T> T getParsedOptionValue(final Option option, final Supplier<T> defaultValue) throws ParseException {
612         if (option == null) {
613             return get(defaultValue);
614         }
615         final String res = getOptionValue(option);
616         try {
617             if (res == null) {
618                 return get(defaultValue);
619             }
620             return (T) option.getConverter().apply(res);
621         } catch (final Exception e) {
622             throw ParseException.wrap(e);
623         }
624     }
625 
626     /**
627      * Gets a version of this {@code Option} converted to a particular type.
628      *
629      * @param option the option.
630      * @param defaultValue the default value to return if opt is not set.
631      * @param <T> The return type for the method.
632      * @return the value parsed into a particular object or the defaultValue if the option is not set.
633      * @throws ParseException if there are problems turning the option value into the desired type.
634      * @see PatternOptionBuilder
635      * @since 1.7.0
636      */
637     public <T> T getParsedOptionValue(final Option option, final T defaultValue) throws ParseException {
638         return getParsedOptionValue(option, () -> defaultValue);
639     }
640 
641     /**
642      * Gets a version of this {@code OptionGroup} converted to a particular type.
643      *
644      * @param optionGroup the option group.
645      * @param <T> The return type for the method.
646      * @return the value parsed into a particular object or null if no option in the OptionGroup is set.
647      * @throws ParseException if there are problems turning the selected option value into the desired type.
648      * @see PatternOptionBuilder
649      * @since 1.9.0
650      */
651     public <T> T getParsedOptionValue(final OptionGroup optionGroup) throws ParseException {
652         return getParsedOptionValue(optionGroup, () -> null);
653     }
654 
655     /**
656      * Gets a version of this {@code OptionGroup} converted to a particular type.
657      *
658      * @param optionGroup the option group.
659      * @param defaultValue the default value to return if opt is not set.
660      * @param <T> The return type for the method.
661      * @return the value parsed into a particular object or the defaultValue if no option in the OptionGroup is set.
662      * @throws ParseException if there are problems turning the selected option value into the desired type.
663      * @see PatternOptionBuilder
664      * @since 1.9.0
665      */
666     public <T> T getParsedOptionValue(final OptionGroup optionGroup, final Supplier<T> defaultValue) throws ParseException {
667         if (optionGroup == null || !optionGroup.isSelected()) {
668             return get(defaultValue);
669         }
670         return getParsedOptionValue(optionGroup.getSelected(), defaultValue);
671     }
672 
673     /**
674      * Gets a version of this {@code OptionGroup} converted to a particular type.
675      *
676      * @param optionGroup the option group.
677      * @param defaultValue the default value to return if an option is not selected.
678      * @param <T> The return type for the method.
679      * @return the value parsed into a particular object or the defaultValue if no option in the OptionGroup is set.
680      * @throws ParseException if there are problems turning the option value into the desired type.
681      * @see PatternOptionBuilder
682      * @since 1.9.0
683      */
684     public <T> T getParsedOptionValue(final OptionGroup optionGroup, final T defaultValue) throws ParseException {
685         return getParsedOptionValue(optionGroup, () -> defaultValue);
686     }
687 
688     /**
689      * Gets a version of this {@code Option} converted to a particular type.
690      *
691      * @param optionName the name of the option.
692      * @param <T> The return type for the method.
693      * @return the value parsed into a particular object or null if the option is not set.
694      * @throws ParseException if there are problems turning the option value into the desired type.
695      * @see PatternOptionBuilder
696      * @since 1.2
697      */
698     public <T> T getParsedOptionValue(final String optionName) throws ParseException {
699         return getParsedOptionValue(resolveOption(optionName));
700     }
701 
702     /**
703      * Gets a version of this {@code Option} converted to a particular type.
704      *
705      * @param optionName the name of the option.
706      * @param defaultValue the default value to return if opt is not set.
707      * @param <T> The return type for the method.
708      * @return the value parsed into a particular object or the defaultValue if the option is not set.
709      * @throws ParseException if there are problems turning the option value into the desired type.
710      * @see PatternOptionBuilder
711      * @since 1.7.0
712      */
713     public <T> T getParsedOptionValue(final String optionName, final Supplier<T> defaultValue) throws ParseException {
714         return getParsedOptionValue(resolveOption(optionName), defaultValue);
715     }
716 
717     /**
718      * Gets a version of this {@code Option} converted to a particular type.
719      *
720      * @param optionName the name of the option.
721      * @param defaultValue the default value to return if opt is not set.
722      * @param <T> The return type for the method.
723      * @return the value parsed into a particular object or the defaultValue if the option is not set.
724      * @throws ParseException if there are problems turning the option value into the desired type.
725      * @see PatternOptionBuilder
726      * @since 1.7.0
727      */
728     public <T> T getParsedOptionValue(final String optionName, final T defaultValue) throws ParseException {
729         return getParsedOptionValue(resolveOption(optionName), defaultValue);
730     }
731 
732     /**
733      * Gets a version of this {@code Option} converted to an array of a particular type.
734      *
735      * @param optionChar the name of the option.
736      * @param <T> The array type for the return value.
737      * @return the values parsed into an array of objects or null if the option is not set.
738      * @throws ParseException if there are problems turning the option value into the desired type.
739      * @see PatternOptionBuilder
740      * @since 1.10.0
741      */
742     public <T> T[] getParsedOptionValues(final char optionChar) throws ParseException {
743         return getParsedOptionValues(String.valueOf(optionChar));
744     }
745 
746     /**
747      * Gets a version of this {@code Option} converted to an array of a particular type.
748      *
749      * @param optionChar the name of the option.
750      * @param defaultValue the default value to return if opt is not set.
751      * @param <T> The array type for the return value.
752      * @return the values parsed into an array of objects or the defaultValue if the option is not set.
753      * @throws ParseException if there are problems turning the option value into the desired type.
754      * @see PatternOptionBuilder
755      * @since 1.10.0
756      */
757     public <T> T[] getParsedOptionValues(final char optionChar, final Supplier<T[]> defaultValue) throws ParseException {
758         return getParsedOptionValues(String.valueOf(optionChar), defaultValue);
759     }
760 
761     /**
762      * Gets a version of this {@code Option} converted to an array of a particular type.
763      *
764      * @param optionChar the name of the option.
765      * @param defaultValue the default value to return if opt is not set.
766      * @param <T> The array type for the return value.
767      * @return the values parsed into an array of objects or the defaultValue if the option is not set.
768      * @throws ParseException if there are problems turning the option value into the desired type.
769      * @see PatternOptionBuilder
770      * @since 1.10.0
771      */
772     public <T> T[] getParsedOptionValues(final char optionChar, final T[] defaultValue) throws ParseException {
773         return getParsedOptionValues(String.valueOf(optionChar), defaultValue);
774     }
775 
776     /**
777      * Gets a version of this {@code Option} converted to an array of a particular type.
778      *
779      * @param option the option.
780      * @param <T> The array type for the return value.
781      * @return the values parsed into an array of objects or null if the option is not set.
782      * @throws ParseException if there are problems turning the option value into the desired type.
783      * @see PatternOptionBuilder
784      * @since 1.10.0
785      */
786     public <T> T[] getParsedOptionValues(final Option option) throws ParseException {
787         return getParsedOptionValues(option, () -> null);
788     }
789 
790     /**
791      * Gets a version of this {@code Option} converted to an array of a particular type.
792      *
793      * @param option the option.
794      * @param defaultValue the default value to return if opt is not set.
795      * @param <T> The array type for the return value.
796      * @return the values parsed into an array of objects or the defaultValue if the option is not set.
797      * @throws ParseException if there are problems turning the option value into the desired type.
798      * @see PatternOptionBuilder
799      * @since 1.10.0
800      */
801     @SuppressWarnings("unchecked")
802     public <T> T[] getParsedOptionValues(final Option option, final Supplier<T[]> defaultValue) throws ParseException {
803         if (option == null) {
804             return get(defaultValue);
805         }
806         final Class<? extends T> clazz = (Class<? extends T>) option.getType();
807         final String[] values = getOptionValues(option);
808         if (values == null) {
809             return get(defaultValue);
810         }
811         final T[] result = (T[]) Array.newInstance(clazz, values.length);
812         try {
813             for (int i = 0; i < values.length; i++) {
814                 result[i] = clazz.cast(option.getConverter().apply(values[i]));
815             }
816             return result;
817         } catch (final Exception t) {
818             throw ParseException.wrap(t);
819         }
820     }
821 
822     /**
823      * Gets a version of this {@code Option} converted to an array of a particular type.
824      *
825      * @param option the option.
826      * @param defaultValue the default value to return if opt is not set.
827      * @param <T> The array type for the return value.
828      * @return the values parsed into an array of objects or the defaultValue if the option is not set.
829      * @throws ParseException if there are problems turning the option value into the desired type.
830      * @see PatternOptionBuilder
831      * @since 1.10.0
832      */
833     public <T> T[] getParsedOptionValues(final Option option, final T[] defaultValue) throws ParseException {
834         return getParsedOptionValues(option, () -> defaultValue);
835     }
836 
837     /**
838      * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
839      *
840      * @param optionGroup the option group.
841      * @param <T> The array type for the return value.
842      * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
843      * @throws ParseException if there are problems turning the selected option value into the desired type.
844      * @see PatternOptionBuilder
845      * @since 1.10.0
846      */
847     public <T> T[] getParsedOptionValues(final OptionGroup optionGroup) throws ParseException {
848         return getParsedOptionValues(optionGroup, () -> null);
849     }
850 
851     /**
852      * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
853      *
854      * @param optionGroup the option group.
855      * @param defaultValue the default value to return if opt is not set.
856      * @param <T> The array type for the return value.
857      * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
858      * @throws ParseException if there are problems turning the selected option value into the desired type.
859      * @see PatternOptionBuilder
860      * @since 1.10.0
861      */
862     public <T> T[] getParsedOptionValues(final OptionGroup optionGroup, final Supplier<T[]> defaultValue) throws ParseException {
863         if (optionGroup == null || !optionGroup.isSelected()) {
864             return get(defaultValue);
865         }
866         return getParsedOptionValues(optionGroup.getSelected(), defaultValue);
867     }
868 
869     /**
870      * Gets a version of this {@code OptionGroup} converted to an array of a particular type.
871      *
872      * @param optionGroup the option group.
873      * @param defaultValue the default value to return if an option is not selected.
874      * @param <T> The array type for the return value.
875      * @return the values parsed into an array of objects or null if no option in the OptionGroup is set.
876      * @throws ParseException if there are problems turning the option value into the desired type.
877      * @see PatternOptionBuilder
878      * @since 1.10.0
879      */
880     public <T> T[] getParsedOptionValues(final OptionGroup optionGroup, final T[] defaultValue) throws ParseException {
881         return getParsedOptionValues(optionGroup, () -> defaultValue);
882     }
883 
884     /**
885      * Gets a version of this {@code Option} converted to an array of a particular type.
886      *
887      * @param optionName the name of the option.
888      * @param <T> The array type for the return value.
889      * @return the values parsed into an array of objects or null if the option is not set.
890      * @throws ParseException if there are problems turning the option value into the desired type.
891      * @see PatternOptionBuilder
892      * @since 1.10.0
893      */
894     public <T> T[] getParsedOptionValues(final String optionName) throws ParseException {
895         return getParsedOptionValues(resolveOption(optionName));
896     }
897 
898     /**
899      * Gets a version of this {@code Option} converted to an array of a particular type.
900      *
901      * @param optionName the name of the option.
902      * @param defaultValue the default value to return if opt is not set.
903      * @param <T> The array type for the return value.
904      * @return the values parsed into an array of objects or defaultValues if the option is not set.
905      * @throws ParseException if there are problems turning the option value into the desired type.
906      * @see PatternOptionBuilder
907      * @since 1.10.0
908      */
909     public <T> T[] getParsedOptionValues(final String optionName, final Supplier<T[]> defaultValue) throws ParseException {
910         return getParsedOptionValues(resolveOption(optionName), defaultValue);
911     }
912 
913     /**
914      * Gets a version of this {@code Option} converted to an array of a particular type.
915      *
916      * @param optionName the name of the option.
917      * @param defaultValue the default value to return if opt is not set.
918      * @param <T> The array type for the return value.
919      * @return the values parsed into an array of objects or defaultValues if the option is not set.
920      * @throws ParseException if there are problems turning the option value into the desired type.
921      * @see PatternOptionBuilder
922      * @since 1.10.0
923      */
924     public <T> T[] getParsedOptionValues(final String optionName, final T[] defaultValue) throws ParseException {
925         return getParsedOptionValues(resolveOption(optionName), defaultValue);
926     }
927 
928     /**
929      * Handles deprecated options.
930      *
931      * @param option a deprecated option.
932      */
933     private void handleDeprecated(final Option option) {
934         if (deprecatedHandler != null) {
935             deprecatedHandler.accept(option);
936         }
937     }
938 
939     /**
940      * jkeyes - commented out until it is implemented properly
941      * <p>
942      * Dump state, suitable for debugging.
943      * </p>
944      *
945      * @return Stringified form of this object.
946      */
947 
948     /*
949      * public String toString() { StringBuilder buf = new StringBuilder();
950      *
951      * buf.append("[ CommandLine: [ options: "); buf.append(options.toString()); buf.append(" ] [ args: ");
952      * buf.append(args.toString()); buf.append(" ] ]");
953      *
954      * return buf.toString(); }
955      */
956 
957     /**
958      * Tests to see if an option has been set.
959      *
960      * @param optionChar character name of the option.
961      * @return true if set, false if not.
962      */
963     public boolean hasOption(final char optionChar) {
964         return hasOption(String.valueOf(optionChar));
965     }
966 
967     /**
968      * Tests to see if an option has been set.
969      *
970      * @param option the option to check.
971      * @return true if set, false if not.
972      * @since 1.5.0
973      */
974     public boolean hasOption(final Option option) {
975         final boolean result = options.contains(option);
976         if (result && option.isDeprecated()) {
977             handleDeprecated(option);
978         }
979         return result;
980     }
981 
982     /**
983      * Tests to see if an option has been set.
984      *
985      * @param optionGroup the option group to check.
986      * @return true if set, false if not.
987      * @since 1.9.0
988      */
989     public boolean hasOption(final OptionGroup optionGroup) {
990         if (optionGroup == null || !optionGroup.isSelected()) {
991             return false;
992         }
993         return hasOption(optionGroup.getSelected());
994     }
995 
996     /**
997      * Tests to see if an option has been set.
998      *
999      * @param optionName Short name of the option.
1000      * @return true if set, false if not.
1001      */
1002     public boolean hasOption(final String optionName) {
1003         return hasOption(resolveOption(optionName));
1004     }
1005 
1006     /**
1007      * Returns an iterator over the Option members of CommandLine.
1008      *
1009      * @return an {@code Iterator} over the processed {@link Option} members of this {@link CommandLine}.
1010      */
1011     public Iterator<Option> iterator() {
1012         return options.iterator();
1013     }
1014 
1015     /**
1016      * Parses a list of values as properties.  All odd numbered values are property keys
1017      * and even numbered values are property values.  If there are an odd number of values
1018      * the last value is assumed to be a boolean with a value of "true".
1019      *
1020      * @param props the properties to update.
1021      * @param values the list of values to parse.
1022      */
1023     private void processPropertiesFromValues(final Properties props, final List<String> values) {
1024         for (int i = 0; i < values.size(); i += 2) {
1025             props.put(values.get(i), i + 1 < values.size() ? values.get(i + 1) : "true");
1026         }
1027     }
1028 
1029     /**
1030      * Retrieves the option object given the long or short option as a String
1031      *
1032      * @param optionName short or long name of the option, may be null.
1033      * @return Canonicalized option.
1034      */
1035     private Option resolveOption(final String optionName) {
1036         final String actual = Util.stripLeadingHyphens(optionName);
1037         if (actual != null) {
1038             return options.stream()
1039                     .filter(opt -> actual.equals(opt.getOpt()) || actual.equals(opt.getLongOpt()))
1040                     .findFirst().orElse(null);
1041         }
1042         return null;
1043     }
1044 }