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