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    
018    package org.apache.commons.cli;
019    
020    /**
021     * OptionBuilder allows the user to create Options using descriptive methods.
022     *
023     * <p>Details on the Builder pattern can be found at
024     * <a href="http://c2.com/cgi-bin/wiki?BuilderPattern">
025     * http://c2.com/cgi-bin/wiki?BuilderPattern</a>.</p>
026     *
027     * @author John Keyes (john at integralsource.com)
028     * @version $Revision: 754830 $, $Date: 2009-03-16 00:26:44 -0700 (Mon, 16 Mar 2009) $
029     * @since 1.0
030     */
031    public final class OptionBuilder
032    {
033        /** long option */
034        private static String longopt;
035    
036        /** option description */
037        private static String description;
038    
039        /** argument name */
040        private static String argName;
041    
042        /** is required? */
043        private static boolean required;
044    
045        /** the number of arguments */
046        private static int numberOfArgs = Option.UNINITIALIZED;
047    
048        /** option type */
049        private static Object type;
050    
051        /** option can have an optional argument value */
052        private static boolean optionalArg;
053    
054        /** value separator for argument value */
055        private static char valuesep;
056    
057        /** option builder instance */
058        private static OptionBuilder instance = new OptionBuilder();
059    
060        /**
061         * private constructor to prevent instances being created
062         */
063        private OptionBuilder()
064        {
065            // hide the constructor
066        }
067    
068        /**
069         * Resets the member variables to their default values.
070         */
071        private static void reset()
072        {
073            description = null;
074            argName = "arg";
075            longopt = null;
076            type = null;
077            required = false;
078            numberOfArgs = Option.UNINITIALIZED;
079    
080    
081            // PMM 9/6/02 - these were missing
082            optionalArg = false;
083            valuesep = (char) 0;
084        }
085    
086        /**
087         * The next Option created will have the following long option value.
088         *
089         * @param newLongopt the long option value
090         * @return the OptionBuilder instance
091         */
092        public static OptionBuilder withLongOpt(String newLongopt)
093        {
094            OptionBuilder.longopt = newLongopt;
095    
096            return instance;
097        }
098    
099        /**
100         * The next Option created will require an argument value.
101         *
102         * @return the OptionBuilder instance
103         */
104        public static OptionBuilder hasArg()
105        {
106            OptionBuilder.numberOfArgs = 1;
107    
108            return instance;
109        }
110    
111        /**
112         * The next Option created will require an argument value if
113         * <code>hasArg</code> is true.
114         *
115         * @param hasArg if true then the Option has an argument value
116         * @return the OptionBuilder instance
117         */
118        public static OptionBuilder hasArg(boolean hasArg)
119        {
120            OptionBuilder.numberOfArgs = hasArg ? 1 : Option.UNINITIALIZED;
121    
122            return instance;
123        }
124    
125        /**
126         * The next Option created will have the specified argument value name.
127         *
128         * @param name the name for the argument value
129         * @return the OptionBuilder instance
130         */
131        public static OptionBuilder withArgName(String name)
132        {
133            OptionBuilder.argName = name;
134    
135            return instance;
136        }
137    
138        /**
139         * The next Option created will be required.
140         *
141         * @return the OptionBuilder instance
142         */
143        public static OptionBuilder isRequired()
144        {
145            OptionBuilder.required = true;
146    
147            return instance;
148        }
149    
150        /**
151         * The next Option created uses <code>sep</code> as a means to
152         * separate argument values.
153         *
154         * <b>Example:</b>
155         * <pre>
156         * Option opt = OptionBuilder.withValueSeparator(':')
157         *                           .create('D');
158         *
159         * CommandLine line = parser.parse(args);
160         * String propertyName = opt.getValue(0);
161         * String propertyValue = opt.getValue(1);
162         * </pre>
163         *
164         * @param sep The value separator to be used for the argument values.
165         *
166         * @return the OptionBuilder instance
167         */
168        public static OptionBuilder withValueSeparator(char sep)
169        {
170            OptionBuilder.valuesep = sep;
171    
172            return instance;
173        }
174    
175        /**
176         * The next Option created uses '<code>=</code>' as a means to
177         * separate argument values.
178         *
179         * <b>Example:</b>
180         * <pre>
181         * Option opt = OptionBuilder.withValueSeparator()
182         *                           .create('D');
183         *
184         * CommandLine line = parser.parse(args);
185         * String propertyName = opt.getValue(0);
186         * String propertyValue = opt.getValue(1);
187         * </pre>
188         *
189         * @return the OptionBuilder instance
190         */
191        public static OptionBuilder withValueSeparator()
192        {
193            OptionBuilder.valuesep = '=';
194    
195            return instance;
196        }
197    
198        /**
199         * The next Option created will be required if <code>required</code>
200         * is true.
201         *
202         * @param newRequired if true then the Option is required
203         * @return the OptionBuilder instance
204         */
205        public static OptionBuilder isRequired(boolean newRequired)
206        {
207            OptionBuilder.required = newRequired;
208    
209            return instance;
210        }
211    
212        /**
213         * The next Option created can have unlimited argument values.
214         *
215         * @return the OptionBuilder instance
216         */
217        public static OptionBuilder hasArgs()
218        {
219            OptionBuilder.numberOfArgs = Option.UNLIMITED_VALUES;
220    
221            return instance;
222        }
223    
224        /**
225         * The next Option created can have <code>num</code> argument values.
226         *
227         * @param num the number of args that the option can have
228         * @return the OptionBuilder instance
229         */
230        public static OptionBuilder hasArgs(int num)
231        {
232            OptionBuilder.numberOfArgs = num;
233    
234            return instance;
235        }
236    
237        /**
238         * The next Option can have an optional argument.
239         *
240         * @return the OptionBuilder instance
241         */
242        public static OptionBuilder hasOptionalArg()
243        {
244            OptionBuilder.numberOfArgs = 1;
245            OptionBuilder.optionalArg = true;
246    
247            return instance;
248        }
249    
250        /**
251         * The next Option can have an unlimited number of optional arguments.
252         *
253         * @return the OptionBuilder instance
254         */
255        public static OptionBuilder hasOptionalArgs()
256        {
257            OptionBuilder.numberOfArgs = Option.UNLIMITED_VALUES;
258            OptionBuilder.optionalArg = true;
259    
260            return instance;
261        }
262    
263        /**
264         * The next Option can have the specified number of optional arguments.
265         *
266         * @param numArgs - the maximum number of optional arguments
267         * the next Option created can have.
268         * @return the OptionBuilder instance
269         */
270        public static OptionBuilder hasOptionalArgs(int numArgs)
271        {
272            OptionBuilder.numberOfArgs = numArgs;
273            OptionBuilder.optionalArg = true;
274    
275            return instance;
276        }
277    
278        /**
279         * The next Option created will have a value that will be an instance
280         * of <code>type</code>.
281         *
282         * @param newType the type of the Options argument value
283         * @return the OptionBuilder instance
284         */
285        public static OptionBuilder withType(Object newType)
286        {
287            OptionBuilder.type = newType;
288    
289            return instance;
290        }
291    
292        /**
293         * The next Option created will have the specified description
294         *
295         * @param newDescription a description of the Option's purpose
296         * @return the OptionBuilder instance
297         */
298        public static OptionBuilder withDescription(String newDescription)
299        {
300            OptionBuilder.description = newDescription;
301    
302            return instance;
303        }
304    
305        /**
306         * Create an Option using the current settings and with
307         * the specified Option <code>char</code>.
308         *
309         * @param opt the character representation of the Option
310         * @return the Option instance
311         * @throws IllegalArgumentException if <code>opt</code> is not
312         * a valid character.  See Option.
313         */
314        public static Option create(char opt) throws IllegalArgumentException
315        {
316            return create(String.valueOf(opt));
317        }
318    
319        /**
320         * Create an Option using the current settings
321         *
322         * @return the Option instance
323         * @throws IllegalArgumentException if <code>longOpt</code> has not been set.
324         */
325        public static Option create() throws IllegalArgumentException
326        {
327            if (longopt == null)
328            {
329                OptionBuilder.reset();
330                throw new IllegalArgumentException("must specify longopt");
331            }
332    
333            return create(null);
334        }
335    
336        /**
337         * Create an Option using the current settings and with
338         * the specified Option <code>char</code>.
339         *
340         * @param opt the <code>java.lang.String</code> representation
341         * of the Option
342         * @return the Option instance
343         * @throws IllegalArgumentException if <code>opt</code> is not
344         * a valid character.  See Option.
345         */
346        public static Option create(String opt) throws IllegalArgumentException
347        {
348            Option option = null;
349            try {
350                // create the option
351                option = new Option(opt, description);
352    
353                // set the option properties
354                option.setLongOpt(longopt);
355                option.setRequired(required);
356                option.setOptionalArg(optionalArg);
357                option.setArgs(numberOfArgs);
358                option.setType(type);
359                option.setValueSeparator(valuesep);
360                option.setArgName(argName);
361            } finally {
362                // reset the OptionBuilder properties
363                OptionBuilder.reset();
364            }
365    
366            // return the Option instance
367            return option;
368        }
369    }