View Javadoc

1   /***
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.cli;
18  
19  /*** 
20   * <p>
21   * Allows Options to be created from a single String.
22   * The pattern contains various single character flags and via
23   * an optional punctuation character, their expected type.
24   * </p>
25   *
26   * <table border="1">
27   * <tr><td>a</td><td>-a flag</td></tr>
28   * <tr><td>b@</td><td>-b [classname]</td></tr>
29   * <tr><td>c&gt;</td><td>-c [filename]</td></tr>
30   * <tr><td>d+</td><td>-d [classname] (creates object via empty contructor)</td></tr>
31   * <tr><td>e%</td><td>-e [number] (creates Double/Long instance depeding on existing of a '.')</td></tr>
32   * <tr><td>f/</td><td>-f [url]</td></tr>
33   * <tr><td>g:</td><td>-g [string]</td></tr>
34   * </table>
35   *
36   * <p>
37   * For example, the following allows command line flags of '-v -p string-value -f /dir/file'.
38   * </p>
39   * <code>Options options = PatternOptionBuilder.parsePattern("vp:f/");</code>
40   *
41   * <p>
42   * TODO These need to break out to OptionType and also 
43   * to be pluggable.
44   * </p>
45   *
46   * @author Henri Yandell (bayard @ generationjava.com)
47   * @version $Revision: 542144 $
48   */
49  public class PatternOptionBuilder {
50  
51      /*** String class */
52      public static final Class STRING_VALUE = java.lang.String.class;
53  
54      /*** Object class */
55      public static final Class OBJECT_VALUE = java.lang.Object.class;
56  
57      /*** Number class */
58      public static final Class NUMBER_VALUE = java.lang.Number.class;
59  
60      /*** Date class */
61      public static final Class DATE_VALUE = java.util.Date.class;
62  
63      /*** Class class */
64      public static final Class CLASS_VALUE = java.lang.Class.class;
65  
66      /// can we do this one?? 
67      // is meant to check that the file exists, else it errors.
68      // ie) it's for reading not writing.
69  
70      /*** FileInputStream class */
71      public static final Class EXISTING_FILE_VALUE = 
72              java.io.FileInputStream.class;
73  
74      /*** File class */
75      public static final Class FILE_VALUE = java.io.File.class;
76  
77      /*** File array class */
78      public static final Class FILES_VALUE = java.io.File[].class;
79  
80      /*** URL class */
81      public static final Class URL_VALUE = java.net.URL.class;
82  
83      /***
84       * <p>Retrieve the class that <code>ch</code> represents.</p>
85       *
86       * @param ch the specified character
87       * @return The class that <code>ch</code> represents
88       */
89      public static Object getValueClass(char ch)
90      {
91          if (ch == '@')
92          {
93              return PatternOptionBuilder.OBJECT_VALUE;
94          }
95          else if (ch == ':')
96          {
97              return PatternOptionBuilder.STRING_VALUE;
98          }
99          else if (ch == '%')
100         {
101             return PatternOptionBuilder.NUMBER_VALUE;
102         }
103         else if (ch == '+')
104         {
105             return PatternOptionBuilder.CLASS_VALUE;
106         }
107         else if (ch == '#')
108         {
109             return PatternOptionBuilder.DATE_VALUE;
110         }
111         else if (ch == '<')
112         {
113             return PatternOptionBuilder.EXISTING_FILE_VALUE;
114         }
115         else if (ch == '>')
116         {
117             return PatternOptionBuilder.FILE_VALUE;
118         }
119         else if (ch == '*')
120         {
121             return PatternOptionBuilder.FILES_VALUE;
122         }
123         else if (ch == '/')
124         {
125             return PatternOptionBuilder.URL_VALUE;
126         }
127 
128         return null;
129     }
130 
131     /***
132      * <p>Returns whether <code>ch</code> is a value code, i.e.
133      * whether it represents a class in a pattern.</p>
134      * 
135      * @param ch the specified character
136      * @return true if <code>ch</code> is a value code, otherwise false.
137      */
138     public static boolean isValueCode(char ch)
139     {
140         if ((ch != '@') && (ch != ':') && (ch != '%') && (ch != '+')
141             && (ch != '#') && (ch != '<') && (ch != '>') && (ch != '*')
142             && (ch != '/') && (ch != '!'))
143         {
144             return false;
145         }
146 
147         return true;
148     }
149 
150     /***
151      * <p>Returns the {@link Options} instance represented by 
152      * <code>pattern</code>.</p>
153      *
154      * @param pattern the pattern string
155      * @return The {@link Options} instance
156      */
157     public static Options parsePattern(String pattern)
158     {
159         int sz = pattern.length();
160 
161         char opt = ' ';
162         char ch = ' ';
163         boolean required = false;
164         Object type = null;
165 
166         Options options = new Options();
167 
168         for (int i = 0; i < sz; i++)
169         {
170             ch = pattern.charAt(i);
171 
172             // a value code comes after an option and specifies 
173             // details about it
174             if (!isValueCode(ch))
175             {
176                 if (opt != ' ')
177                 {
178                     OptionBuilder.hasArg(type != null);
179                     OptionBuilder.isRequired(required);
180                     OptionBuilder.withType(type);
181                     
182                     // we have a previous one to deal with
183                     options.addOption(OptionBuilder.create(opt));
184                     required = false;
185                     type = null;
186                     opt = ' ';
187                 }
188 
189                 opt = ch;
190             }
191             else if (ch == '!')
192             {
193                 required = true;
194             }
195             else
196             {
197                 type = getValueClass(ch);
198             }
199         }
200 
201         if (opt != ' ')
202         {
203             OptionBuilder.hasArg(type != null);
204             OptionBuilder.isRequired(required);
205             OptionBuilder.withType(type);
206             
207             // we have a final one to deal with
208             options.addOption(OptionBuilder.create(opt));
209         }
210 
211         return options;
212     }
213 }