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