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    }