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="https://c2.com/cgi-bin/wiki?BuilderPattern">https://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 * @since 1.0 029 * @deprecated since 1.3, use {@link Option#builder(String)} instead 030 */ 031@Deprecated 032public final class OptionBuilder { 033 034 035 /** Long option */ 036 private static String longOption; 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 argCount = 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 valueSeparator; 058 059 /** Option builder instance */ 060 private static final OptionBuilder INSTANCE = new OptionBuilder(); 061 062 static { 063 // ensure the consistency of the initial values 064 reset(); 065 } 066 067 /** 068 * Creates an Option using the current settings 069 * 070 * @return the Option instance 071 * @throws IllegalArgumentException if {@code longOpt} has not been set. 072 */ 073 public static Option create() throws IllegalArgumentException { 074 if (longOption == null) { 075 OptionBuilder.reset(); 076 throw new IllegalArgumentException("must specify longopt"); 077 } 078 079 return create(null); 080 } 081 082 /** 083 * Creates an Option using the current settings and with the specified Option {@code char}. 084 * 085 * @param opt the character representation of the Option 086 * @return the Option instance 087 * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option. 088 */ 089 public static Option create(final char opt) throws IllegalArgumentException { 090 return create(String.valueOf(opt)); 091 } 092 093 /** 094 * Creates an Option using the current settings and with the specified Option {@code char}. 095 * 096 * @param opt the {@code String} representation of the Option 097 * @return the Option instance 098 * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option. 099 */ 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}