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    }