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