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 static org.apache.commons.cli.Util.EMPTY_STRING_ARRAY;
21  
22  import java.io.Serializable;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Objects;
26  import java.util.function.Supplier;
27  
28  /**
29   * Describes a single command-line option. It maintains information regarding the short-name of the option, the long-name, if any exists, a flag indicating if
30   * an argument is required for this option, and a self-documenting description of the option.
31   * <p>
32   * An Option is not created independently, but is created through an instance of {@link Options}. An Option is required to have at least a short or a long-name.
33   * </p>
34   * <p>
35   * <strong>Note:</strong> once an {@link Option} has been added to an instance of {@link Options}, its required flag cannot be changed.
36   * </p>
37   *
38   * @see org.apache.commons.cli.Options
39   * @see org.apache.commons.cli.CommandLine
40   */
41  public class Option implements Cloneable, Serializable {
42  
43      /**
44       * Builds {@code Option} instances using descriptive methods.
45       * <p>
46       * Example usage:
47       * </p>
48       *
49       * <pre>
50       * Option option = Option.builder("a").required(true).longOpt("arg-name").build();
51       * </pre>
52       *
53       * @since 1.3
54       */
55      public static final class Builder implements Supplier<Option> {
56  
57          /** The default type. */
58          private static final Class<String> DEFAULT_TYPE = String.class;
59  
60          /**
61           * Returns the input Class or the default type (String) if null.
62           *
63           * @param type the candidate Class.
64           * @return the input Class or the default type (String) if null.
65           */
66          private static Class<?> toType(final Class<?> type) {
67              return type != null ? type : DEFAULT_TYPE;
68          }
69  
70          /** The number of argument values this option can have. */
71          private int argCount = UNINITIALIZED;
72  
73          /** The name of the argument for this option. */
74          private String argName;
75  
76          /** The converter to convert to type. **/
77          private Converter<?, ?> converter;
78  
79          /** Specifies whether this option is deprecated. */
80          private DeprecatedAttributes deprecated;
81  
82          /** Description of the option. */
83          private String description;
84  
85          /** The long representation of the option. */
86          private String longOption;
87  
88          /** The name of the option. */
89          private String option;
90  
91          /** Specifies whether the argument value of this Option is optional. */
92          private boolean optionalArg;
93  
94          /** Specifies whether this option is required to be present. */
95          private boolean required;
96  
97          /** Specifies the version when this option was added.  May be null */
98          private String since;
99  
100         /** The type of this Option. */
101         private Class<?> type = DEFAULT_TYPE;
102 
103         /** The character that is the value separator. */
104         private char valueSeparator;
105 
106         /**
107          * Constructs a new {@code Builder} with the minimum required parameters for an {@code Option} instance.
108          *
109          * @param option short representation of the option.
110          * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
111          */
112         private Builder(final String option) throws IllegalArgumentException {
113             option(option);
114         }
115 
116         /**
117          * Sets the display name for the argument value.
118          *
119          * @param argName the display name for the argument value.
120          * @return {@code this} instance..
121          */
122         public Builder argName(final String argName) {
123             this.argName = argName;
124             return this;
125         }
126 
127         /**
128          * Constructs an Option with the values declared by this {@link Builder}.
129          *
130          * @return the new {@link Option}.
131          * @throws IllegalArgumentException if neither {@code opt} or {@code longOpt} has been set.
132          * @deprecated Use {@link #get()}.
133          */
134         @Deprecated
135         public Option build() {
136             return get();
137         }
138 
139         /**
140          * Sets the converter for the option.
141          * <p>
142          * Note: See {@link TypeHandler} for serialization discussion.
143          * </p>
144          *
145          * @param converter the Converter to use.
146          * @return {@code this} instance..
147          * @since 1.7.0
148          */
149         public Builder converter(final Converter<?, ?> converter) {
150             this.converter = converter;
151             return this;
152         }
153 
154         /**
155          * Marks this Option as deprecated.
156          *
157          * @return this builder.
158          * @since 1.7.0
159          */
160         public Builder deprecated() {
161             return deprecated(DeprecatedAttributes.DEFAULT);
162         }
163 
164         /**
165          * Sets whether the Option is deprecated.
166          *
167          * @param deprecated specifies whether the Option is deprecated.
168          * @return this builder.
169          * @since 1.7.0
170          */
171         public Builder deprecated(final DeprecatedAttributes deprecated) {
172             this.deprecated = deprecated;
173             return this;
174         }
175 
176         /**
177          * Sets the description for this option.
178          *
179          * @param description the description of the option.
180          * @return {@code this} instance..
181          */
182         public Builder desc(final String description) {
183             this.description = description;
184             return this;
185         }
186 
187         /**
188          * Constructs an Option with the values declared by this {@link Builder}.
189          *
190          * @return the new {@link Option}.
191          * @throws IllegalStateException if neither {@code opt} or {@code longOpt} has been set.
192          */
193         @Override
194         public Option get() {
195             return new Option(this);
196         }
197 
198         /**
199          * Tests whether the Option will require an argument.
200          *
201          * @return {@code this} instance..
202          */
203         public Builder hasArg() {
204             return hasArg(true);
205         }
206 
207         /**
208          * Tests whether the Option has an argument or not.
209          *
210          * @param hasArg specifies whether the Option takes an argument or not.
211          * @return {@code this} instance..
212          */
213         public Builder hasArg(final boolean hasArg) {
214             // set to UNINITIALIZED when no arg is specified to be compatible with OptionBuilder
215             argCount = hasArg ? 1 : UNINITIALIZED;
216             return this;
217         }
218 
219         /**
220          * Tests whether the Option can have unlimited argument values.
221          *
222          * @return this builder.
223          */
224         public Builder hasArgs() {
225             argCount = UNLIMITED_VALUES;
226             return this;
227         }
228 
229         /**
230          * Sets the long name of the Option.
231          *
232          * @param longOption the long name of the Option
233          * @return this builder.
234          */
235         public Builder longOpt(final String longOption) {
236             this.longOption = longOption;
237             return this;
238         }
239 
240         /**
241          * Sets the number of argument values the Option can take.
242          *
243          * @param argCount the number of argument values
244          * @return this builder.
245          */
246         public Builder numberOfArgs(final int argCount) {
247             this.argCount = argCount;
248             return this;
249         }
250 
251         /**
252          * Sets the name of the Option.
253          *
254          * @param option the name of the Option.
255          * @return this builder.
256          * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
257          * @since 1.5.0
258          */
259         public Builder option(final String option) throws IllegalArgumentException {
260             this.option = OptionValidator.validate(option);
261             return this;
262         }
263 
264         /**
265          * Sets whether the Option can have an optional argument.
266          *
267          * @param optionalArg specifies whether the Option can have an optional argument.
268          * @return this builder.
269          */
270         public Builder optionalArg(final boolean optionalArg) {
271             if (optionalArg && argCount == UNINITIALIZED) {
272                 argCount = 1;
273             }
274             this.optionalArg = optionalArg;
275             return this;
276         }
277 
278         /**
279          * Marks this Option as required.
280          *
281          * @return this builder.
282          */
283         public Builder required() {
284             return required(true);
285         }
286 
287         /**
288          * Sets whether the Option is required.
289          *
290          * @param required specifies whether the Option is required.
291          * @return this builder.
292          */
293         public Builder required(final boolean required) {
294             this.required = required;
295             return this;
296         }
297 
298         /** Sets the version number when this option was first defined."
299          *
300          * @param since the version number when this option was first defined.
301          * @return this builder.
302          */
303         public Builder since(final String since) {
304             this.since = since;
305             return this;
306         }
307 
308         /**
309          * Sets the type of the Option.
310          *
311          * @param type the type of the Option.
312          * @return this builder.
313          */
314         public Builder type(final Class<?> type) {
315             this.type = toType(type);
316             return this;
317         }
318 
319         /**
320          * The Option will use '=' as a means to separate argument value.
321          *
322          * @return this builder.
323          */
324         public Builder valueSeparator() {
325             return valueSeparator(Char.EQUAL);
326         }
327 
328         /**
329          * The Option will use {@code sep} as a means to separate argument values.
330          * <p>
331          * <strong>Example:</strong>
332          * </p>
333          *
334          * <pre>
335          * Option opt = Option.builder("D").hasArgs().valueSeparator('=').build();
336          * Options options = new Options();
337          * options.addOption(opt);
338          * String[] args = { "-Dkey=value" };
339          * CommandLineParser parser = new DefaultParser();
340          * CommandLine line = parser.parse(options, args);
341          * String propertyName = line.getOptionValues("D")[0]; // will be "key"
342          * String propertyValue = line.getOptionValues("D")[1]; // will be "value"
343          * </pre>
344          *
345          * @param valueSeparator The value separator.
346          * @return this builder.
347          */
348         public Builder valueSeparator(final char valueSeparator) {
349             this.valueSeparator = valueSeparator;
350             return this;
351         }
352 
353     }
354 
355     /** Empty array. */
356     static final Option[] EMPTY_ARRAY = {};
357 
358     /** The serial version UID. */
359     private static final long serialVersionUID = 1L;
360 
361     /** Specifies the number of argument values has not been specified. */
362     public static final int UNINITIALIZED = -1;
363 
364     /** Specifies the number of argument values is infinite. */
365     public static final int UNLIMITED_VALUES = -2;
366 
367     /**
368      * Returns a {@link Builder} to create an {@link Option} using descriptive methods.
369      *
370      * @return a new {@link Builder} instance.
371      * @since 1.3
372      */
373     public static Builder builder() {
374         return builder(null);
375     }
376 
377     /**
378      * Returns a {@link Builder} to create an {@link Option} using descriptive methods.
379      *
380      * @param option short representation of the option.
381      * @return a new {@link Builder} instance.
382      * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
383      * @since 1.3
384      */
385     public static Builder builder(final String option) {
386         return new Builder(option);
387     }
388 
389     /** The number of argument values this option can have. */
390     private int argCount = UNINITIALIZED;
391 
392     /** The name of the argument for this option. */
393     private String argName;
394 
395     /** The explicit converter for this option. May be null. */
396     private transient Converter<?, ?> converter;
397 
398     /**
399      * Specifies whether this option is deprecated, may be null.
400      * <p>
401      * If you want to serialize this field, use a serialization proxy.
402      * </p>
403      */
404     private final transient DeprecatedAttributes deprecated;
405 
406     /** Description of the option. */
407     private String description;
408 
409     /** The long representation of the option. */
410     private String longOption;
411 
412     /** The name of the option. */
413     private final String option;
414 
415     /** Specifies whether the argument value of this Option is optional. */
416     private boolean optionalArg;
417 
418     /** Specifies whether this option is required to be present. */
419     private boolean required;
420 
421     /** Specifies the version when this option was added.  May be null */
422     private String since;
423 
424     /** The type of this Option. */
425     private Class<?> type = String.class;
426 
427     /** The list of argument values. **/
428     private List<String> values = new ArrayList<>();
429 
430     /** The character that is the value separator. */
431     private char valueSeparator;
432 
433     /**
434      * Private constructor used by the nested Builder class.
435      *
436      * @param builder builder used to create this option.
437      * @throws IllegalStateException if neither {@code opt} or {@code longOpt} has been set.
438      */
439     private Option(final Builder builder) {
440         if (builder.option == null && builder.longOption == null) {
441             throw new IllegalStateException("Either opt or longOpt must be specified");
442         }
443         this.argName = builder.argName;
444         this.description = builder.description;
445         this.longOption = builder.longOption;
446         this.argCount = builder.argCount;
447         this.option = builder.option;
448         this.optionalArg = builder.optionalArg;
449         this.deprecated = builder.deprecated;
450         this.required = builder.required;
451         this.since = builder.since;
452         this.type = builder.type;
453         this.valueSeparator = builder.valueSeparator;
454         this.converter = builder.converter;
455     }
456 
457     /**
458      * Creates an Option using the specified parameters.
459      *
460      * @param option      short representation of the option.
461      * @param hasArg      specifies whether the Option takes an argument or not.
462      * @param description describes the function of the option.
463      * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
464      */
465     public Option(final String option, final boolean hasArg, final String description) throws IllegalArgumentException {
466         this(option, null, hasArg, description);
467     }
468 
469     /**
470      * Creates an Option using the specified parameters. The option does not take an argument.
471      *
472      * @param option      short representation of the option.
473      * @param description describes the function of the option.
474      * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
475      */
476     public Option(final String option, final String description) throws IllegalArgumentException {
477         this(option, null, false, description);
478     }
479 
480     /**
481      * Creates an Option using the specified parameters.
482      *
483      * @param option      short representation of the option.
484      * @param longOption  the long representation of the option.
485      * @param hasArg      specifies whether the Option takes an argument or not.
486      * @param description describes the function of the option.
487      * @throws IllegalArgumentException if there are any non valid Option characters in {@code opt}.
488      */
489     public Option(final String option, final String longOption, final boolean hasArg, final String description) throws IllegalArgumentException {
490         // ensure that the option is valid
491         this.deprecated = null;
492         this.option = OptionValidator.validate(option);
493         this.longOption = longOption;
494         // if hasArg is set then the number of arguments is 1
495         if (hasArg) {
496             this.argCount = 1;
497         }
498         this.description = description;
499     }
500 
501     /**
502      * Tests whether the option can accept more arguments.
503      *
504      * @return false if the maximum number of arguments is reached.
505      * @since 1.3
506      */
507     boolean acceptsArg() {
508         return (hasArg() || hasArgs() || hasOptionalArg()) && (argCount <= 0 || values.size() < argCount);
509     }
510 
511     /**
512      * Adds the value to this Option. If the number of arguments is greater than zero and there is enough space in the list then add the value. Otherwise, throw
513      * a runtime exception.
514      *
515      * @param value The value to be added to this Option.
516      */
517     private void add(final String value) {
518         if (!acceptsArg()) {
519             throw new IllegalArgumentException("Cannot add value, list full.");
520         }
521         // store value
522         values.add(value);
523     }
524 
525     /**
526      * This method is not intended to be used. It was a piece of internal API that was made public in 1.0. It currently throws an UnsupportedOperationException.
527      *
528      * @param value the value to add.
529      * @return always throws an {@link UnsupportedOperationException}.
530      * @throws UnsupportedOperationException always.
531      * @deprecated Unused.
532      */
533     @Deprecated
534     public boolean addValue(final String value) {
535         throw new UnsupportedOperationException("The addValue method is not intended for client use. Subclasses should use the processValue method instead.");
536     }
537 
538     /**
539      * Clears the Option values. After a parse is complete, these are left with data in them and they need clearing if another parse is done.
540      *
541      * See: <a href="https://issues.apache.org/jira/browse/CLI-71">CLI-71</a>
542      */
543     void clearValues() {
544         values.clear();
545     }
546 
547     /**
548      * A rather odd clone method - due to incorrect code in 1.0 it is public and in 1.1 rather than throwing a CloneNotSupportedException it throws a
549      * RuntimeException so as to maintain backwards compatible at the API level.
550      *
551      * After calling this method, it is very likely you will want to call clearValues().
552      *
553      * @return a clone of this Option instance.
554      * @throws RuntimeException if a {@link CloneNotSupportedException} has been thrown by {@code super.clone()}.
555      */
556     @Override
557     public Object clone() {
558         try {
559             final Option option = (Option) super.clone();
560             option.values = new ArrayList<>(values);
561             return option;
562         } catch (final CloneNotSupportedException e) {
563             throw new UnsupportedOperationException(e.getMessage(), e);
564         }
565     }
566 
567     @Override
568     public boolean equals(final Object obj) {
569         if (this == obj) {
570             return true;
571         }
572         if (!(obj instanceof Option)) {
573             return false;
574         }
575         final Option other = (Option) obj;
576         return Objects.equals(longOption, other.longOption) && Objects.equals(option, other.option);
577     }
578 
579     /**
580      * Gets the display name for the argument value.
581      *
582      * @return the display name for the argument value.
583      */
584     public String getArgName() {
585         return argName;
586     }
587 
588     /**
589      * Gets the number of argument values this Option can take.
590      *
591      * <p>
592      * A value equal to the constant {@link #UNINITIALIZED} (= -1) indicates the number of arguments has not been specified. A value equal to the constant
593      * {@link #UNLIMITED_VALUES} (= -2) indicates that this options takes an unlimited amount of values.
594      * </p>
595      *
596      * @return num the number of argument values.
597      * @see #UNINITIALIZED
598      * @see #UNLIMITED_VALUES
599      */
600     public int getArgs() {
601         return argCount;
602     }
603 
604     /**
605      * Gets the value to type converter.
606      *
607      * @return the value to type converter.
608      * @since 1.7.0
609      */
610     public Converter<?, ?> getConverter() {
611         return converter == null ? TypeHandler.getDefault().getConverter(type) : converter;
612     }
613 
614     /**
615      * Gets deprecated attributes if any.
616      *
617      * @return boolean deprecated attributes or null.
618      * @since 1.7.0
619      */
620     public DeprecatedAttributes getDeprecated() {
621         return deprecated;
622     }
623 
624     /**
625      * Gets the self-documenting description of this Option.
626      *
627      * @return The string description of this option.
628      */
629     public String getDescription() {
630         return description;
631     }
632 
633     /**
634      * Gets the id of this Option. This is only set when the Option shortOpt is a single character. This is used for switch statements.
635      *
636      * @return the id of this Option.
637      */
638     public int getId() {
639         return getKey().charAt(0);
640     }
641 
642     /**
643      * Gets the 'unique' Option identifier. This is the option value if set or the long value if the options value is not set.
644      *
645      * @return the 'unique' Option identifier.
646      * @since 1.7.0
647      */
648     public String getKey() {
649         // if 'opt' is null, then it is a 'long' option
650         return option == null ? longOption : option;
651     }
652 
653     /**
654      * Gets the long name of this Option.
655      *
656      * @return Long name of this option, or null, if there is no long name.
657      */
658     public String getLongOpt() {
659         return longOption;
660     }
661 
662     /**
663      * Gets the name of this Option.
664      *
665      * It is this String which can be used with {@link CommandLine#hasOption(String opt)} and {@link CommandLine#getOptionValue(String opt)} to check for
666      * existence and argument.
667      *
668      * @return The name of this option.
669      */
670     public String getOpt() {
671         return option;
672     }
673 
674     /**
675      * Gets the version when this option was added.
676      * @return the version when this option was added, or {@code null} if not set.
677      */
678     public String getSince() {
679         return since;
680     }
681 
682     /**
683      * Gets the type of this Option.
684      *
685      * @return The type of this option.
686      */
687     public Object getType() {
688         return type;
689     }
690 
691     /**
692      * Gets the specified value of this Option or {@code null} if there is no value.
693      *
694      * @return the value/first value of this Option or {@code null} if there is no value.
695      */
696     public String getValue() {
697         return hasNoValues() ? null : values.get(0);
698     }
699 
700     /**
701      * Gets the specified value of this Option or {@code null} if there is no value.
702      *
703      * @param index The index of the value to be returned.
704      * @return the specified value of this Option or {@code null} if there is no value.
705      * @throws IndexOutOfBoundsException if index is less than 1 or greater than the number of the values for this Option.
706      */
707     public String getValue(final int index) throws IndexOutOfBoundsException {
708         return hasNoValues() ? null : values.get(index);
709     }
710 
711     /**
712      * Gets the value/first value of this Option or the {@code defaultValue} if there is no value.
713      *
714      * @param defaultValue The value to be returned if there is no value.
715      * @return the value/first value of this Option or the {@code defaultValue} if there are no values.
716      */
717     public String getValue(final String defaultValue) {
718         final String value = getValue();
719         return value != null ? value : defaultValue;
720     }
721 
722     /**
723      * Gets the values of this Option as a String array or an empty array if there are no values.
724      *
725      * @return the values of this Option as a String array or an empty array if there are no values.
726      */
727     public String[] getValues() {
728         return hasNoValues() ? null : values.toArray(EMPTY_STRING_ARRAY);
729     }
730 
731     /**
732      * Gets the value separator character.
733      *
734      * @return the value separator character.
735      */
736     public char getValueSeparator() {
737         return valueSeparator;
738     }
739 
740     /**
741      * Gets the values of this Option as a List.  Will return an empty list if there are no values.
742      *
743      * @return the values of this Option as a List or an empty List if there are no values.
744      */
745     public List<String> getValuesList() {
746         return values;
747     }
748 
749     /**
750      * Tests whether this Option requires an argument.
751      *
752      * @return boolean flag indicating if an argument is required.
753      */
754     public boolean hasArg() {
755         return argCount > 0 || argCount == UNLIMITED_VALUES;
756     }
757 
758     /**
759      * Tests whether the display name for the argument value has been set.
760      *
761      * @return if the display name for the argument value has been set.
762      */
763     public boolean hasArgName() {
764         return argName != null && !argName.isEmpty();
765     }
766 
767     /**
768      * Tests whether this Option can take many values.
769      *
770      * @return boolean flag indicating if multiple values are allowed.
771      */
772     public boolean hasArgs() {
773         return argCount > 1 || argCount == UNLIMITED_VALUES;
774     }
775 
776     @Override
777     public int hashCode() {
778         return Objects.hash(longOption, option);
779     }
780 
781     /**
782      * Tests whether this Option has a long name.
783      *
784      * @return boolean flag indicating existence of a long name.
785      */
786     public boolean hasLongOpt() {
787         return longOption != null;
788     }
789 
790     /**
791      * Tests whether this Option has any values.
792      *
793      * @return whether this Option has any values.
794      */
795     private boolean hasNoValues() {
796         return values.isEmpty();
797     }
798 
799     /**
800      * Tests whether this Option can have an optional argument.
801      *
802      * @return whether this Option can have an optional argument.
803      */
804     public boolean hasOptionalArg() {
805         return optionalArg;
806     }
807 
808     /**
809      * Tests whether this Option has specified a value separator.
810      *
811      * @return whether this Option has specified a value separator.
812      * @since 1.1
813      */
814     public boolean hasValueSeparator() {
815         return valueSeparator > 0;
816     }
817 
818     /**
819      * Tests whether this Option is deprecated.
820      *
821      * @return boolean flag indicating whether this Option is deprecated.
822      * @since 1.7.0
823      */
824     public boolean isDeprecated() {
825         return deprecated != null;
826     }
827 
828     /**
829      * Tests whether this Option is required.
830      *
831      * @return boolean flag indicating whether this Option is required.
832      */
833     public boolean isRequired() {
834         return required;
835     }
836 
837     /**
838      * Processes the value. If this Option has a value separator the value will have to be parsed into individual tokens. When n-1 tokens have been processed
839      * and there are more value separators in the value, parsing is ceased and the remaining characters are added as a single token.
840      *
841      * @param value The String to be processed.
842      */
843     void processValue(final String value) {
844         if (argCount == UNINITIALIZED) {
845             throw new IllegalStateException("NO_ARGS_ALLOWED");
846         }
847         String add = Objects.requireNonNull(value, "value");
848         // this Option has a separator character
849         if (hasValueSeparator()) {
850             // get the separator character
851             final char sep = getValueSeparator();
852             // store the index for the value separator
853             int index = add.indexOf(sep);
854             // while there are more value separators
855             while (index != -1) {
856                 // next value to be added
857                 if (values.size() == argCount - 1) {
858                     break;
859                 }
860                 // store
861                 add(add.substring(0, index));
862                 // parse
863                 add = add.substring(index + 1);
864                 // get new index
865                 index = add.indexOf(sep);
866             }
867         }
868         // store the actual value or the last value that has been parsed
869         add(add);
870     }
871 
872     /**
873      * Tests whether the option requires more arguments to be valid.
874      *
875      * @return false if the option doesn't require more arguments.
876      */
877     boolean requiresArg() {
878         if (optionalArg) {
879             return false;
880         }
881         if (argCount == UNLIMITED_VALUES) {
882             return values.isEmpty();
883         }
884         return acceptsArg();
885     }
886 
887     /**
888      * Sets the display name for the argument value.
889      *
890      * @param argName the display name for the argument value.
891      */
892     public void setArgName(final String argName) {
893         this.argName = argName;
894     }
895 
896     /**
897      * Sets the number of argument values this Option can take.
898      *
899      * @param num the number of argument values.
900      */
901     public void setArgs(final int num) {
902         this.argCount = num;
903     }
904 
905     /**
906      * Sets the value to type converter.
907      *
908      * @param converter The converter to convert the string value to the type.
909      * @since 1.7.0
910      */
911     public void setConverter(final Converter<?, ?> converter) {
912         this.converter = converter;
913     }
914 
915     /**
916      * Sets the self-documenting description of this Option.
917      *
918      * @param description The description of this option.
919      * @since 1.1
920      */
921     public void setDescription(final String description) {
922         this.description = description;
923     }
924 
925     /**
926      * Sets the long name of this Option.
927      *
928      * @param longOpt the long name of this Option.
929      */
930     public void setLongOpt(final String longOpt) {
931         this.longOption = longOpt;
932     }
933 
934     /**
935      * Sets whether this Option can have an optional argument.
936      *
937      * @param optionalArg specifies whether the Option can have an optional argument.
938      */
939     public void setOptionalArg(final boolean optionalArg) {
940         this.optionalArg = optionalArg;
941     }
942 
943     /**
944      * Sets whether this Option is mandatory.
945      *
946      * @param required specifies whether this Option is mandatory.
947      */
948     public void setRequired(final boolean required) {
949         this.required = required;
950     }
951 
952     /**
953      * Sets the type of this Option.
954      *
955      * @param type the type of this Option.
956      * @since 1.3
957      */
958     public void setType(final Class<?> type) {
959         this.type = Builder.toType(type);
960     }
961 
962     /**
963      * Sets the type of this Option.
964      * <p>
965      * <strong>Note:</strong> this method is kept for binary compatibility and the input type is supposed to be a {@link Class} object.
966      * </p>
967      *
968      * @param type the type of this Option.
969      * @deprecated since 1.3, use {@link #setType(Class)} instead.
970      */
971     @Deprecated
972     public void setType(final Object type) {
973         setType((Class<?>) type);
974     }
975 
976     /**
977      * Sets the value separator. For example if the argument value was a Java property, the value separator would be '='.
978      *
979      * @param valueSeparator The value separator.
980      */
981     public void setValueSeparator(final char valueSeparator) {
982         this.valueSeparator = valueSeparator;
983     }
984 
985     String toDeprecatedString() {
986         if (!isDeprecated()) {
987             return "";
988         }
989         // @formatter:off
990         final StringBuilder buf = new StringBuilder()
991                 .append("Option '")
992                 .append(option)
993                 .append(Char.APOS);
994         // @formatter:on
995         if (longOption != null) {
996             buf.append(Char.APOS).append(longOption).append(Char.APOS);
997         }
998         buf.append(": ").append(deprecated);
999         return buf.toString();
1000     }
1001 
1002     /**
1003      * Creates a String suitable for debugging.
1004      *
1005      * @return a String suitable for debugging.
1006      */
1007     @Override
1008     public String toString() {
1009         final StringBuilder buf = new StringBuilder().append("[ ");
1010         buf.append("Option ");
1011         buf.append(option);
1012         if (longOption != null) {
1013             buf.append(Char.SP).append(longOption);
1014         }
1015         if (isDeprecated()) {
1016             buf.append(Char.SP);
1017             buf.append(deprecated.toString());
1018         }
1019         if (hasArgs()) {
1020             buf.append("[ARG...]");
1021         } else if (hasArg()) {
1022             buf.append(" [ARG]");
1023         }
1024         // @formatter:off
1025         return buf.append(" :: ")
1026             .append(description)
1027             .append(" :: ")
1028             .append(type)
1029             .append(" ]")
1030             .toString();
1031         // @formatter:on
1032     }
1033 }