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
18 package org.apache.commons.cli;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.net.URL;
23 import java.util.Date;
24
25 /**
26 * <p>
27 * Allows Options to be created from a single String.
28 * The pattern contains various single character flags and via
29 * an optional punctuation character, their expected type.
30 * </p>
31 *
32 * <table border="1">
33 * <tr><td>a</td><td>-a flag</td></tr>
34 * <tr><td>b@</td><td>-b [classname]</td></tr>
35 * <tr><td>c></td><td>-c [filename]</td></tr>
36 * <tr><td>d+</td><td>-d [classname] (creates object via empty contructor)</td></tr>
37 * <tr><td>e%</td><td>-e [number] (creates Double/Long instance depeding on existing of a '.')</td></tr>
38 * <tr><td>f/</td><td>-f [url]</td></tr>
39 * <tr><td>g:</td><td>-g [string]</td></tr>
40 * </table>
41 *
42 * <p>
43 * For example, the following allows command line flags of '-v -p string-value -f /dir/file'.
44 * The exclamation mark precede a mandatory option.
45 * </p>
46 * <code>Options options = PatternOptionBuilder.parsePattern("vp:!f/");</code>
47 *
48 * <p>
49 * TODO These need to break out to OptionType and also
50 * to be pluggable.
51 * </p>
52 *
53 * @version $Revision: 734339 $, $Date: 2009-01-14 05:56:47 +0000 (Wed, 14 Jan 2009) $
54 */
55 public class PatternOptionBuilder
56 {
57 /** String class */
58 public static final Class STRING_VALUE = String.class;
59
60 /** Object class */
61 public static final Class OBJECT_VALUE = Object.class;
62
63 /** Number class */
64 public static final Class NUMBER_VALUE = Number.class;
65
66 /** Date class */
67 public static final Class DATE_VALUE = Date.class;
68
69 /** Class class */
70 public static final Class CLASS_VALUE = Class.class;
71
72 /// can we do this one??
73 // is meant to check that the file exists, else it errors.
74 // ie) it's for reading not writing.
75
76 /** FileInputStream class */
77 public static final Class EXISTING_FILE_VALUE = FileInputStream.class;
78
79 /** File class */
80 public static final Class FILE_VALUE = File.class;
81
82 /** File array class */
83 public static final Class FILES_VALUE = File[].class;
84
85 /** URL class */
86 public static final Class URL_VALUE = URL.class;
87
88 /**
89 * Retrieve the class that <code>ch</code> represents.
90 *
91 * @param ch the specified character
92 * @return The class that <code>ch</code> represents
93 */
94 public static Object getValueClass(char ch)
95 {
96 switch (ch)
97 {
98 case '@':
99 return PatternOptionBuilder.OBJECT_VALUE;
100 case ':':
101 return PatternOptionBuilder.STRING_VALUE;
102 case '%':
103 return PatternOptionBuilder.NUMBER_VALUE;
104 case '+':
105 return PatternOptionBuilder.CLASS_VALUE;
106 case '#':
107 return PatternOptionBuilder.DATE_VALUE;
108 case '<':
109 return PatternOptionBuilder.EXISTING_FILE_VALUE;
110 case '>':
111 return PatternOptionBuilder.FILE_VALUE;
112 case '*':
113 return PatternOptionBuilder.FILES_VALUE;
114 case '/':
115 return PatternOptionBuilder.URL_VALUE;
116 }
117
118 return null;
119 }
120
121 /**
122 * Returns whether <code>ch</code> is a value code, i.e.
123 * whether it represents a class in a pattern.
124 *
125 * @param ch the specified character
126 * @return true if <code>ch</code> is a value code, otherwise false.
127 */
128 public static boolean isValueCode(char ch)
129 {
130 return ch == '@'
131 || ch == ':'
132 || ch == '%'
133 || ch == '+'
134 || ch == '#'
135 || ch == '<'
136 || ch == '>'
137 || ch == '*'
138 || ch == '/'
139 || ch == '!';
140 }
141
142 /**
143 * Returns the {@link Options} instance represented by <code>pattern</code>.
144 *
145 * @param pattern the pattern string
146 * @return The {@link Options} instance
147 */
148 public static Options parsePattern(String pattern)
149 {
150 char opt = ' ';
151 boolean required = false;
152 Object type = null;
153
154 Options options = new Options();
155
156 for (int i = 0; i < pattern.length(); i++)
157 {
158 char ch = pattern.charAt(i);
159
160 // a value code comes after an option and specifies
161 // details about it
162 if (!isValueCode(ch))
163 {
164 if (opt != ' ')
165 {
166 OptionBuilder.hasArg(type != null);
167 OptionBuilder.isRequired(required);
168 OptionBuilder.withType(type);
169
170 // we have a previous one to deal with
171 options.addOption(OptionBuilder.create(opt));
172 required = false;
173 type = null;
174 opt = ' ';
175 }
176
177 opt = ch;
178 }
179 else if (ch == '!')
180 {
181 required = true;
182 }
183 else
184 {
185 type = getValueClass(ch);
186 }
187 }
188
189 if (opt != ' ')
190 {
191 OptionBuilder.hasArg(type != null);
192 OptionBuilder.isRequired(required);
193 OptionBuilder.withType(type);
194
195 // we have a final one to deal with
196 options.addOption(OptionBuilder.create(opt));
197 }
198
199 return options;
200 }
201 }