    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.Iterator;
    024    import java.util.LinkedList;
    025    import java.util.List;
    026    import java.util.Properties;
    027
    028    /**
    029     * Represents list of arguments parsed against a {@link Options} descriptor.
    030     *
    031     * <p>It allows querying of a boolean {@link #hasOption(String opt)},
    032     * in addition to retrieving the {@link #getOptionValue(String opt)}
    033     * for options requiring arguments.</p>
    034     *
    035     * <p>Additionally, any left-over or unrecognized arguments,
    036     * are available for further processing.</p>
    037     *
    038     * @author bob mcwhirter (bob @ werken.com)
    039     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
    040     * @author John Keyes (john at integralsource.com)
    041     * @version $Revision: 735247 $, $Date: 2009-01-17 00:23:35 -0800 (Sat, 17 Jan 2009) $
    042     */
    043    public class CommandLine implements Serializable
    044    {
    045        private static final long serialVersionUID = 1L;
    046
    047        /** the unrecognised options/arguments */
    048        private List args = new LinkedList();
    049
    050        /** the processed options */
    051        private List options = new ArrayList();
    052
    053        /**
    054         * Creates a command line.
    055         */
    056        CommandLine()
    057        {
    058            // nothing to do
    059        }
    060
    061        /**
    062         * Query to see if an option has been set.
    063         *
    064         * @param opt Short name of the option
    065         * @return true if set, false if not
    066         */
    067        public boolean hasOption(String opt)
    068        {
    069            return options.contains(resolveOption(opt));
    070        }
    071
    072        /**
    073         * Query to see if an option has been set.
    074         *
    075         * @param opt character name of the option
    076         * @return true if set, false if not
    077         */
    078        public boolean hasOption(char opt)
    079        {
    080            return hasOption(String.valueOf(opt));
    081        }
    082
    083        /**
    084         * Return the <code>Object</code> type of this <code>Option</code>.
    085         *
    086         * @param opt the name of the option
    087         * @return the type of this <code>Option</code>
    088         * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
    089         */
    090        public Object getOptionObject(String opt)
    091        {
    092            try {
    093                return getParsedOptionValue(opt);
    094            } catch(ParseException pe) {
    095                System.err.println("Exception found converting " + opt + " to desired type: " +
    096                    pe.getMessage() );
    097                return null;
    098            }
    099        }
    100
    101        /**
    102         * Return a version of this <code>Option</code> converted to a particular type.
    103         *
    104         * @param opt the name of the option
    105         * @return the value parsed into a particluar object
    106         * @throws ParseException if there are problems turning the option value into the desired type
    107         * @see PatternOptionBuilder
    108         */
    109        public Object getParsedOptionValue(String opt)
    110        throws ParseException
    111        {
    112            String res = getOptionValue(opt);
    113
    114            Option option = resolveOption(opt);
    115            if (option == null)
    116            {
    117                return null;
    118            }
    119
    120            Object type = option.getType();
    121
    122            return (res == null)        ? null : TypeHandler.createValue(res, type);
    123        }
    124
    125        /**
    126         * Return the <code>Object</code> type of this <code>Option</code>.
    127         *
    128         * @param opt the name of the option
    129         * @return the type of opt
    130         */
    131        public Object getOptionObject(char opt)
    132        {
    133            return getOptionObject(String.valueOf(opt));
    134        }
    135
    136        /**
    137         * Retrieve the argument, if any, of this option.
    138         *
    139         * @param opt the name of the option
    140         * @return Value of the argument if option is set, and has an argument,
    141         * otherwise null.
    142         */
    143        public String getOptionValue(String opt)
    144        {
    145            String[] values = getOptionValues(opt);
    146
    147            return (values == null) ? null : values[0];
    148        }
    149
    150        /**
    151         * Retrieve the argument, if any, of this option.
    152         *
    153         * @param opt the character name of the option
    154         * @return Value of the argument if option is set, and has an argument,
    155         * otherwise null.
    156         */
    157        public String getOptionValue(char opt)
    158        {
    159            return getOptionValue(String.valueOf(opt));
    160        }
    161
    162        /**
    163         * Retrieves the array of values, if any, of an option.
    164         *
    165         * @param opt string name of the option
    166         * @return Values of the argument if option is set, and has an argument,
    167         * otherwise null.
    168         */
    169        public String[] getOptionValues(String opt)
    170        {
    171            List values = new ArrayList();
    172
    173            for (Iterator it = options.iterator(); it.hasNext();)
    174            {
    175                Option option = (Option) it.next();
    176                if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
    177                {
    178                    values.addAll(option.getValuesList());
    179                }
    180            }
    181
    182            return values.isEmpty() ? null : (String[]) values.toArray(new String[values.size()]);
    183        }
    184
    185        /**
    186         * Retrieves the option object given the long or short option as a String
    187         *
    188         * @param opt short or long name of the option
    189         * @return Canonicalized option
    190         */
    191        private Option resolveOption(String opt)
    192        {
    193            opt = Util.stripLeadingHyphens(opt);
    194            for (Iterator it = options.iterator(); it.hasNext();)
    195            {
    196                Option option = (Option) it.next();
    197                if (opt.equals(option.getOpt()))
    198                {
    199                    return option;
    200                }
    201
    202                if (opt.equals(option.getLongOpt()))
    203                {
    204                    return option;
    205                }
    206
    207            }
    208            return null;
    209        }
    210
    211        /**
    212         * Retrieves the array of values, if any, of an option.
    213         *
    214         * @param opt character name of the option
    215         * @return Values of the argument if option is set, and has an argument,
    216         * otherwise null.
    217         */
    218        public String[] getOptionValues(char opt)
    219        {
    220            return getOptionValues(String.valueOf(opt));
    221        }
    222
    223        /**
    224         * Retrieve the argument, if any, of an option.
    225         *
    226         * @param opt name of the option
    227         * @param defaultValue is the default value to be returned if the option
    228         * is not specified
    229         * @return Value of the argument if option is set, and has an argument,
    230         * otherwise <code>defaultValue</code>.
    231         */
    232        public String getOptionValue(String opt, String defaultValue)
    233        {
    234            String answer = getOptionValue(opt);
    235
    236            return (answer != null) ? answer : defaultValue;
    237        }
    238
    239        /**
    240         * Retrieve the argument, if any, of an option.
    241         *
    242         * @param opt character name of the option
    243         * @param defaultValue is the default value to be returned if the option
    244         * is not specified
    245         * @return Value of the argument if option is set, and has an argument,
    246         * otherwise <code>defaultValue</code>.
    247         */
    248        public String getOptionValue(char opt, String defaultValue)
    249        {
    250            return getOptionValue(String.valueOf(opt), defaultValue);
    251        }
    252
    253        /**
    254         * Retrieve the map of values associated to the option. This is convenient
    255         * for options specifying Java properties like <tt>-Dparam1=value1
    256         * -Dparam2=value2</tt>. The first argument of the option is the key, and
    257         * the 2nd argument is the value. If the option has only one argument
    258         * (<tt>-Dfoo</tt>) it is considered as a boolean flag and the value is
    259         * <tt>"true"</tt>.
    260         *
    261         * @param opt name of the option
    262         * @return The Properties mapped by the option, never <tt>null</tt>
    263         *         even if the option doesn't exists
    264         * @since 1.2
    265         */
    266        public Properties getOptionProperties(String opt)
    267        {
    268            Properties props = new Properties();
    269
    270            for (Iterator it = options.iterator(); it.hasNext();)
    271            {
    272                Option option = (Option) it.next();
    273
    274                if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
    275                {
    276                    List values = option.getValuesList();
    277                    if (values.size() >= 2)
    278                    {
    279                        // use the first 2 arguments as the key/value pair
    280                        props.put(values.get(0), values.get(1));
    281                    }
    282                    else if (values.size() == 1)
    283                    {
    284                        // no explicit value, handle it as a boolean
    285                        props.put(values.get(0), "true");
    286                    }
    287                }
    288            }
    289
    290            return props;
    291        }
    292
    293        /**
    294         * Retrieve any left-over non-recognized options and arguments
    295         *
    296         * @return remaining items passed in but not parsed as an array
    297         */
    298        public String[] getArgs()
    299        {
    300            String[] answer = new String[args.size()];
    301
    302            args.toArray(answer);
    303
    304            return answer;
    305        }
    306
    307        /**
    308         * Retrieve any left-over non-recognized options and arguments
    309         *
    310         * @return remaining items passed in but not parsed as a <code>List</code>.
    311         */
    312        public List getArgList()
    313        {
    314            return args;
    315        }
    316
    317        /**
    318         * jkeyes
    319         * - commented out until it is implemented properly
    320         * <p>Dump state, suitable for debugging.</p>
    321         *
    322         * @return Stringified form of this object
    323         */
    324
    325        /*
    326        public String toString() {
    327            StringBuffer buf = new StringBuffer();
    328
    329            buf.append("[ CommandLine: [ options: ");
    330            buf.append(options.toString());
    331            buf.append(" ] [ args: ");
    332            buf.append(args.toString());
    333            buf.append(" ] ]");
    334
    335            return buf.toString();
    336        }
    337        */
    338
    339        /**
    340         * Add left-over unrecognized option/argument.
    341         *
    342         * @param arg the unrecognised option/argument.
    343         */
    344        void addArg(String arg)
    345        {
    346            args.add(arg);
    347        }
    348
    349        /**
    350         * Add an option to the command line.  The values of the option are stored.
    351         *
    352         * @param opt the processed option
    353         */
    354        void addOption(Option opt)
    355        {
    356            options.add(opt);
    357        }
    358
    359        /**
    360         * Returns an iterator over the Option members of CommandLine.
    361         *
    362         * @return an <code>Iterator</code> over the processed {@link Option}
    363         * members of this {@link CommandLine}
    364         */
    365        public Iterator iterator()
    366        {
    367            return options.iterator();
    368        }
    369
    370        /**
    371         * Returns an array of the processed {@link Option}s.
    372         *
    373         * @return an array of the processed {@link Option}s.
    374         */
    375        public Option[] getOptions()
    376        {
    377            Collection processed = options;
    378
    379            // reinitialise array
    380            Option[] optionsArray = new Option[processed.size()];
    381
    382            // return the array
    383            return (Option[]) processed.toArray(optionsArray);
    384        }
    385    }