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
018package org.apache.commons.cli;
019
020import java.io.Serializable;
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.HashSet;
026import java.util.Iterator;
027import java.util.List;
028import 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 */
046public 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}