001: /**********************************************************************
002: Copyright (c) 2004 Kikuchi Kousuke and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: ...
017: **********************************************************************/package org.jpox.util;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021:
022: /**
023: * Command line option parser.
024: * Used by command line applications such as JPOX Enhancer and JPOX SchemaTool to process command line arguments.
025: *
026: * @version $Revision: 1.3 $
027: */
028: public class CommandLine {
029: /** Appended options */
030: protected HashMap options = new HashMap();
031:
032: /** Appended options */
033: protected HashMap valueOptions = new HashMap();
034:
035: /** Appended options */
036: protected ArrayList optionList = new ArrayList();
037:
038: /** Default arguments */
039: protected String defaultArg[];
040:
041: protected String originalArguments;
042:
043: /** displays dash **/
044: protected boolean displaysDash = true;
045:
046: /**
047: * CommandLine option base class
048: */
049: protected static class Option {
050: /** Short name option */
051: final String shortName;
052: /** Long name option */
053: final String longName;
054: /** option description */
055: final String description;
056:
057: /**
058: * Constructor
059: * @param shortName Short name option(exclude "-")
060: * @param longName Long name option(exclude "--")
061: * @param desc option description
062: */
063: public Option(String shortName, String longName, String desc) {
064: this .shortName = shortName;
065: this .longName = longName;
066: this .description = desc;
067: }
068: }
069:
070: /**
071: * No argument option class.
072: **/
073: protected static class NoArgOption extends Option {
074: /** designated */
075: boolean selected;
076:
077: /**
078: * Constructor
079: * @param shortName Short name option(exclude "-")
080: * @param longName Long name option(exclude "--")
081: * @param desc option description
082: */
083: public NoArgOption(String shortName, String longName,
084: String desc) {
085: super (shortName, longName, desc);
086: }
087: }
088:
089: /**
090: * Use argment option class.
091: **/
092: protected static class WithArgOption extends Option {
093: /** Option argment name */
094: String name;
095: /** Designated argment value */
096: String option;
097:
098: /**
099: * Constructor
100: * @param shortName Short name option(exclude "-")
101: * @param longName Long name option(exclude "--")
102: * @param desc option description
103: * @param name argment name
104: */
105: public WithArgOption(String shortName, String longName,
106: String desc, String name) {
107: super (shortName, longName, desc);
108: this .name = name;
109: }
110: }
111:
112: /**
113: * Default constructor
114: **/
115: public CommandLine() {
116: //default constructor
117: }
118:
119: /**
120: * Default constructor
121: * @param displaysDash whether to display a dash in the short name
122: **/
123: public CommandLine(boolean displaysDash) {
124: this .displaysDash = displaysDash;
125: }
126:
127: /**
128: * Add new Option.
129: * <br>
130: * If argName is null, set this option no-arg option.
131: * @param shortName Short name option eg "d"
132: * @param longName Long name option eg "directory"
133: * @param argName Argment name. No argment option if this param is null.
134: * @param desc Desription this option.
135: */
136: public void addOption(String shortName, String longName,
137: String argName, String desc) {
138: Option option = null;
139: if (StringUtils.isEmpty(shortName)
140: && StringUtils.isEmpty(longName)) {
141: throw new IllegalArgumentException(
142: "require shortName or longName");
143: }
144:
145: if (StringUtils.notEmpty(argName)) {
146: option = new WithArgOption(shortName, longName, desc,
147: argName);
148: } else {
149: option = new NoArgOption(shortName, longName, desc);
150: }
151:
152: optionList.add(option);
153: if (StringUtils.notEmpty(shortName)) {
154: options.put("-" + shortName, option);
155: valueOptions.put(shortName, option);
156: }
157:
158: if (StringUtils.notEmpty(longName)) {
159: options.put("--" + longName, option);
160: valueOptions.put(longName, option);
161: }
162: }
163:
164: /**
165: * Parse command line argments.
166: * @param args Command line argments
167: */
168: public void parse(String args[]) {
169: ArrayList defaultArg = new ArrayList();
170: if ((args == null || (args.length == 0))) {
171: return;
172: }
173: int i = 0;
174: while (i < args.length) {
175: if (StringUtils.isEmpty(args[i])) {
176: //do nothing
177: } else if (args[i].startsWith("-")) {
178: originalArguments += args + " ";
179: if (options.containsKey(args[i])) {
180: Option option = (Option) options.get(args[i]);
181: if (option instanceof NoArgOption) {
182: ((NoArgOption) option).selected = true;
183: } else {
184: if (args.length - 1 == i) {
185: throw new RuntimeException("option "
186: + args[i] + " needs an argument");
187: } else {
188: ((WithArgOption) option).option = args[i + 1];
189: i++;
190: }
191: }
192: } else {
193: defaultArg.add(args[i]);
194: }
195: } else {
196: defaultArg.add(args[i]);
197: }
198:
199: i++;
200: }
201:
202: if (defaultArg.size() == 0) {
203: this .defaultArg = new String[0];
204: }
205: String result[] = new String[defaultArg.size()];
206: for (i = 0; i < result.length; i++) {
207: result[i] = (String) defaultArg.get(i);
208: }
209: this .defaultArg = result;
210: }
211:
212: /**
213: * Check option selected
214: * @param name Option name (both short name and long name ok)
215: * @return Return true, if option selected.
216: */
217: public boolean hasOption(String name) {
218: if (!valueOptions.containsKey(name)) {
219: throw new IllegalArgumentException("no such option " + name);
220: }
221: Option option = (Option) valueOptions.get(name);
222: if (option instanceof NoArgOption) {
223: return ((NoArgOption) option).selected;
224: }
225: return StringUtils.notEmpty(((WithArgOption) option).option);
226: }
227:
228: /**
229: * Return option argument.
230: * @param name Option name (both short name and long name ok)
231: * @return option Argument
232: * @throws IllegalArgumentException If unmanaged name recieved.
233: */
234: public String getOptionArg(String name) {
235: if (!valueOptions.containsKey(name)) {
236: throw new IllegalArgumentException("no such option " + name);
237: }
238: Option option = (Option) valueOptions.get(name);
239: if (option instanceof NoArgOption) {
240: return "" + ((NoArgOption) option).selected;
241: }
242: return ((WithArgOption) option).option;
243: }
244:
245: /**
246: * Return string like useage.
247: * @return Useage string
248: */
249: public String toString() {
250: if (optionList.size() == 0) {
251: return "[NO OPTIONS]";
252: }
253: int maxLength = 80;
254: StringBuffer sb = new StringBuffer();
255: int shortMax = 0;
256: int longMax = 0;
257: int argNameMax = 0;
258: int descMax = 0;
259: for (int i = 0; i < optionList.size(); i++) {
260: Option o = (Option) optionList.get(i);
261: if (o.shortName != null) {
262: if ((o.shortName != null)
263: && (o.shortName.length() > shortMax)) {
264: shortMax = o.shortName.length();
265: }
266:
267: if ((o.longName != null)
268: && (o.longName.length() > longMax)) {
269: longMax = o.longName.length();
270: }
271:
272: if (o instanceof WithArgOption) {
273: WithArgOption op = (WithArgOption) o;
274: if (op.name.length() > argNameMax) {
275: argNameMax = op.name.length();
276: }
277: }
278:
279: if ((o.description != null)
280: && (o.description.length() > descMax)) {
281: descMax = o.description.length();
282: }
283: }
284: }
285: if (shortMax > 0) {
286: shortMax += 3;
287: }
288: if (longMax > 0) {
289: longMax += 3;
290: }
291: if (argNameMax > 0) {
292: argNameMax += 3;
293: }
294: for (int i = 0; i < optionList.size(); i++) {
295: int j = 0;
296: Option o = (Option) optionList.get(i);
297: if (StringUtils.notEmpty(o.shortName)) {
298: if (this .displaysDash) {
299: sb.append("-");
300: }
301: sb.append(o.shortName);
302: j = o.shortName.length() + 1;
303: }
304: for (; j < shortMax; j++) {
305: sb.append(" ");
306: }
307:
308: j = 0;
309: if (StringUtils.notEmpty(o.longName)) {
310: sb.append("--");
311: sb.append(o.longName);
312: j = o.longName.length() + 2;
313: }
314: for (; j < longMax; j++) {
315: sb.append(" ");
316: }
317:
318: j = 0;
319: if (o instanceof WithArgOption) {
320: WithArgOption op = (WithArgOption) o;
321: sb.append(op.name);
322: j = op.name.length();
323: }
324: for (; j < argNameMax; j++) {
325: sb.append(" ");
326: }
327:
328: if (StringUtils.notEmpty(o.description)) {
329: int basePos;
330: if ((shortMax + longMax + argNameMax) > maxLength) {
331: basePos = maxLength / 2;
332: sb.append("\n");
333: for (int k = 0; k < basePos; k++) {
334: sb.append(" ");
335: }
336: } else {
337: basePos = (shortMax + longMax + argNameMax);
338: }
339: int pos = basePos;
340: for (j = 0; j < o.description.length(); j++) {
341: sb.append(o.description.charAt(j));
342: if (pos >= maxLength) {
343: if (j < o.description.length() - 1
344: && o.description.charAt(j + 1) != ' ') {
345: //just do not break work in the middle, and wrap word to next line
346: for (int p = sb.length() - 1; p >= 0; p--) {
347: if (sb.charAt(p) == ' ') {
348: sb.insert(p, '\n');
349: for (int k = 0; k < basePos - 1; k++) {
350: sb.insert(p + 1, " ");
351: }
352: break;
353: }
354: }
355: } else {
356: sb.append("\n");
357: for (int k = 0; k < basePos; k++) {
358: sb.append(" ");
359: }
360: }
361: pos = basePos;
362: }
363: pos++;
364: }
365: }
366: sb.append("\n");
367: }
368: return sb.toString();
369: }
370:
371: /**
372: * Return default arguments.
373: * @return Default arguments
374: */
375: public String[] getDefaultArgs() {
376: return this .defaultArg;
377: }
378:
379: /**
380: * Return original arguments.
381: * @return Original arguments
382: */
383: public String getOriginalArguments() {
384: return originalArguments;
385: }
386: }
|