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 }