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