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: */package org.apache.commons.cli;
017:
018: /**
019: * <p>
020: * Allows Options to be created from a single String.
021: * The pattern contains various single character flags and via
022: * an optional punctuation character, their expected type.
023: * </p>
024: *
025: * <table border="1">
026: * <tr><td>a</td><td>-a flag</td></tr>
027: * <tr><td>b@</td><td>-b [classname]</td></tr>
028: * <tr><td>c></td><td>-c [filename]</td></tr>
029: * <tr><td>d+</td><td>-d [classname] (creates object via empty contructor)</td></tr>
030: * <tr><td>e%</td><td>-e [number] (creates Double/Long instance depeding on existing of a '.')</td></tr>
031: * <tr><td>f/</td><td>-f [url]</td></tr>
032: * <tr><td>g:</td><td>-g [string]</td></tr>
033: * </table>
034: *
035: * <p>
036: * For example, the following allows command line flags of '-v -p string-value -f /dir/file'.
037: * </p>
038: * <code>Options options = PatternOptionBuilder.parsePattern("vp:f/");</code>
039: *
040: * <p>
041: * TODO These need to break out to OptionType and also
042: * to be pluggable.
043: * </p>
044: *
045: * @author Henri Yandell (bayard @ generationjava.com)
046: * @version $Revision: 542144 $
047: */
048: public class PatternOptionBuilder {
049:
050: /** String class */
051: public static final Class STRING_VALUE = java.lang.String.class;
052:
053: /** Object class */
054: public static final Class OBJECT_VALUE = java.lang.Object.class;
055:
056: /** Number class */
057: public static final Class NUMBER_VALUE = java.lang.Number.class;
058:
059: /** Date class */
060: public static final Class DATE_VALUE = java.util.Date.class;
061:
062: /** Class class */
063: public static final Class CLASS_VALUE = java.lang.Class.class;
064:
065: /// can we do this one??
066: // is meant to check that the file exists, else it errors.
067: // ie) it's for reading not writing.
068:
069: /** FileInputStream class */
070: public static final Class EXISTING_FILE_VALUE = java.io.FileInputStream.class;
071:
072: /** File class */
073: public static final Class FILE_VALUE = java.io.File.class;
074:
075: /** File array class */
076: public static final Class FILES_VALUE = java.io.File[].class;
077:
078: /** URL class */
079: public static final Class URL_VALUE = java.net.URL.class;
080:
081: /**
082: * <p>Retrieve the class that <code>ch</code> represents.</p>
083: *
084: * @param ch the specified character
085: * @return The class that <code>ch</code> represents
086: */
087: public static Object getValueClass(char ch) {
088: if (ch == '@') {
089: return PatternOptionBuilder.OBJECT_VALUE;
090: } else if (ch == ':') {
091: return PatternOptionBuilder.STRING_VALUE;
092: } else if (ch == '%') {
093: return PatternOptionBuilder.NUMBER_VALUE;
094: } else if (ch == '+') {
095: return PatternOptionBuilder.CLASS_VALUE;
096: } else if (ch == '#') {
097: return PatternOptionBuilder.DATE_VALUE;
098: } else if (ch == '<') {
099: return PatternOptionBuilder.EXISTING_FILE_VALUE;
100: } else if (ch == '>') {
101: return PatternOptionBuilder.FILE_VALUE;
102: } else if (ch == '*') {
103: return PatternOptionBuilder.FILES_VALUE;
104: } else if (ch == '/') {
105: return PatternOptionBuilder.URL_VALUE;
106: }
107:
108: return null;
109: }
110:
111: /**
112: * <p>Returns whether <code>ch</code> is a value code, i.e.
113: * whether it represents a class in a pattern.</p>
114: *
115: * @param ch the specified character
116: * @return true if <code>ch</code> is a value code, otherwise false.
117: */
118: public static boolean isValueCode(char ch) {
119: if ((ch != '@') && (ch != ':') && (ch != '%') && (ch != '+')
120: && (ch != '#') && (ch != '<') && (ch != '>')
121: && (ch != '*') && (ch != '/') && (ch != '!')) {
122: return false;
123: }
124:
125: return true;
126: }
127:
128: /**
129: * <p>Returns the {@link Options} instance represented by
130: * <code>pattern</code>.</p>
131: *
132: * @param pattern the pattern string
133: * @return The {@link Options} instance
134: */
135: public static Options parsePattern(String pattern) {
136: int sz = pattern.length();
137:
138: char opt = ' ';
139: char ch = ' ';
140: boolean required = false;
141: Object type = null;
142:
143: Options options = new Options();
144:
145: for (int i = 0; i < sz; i++) {
146: ch = pattern.charAt(i);
147:
148: // a value code comes after an option and specifies
149: // details about it
150: if (!isValueCode(ch)) {
151: if (opt != ' ') {
152: OptionBuilder.hasArg(type != null);
153: OptionBuilder.isRequired(required);
154: OptionBuilder.withType(type);
155:
156: // we have a previous one to deal with
157: options.addOption(OptionBuilder.create(opt));
158: required = false;
159: type = null;
160: opt = ' ';
161: }
162:
163: opt = ch;
164: } else if (ch == '!') {
165: required = true;
166: } else {
167: type = getValueClass(ch);
168: }
169: }
170:
171: if (opt != ' ') {
172: OptionBuilder.hasArg(type != null);
173: OptionBuilder.isRequired(required);
174: OptionBuilder.withType(type);
175:
176: // we have a final one to deal with
177: options.addOption(OptionBuilder.create(opt));
178: }
179:
180: return options;
181: }
182: }
|