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.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  /**
31   * <p>Main entry-point into the library.</p>
32   *
33   * <p>Options represents a collection of {@link Option} objects, which
34   * describe the possible options for a command-line.<p>
35   *
36   * <p>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.<p>
39   *
40   * @see org.apache.commons.cli.CommandLine
41   *
42   * @author bob mcwhirter (bob @ werken.com)
43   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
44   * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
45   */
46  public class Options implements Serializable
47  {
48      private static final long serialVersionUID = 1L;
49  
50      /** a map of the options with the character key */
51      private Map shortOpts = new HashMap();
52  
53      /** a map of the options with the long key */
54      private Map longOpts = new HashMap();
55  
56      /** a map of the required options */
57      private List requiredOpts = new ArrayList();
58  
59      /** a map of the option groups */
60      private Map optionGroups = new HashMap();
61  
62      /**
63       * Add the specified option group.
64       *
65       * @param group the OptionGroup that is to be added
66       * @return the resulting Options instance
67       */
68      public Options addOptionGroup(OptionGroup group)
69      {
70          Iterator options = group.getOptions().iterator();
71  
72          if (group.isRequired())
73          {
74              requiredOpts.add(group);
75          }
76  
77          while (options.hasNext())
78          {
79              Option option = (Option) options.next();
80  
81              // an Option cannot be required if it is in an
82              // OptionGroup, either the group is required or
83              // nothing is required
84              option.setRequired(false);
85              addOption(option);
86  
87              optionGroups.put(option.getKey(), group);
88          }
89  
90          return this;
91      }
92  
93      /**
94       * Lists the OptionGroups that are members of this Options instance.
95       *
96       * @return a Collection of OptionGroup instances.
97       */
98      Collection getOptionGroups()
99      {
100         return new HashSet(optionGroups.values());
101     }
102 
103     /**
104      * Add an option that only contains a short-name.
105      * It may be specified as requiring an argument.
106      *
107      * @param opt Short single-character name of the option.
108      * @param hasArg flag signally if an argument is required after this option
109      * @param description Self-documenting description
110      * @return the resulting Options instance
111      */
112     public Options addOption(String opt, boolean hasArg, String description)
113     {
114         addOption(opt, null, hasArg, description);
115 
116         return this;
117     }
118 
119     /**
120      * Add an option that contains a short-name and a long-name.
121      * It may be specified as requiring an argument.
122      *
123      * @param opt Short single-character name of the option.
124      * @param longOpt Long multi-character name of the option.
125      * @param hasArg flag signally if an argument is required after this option
126      * @param description Self-documenting description
127      * @return the resulting Options instance
128      */
129     public Options addOption(String opt, String longOpt, boolean hasArg, String description)
130     {
131         addOption(new Option(opt, longOpt, hasArg, description));
132 
133         return this;
134     }
135 
136     /**
137      * Adds an option instance
138      *
139      * @param opt the option that is to be added
140      * @return the resulting Options instance
141      */
142     public Options addOption(Option opt)
143     {
144         String key = opt.getKey();
145 
146         // add it to the long option list
147         if (opt.hasLongOpt())
148         {
149             longOpts.put(opt.getLongOpt(), opt);
150         }
151 
152         // if the option is required add it to the required list
153         if (opt.isRequired())
154         {
155             if (requiredOpts.contains(key))
156             {
157                 requiredOpts.remove(requiredOpts.indexOf(key));
158             }
159             requiredOpts.add(key);
160         }
161 
162         shortOpts.put(key, opt);
163 
164         return this;
165     }
166 
167     /**
168      * Retrieve a read-only list of options in this set
169      *
170      * @return read-only Collection of {@link Option} objects in this descriptor
171      */
172     public Collection getOptions()
173     {
174         return Collections.unmodifiableCollection(helpOptions());
175     }
176 
177     /**
178      * Returns the Options for use by the HelpFormatter.
179      *
180      * @return the List of Options
181      */
182     List helpOptions()
183     {
184         return new ArrayList(shortOpts.values());
185     }
186 
187     /**
188      * Returns the required options.
189      *
190      * @return List of required options
191      */
192     public List getRequiredOptions()
193     {
194         return requiredOpts;
195     }
196 
197     /**
198      * Retrieve the {@link Option} matching the long or short name specified.
199      * The leading hyphens in the name are ignored (up to 2).
200      *
201      * @param opt short or long name of the {@link Option}
202      * @return the option represented by opt
203      */
204     public Option getOption(String opt)
205     {
206         opt = Util.stripLeadingHyphens(opt);
207 
208         if (shortOpts.containsKey(opt))
209         {
210             return (Option) shortOpts.get(opt);
211         }
212 
213         return (Option) longOpts.get(opt);
214     }
215 
216     /**
217      * Returns whether the named {@link Option} is a member of this {@link Options}.
218      *
219      * @param opt short or long name of the {@link Option}
220      * @return true if the named {@link Option} is a member
221      * of this {@link Options}
222      */
223     public boolean hasOption(String opt)
224     {
225         opt = Util.stripLeadingHyphens(opt);
226 
227         return shortOpts.containsKey(opt) || longOpts.containsKey(opt);
228     }
229 
230     /**
231      * Returns the OptionGroup the <code>opt</code> belongs to.
232      * @param opt the option whose OptionGroup is being queried.
233      *
234      * @return the OptionGroup if <code>opt</code> is part
235      * of an OptionGroup, otherwise return null
236      */
237     public OptionGroup getOptionGroup(Option opt)
238     {
239         return (OptionGroup) optionGroups.get(opt.getKey());
240     }
241 
242     /**
243      * Dump state, suitable for debugging.
244      *
245      * @return Stringified form of this object
246      */
247     public String toString()
248     {
249         StringBuffer buf = new StringBuffer();
250 
251         buf.append("[ Options: [ short ");
252         buf.append(shortOpts.toString());
253         buf.append(" ] [ long ");
254         buf.append(longOpts);
255         buf.append(" ]");
256 
257         return buf.toString();
258     }
259 }
260