View Javadoc
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   * <p>
23   * Details on the Builder pattern can be found at
24   * <a href="https://c2.com/cgi-bin/wiki?BuilderPattern">https://c2.com/cgi-bin/wiki?BuilderPattern</a>.
25   * <p>
26   * This class is NOT thread safe. See <a href="https://issues.apache.org/jira/browse/CLI-209">CLI-209</a>
27   *
28   * @since 1.0
29   * @deprecated since 1.3, use {@link Option#builder(String)} instead
30   */
31  @Deprecated
32  public final class OptionBuilder {
33  
34  
35      /** Long option */
36      private static String longOption;
37  
38      /** Option description */
39      private static String description;
40  
41      /** Argument name */
42      private static String argName;
43  
44      /** Is required? */
45      private static boolean required;
46  
47      /** The number of arguments */
48      private static int argCount = Option.UNINITIALIZED;
49  
50      /** Option type */
51      private static Class<?> type;
52  
53      /** Option can have an optional argument value */
54      private static boolean optionalArg;
55  
56      /** Value separator for argument value */
57      private static char valueSeparator;
58  
59      /** Option builder instance */
60      private static final OptionBuilder INSTANCE = new OptionBuilder();
61  
62      static {
63          // ensure the consistency of the initial values
64          reset();
65      }
66  
67      /**
68       * Creates an Option using the current settings
69       *
70       * @return the Option instance
71       * @throws IllegalArgumentException if {@code longOpt} has not been set.
72       */
73      public static Option create() throws IllegalArgumentException {
74          if (longOption == null) {
75              OptionBuilder.reset();
76              throw new IllegalArgumentException("must specify longopt");
77          }
78  
79          return create(null);
80      }
81  
82      /**
83       * Creates an Option using the current settings and with the specified Option {@code char}.
84       *
85       * @param opt the character representation of the Option
86       * @return the Option instance
87       * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option.
88       */
89      public static Option create(final char opt) throws IllegalArgumentException {
90          return create(String.valueOf(opt));
91      }
92  
93      /**
94       * Creates an Option using the current settings and with the specified Option {@code char}.
95       *
96       * @param opt the {@code String} representation of the Option
97       * @return the Option instance
98       * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option.
99       */
100     public static Option create(final String opt) throws IllegalArgumentException {
101         Option option;
102         try {
103             // create the option
104             option = new Option(opt, description);
105 
106             // set the option properties
107             option.setLongOpt(longOption);
108             option.setRequired(required);
109             option.setOptionalArg(optionalArg);
110             option.setArgs(argCount);
111             option.setType(type);
112             option.setConverter(TypeHandler.getDefault().getConverter(type));
113             option.setValueSeparator(valueSeparator);
114             option.setArgName(argName);
115         } finally {
116             // reset the OptionBuilder properties
117             OptionBuilder.reset();
118         }
119 
120         // return the Option instance
121         return option;
122     }
123 
124     /**
125      * The next Option created will require an argument value.
126      *
127      * @return the OptionBuilder instance
128      */
129     public static OptionBuilder hasArg() {
130         OptionBuilder.argCount = 1;
131 
132         return INSTANCE;
133     }
134 
135     /**
136      * The next Option created will require an argument value if {@code hasArg} is true.
137      *
138      * @param hasArg if true then the Option has an argument value
139      * @return the OptionBuilder instance
140      */
141     public static OptionBuilder hasArg(final boolean hasArg) {
142         OptionBuilder.argCount = hasArg ? 1 : Option.UNINITIALIZED;
143 
144         return INSTANCE;
145     }
146 
147     /**
148      * The next Option created can have unlimited argument values.
149      *
150      * @return the OptionBuilder instance
151      */
152     public static OptionBuilder hasArgs() {
153         OptionBuilder.argCount = Option.UNLIMITED_VALUES;
154 
155         return INSTANCE;
156     }
157 
158     /**
159      * The next Option created can have {@code num} argument values.
160      *
161      * @param num the number of args that the option can have
162      * @return the OptionBuilder instance
163      */
164     public static OptionBuilder hasArgs(final int num) {
165         OptionBuilder.argCount = num;
166 
167         return INSTANCE;
168     }
169 
170     /**
171      * The next Option can have an optional argument.
172      *
173      * @return the OptionBuilder instance
174      */
175     public static OptionBuilder hasOptionalArg() {
176         OptionBuilder.argCount = 1;
177         OptionBuilder.optionalArg = true;
178 
179         return INSTANCE;
180     }
181 
182     /**
183      * The next Option can have an unlimited number of optional arguments.
184      *
185      * @return the OptionBuilder instance
186      */
187     public static OptionBuilder hasOptionalArgs() {
188         OptionBuilder.argCount = Option.UNLIMITED_VALUES;
189         OptionBuilder.optionalArg = true;
190 
191         return INSTANCE;
192     }
193 
194     /**
195      * The next Option can have the specified number of optional arguments.
196      *
197      * @param numArgs - the maximum number of optional arguments the next Option created can have.
198      * @return the OptionBuilder instance
199      */
200     public static OptionBuilder hasOptionalArgs(final int numArgs) {
201         OptionBuilder.argCount = numArgs;
202         OptionBuilder.optionalArg = true;
203 
204         return INSTANCE;
205     }
206 
207     /**
208      * The next Option created will be required.
209      *
210      * @return the OptionBuilder instance
211      */
212     public static OptionBuilder isRequired() {
213         OptionBuilder.required = true;
214 
215         return INSTANCE;
216     }
217 
218     /**
219      * The next Option created will be required if {@code required} is true.
220      *
221      * @param newRequired if true then the Option is required
222      * @return the OptionBuilder instance
223      */
224     public static OptionBuilder isRequired(final boolean newRequired) {
225         OptionBuilder.required = newRequired;
226 
227         return INSTANCE;
228     }
229 
230     /**
231      * Resets the member variables to their default values.
232      */
233     private static void reset() {
234         description = null;
235         argName = null;
236         longOption = null;
237         type = String.class;
238         required = false;
239         argCount = Option.UNINITIALIZED;
240         optionalArg = false;
241         valueSeparator = (char) 0;
242     }
243 
244     /**
245      * The next Option created will have the specified argument value name.
246      *
247      * @param name the name for the argument value
248      * @return the OptionBuilder instance
249      */
250     public static OptionBuilder withArgName(final String name) {
251         OptionBuilder.argName = name;
252 
253         return INSTANCE;
254     }
255 
256     /**
257      * The next Option created will have the specified description
258      *
259      * @param newDescription a description of the Option's purpose
260      * @return the OptionBuilder instance
261      */
262     public static OptionBuilder withDescription(final String newDescription) {
263         OptionBuilder.description = newDescription;
264 
265         return INSTANCE;
266     }
267 
268     /**
269      * The next Option created will have the following long option value.
270      *
271      * @param newLongopt the long option value
272      * @return the OptionBuilder instance
273      */
274     public static OptionBuilder withLongOpt(final String newLongopt) {
275         OptionBuilder.longOption = newLongopt;
276 
277         return INSTANCE;
278     }
279 
280     /**
281      * The next Option created will have a value that will be an instance of {@code type}.
282      *
283      * @param newType the type of the Options argument value
284      * @return the OptionBuilder instance
285      * @since 1.3
286      */
287     public static OptionBuilder withType(final Class<?> newType) {
288         OptionBuilder.type = newType;
289 
290         return INSTANCE;
291     }
292 
293     /**
294      * The next Option created will have a value that will be an instance of {@code type}.
295      * <p>
296      * <b>Note:</b> this method is kept for binary compatibility and the input type is supposed to be a {@link Class}
297      * object.
298      *
299      * @param newType the type of the Options argument value
300      * @return the OptionBuilder instance
301      * @deprecated since 1.3, use {@link #withType(Class)} instead
302      */
303     @Deprecated
304     public static OptionBuilder withType(final Object newType) {
305         return withType((Class<?>) newType);
306     }
307 
308     /**
309      * The next Option created uses '{@code =}' as a means to separate argument values.
310      *
311      * <b>Example:</b>
312      *
313      * <pre>
314      * Option opt = OptionBuilder.withValueSeparator().create('D');
315      *
316      * CommandLine line = parser.parse(args);
317      * String propertyName = opt.getValue(0);
318      * String propertyValue = opt.getValue(1);
319      * </pre>
320      *
321      * @return the OptionBuilder instance
322      */
323     public static OptionBuilder withValueSeparator() {
324         OptionBuilder.valueSeparator = Char.EQUAL;
325 
326         return INSTANCE;
327     }
328 
329     /**
330      * The next Option created uses {@code sep} as a means to separate argument values.
331      * <p>
332      * <b>Example:</b>
333      *
334      * <pre>
335      * Option opt = OptionBuilder.withValueSeparator('=').create('D');
336      *
337      * String args = "-Dkey=value";
338      * CommandLine line = parser.parse(args);
339      * String propertyName = opt.getValue(0); // will be "key"
340      * String propertyValue = opt.getValue(1); // will be "value"
341      * </pre>
342      *
343      * @param sep The value separator to be used for the argument values.
344      *
345      * @return the OptionBuilder instance
346      */
347     public static OptionBuilder withValueSeparator(final char sep) {
348         OptionBuilder.valueSeparator = sep;
349 
350         return INSTANCE;
351     }
352 
353     /**
354      * private constructor to prevent instances being created
355      */
356     private OptionBuilder() {
357         // hide the constructor
358     }
359 }