1 // Copyright 2008 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.tools
.util
;
5 import com
.google
.appengine
.tools
.util
.Action
;
6 import com
.google
.appengine
.tools
.util
.Option
;
9 import java
.util
.ArrayList
;
10 import java
.util
.Arrays
;
13 * Parses command line arguments.
19 * Contains the parsed {@link Action} and {@link Option arguments}
20 * from a program command line.
22 public static class ParseResult
{
23 private final List
<Option
> parsedOptions
;
24 private final Action action
;
26 ParseResult(List
<Option
> parsedOptions
, Action action
) {
27 this.parsedOptions
= parsedOptions
;
31 public List
<Option
> getParsedOptions() {
35 public Action
getAction() {
40 * Applies the arguments to all {@link Option#apply() options} and
41 * to the parsed {@link Action#apply() action}.
43 public void applyArgs() {
44 for (Option option
: parsedOptions
) {
52 * Finds the action for a particular name.
53 * @param actions the actions available
54 * @param name the name of the desired action
55 * @returns an {@link Action} for the given name, or {@code null} if there
58 public static Action
lookupAction(List
<Action
> actions
, String
[] args
, int index
) {
59 for (Action action
: actions
) {
60 if (matchesAction(action
, args
, index
)) {
67 private static boolean matchesAction(Action action
, String
[] args
, int index
) {
68 if ((args
.length
- index
) < action
.getNames().length
) {
71 for (String name
: action
.getNames()) {
72 if (!name
.equals(args
[index
++])) {
80 * Parses command line arguments for the specified {@code actions}
81 * and {@code args}. This variant assumes that there is only a
82 * single {@link Action} and, as a result, the user does not specify
83 * an action name on the command line.
85 * @param actions a single not-{@code null} {@link Action}
86 * @param options a not {@code null}, optionally empty, list
87 * @param cmdLineArgs a not {@code null} array of command line arguments
89 * @return a not {@code null} {@code ParseResult}
91 public ParseResult
parseArgs(Action action
, List
<Option
> options
, String
[] cmdLineArgs
) {
92 List
<Option
> parsedOptions
= new ArrayList
<Option
>();
93 int currentArg
= parseOptions(options
, parsedOptions
, cmdLineArgs
);
95 List
<String
> actionArgs
= Arrays
.asList(cmdLineArgs
).subList(currentArg
, cmdLineArgs
.length
);
96 action
.setArgs(actionArgs
);
97 return new ParseResult(parsedOptions
, action
);
101 * Parses command line arguments using the specified {@code actions} and
104 * @param actions a not {@code null}, not empty, list
105 * @param options a not {@code null}, optionally empty, list
106 * @param cmdLineArgs a not {@code null} array of command line arguments
108 * @return a not {@code null} {@code ParseResult}
110 public ParseResult
parseArgs(List
<Action
> actions
, List
<Option
> options
, String
[] cmdLineArgs
) {
111 List
<Option
> parsedOptions
= new ArrayList
<Option
>();
113 int currentArg
= parseOptions(options
, parsedOptions
, cmdLineArgs
);
114 if (currentArg
>= cmdLineArgs
.length
) {
115 throw new IllegalArgumentException("Expected an action: " + buildActionString(actions
));
118 String actionString
= cmdLineArgs
[currentArg
];
119 if (actionString
.startsWith("-") || actionString
.startsWith("--")) {
120 throw new IllegalArgumentException("Unknown option: " + actionString
);
123 Action foundAction
= lookupAction(actions
, cmdLineArgs
, currentArg
);
124 if (foundAction
== null) {
125 throw new IllegalArgumentException("Expected an action: " + buildActionString(actions
));
127 currentArg
+= foundAction
.getNames().length
;
129 List
<String
> actionArgs
= Arrays
.asList(cmdLineArgs
).subList(currentArg
, cmdLineArgs
.length
);
130 foundAction
.setArgs(actionArgs
);
131 return new ParseResult(parsedOptions
, foundAction
);
134 private int parseOptions(List
<Option
> availableOptions
, List
<Option
> parsedOptions
,
135 String
[] cmdLineArgs
) {
140 if (currentArg
>= cmdLineArgs
.length
) {
143 Option option
= parseArg(availableOptions
, cmdLineArgs
, currentArg
);
144 if (option
!= null) {
145 parsedOptions
.add(option
);
146 if (option
.getArgStyle() == Option
.Style
.Short
) {
157 private static String
buildActionString(List
<Action
> actions
) {
158 StringBuffer msg
= new StringBuffer("[");
160 for (int i
= 0; i
< actions
.size(); ++i
) {
161 Action action
= actions
.get(i
);
162 msg
.append(action
.getNameString());
163 if (i
!= actions
.size() - 1) {
170 return msg
.toString();
173 private static Option
parseArg(List
<Option
> optionParsers
, String
[] cmdLineArgs
, int currentArg
) {
174 for (Option option
: optionParsers
) {
175 if (option
.parse(cmdLineArgs
, currentArg
)) {