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 */
017
018 package org.apache.commons.cli;
019
020 import java.io.Serializable;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.Collections;
024 import java.util.HashMap;
025 import java.util.HashSet;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Map;
029
030 /**
031 * <p>Main entry-point into the library.</p>
032 *
033 * <p>Options represents a collection of {@link Option} objects, which
034 * describe the possible options for a command-line.<p>
035 *
036 * <p>It may flexibly parse long and short options, with or without
037 * values. Additionally, it may parse only a portion of a commandline,
038 * allowing for flexible multi-stage parsing.<p>
039 *
040 * @see org.apache.commons.cli.CommandLine
041 *
042 * @author bob mcwhirter (bob @ werken.com)
043 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
044 * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
045 */
046 public class Options implements Serializable
047 {
048 private static final long serialVersionUID = 1L;
049
050 /** a map of the options with the character key */
051 private Map shortOpts = new HashMap();
052
053 /** a map of the options with the long key */
054 private Map longOpts = new HashMap();
055
056 /** a map of the required options */
057 private List requiredOpts = new ArrayList();
058
059 /** a map of the option groups */
060 private Map optionGroups = new HashMap();
061
062 /**
063 * Add the specified option group.
064 *
065 * @param group the OptionGroup that is to be added
066 * @return the resulting Options instance
067 */
068 public Options addOptionGroup(OptionGroup group)
069 {
070 Iterator options = group.getOptions().iterator();
071
072 if (group.isRequired())
073 {
074 requiredOpts.add(group);
075 }
076
077 while (options.hasNext())
078 {
079 Option option = (Option) options.next();
080
081 // an Option cannot be required if it is in an
082 // OptionGroup, either the group is required or
083 // nothing is required
084 option.setRequired(false);
085 addOption(option);
086
087 optionGroups.put(option.getKey(), group);
088 }
089
090 return this;
091 }
092
093 /**
094 * Lists the OptionGroups that are members of this Options instance.
095 *
096 * @return a Collection of OptionGroup instances.
097 */
098 Collection getOptionGroups()
099 {
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 }