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  /**
21   * OptionBuilder allows the user to create Options using descriptive methods.
22   *
23   * <p>Details on the Builder pattern can be found at
24   * <a href="http://c2.com/cgi-bin/wiki?BuilderPattern">
25   * http://c2.com/cgi-bin/wiki?BuilderPattern</a>.</p>
26   *
27   * @author John Keyes (john at integralsource.com)
28   * @version $Revision: 754830 $, $Date: 2009-03-16 00:26:44 -0700 (Mon, 16 Mar 2009) $
29   * @since 1.0
30   */
31  public final class OptionBuilder
32  {
33      /** long option */
34      private static String longopt;
35  
36      /** option description */
37      private static String description;
38  
39      /** argument name */
40      private static String argName;
41  
42      /** is required? */
43      private static boolean required;
44  
45      /** the number of arguments */
46      private static int numberOfArgs = Option.UNINITIALIZED;
47  
48      /** option type */
49      private static Object type;
50  
51      /** option can have an optional argument value */
52      private static boolean optionalArg;
53  
54      /** value separator for argument value */
55      private static char valuesep;
56  
57      /** option builder instance */
58      private static OptionBuilder instance = new OptionBuilder();
59  
60      /**
61       * private constructor to prevent instances being created
62       */
63      private OptionBuilder()
64      {
65          // hide the constructor
66      }
67  
68      /**
69       * Resets the member variables to their default values.
70       */
71      private static void reset()
72      {
73          description = null;
74          argName = "arg";
75          longopt = null;
76          type = null;
77          required = false;
78          numberOfArgs = Option.UNINITIALIZED;
79  
80  
81          // PMM 9/6/02 - these were missing
82          optionalArg = false;
83          valuesep = (char) 0;
84      }
85  
86      /**
87       * The next Option created will have the following long option value.
88       *
89       * @param newLongopt the long option value
90       * @return the OptionBuilder instance
91       */
92      public static OptionBuilder withLongOpt(String newLongopt)
93      {
94          OptionBuilder.longopt = newLongopt;
95  
96          return instance;
97      }
98  
99      /**
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 }
370