• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts;
18 
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Set;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 
27 /**
28  * CommandParser is responsible for parsing command line arguments. To get
29  * action, option or values easy via functions.
30  * For example:
31  * <ul>
32  *    <li> CommandParser cp = CommandParser.parse("start -plan test_plan")
33  *    <li> cp.getAction() will get "start"
34  *    <li> cp.getValue("-plan") will get "test_plan"
35  *    <li> cp.containsKey("-noplan") will get null
36  * </ul>
37  *
38  */
39 public class CommandParser {
40 
41     /**
42      * The hash map mapping the options and option values.
43      */
44     private HashMap<String, String> mValues = new HashMap<String, String>();
45 
46     /**
47      * The action the user chose to ask CTS host to take.
48      */
49     private String mAction;
50     private ArrayList<String> mActionValues = new ArrayList<String>();
51     private int mArgLength;
52     private static final String COMMAND_PARSE_EXPRESSION = "(((\\\\\\s)|[\\S&&[^\"]])+|\".+\")";
53 
54     private static Set<String> sOptionsSet = new HashSet<String>(Arrays.asList(
55             CTSCommand.OPTION_CFG, CTSCommand.OPTION_PACKAGE, CTSCommand.OPTION_PLAN,
56             CTSCommand.OPTION_DEVICE, CTSCommand.OPTION_RESULT, CTSCommand.OPTION_E,
57             CTSCommand.OPTION_SESSION, CTSCommand.OPTION_TEST, CTSCommand.OPTION_DERIVED_PLAN));
58     private static HashMap<String, String> sOptionMap = new HashMap<String, String>();
59     static {
60         final String[] keys = new String[] {
61                 CTSCommand.OPTION_CFG,
62                 CTSCommand.OPTION_P,
63                 CTSCommand.OPTION_PACKAGE,
64                 CTSCommand.OPTION_PLAN,
65                 CTSCommand.OPTION_D,
66                 CTSCommand.OPTION_DEVICE,
67                 CTSCommand.OPTION_R,
68                 CTSCommand.OPTION_RESULT,
69                 CTSCommand.OPTION_E,
70                 CTSCommand.OPTION_S,
71                 CTSCommand.OPTION_SESSION,
72                 CTSCommand.OPTION_T,
73                 CTSCommand.OPTION_TEST,
74                 CTSCommand.OPTION_DERIVED_PLAN};
75 
76         final String[] values = new String[] {
77                 CTSCommand.OPTION_CFG,
78                 CTSCommand.OPTION_PACKAGE,
79                 CTSCommand.OPTION_PACKAGE,
80                 CTSCommand.OPTION_PLAN,
81                 CTSCommand.OPTION_DEVICE,
82                 CTSCommand.OPTION_DEVICE,
83                 CTSCommand.OPTION_RESULT,
84                 CTSCommand.OPTION_RESULT,
85                 CTSCommand.OPTION_E,
86                 CTSCommand.OPTION_SESSION,
87                 CTSCommand.OPTION_SESSION,
88                 CTSCommand.OPTION_TEST,
89                 CTSCommand.OPTION_TEST,
90                 CTSCommand.OPTION_DERIVED_PLAN};
91 
92         for (int i = 0; i < keys.length; i++) {
sOptionMap.put(keys[i], values[i])93             sOptionMap.put(keys[i], values[i]);
94         }
95     }
96 
97     /**
98      * Parse the command line into array of argument.
99      *
100      * @param line The original command line.
101      * @return The command container.
102      */
parse(final String line)103     public static CommandParser parse(final String line)
104             throws UnknownCommandException, CommandNotFoundException {
105         ArrayList<String> arglist = new ArrayList<String>();
106 
107         Pattern p = Pattern.compile(COMMAND_PARSE_EXPRESSION);
108         Matcher m = p.matcher(line);
109         while (m.find()) {
110             arglist.add(m.group(1));
111         }
112         CommandParser cp = new CommandParser();
113         if (arglist.size() == 0) {
114             throw new CommandNotFoundException("No command");
115         }
116         cp.parse(arglist);
117         return cp;
118     }
119 
120     /**
121      * Parse the argument list.
122      *
123      * @param arglist The argument list.
124      */
parse(ArrayList<String> arglist)125     private void parse(ArrayList<String> arglist)
126             throws UnknownCommandException {
127         mArgLength = arglist.size();
128         int currentArgIndex = 0;
129         mAction = arglist.get(currentArgIndex).toLowerCase();
130         String originalOption = null;
131         String option = null;
132 
133         // parse action values
134         while (++currentArgIndex < arglist.size()) {
135             originalOption = arglist.get(currentArgIndex).trim();
136             if (originalOption.startsWith("-")) {
137                 if (isNumber(originalOption)) {
138                     mActionValues.add(originalOption);
139                 } else {
140                     --currentArgIndex;
141                     break;
142                 }
143             } else {
144                 mActionValues.add(originalOption);
145             }
146         }
147 
148         // parse option
149         while (++currentArgIndex < arglist.size()) {
150             originalOption = arglist.get(currentArgIndex).trim().toLowerCase();
151             option = originalOption;
152             if (!option.startsWith("-")) {
153                 throw new UnknownCommandException(
154                         "Option should start with '-'");
155             }
156 
157             option = inputToOption(option);
158             if (!sOptionsSet.contains(option)) {
159                 throw new UnknownCommandException("Unknown option :"
160                         + originalOption);
161             }
162 
163             if (mValues.containsKey(option)) {
164                 throw new UnknownCommandException("Duplicate option: "
165                          + originalOption);
166             }
167 
168             if (currentArgIndex + 1 == arglist.size()) {
169                 mValues.put(option, "");
170                 continue;
171             }
172 
173             String value = arglist.get(++currentArgIndex).trim();
174             if (value.startsWith("-")) {
175                 if (!isNumber(value)) {
176                     value = "";
177                     currentArgIndex--;
178                 }
179             }
180 
181             mValues.put(option, value);
182         }
183     }
184 
185     /**
186      * Translate the input to option.
187      *
188      * @param option The option typed in.
189      * @return The option found.
190      */
inputToOption(String option)191     private String inputToOption(String option) throws UnknownCommandException {
192         String op = sOptionMap.get(option);
193         if (op == null) {
194             throw new UnknownCommandException("Unknow option " + option);
195         }
196 
197         return op;
198     }
199 
200     /**
201      * Check if the option is a number.
202      *
203      * @param option The option.
204      * @return If the option is a number, return true; else, return false.
205      */
isNumber(String option)206     private boolean isNumber(String option) {
207         try {
208             Integer.parseInt(option);
209             return true;
210         } catch (Exception e) {
211             return false;
212         }
213     }
214 
215     /**
216      * Get the arguments size.
217      *
218      * @return The argument size.
219      */
getArgSize()220     public int getArgSize() {
221         return mArgLength;
222     }
223 
224     /**
225      * Get the action.
226      *
227      * @return The action.
228      */
getAction()229     public String getAction() {
230         return mAction;
231     }
232 
233     /**
234      * Get the option size.
235      *
236      * @return The option size.
237      */
getOptionSize()238     public int getOptionSize() {
239         return mValues.size();
240     }
241 
242     /**
243      * Get command option by hash key from parsed argument list.
244      *
245      * @param key The key.
246      * @return The value according to the key.
247      */
getValue(String key)248     public String getValue(String key) {
249         if (mValues.containsKey(key)) {
250             return mValues.get(key);
251         } else {
252             return null;
253         }
254     }
255 
256     /**
257      * Check if option list contains the key.
258      *
259      * @param key The key.
260      * @return If containing the key, return true; else, return false.
261      */
containsKey(String key)262     public boolean containsKey(String key) {
263         return mValues.containsKey(key);
264     }
265 
266     /**
267      * Get all of the option keys.
268      *
269      * @return All of the option keys.
270      */
getOptionKeys()271     public Set<String> getOptionKeys() {
272         return mValues.keySet();
273     }
274 
275     /**
276      * Get action list.
277      *
278      * @return The action list.
279      */
getActionValues()280     public ArrayList<String> getActionValues() {
281         return mActionValues;
282     }
283 
284     /**
285      * Remove a specific key.
286      *
287      * @param key The key to be removed.
288      */
removeKey(String key)289     public void removeKey(String key) {
290         mValues.remove(key);
291     }
292 
293 }
294