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