KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > cli > PosixParser


1 /*
2  * $Header: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/PosixParser.java,v 1.11 2002/09/19 22:59:43 jkeyes Exp $
3  * $Revision: 1.11 $
4  * $Date: 2002/09/19 22:59:43 $
5  *
6  * ====================================================================
7  *
8  * The Apache Software License, Version 1.1
9  *
10  * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
11  * reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. The end-user documentation included with the redistribution, if
26  * any, must include the following acknowlegement:
27  * "This product includes software developed by the
28  * Apache Software Foundation (http://www.apache.org/)."
29  * Alternately, this acknowlegement may appear in the software itself,
30  * if and wherever such third-party acknowlegements normally appear.
31  *
32  * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33  * Foundation" must not be used to endorse or promote products derived
34  * from this software without prior written permission. For written
35  * permission, please contact apache@apache.org.
36  *
37  * 5. Products derived from this software may not be called "Apache"
38  * nor may "Apache" appear in their names without prior written
39  * permission of the Apache Group.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  * ====================================================================
54  *
55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation. For more
57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>.
59  *
60  */

61 package org.apache.commons.cli;
62
63 import java.util.Arrays JavaDoc;
64 import java.util.ArrayList JavaDoc;
65 import java.util.Collection JavaDoc;
66 import java.util.Iterator JavaDoc;
67 import java.util.Map JavaDoc;
68
69 /**
70  * The class PosixParser provides an implementation of the
71  * {@link Parser#flatten(Options,String[],boolean) flatten} method.
72  *
73  * @author John Keyes (john at integralsource.com)
74  * @see Parser
75  * @version $Revision: 1.11 $
76  */

