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.Collections;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  /**
31   * Main entry-point into the library.
32   * <p>
33   * Options represents a collection of {@link Option} objects, which
34   * describe the possible options for a command-line.
35   * <p>
36   * It may flexibly parse long and short options, with or without
37   * values.  Additionally, it may parse only a portion of a commandline,
38   * allowing for flexible multi-stage parsing.
39   *
40   * @see org.apache.commons.cli.CommandLine
41   *
42   * @version $Id: Options.java 1444940 2013-02-11 19:52:22Z tn $
43   */
44  public class Options implements Serializable
45  {
46      /** The serial version UID. */
47      private static final long serialVersionUID = 1L;
48  
49      /** a map of the options with the character key */
50      private Map<String, Option> shortOpts = new LinkedHashMap<String, Option>();
51  
52      /** a map of the options with the long key */
53      private Map<String, Option> longOpts = new LinkedHashMap<String, Option>();
54  
55      /** a map of the required options */
56      // N.B. This can contain either a String (addOption) or an OptionGroup (addOptionGroup)
57      // TODO this seems wrong
58      private List<Object> requiredOpts = new ArrayList<Object>();
59  
60      /** a map of the option groups */
61      private Map<String, OptionGroup> optionGroups = new HashMap<String, OptionGroup>();
62  
63      /**
64       * Add the specified option group.
65       *
66       * @param group the OptionGroup that is to be added
67       * @return the resulting Options instance
68       */
69      public Options addOptionGroup(OptionGroup group)
70      {
71          if (group.isRequired())
72          {
73              requiredOpts.add(group);
74          }
75  
76          for (Option option : group.getOptions())
77          {
78              // an Option cannot be required if it is in an
79              // OptionGroup, either the group is required or
80              // nothing is required
81              option.setRequired(false);
82              addOption(option);
83  
84              optionGroups.put(option.getKey(), group);
85          }
86  
87          return this;
88      }
89  
90      /**
91       * Lists the OptionGroups that are members of this Options instance.
92       *
93       * @return a Collection of OptionGroup instances.
94       */
95      Collection<OptionGroup> getOptionGroups()
96      {
97          return new HashSet<OptionGroup>(optionGroups.values());
98      }
99  
100     /**
101      * Add an option that only contains a short name.
102      * The option does not take an argument.
103      *
104      * @param opt Short single-character name of the option.
105      * @param description Self-documenting description
106      * @return the resulting Options instance
107      * @since 1.3
108      */
109     public Options addOption(String opt, String description)
110     {
111         addOption(opt, null, false, description);
112         return this;
113     }
114 
115     /**
116      * Add an option that only contains a short-name.
117      * It may be specified as requiring an argument.
118      *
119      * @param opt Short single-character name of the option.
120      * @param hasArg flag signally if an argument is required after this option
121      * @param description Self-documenting description
122      * @return the resulting Options instance
123      */
124     public Options addOption(String opt, boolean hasArg, String description)
125     {
126         addOption(opt, null, hasArg, description);
127         return this;
128     }
129 
130     /**
131      * Add an option that contains a short-name and a long-name.
132      * It may be specified as requiring an argument.
133      *
134      * @param opt Short single-character name of the option.
135      * @param longOpt Long multi-character name of the option.
136      * @param hasArg flag signally if an argument is required after this option
137      * @param description Self-documenting description
138      * @return the resulting Options instance
139      */
140     public Options addOption(String opt, String longOpt, boolean hasArg, String description)
141     {
142         addOption(new Option(opt, longOpt, hasArg, description));
143         return this;
144     }
145 
146     /**
147      * Adds an option instance
148      *
149      * @param opt the option that is to be added
150      * @return the resulting Options instance
151      */
152     public Options addOption(Option opt)
153     {
154         String key = opt.getKey();
155 
156         // add it to the long option list
157         if (opt.hasLongOpt())
158         {
159             longOpts.put(opt.getLongOpt(), opt);
160         }
161 
162         // if the option is required add it to the required list
163         if (opt.isRequired())
164         {
165             if (requiredOpts.contains(key))
166             {
167                 requiredOpts.remove(requiredOpts.indexOf(key));
168             }
169             requiredOpts.add(key);
170         }
171 
172         shortOpts.put(key, opt);
173 
174         return this;
175     }
176 
177     /**
178      * Retrieve a read-only list of options in this set
179      *
180      * @return read-only Collection of {@link Option} objects in this descriptor
181      */
182     public Collection<Option> getOptions()
183     {
184         return Collections.unmodifiableCollection(helpOptions());
185     }
186 
187     /**
188      * Returns the Options for use by the HelpFormatter.
189      *
190      * @return the List of Options
191      */
192     List<Option> helpOptions()
193     {
194         return new ArrayList<Option>(shortOpts.values());
195     }
196 
197     /**
198      * Returns the required options.
199      *
200      * @return read-only List of required options
201      */
202     public List getRequiredOptions()
203     {
204         return Collections.unmodifiableList(requiredOpts);
205     }
206 
207     /**
208      * Retrieve the {@link Option} matching the long or short name specified.
209      * The leading hyphens in the name are ignored (up to 2).
210      *
211      * @param opt short or long name of the {@link Option}
212      * @return the option represented by opt
213      */
214     public Option getOption(String opt)
215     {
216         opt = Util.stripLeadingHyphens(opt);
217 
218         if (shortOpts.containsKey(opt))
219         {
220             return shortOpts.get(opt);
221         }
222 
223         return longOpts.get(opt);
224     }
225 
226     /**
227      * Returns the options with a long name starting with the name specified.
228      * 
229      * @param opt the partial name of the option
230      * @return the options matching the partial name specified, or an empty list if none matches
231      * @since 1.3
232      */
233     public List<String> getMatchingOptions(String opt)
234     {
235         opt = Util.stripLeadingHyphens(opt);
236         
237         List<String> matchingOpts = new ArrayList<String>();
238         
239         for (String longOpt : longOpts.keySet())
240         {
241             if (longOpt.startsWith(opt))
242             {
243                 matchingOpts.add(longOpt);
244             }
245         }
246         
247         return matchingOpts;
248     }
249 
250     /**
251      * Returns whether the named {@link Option} is a member of this {@link Options}.
252      *
253      * @param opt short or long name of the {@link Option}
254      * @return true if the named {@link Option} is a member of this {@link Options}
255      */
256     public boolean hasOption(String opt)
257     {
258         opt = Util.stripLeadingHyphens(opt);
259 
260         return shortOpts.containsKey(opt) || longOpts.containsKey(opt);
261     }
262 
263     /**
264      * Returns whether the named {@link Option} is a member of this {@link Options}.
265      *
266      * @param opt long name of the {@link Option}
267      * @return true if the named {@link Option} is a member of this {@link Options}
268      * @since 1.3
269      */
270     public boolean hasLongOption(String opt)
271     {
272         opt = Util.stripLeadingHyphens(opt);
273 
274         return longOpts.containsKey(opt);
275     }
276 
277     /**
278      * Returns whether the named {@link Option} is a member of this {@link Options}.
279      *
280      * @param opt short name of the {@link Option}
281      * @return true if the named {@link Option} is a member of this {@link Options}
282      * @since 1.3
283      */
284     public boolean hasShortOption(String opt)
285     {
286         opt = Util.stripLeadingHyphens(opt);
287 
288         return shortOpts.containsKey(opt);
289     }
290 
291     /**
292      * Returns the OptionGroup the <code>opt</code> belongs to.
293      * @param opt the option whose OptionGroup is being queried.
294      *
295      * @return the OptionGroup if <code>opt</code> is part
296      * of an OptionGroup, otherwise return null
297      */
298     public OptionGroup getOptionGroup(Option opt)
299     {
300         return optionGroups.get(opt.getKey());
301     }
302 
303     /**
304      * Dump state, suitable for debugging.
305      *
306      * @return Stringified form of this object
307      */
308     @Override
309     public String toString()
310     {
311         StringBuilder buf = new StringBuilder();
312 
313         buf.append("[ Options: [ short ");
314         buf.append(shortOpts.toString());
315         buf.append(" ] [ long ");
316         buf.append(longOpts);
317         buf.append(" ]");
318 
319         return buf.toString();
320     }
321 }