001: /*
002: * ArgumentParser.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.util;
013:
014: import java.util.ArrayList;
015: import java.util.Collection;
016: import java.util.Comparator;
017: import java.util.Iterator;
018: import java.util.List;
019: import java.util.Map;
020: import java.util.TreeMap;
021: import java.util.TreeSet;
022: import workbench.log.LogMgr;
023:
024: /**
025: *
026: * @author support@sql-workbench.net
027: */
028: public class ArgumentParser {
029: private static final String ARG_PRESENT = "$WB$__ARG_PRESENT__$WB$";
030: private Map<String, String> arguments;
031: private Map<String, ArgumentType> argTypes;
032: private List<String> unknownParameters = new ArrayList<String>();
033: private Map<String, Collection<String>> allowedValues;
034: private int argCount = 0;
035: private boolean needSwitch = true;
036:
037: public ArgumentParser() {
038: Comparator<String> c = new CaseInsensitiveComparator();
039: arguments = new TreeMap<String, String>(c);
040: argTypes = new TreeMap<String, ArgumentType>(c);
041: allowedValues = new TreeMap<String, Collection<String>>(c);
042: }
043:
044: public ArgumentParser(boolean parameterSwitchNeeded) {
045: this ();
046: this .needSwitch = parameterSwitchNeeded;
047: }
048:
049: public boolean needsSwitch() {
050: return needSwitch;
051: }
052:
053: public Collection<String> getAllowedValues(String key) {
054: return allowedValues.get(key);
055: }
056:
057: public void addArgument(String key, List<String> values) {
058: addArgument(key, ArgumentType.ListArgument);
059: if (values == null)
060: return;
061: Collection<String> v = new TreeSet<String>(
062: new CaseInsensitiveComparator());
063: v.addAll(values);
064: allowedValues.put(key, v);
065: }
066:
067: public void addArgument(String key) {
068: addArgument(key, ArgumentType.StringArgument);
069: }
070:
071: public void addArgument(String key, ArgumentType type) {
072: if (key == null)
073: throw new NullPointerException("Key may not be null");
074:
075: this .arguments.put(key, null);
076: this .argTypes.put(key, type);
077: }
078:
079: public void parse(String args[]) {
080: this .reset();
081: StringBuilder line = new StringBuilder(200);
082: for (int i = 0; i < args.length; i++) {
083: line.append(args[i]);
084: line.append(' ');
085: }
086: this .parse(line.toString());
087: }
088:
089: public void parse(String aCmdLine) {
090: this .reset();
091:
092: try {
093: WbStringTokenizer tok = new WbStringTokenizer('-', "\"'",
094: false);
095: tok.setDelimiterNeedsWhitspace(true);
096: tok.setSourceString(aCmdLine.trim());
097:
098: while (tok.hasMoreTokens()) {
099: String word = tok.nextToken();
100: if (word == null || word.length() == 0)
101: continue;
102: String arg = null;
103: String value = null;
104: int pos = word.indexOf('=');
105: if (pos > -1) {
106: arg = word.substring(0, pos).trim().toLowerCase();
107: value = word.substring(pos + 1).trim();
108: } else {
109: arg = word.trim().toLowerCase();
110: }
111:
112: if (value == null) {
113: value = ARG_PRESENT;
114: }
115:
116: if (arguments.containsKey(arg)) {
117: arguments.put(arg, value);
118: this .argCount++;
119: } else {
120: this .unknownParameters.add(arg);
121: }
122: }
123: } catch (Exception e) {
124: LogMgr.logError("ArgumentParser.parse()",
125: "Error when parsing input line: " + aCmdLine, e);
126: }
127: }
128:
129: public List<String> getArgumentsOnCommandLine() {
130: ArrayList<String> result = new ArrayList<String>(this .arguments
131: .size());
132: for (Map.Entry<String, String> entry : arguments.entrySet()) {
133: if (entry.getValue() != null) {
134: result.add(entry.getKey());
135: }
136: }
137: return result;
138: }
139:
140: /**
141: * Returns the list of known arguments for this ArgumentParser
142: * @return the registered argument types
143: */
144: public List<String> getRegisteredArguments() {
145: Iterator<Map.Entry<String, ArgumentType>> itr = this .argTypes
146: .entrySet().iterator();
147:
148: List<String> result = new ArrayList<String>(this .argTypes
149: .size());
150: while (itr.hasNext()) {
151: Map.Entry<String, ArgumentType> entry = itr.next();
152: if (entry.getValue() != ArgumentType.Deprecated) {
153: result.add(entry.getKey());
154: }
155: }
156: return result;
157: }
158:
159: /**
160: * Returns the type of an argument
161: */
162: public ArgumentType getArgumentType(String arg) {
163: return this .argTypes.get(arg);
164: }
165:
166: public boolean hasArguments() {
167: return this .argCount > 0;
168: }
169:
170: public int getArgumentCount() {
171: return this .argCount;
172: }
173:
174: public boolean hasUnknownArguments() {
175: return this .unknownParameters.size() > 0;
176: }
177:
178: /**
179: * Return a list of unknown arguments.
180: * Each argument passed in the original command line
181: * that has not been registered using addArgument()
182: * will be listed in the result. For each argument
183: * in this list, isRegistered() would return false.
184: *
185: * @return a comma separated string with unknown arguments
186: */
187: public String getUnknownArguments() {
188: StringBuilder msg = new StringBuilder();
189:
190: if (unknownParameters.size() > 0) {
191: for (int i = 0; i < unknownParameters.size(); i++) {
192: if (i > 0)
193: msg.append(' ');
194: msg.append('-');
195: msg.append(unknownParameters.get(i));
196: }
197: }
198: return msg.toString();
199: }
200:
201: /**
202: * Check if the given argument is a valid argument for the current commandline
203: * @return true if arg was registered with addArgument()
204: */
205: public boolean isRegistered(String arg) {
206: return this .arguments.containsKey(arg);
207: }
208:
209: /**
210: * Check if the given argument was passed on the commandline.
211: * This does not check if a value has been supplied with the
212: * argument. This can be used for argument-less parameters
213: * e.g. -showEncodings
214: *
215: * @return true if the given argument was part of the commandline
216: */
217: public boolean isArgPresent(String arg) {
218: if (arg == null)
219: return false;
220: // Even arguments without a value will have something
221: // in the map (the ARG_PRESENT marker object), otherwise
222: // they could not be distinguished from arguments that
223: // are merely registered.
224: Object value = this .arguments.get(arg);
225: return (value != null);
226: }
227:
228: private void reset() {
229: Iterator<String> keys = this .arguments.keySet().iterator();
230: while (keys.hasNext()) {
231: String key = keys.next();
232: this .arguments.put(key, null);
233: }
234: this .argCount = 0;
235: this .unknownParameters.clear();
236: }
237:
238: /**
239: * Return a parameter as a boolean.
240: * @return the value as passed on the command line
241: * false if no value was specified
242: *
243: * @see #getBoolean(String, boolean)
244: */
245: public boolean getBoolean(String key) {
246: return getBoolean(key, false);
247: }
248:
249: /**
250: * Return a parameter value as a boolean.
251: * If no value was specified the given default value will be returned
252: *
253: * @param key the parameter key
254: * @param defaultValue the default to be returned if the parameter is not present
255: *
256: * @return the value as passed on the commandline
257: * the defaultValue if the parameter was not supplied by the user
258: *
259: * @see #getValue(String)
260: * @see #getBoolean(String)
261: * @see StringUtil#stringToBool(String)
262: */
263: public boolean getBoolean(String key, boolean defaultValue) {
264: String value = this .getValue(key);
265: if (value == null || value.trim().length() == 0)
266: return defaultValue;
267: return StringUtil.stringToBool(value);
268: }
269:
270: /**
271: * Return the parameter for the give argument.
272: *
273: * If no value was specified or the parameter was not
274: * passed on the commandline null will be returned.
275: * Any leading or trailing quotes will be removed from the argument
276: * before it is returned.
277: *
278: * @param key the parameter to retrieve
279: * @return the value as provided by the user or null if no value specified
280: *
281: * @see StringUtil#trimQuotes(String)
282: */
283: public String getValue(String key) {
284: String value = this .arguments.get(key);
285: if (value == ARG_PRESENT)
286: return null;
287: return value;
288: }
289:
290: public int getIntValue(String key, int def) {
291: return StringUtil.getIntValue(this.getValue(key), def);
292: }
293:
294: }
|