77 public class PosixParser extends Parser {
78
79     /** holder for flattened tokens */
80     private ArrayList JavaDoc tokens = new ArrayList JavaDoc();
81     /** specifies if bursting should continue */
82     private boolean eatTheRest;
83     /** holder for the current option */
84     private Option currentOption;
85     /** the command line Options */
86     private Options options;
87
88     /**
89      * <p>Resets the members to their original state i.e. remove
90      * all of <code>tokens</code> entries, set <code>eatTheRest</code>
91      * to false and set <code>currentOption</code> to null.</p>
92      */

93     private void init() {
94         eatTheRest = false;
95         tokens.clear();
96         currentOption = null;
97     }
98
99     /**
100      * <p>An implementation of {@link Parser}'s abstract
101      * {@link Parser#flatten(Options,String[],boolean) flatten} method.</p>
102      *
103      * <p>The following are the rules used by this flatten method.
104      * <ol>
105      * <li>if <code>stopAtNonOption</code> is <b>true</b> then do not
106      * burst anymore of <code>arguments</code> entries, just add each
107      * successive entry without further processing. Otherwise, ignore
108      * <code>stopAtNonOption</code>.</li>
109      * <li>if the current <code>arguments</code> entry is "<b>--</b>"
110      * just add the entry to the list of processed tokens</li>
111      * <li>if the current <code>arguments</code> entry is "<b>-</b>"
112      * just add the entry to the list of processed tokens</li>
113      * <li>if the current <code>arguments</code> entry is two characters
114      * in length and the first character is "<b>-</b>" then check if this
115      * is a valid {@link Option} id. If it is a valid id, then add the
116      * entry to the list of processed tokens and set the current {@link Option}
117      * member. If it is not a valid id and <code>stopAtNonOption</code>
118      * is true, then the remaining entries are copied to the list of
119      * processed tokens. Otherwise, the current entry is ignored.</li>
120      * <li>if the current <code>arguments</code> entry is more than two
121      * characters in length and the first character is "<b>-</b>" then
122      * we need to burst the entry to determine its constituents. For more
123      * information on the bursting algorithm see
124      * {@link PosixParser#burstToken( String, boolean) burstToken}.</li>
125      * <li>if the current <code>arguments</code> entry is not handled
126      * by any of the previous rules, then the entry is added to the list
127      * of processed tokens.</li>
128      * </ol>
129      * </p>
130      *
131      * @param options The command line {@link Options}
132      * @param arguments The command line arguments to be parsed
133      * @param stopAtNonOption Specifies whether to stop flattening
134      * when an non option is found.
135      * @return The flattened <code>arguments</code> String array.
136      */

137     protected String JavaDoc[] flatten( Options options,
138                                 String JavaDoc[] arguments,
139                                 boolean stopAtNonOption )
140     {
141         init();
142         this.options = options;
143
144         // an iterator for the command line tokens
145
Iterator JavaDoc iter = Arrays.asList( arguments ).iterator();
146         String JavaDoc token = null;
147         
148         // process each command line token
149
while ( iter.hasNext() ) {
150
151             // get the next command line token
152
token = (String JavaDoc) iter.next();
153
154             // handle SPECIAL TOKEN
155
if( token.startsWith( "--" ) ) {
156                 if( token.indexOf( '=' ) != -1 ) {
157                     tokens.add( token.substring( 0, token.indexOf( '=' ) ) );
158                     tokens.add( token.substring( token.indexOf( '=' ) + 1,
159                                                  token.length() ) );
160                 }
161                 else {
162                     tokens.add( token );
163                 }
164             }
165             // single hyphen
166
else if( "-".equals( token ) ) {
167                 processSingleHyphen( token );
168             }
169             else if( token.startsWith( "-" ) ) {
170                 int tokenLength = token.length();
171                 if( tokenLength == 2 ) {
172                     processOptionToken( token, stopAtNonOption );
173                 }
174                 // requires bursting
175
else {
176                     burstToken( token, stopAtNonOption );
177                 }
178             }
179             else {
180                 if( stopAtNonOption ) {
181                     process( token );
182                 }
183                 else {
184                     tokens.add( token );
185                 }
186             }
187
188             gobble( iter );
189         }
190
191         return (String JavaDoc[])tokens.toArray( new String JavaDoc[] {} );
192     }
193
194     /**
195      * <p>Adds the remaining tokens to the processed tokens list.</p>
196      *
197      * @param iter An iterator over the remaining tokens
198      */

199     private void gobble( Iterator JavaDoc iter ) {
200         if( eatTheRest ) {
201             while( iter.hasNext() ) {
202                 tokens.add( iter.next() );
203             }
204         }
205     }
206
207     /**
208      * <p>If there is a current option and it can have an argument
209      * value then add the token to the processed tokens list and
210      * set the current option to null.</p>
211      * <p>If there is a current option and it can have argument
212      * values then add the token to the processed tokens list.</p>
213      * <p>If there is not a current option add the special token
214      * "<b>--</b>" and the current <code>value</code> to the processed
215      * tokens list. The add all the remaining <code>argument</code>
216      * values to the processed tokens list.</p>
217      *
218      * @param value The current token
219      */

220     private void process( String JavaDoc value ) {
221         if( currentOption != null && currentOption.hasArg() ) {
222             if( currentOption.hasArg() ) {
223                 tokens.add( value );
224                 currentOption = null;
225             }
226             else if (currentOption.hasArgs() ) {
227                 tokens.add( value );
228             }
229         }
230         else {
231             eatTheRest = true;
232             tokens.add( "--" );
233             tokens.add( value );
234         }
235     }
236
237     /**
238      * <p>If it is a hyphen then add the hyphen directly to
239      * the processed tokens list.</p>
240      *
241      * @param hyphen The hyphen token
242      */

243     private void processSingleHyphen( String JavaDoc hyphen ) {
244         tokens.add( hyphen );
245     }
246
247     /**
248      * <p>If an {@link Option} exists for <code>token</code> then
249      * set the current option and add the token to the processed
250      * list.</p>
251      * <p>If an {@link Option} does not exist and <code>stopAtNonOption</code>
252      * is set then ignore the current token and add the remaining tokens
253      * to the processed tokens list directly.</p>
254      *
255      * @param token The current option token
256      * @param stopAtNonOption Specifies whether flattening should halt
257      * at the first non option.
258      */

259     private void processOptionToken( String JavaDoc token, boolean stopAtNonOption ) {
260         if( this.options.hasOption( token ) ) {
261             currentOption = this.options.getOption( token );
262             tokens.add( token );
263         }
264         else if( stopAtNonOption ) {
265             eatTheRest = true;
266         }
267     }
268
269     /**
270      * <p>Breaks <code>token</code> into its constituent parts
271      * using the following algorithm.
272      * <ul>
273      * <li>ignore the first character ("<b>-</b>" )</li>
274      * <li>foreach remaining character check if an {@link Option}
275      * exists with that id.</li>
276      * <li>if an {@link Option} does exist then add that character
277      * prepended with "<b>-</b>" to the list of processed tokens.</li>
278      * <li>if the {@link Option} can have an argument value and there
279      * are remaining characters in the token then add the remaining
280      * characters as a token to the list of processed tokens.</li>
281      * <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
282      * <code>stopAtNonOption</code> <b>IS</b> set then add the special token
283      * "<b>--</b>" followed by the remaining characters and also
284      * the remaining tokens directly to the processed tokens list.</li>
285      * <li>if an {@link Option} does <b>NOT</b> exist <b>AND</b>
286      * <code>stopAtNonOption</code> <b>IS NOT</b> set then add that
287      * character prepended with "<b>-</b>".</li>
288      * </ul>
289      * </p>
290      */

291     protected void burstToken( String JavaDoc token, boolean stopAtNonOption ) {
292         int tokenLength = token.length();
293
294         for( int i = 1; i < tokenLength; i++) {
295             String JavaDoc ch = String.valueOf( token.charAt( i ) );
296             boolean hasOption = options.hasOption( ch );
297
298             if( hasOption ) {
299                 tokens.add( "-" + ch );
300                 currentOption = options.getOption( ch );
301                 if( currentOption.hasArg() && token.length()!=i+1 ) {
302                     tokens.add( token.substring( i+1 ) );
303                     break;
304                 }
305             }
306             else if( stopAtNonOption ) {
307                 process( token.substring( i ) );
308             }
309             else {
310                 tokens.add( "-" + ch );
311             }
312         }
313     }
314 }
Popular Tags