Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / tools / util / Parser.java
blob85755d4bf8013230bf1c16b0b1843020a3483c80
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;
8 import java.util.List;
9 import java.util.ArrayList;
10 import java.util.Arrays;
12 /**
13 * Parses command line arguments.
16 public class Parser {
18 /**
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;
28 this.action = action;
31 public List<Option> getParsedOptions() {
32 return parsedOptions;
35 public Action getAction() {
36 return action;
39 /**
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) {
45 option.apply();
47 action.apply();
51 /**
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
56 * is no match.
58 public static Action lookupAction(List<Action> actions, String[] args, int index) {
59 for (Action action : actions) {
60 if (matchesAction(action, args, index)) {
61 return action;
64 return null;
67 private static boolean matchesAction(Action action, String[] args, int index) {
68 if ((args.length - index) < action.getNames().length) {
69 return false;
71 for (String name : action.getNames()) {
72 if (!name.equals(args[index++])) {
73 return false;
76 return true;
79 /**
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
102 * {@code args}.
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) {
136 int currentArg = -1;
138 while (true) {
139 ++currentArg;
140 if (currentArg >= cmdLineArgs.length) {
141 break;
143 Option option = parseArg(availableOptions, cmdLineArgs, currentArg);
144 if (option != null) {
145 parsedOptions.add(option);
146 if (option.getArgStyle() == Option.Style.Short) {
147 ++currentArg;
149 continue;
151 break;
154 return currentArg;
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) {
164 msg.append(", ");
165 } else {
166 msg.append("]");
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)) {
176 return option;
179 return null;