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  import java.io.Serializable;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Properties;
27  
28  /**
29   * Represents list of arguments parsed against a {@link Options} descriptor.
30   * <p>
31   * It allows querying of a boolean {@link #hasOption(String opt)},
32   * in addition to retrieving the {@link #getOptionValue(String opt)}
33   * for options requiring arguments.
34   * <p>
35   * Additionally, any left-over or unrecognized arguments,
36   * are available for further processing.
37   *
38   * @version $Id$
39   */
40  public class CommandLine implements Serializable
41  {
42      /** The serial version UID. */
43      private static final long serialVersionUID = 1L;
44  
45      /** the unrecognized options/arguments */
46      private final List<String> args = new LinkedList<String>();
47  
48      /** the processed options */
49      private final List<Option> options = new ArrayList<Option>();
50  
51      /**
52       * Creates a command line.
53       */
54      protected CommandLine()
55      {
56          // nothing to do
57      }
58      
59      /** 
60       * Query to see if an option has been set.
61       *
62       * @param opt the option to check
63       * @return true if set, false if not
64       * @since 1.5
65       */
66      public boolean hasOption(final Option opt)
67      {
68          return options.contains(opt);
69      }
70  
71      /** 
72       * Query to see if an option has been set.
73       *
74       * @param opt Short name of the option
75       * @return true if set, false if not
76       */
77      public boolean hasOption(final String opt)
78      {
79          return hasOption(resolveOption(opt));
80      }
81      
82      /** 
83       * Query to see if an option has been set.
84       *
85       * @param opt character name of the option
86       * @return true if set, false if not
87       */
88      public boolean hasOption(final char opt)
89      {
90          return hasOption(String.valueOf(opt));
91      }
92  
93      /**
94       * Return the <code>Object</code> type of this <code>Option</code>.
95       *
96       * @param opt the name of the option
97       * @return the type of this <code>Option</code>
98       * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
99       */
100     @Deprecated
101     public Object getOptionObject(final String opt)
102     {
103         try
104         {
105             return getParsedOptionValue(opt);
106         }
107         catch (final ParseException pe)
108         {
109             System.err.println("Exception found converting " + opt + " to desired type: " + pe.getMessage());
110             return null;
111         }
112     }
113     
114     /**
115      * Return a version of this <code>Option</code> converted to a particular type. 
116      *
117      * @param option the name of the option
118      * @return the value parsed into a particular object
119      * @throws ParseException if there are problems turning the option value into the desired type
120      * @see PatternOptionBuilder
121      * @since 1.5
122      */
123     public Object getParsedOptionValue(final Option option) throws ParseException
124     {
125         if (option == null)
126         {
127             return null;
128         }
129         final String res = getOptionValue(option);
130         if (res == null)
131         {
132             return null;
133         }
134         return TypeHandler.createValue(res, option.getType());
135     }
136 
137     /**
138      * Return a version of this <code>Option</code> converted to a particular type. 
139      *
140      * @param opt the name of the option
141      * @return the value parsed into a particular object
142      * @throws ParseException if there are problems turning the option value into the desired type
143      * @see PatternOptionBuilder
144      * @since 1.2
145      */
146     public Object getParsedOptionValue(final String opt) throws ParseException
147     {
148         return getParsedOptionValue(resolveOption(opt));
149     }
150     
151     /**
152      * Return a version of this <code>Option</code> converted to a particular type. 
153      *
154      * @param opt the name of the option
155      * @return the value parsed into a particular object
156      * @throws ParseException if there are problems turning the option value into the desired type
157      * @see PatternOptionBuilder
158      * @since 1.5
159      */
160     public Object getParsedOptionValue(final char opt) throws ParseException
161     {
162         return getParsedOptionValue(String.valueOf(opt));
163     }
164 
165     /**
166      * Return the <code>Object</code> type of this <code>Option</code>.
167      *
168      * @deprecated due to System.err message. Instead use getParsedOptionValue(char)
169      * @param opt the name of the option
170      * @return the type of opt
171      */
172     public Object getOptionObject(final char opt)
173     {
174         return getOptionObject(String.valueOf(opt));
175     }
176     
177     /** 
178      * Retrieve the first argument, if any, of this option.
179      *
180      * @param option the name of the option
181      * @return Value of the argument if option is set, and has an argument,
182      * otherwise null.
183      * @since 1.5
184      */
185     public String getOptionValue(final Option option)
186     {
187         if (option == null)
188         {
189             return null;
190         }
191         final String[] values = getOptionValues(option);
192         return (values == null) ? null : values[0];
193     }
194 
195     /** 
196      * Retrieve the first argument, if any, of this option.
197      *
198      * @param opt the name of the option
199      * @return Value of the argument if option is set, and has an argument,
200      * otherwise null.
201      */
202     public String getOptionValue(final String opt)
203     {
204         return getOptionValue(resolveOption(opt));
205     }
206 
207     /** 
208      * Retrieve the first argument, if any, of this option.
209      *
210      * @param opt the character name of the option
211      * @return Value of the argument if option is set, and has an argument,
212      * otherwise null.
213      */
214     public String getOptionValue(final char opt)
215     {
216         return getOptionValue(String.valueOf(opt));
217     }
218     
219     /** 
220      * Retrieves the array of values, if any, of an option.
221      *
222      * @param option string name of the option
223      * @return Values of the argument if option is set, and has an argument,
224      * otherwise null.
225      * @since 1.5
226      */
227     public String[] getOptionValues(final Option option)
228     {
229         final List<String> values = new ArrayList<String>();
230 
231         for (final Option processedOption : options)
232         {
233             if (processedOption.equals(option))
234             {
235                 values.addAll(processedOption.getValuesList());
236             }
237         }
238 
239         return values.isEmpty() ? null : values.toArray(new String[values.size()]);
240     }
241 
242     /** 
243      * Retrieves the array of values, if any, of an option.
244      *
245      * @param opt string name of the option
246      * @return Values of the argument if option is set, and has an argument,
247      * otherwise null.
248      */
249     public String[] getOptionValues(final String opt)
250     {
251         return getOptionValues(resolveOption(opt));
252     }
253 
254     /**
255      * Retrieves the option object given the long or short option as a String
256      * 
257      * @param opt short or long name of the option
258      * @return Canonicalized option
259      */
260     private Option resolveOption(String opt)
261     {
262         opt = Util.stripLeadingHyphens(opt);
263         for (final Option option : options)
264         {
265             if (opt.equals(option.getOpt()))
266             {
267                 return option;
268             }
269 
270             if (opt.equals(option.getLongOpt()))
271             {
272                 return option;
273             }
274 
275         }
276         return null;
277     }
278 
279     /** 
280      * Retrieves the array of values, if any, of an option.
281      *
282      * @param opt character name of the option
283      * @return Values of the argument if option is set, and has an argument,
284      * otherwise null.
285      */
286     public String[] getOptionValues(final char opt)
287     {
288         return getOptionValues(String.valueOf(opt));
289     }
290     
291     /** 
292      * Retrieve the first argument, if any, of an option.
293      *
294      * @param option name of the option
295      * @param defaultValue is the default value to be returned if the option
296      * is not specified
297      * @return Value of the argument if option is set, and has an argument,
298      * otherwise <code>defaultValue</code>.
299      * @since 1.5
300      */
301     public String getOptionValue(final Option option, final String defaultValue)
302     {
303         final String answer = getOptionValue(option);
304         return (answer != null) ? answer : defaultValue;
305     }
306 
307     /** 
308      * Retrieve the first argument, if any, of an option.
309      *
310      * @param opt name of the option
311      * @param defaultValue is the default value to be returned if the option
312      * is not specified
313      * @return Value of the argument if option is set, and has an argument,
314      * otherwise <code>defaultValue</code>.
315      */
316     public String getOptionValue(final String opt, final String defaultValue)
317     {
318         return getOptionValue(resolveOption(opt), defaultValue);
319     }
320 
321     /** 
322      * Retrieve the argument, if any, of an option.
323      *
324      * @param opt character name of the option
325      * @param defaultValue is the default value to be returned if the option
326      * is not specified
327      * @return Value of the argument if option is set, and has an argument,
328      * otherwise <code>defaultValue</code>.
329      */
330     public String getOptionValue(final char opt, final String defaultValue)
331     {
332         return getOptionValue(String.valueOf(opt), defaultValue);
333     }
334     
335     /**
336      * Retrieve the map of values associated to the option. This is convenient
337      * for options specifying Java properties like <tt>-Dparam1=value1
338      * -Dparam2=value2</tt>. The first argument of the option is the key, and
339      * the 2nd argument is the value. If the option has only one argument
340      * (<tt>-Dfoo</tt>) it is considered as a boolean flag and the value is
341      * <tt>"true"</tt>.
342      *
343      * @param option name of the option
344      * @return The Properties mapped by the option, never <tt>null</tt>
345      *         even if the option doesn't exists
346      * @since 1.5
347      */
348     public Properties getOptionProperties(final Option option)
349     {
350         final Properties props = new Properties();
351 
352         for (final Option processedOption : options)
353         {
354             if (processedOption.equals(option))
355             {
356                 final List<String> values = processedOption.getValuesList();
357                 if (values.size() >= 2)
358                 {
359                     // use the first 2 arguments as the key/value pair
360                     props.put(values.get(0), values.get(1));
361                 }
362                 else if (values.size() == 1)
363                 {
364                     // no explicit value, handle it as a boolean
365                     props.put(values.get(0), "true");
366                 }
367             }
368         }
369 
370         return props;
371     }
372 
373     /**
374      * Retrieve the map of values associated to the option. This is convenient
375      * for options specifying Java properties like <tt>-Dparam1=value1
376      * -Dparam2=value2</tt>. The first argument of the option is the key, and
377      * the 2nd argument is the value. If the option has only one argument
378      * (<tt>-Dfoo</tt>) it is considered as a boolean flag and the value is
379      * <tt>"true"</tt>.
380      *
381      * @param opt name of the option
382      * @return The Properties mapped by the option, never <tt>null</tt>
383      *         even if the option doesn't exists
384      * @since 1.2
385      */
386     public Properties getOptionProperties(final String opt)
387     {
388         final Properties props = new Properties();
389 
390         for (final Option option : options)
391         {
392             if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
393             {
394                 final List<String> values = option.getValuesList();
395                 if (values.size() >= 2)
396                 {
397                     // use the first 2 arguments as the key/value pair
398                     props.put(values.get(0), values.get(1));
399                 }
400                 else if (values.size() == 1)
401                 {
402                     // no explicit value, handle it as a boolean
403                     props.put(values.get(0), "true");
404                 }
405             }
406         }
407 
408         return props;
409     }
410 
411     /** 
412      * Retrieve any left-over non-recognized options and arguments
413      *
414      * @return remaining items passed in but not parsed as an array
415      */
416     public String[] getArgs()
417     {
418         final String[] answer = new String[args.size()];
419 
420         args.toArray(answer);
421 
422         return answer;
423     }
424 
425     /** 
426      * Retrieve any left-over non-recognized options and arguments
427      *
428      * @return remaining items passed in but not parsed as a <code>List</code>.
429      */
430     public List<String> getArgList()
431     {
432         return args;
433     }
434 
435     /** 
436      * jkeyes
437      * - commented out until it is implemented properly
438      * <p>Dump state, suitable for debugging.</p>
439      *
440      * @return Stringified form of this object
441      */
442 
443     /*
444     public String toString() {
445         StringBuilder buf = new StringBuilder();
446             
447         buf.append("[ CommandLine: [ options: ");
448         buf.append(options.toString());
449         buf.append(" ] [ args: ");
450         buf.append(args.toString());
451         buf.append(" ] ]");
452             
453         return buf.toString();
454     }
455     */
456 
457     /**
458      * Add left-over unrecognized option/argument.
459      *
460      * @param arg the unrecognized option/argument.
461      */
462     protected void addArg(final String arg)
463     {
464         args.add(arg);
465     }
466 
467     /**
468      * Add an option to the command line.  The values of the option are stored.
469      *
470      * @param opt the processed option
471      */
472     protected void addOption(final Option opt)
473     {
474         options.add(opt);
475     }
476 
477     /**
478      * Returns an iterator over the Option members of CommandLine.
479      *
480      * @return an <code>Iterator</code> over the processed {@link Option}
481      * members of this {@link CommandLine}
482      */
483     public Iterator<Option> iterator()
484     {
485         return options.iterator();
486     }
487 
488     /**
489      * Returns an array of the processed {@link Option}s.
490      *
491      * @return an array of the processed {@link Option}s.
492      */
493     public Option[] getOptions()
494     {
495         final Collection<Option> processed = options;
496 
497         // reinitialise array
498         final Option[] optionsArray = new Option[processed.size()];
499 
500         // return the array
501         return processed.toArray(optionsArray);
502     }
503 
504     /**
505      * A nested builder class to create <code>CommandLine</code> instance
506      * using descriptive methods.
507      * 
508      * @since 1.4
509      */
510     public static final class Builder
511     {
512         /**
513          * CommandLine that is being build by this Builder.
514          */
515         private final CommandLine commandLine = new CommandLine();
516 
517         /**
518          * Add an option to the command line. The values of the option are stored.
519          *
520          * @param opt the processed option
521          *
522          * @return this Builder instance for method chaining.
523          */
524         public Builder addOption(final Option opt)
525         {
526             commandLine.addOption(opt);
527             return this;
528         }
529 
530         /**
531          * Add left-over unrecognized option/argument.
532          *
533          * @param arg the unrecognized option/argument.
534          *
535          * @return this Builder instance for method chaining.
536          */
537         public Builder addArg(final String arg)
538         {
539             commandLine.addArg(arg);
540             return this;
541         }
542 
543         public CommandLine build()
544         {
545             return commandLine;
546         }
547     }
548 }