    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    }