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