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 */ 017package Apache.CLI; 018 019import static Apache.CLI.Util.EMPTY_STRING_ARRAY; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.Iterator; 024import java.util.LinkedList; 025import java.util.List; 026import java.util.Properties; 027 028/** 029 * Represents list of arguments parsed against a {@link Options} descriptor. 030 * 031 * <BR /><BR />It allows querying of a boolean {@link #hasOption(String opt)}, in addition to 032 * retrieving the {@link #getOptionValue(String opt)} for options requiring arguments. 033 * 034 * <BR /><BR />Additionally, any left-over or unrecognized arguments, are available for further 035 * processing. 036 */ 037@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="LICENSE") 038public class CommandLine implements Serializable { 039 040 /** A nested builder class to create {@code CommandLine} instance using descriptive methods. */ 041 @Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="LICENSE") 042 public static final class Builder 043 { 044 // CommandLine that is being build by this Builder. 045 private final CommandLine commandLine = new CommandLine(); 046 047 /** 048 * Adds left-over unrecognized option/argument. 049 * @param arg the unrecognized option/argument. 050 * @return this Builder instance for method chaining. 051 */ 052 public Builder addArg(final String arg) 053 { 054 commandLine.addArg(arg); 055 return this; 056 } 057 058 /** 059 * Adds an option to the command line. The values of the option are stored. 060 * @param opt the processed option. 061 * @return this Builder instance for method chaining. 062 */ 063 public Builder addOption(final Option opt) 064 { 065 commandLine.addOption(opt); 066 return this; 067 } 068 069 /** 070 * Returns the new instance. 071 * @return the new instance. 072 */ 073 public CommandLine build() 074 { return commandLine; } 075 } 076 077 // The serial version UID. 078 private static final long serialVersionUID = 1L; 079 080 // The unrecognized options/arguments 081 private final List<String> args = new LinkedList<>(); 082 083 // The processed options 084 private final List<Option> options = new ArrayList<>(); 085 086 /** Creates a command line. */ 087 protected CommandLine() 088 { /* nothing to do */ } 089 090 /** 091 * Adds left-over unrecognized option/argument. 092 * @param arg the unrecognized option/argument. 093 */ 094 protected void addArg(final String arg) 095 { if (arg != null) args.add(arg); } 096 097 /** 098 * Adds an option to the command line. The values of the option are stored. 099 * @param opt the processed option. 100 */ 101 protected void addOption(final Option opt) 102 { if (opt != null) options.add(opt); } 103 104 /** 105 * Gets any left-over non-recognized options and arguments 106 * @return remaining items passed in but not parsed as a {@code List}. 107 */ 108 public List<String> getArgList() 109 { return args; } 110 111 /** 112 * Gets any left-over non-recognized options and arguments 113 * @return remaining items passed in but not parsed as an array. 114 */ 115 public String[] getArgs() 116 { return args.toArray(Util.EMPTY_STRING_ARRAY); } 117 118 /** 119 * Gets the map of values associated to the option. This is convenient for options specifying 120 * Java properties like <code>-Dparam1=value1 -Dparam2=value2</code>. The first argument of the 121 * option is the key, and the 2nd argument is the value. If the option has only one argument 122 * ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 123 * 124 * @param option name of the option. 125 * 126 * @return The Properties mapped by the option, never {@code null} even if the option doesn't 127 * exists. 128 */ 129 public Properties getOptionProperties(final Option option) 130 { 131 final Properties props = new Properties(); 132 133 for (final Option processedOption : options) 134 { 135 if (processedOption.equals(option)) 136 { 137 final List<String> values = processedOption.getValuesList(); 138 139 if (values.size() >= 2) 140 141 // use the first 2 arguments as the key/value pair 142 props.put(values.get(0), values.get(1)); 143 144 else if (values.size() == 1) 145 146 // no explicit value, handle it as a boolean 147 props.put(values.get(0), "true"); 148 } 149 } 150 151 return props; 152 } 153 154 /** 155 * Gets the map of values associated to the option. This is convenient for options specifying 156 * Java properties like <code>-Dparam1=value1 -Dparam2=value2</code>. The first argument of the 157 * option is the key, and the 2nd argument is the value. If the option has only one argument 158 * ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 159 * 160 * @param opt name of the option. 161 * 162 * @return The Properties mapped by the option, never {@code null} even if the option doesn't 163 * exists. 164 */ 165 public Properties getOptionProperties(final String opt) 166 { 167 final Properties props = new Properties(); 168 169 for (final Option option : options) 170 { 171 if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt())) 172 { 173 final List<String> values = option.getValuesList(); 174 175 if (values.size() >= 2) 176 177 // use the first 2 arguments as the key/value pair 178 props.put(values.get(0), values.get(1)); 179 180 else if (values.size() == 1) 181 182 // no explicit value, handle it as a boolean 183 props.put(values.get(0), "true"); 184 } 185 } 186 187 return props; 188 } 189 190 /** 191 * Gets an array of the processed {@link Option}'s. 192 * @return an array of the processed {@link Option}s. 193 */ 194 public Option[] getOptions() 195 { return options.toArray(Option.EMPTY_ARRAY); } 196 197 /** 198 * Gets the first argument, if any, of this option. 199 * @param opt the character name of the option. 200 * @return Value of the argument if option is set, and has an argument, otherwise null. 201 */ 202 public String getOptionValue(final char opt) 203 { return getOptionValue(String.valueOf(opt)); } 204 205 /** 206 * Gets the argument, if any, of an option. 207 * @param opt character name of the option 208 * @param defaultValue is the default value to be returned if the option is not specified. 209 * 210 * @return Value of the argument if option is set, and has an argument, otherwise 211 * {@code defaultValue}. 212 */ 213 public String getOptionValue(final char opt, final String defaultValue) 214 { return getOptionValue(String.valueOf(opt), defaultValue); } 215 216 /** 217 * Gets the first argument, if any, of this option. 218 * @param option the name of the option. 219 * @return Value of the argument if option is set, and has an argument, otherwise null. 220 */ 221 public String getOptionValue(final Option option) 222 { 223 if (option == null) return null; 224 225 final String[] values = getOptionValues(option); 226 227 return values == null ? null : values[0]; 228 } 229 230 /** 231 * Gets the first argument, if any, of an option. 232 * @param option name of the option. 233 * @param defaultValue is the default value to be returned if the option is not specified. 234 * 235 * @return Value of the argument if option is set, and has an argument, otherwise 236 * {@code defaultValue}. 237 */ 238 public String getOptionValue(final Option option, final String defaultValue) 239 { 240 final String answer = getOptionValue(option); 241 return answer != null ? answer : defaultValue; 242 } 243 244 /** 245 * Gets the first argument, if any, of this option. 246 * @param opt the name of the option. 247 * @return Value of the argument if option is set, and has an argument, otherwise null. 248 */ 249 public String getOptionValue(final String opt) 250 { return getOptionValue(resolveOption(opt)); } 251 252 /** 253 * Gets the first argument, if any, of an option. 254 * @param opt name of the option. 255 * @param defaultValue is the default value to be returned if the option is not specified. 256 * 257 * @return Value of the argument if option is set, and has an argument, otherwise 258 * {@code defaultValue}. 259 */ 260 public String getOptionValue(final String opt, final String defaultValue) 261 { return getOptionValue(resolveOption(opt), defaultValue); } 262 263 /** 264 * Gets the array of values, if any, of an option. 265 * @param opt character name of the option. 266 * @return Values of the argument if option is set, and has an argument, otherwise null. 267 */ 268 public String[] getOptionValues(final char opt) 269 { return getOptionValues(String.valueOf(opt)); } 270 271 /** 272 * Gets the array of values, if any, of an option. 273 * @param option string name of the option. 274 * @return Values of the argument if option is set, and has an argument, otherwise null. 275 */ 276 public String[] getOptionValues(final Option option) 277 { 278 final List<String> values = new ArrayList<>(); 279 280 for (final Option processedOption : options) 281 if (processedOption.equals(option)) 282 values.addAll(processedOption.getValuesList()); 283 284 return values.isEmpty() ? null : values.toArray(EMPTY_STRING_ARRAY); 285 } 286 287 /** 288 * Gets the array of values, if any, of an option. 289 * @param opt string name of the option. 290 * @return Values of the argument if option is set, and has an argument, otherwise null. 291 */ 292 public String[] getOptionValues(final String opt) 293 { return getOptionValues(resolveOption(opt)); } 294 295 /** 296 * Gets a version of this {@code Option} converted to a particular type. 297 * @param opt the name of the option. 298 * @return the value parsed into a particular object. 299 * @throws ParseException if there are problems turning the option value into the desired type 300 * @see PatternOptionBuilder 301 */ 302 public Object getParsedOptionValue(final char opt) throws ParseException 303 { return getParsedOptionValue(String.valueOf(opt)); } 304 305 /** 306 * Gets a version of this {@code Option} converted to a particular type. 307 * @param option the name of the option. 308 * @return the value parsed into a particular object. 309 * @throws ParseException if there are problems turning the option value into the desired type 310 * @see PatternOptionBuilder 311 */ 312 public Object getParsedOptionValue(final Option option) throws ParseException 313 { 314 if (option == null) return null; 315 316 final String res = getOptionValue(option); 317 318 if (res == null) return null; 319 320 return TypeHandler.createValue(res, option.getType()); 321 } 322 323 /** 324 * Gets a version of this {@code Option} converted to a particular type. 325 * @param opt the name of the option. 326 * @return the value parsed into a particular object. 327 * @throws ParseException if there are problems turning the option value into the desired type 328 * @see PatternOptionBuilder 329 */ 330 public Object getParsedOptionValue(final String opt) throws ParseException 331 { return getParsedOptionValue(resolveOption(opt)); } 332 333 /** 334 * Tests to see if an option has been set. 335 * @param opt character name of the option. 336 * @return true if set, false if not. 337 */ 338 public boolean hasOption(final char opt) 339 { return hasOption(String.valueOf(opt)); } 340 341 /** 342 * Tests to see if an option has been set. 343 * @param opt the option to check. 344 * @return true if set, false if not. 345 */ 346 public boolean hasOption(final Option opt) 347 { return options.contains(opt); } 348 349 /** 350 * Tests to see if an option has been set. 351 * @param opt Short name of the option. 352 * @return true if set, false if not. 353 */ 354 public boolean hasOption(final String opt) 355 { return hasOption(resolveOption(opt)); } 356 357 /** 358 * Returns an iterator over the Option members of CommandLine. 359 * 360 * @return an {@code Iterator} over the processed {@link Option} members of this 361 * {@link CommandLine}. 362 */ 363 public Iterator<Option> iterator() 364 { return options.iterator(); } 365 366 /** 367 * Retrieves the option object given the long or short option as a String 368 * @param opt short or long name of the option, may be null. 369 * @return Canonicalized option. 370 */ 371 private Option resolveOption(final String opt) 372 { 373 final String actual = Util.stripLeadingHyphens(opt); 374 375 if (actual != null) 376 for (final Option option : options) 377 if (actual.equals(option.getOpt()) || actual.equals(option.getLongOpt())) 378 return option; 379 380 return null; 381 } 382}