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
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 */
031public 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}