6
|
1 /**
|
|
2 *
|
|
3 * Copyright INRA-URGI 2009-2010
|
|
4 *
|
|
5 * This software is governed by the CeCILL license under French law and
|
|
6 * abiding by the rules of distribution of free software. You can use,
|
|
7 * modify and/ or redistribute the software under the terms of the CeCILL
|
|
8 * license as circulated by CEA, CNRS and INRIA at the following URL
|
|
9 * "http://www.cecill.info".
|
|
10 *
|
|
11 * As a counterpart to the access to the source code and rights to copy,
|
|
12 * modify and redistribute granted by the license, users are provided only
|
|
13 * with a limited warranty and the software's author, the holder of the
|
|
14 * economic rights, and the successive licensors have only limited
|
|
15 * liability.
|
|
16 *
|
|
17 * In this respect, the user's attention is drawn to the risks associated
|
|
18 * with loading, using, modifying and/or developing or reproducing the
|
|
19 * software by the user in light of its specific status of free software,
|
|
20 * that may mean that it is complicated to manipulate, and that also
|
|
21 * therefore means that it is reserved for developers and experienced
|
|
22 * professionals having in-depth computer knowledge. Users are therefore
|
|
23 * encouraged to load and test the software's suitability as regards their
|
|
24 * requirements in conditions enabling the security of their systems and/or
|
|
25 * data to be ensured and, more generally, to use and operate it in the
|
|
26 * same conditions as regards security.
|
|
27 *
|
|
28 * The fact that you are presently reading this means that you have had
|
|
29 * knowledge of the CeCILL license and that you accept its terms.
|
|
30 *
|
|
31 */
|
|
32 import java.util.*;
|
|
33 import java.io.File;
|
|
34 import java.io.*;
|
|
35 import java.util.regex.*;
|
|
36
|
|
37 public class PythonHelperReader {
|
|
38
|
|
39 String fileName;
|
|
40 Program program;
|
|
41 BufferedReader reader;
|
|
42 String message;
|
|
43
|
|
44 public PythonHelperReader(String fileName) {
|
|
45 this.fileName = fileName;
|
|
46 this.reader = reader;
|
|
47 this.message = null;
|
|
48 }
|
|
49
|
|
50 public void setReader(BufferedReader reader) {
|
|
51 this.reader = reader;
|
|
52 }
|
|
53
|
|
54 public void run() {
|
|
55 this.program = new Program();
|
|
56 boolean inBeginning = true;
|
|
57 boolean inUsage = false;
|
|
58 boolean afterUsage = false;
|
|
59 boolean inDescription = false;
|
|
60 boolean afterDescription = false;
|
|
61 boolean inOptions = false;
|
|
62 boolean inOptionBlank = false;
|
|
63 boolean inError = false;
|
|
64 String usage = null;
|
|
65 String description = null;
|
|
66 String option = null;
|
|
67 Vector <String> options = new Vector < String > ();
|
|
68 String[] optionSplitted;
|
|
69
|
|
70 // Parse file
|
|
71 try {
|
|
72 String line = null;
|
|
73
|
|
74 while ((line = reader.readLine()) != null) {
|
|
75 line = line.trim();
|
|
76 if (line.startsWith("Traceback")) {
|
|
77 this.message = "Problem with header of '" + this.fileName + "':\n" + line + "\n";
|
|
78 inError = true;
|
|
79 inBeginning = false;
|
|
80 inUsage = false;
|
|
81 afterUsage = false;
|
|
82 inDescription = false;
|
|
83 afterDescription = false;
|
|
84 inOptions = false;
|
|
85 inOptionBlank = false;
|
|
86 }
|
|
87 else if (inError) {
|
|
88 this.message += line + "\n";
|
|
89 }
|
|
90 else if (inBeginning) {
|
|
91 if (line.startsWith("Usage:")) {
|
|
92 inUsage = true;
|
|
93 inBeginning = false;
|
|
94 usage = line;
|
|
95 }
|
|
96 }
|
|
97 else if (inUsage) {
|
|
98 if ("".equals(line)) {
|
|
99 inUsage = false;
|
|
100 afterUsage = true;
|
|
101 }
|
|
102 else {
|
|
103 usage += " " + line;
|
|
104 }
|
|
105 }
|
|
106 else if (afterUsage) {
|
|
107 if (! "".equals(line)) {
|
|
108 description = line;
|
|
109 afterUsage = false;
|
|
110 inDescription = true;
|
|
111 }
|
|
112 }
|
|
113 else if (inDescription) {
|
|
114 if ("".equals(line)) {
|
|
115 inDescription = false;
|
|
116 afterDescription = true;
|
|
117 }
|
|
118 else {
|
|
119 description += " " + line;
|
|
120 }
|
|
121 }
|
|
122 else if (afterDescription) {
|
|
123 if (! "".equals(line)) {
|
|
124 afterDescription = false;
|
|
125 inOptions = true;
|
|
126 }
|
|
127 }
|
|
128 else if (inOptions) {
|
|
129 if ("".equals(line)) {
|
|
130 inOptions = false;
|
|
131 inOptionBlank = true;
|
|
132 }
|
|
133 else {
|
|
134 if (option == null) {
|
|
135 option = line;
|
|
136 }
|
|
137 else {
|
|
138 if (line.charAt(0) == '-') {
|
|
139 options.add(option);
|
|
140 option = line;
|
|
141 }
|
|
142 else {
|
|
143 option += " " + line;
|
|
144 }
|
|
145 }
|
|
146 }
|
|
147 }
|
|
148 else if (inOptionBlank) {
|
|
149 if (! "".equals(line)) {
|
|
150 inOptionBlank = false;
|
|
151 inOptions = true;
|
|
152 }
|
|
153 }
|
|
154 else {
|
|
155 this.message = "Something is wrong in the file '" + this.fileName + "'.";
|
|
156 return;
|
|
157 }
|
|
158 }
|
|
159
|
|
160 reader.close();
|
|
161 }
|
|
162 catch (FileNotFoundException e) {
|
|
163 this.message = "File " + this.fileName + " not found";
|
|
164 return;
|
|
165 }
|
|
166 catch (IOException e) {
|
|
167 this.message = "IOException while reading file " + this.fileName;
|
|
168 return;
|
|
169 }
|
|
170
|
|
171 if (inError) {
|
|
172 return;
|
|
173 }
|
|
174
|
|
175 if (option != null) {
|
|
176 options.add(option);
|
|
177 }
|
|
178
|
|
179 HashMap < String, ProgramOption > identifierToOptions = new HashMap < String, ProgramOption > ();
|
|
180 HashMap < ProgramOption, String > associatedOption = new HashMap < ProgramOption, String > ();
|
|
181
|
|
182 if (usage == null) {
|
|
183 this.message = "Cannot read the usage of file " + this.fileName;
|
|
184 return;
|
|
185 }
|
|
186 program.setShortName(usage.split(" ")[1].trim());
|
|
187 program.setName(description.split(":")[0].trim());
|
|
188
|
|
189 Pattern pattern = Pattern.compile("\\[Category: .*\\]");
|
|
190 Matcher matcher = pattern.matcher(description);
|
|
191 if (matcher.find()) {
|
|
192 program.setSection(description.substring(matcher.start() + "[Category: ".length(), matcher.end() - 1));
|
|
193 program.setDescription(description.substring(0, matcher.start() - 1).trim());
|
|
194 }
|
|
195 else {
|
|
196 this.message = "Cannot find category in description '" + description + "' in file " + this.fileName;
|
|
197 return;
|
|
198 }
|
|
199 for (int i = 0; i < options.size(); i++) {
|
|
200 option = options.get(i).replace("\t", " ");
|
|
201 optionSplitted = option.split(" ");
|
|
202 option = "";
|
|
203 for (int j = 3; j < optionSplitted.length; j++) {
|
|
204 option += optionSplitted[j] + " ";
|
|
205 }
|
|
206
|
|
207 String identifier = optionSplitted[0].replace("-", "").replace(",", "");
|
|
208 // Skip -h and -v options
|
|
209 if (("h".equals(identifier)) || ("v".equals(identifier)))
|
|
210 continue;
|
|
211
|
|
212 ProgramOption programOption = new ProgramOption();
|
|
213 programOption.setIdentifier("-" + identifier);
|
|
214 programOption.setComment(option.substring(0, option.indexOf("[")).trim());
|
|
215 identifierToOptions.put(identifier, programOption);
|
|
216
|
|
217 pattern = Pattern.compile("\\[[^\\]]*\\]");
|
|
218 matcher = pattern.matcher(option);
|
|
219 while (matcher.find()) {
|
|
220 String inner = option.substring(matcher.start()+1, matcher.end()-1);
|
|
221 if (inner.contains(":")) {
|
|
222 String type = inner.substring(0, inner.indexOf(":")).trim();
|
|
223 String value = inner.substring(inner.indexOf(":")+1).trim();
|
|
224 // Types of the options
|
|
225 if ("format".compareToIgnoreCase(type) == 0) {
|
|
226 String currentWord = "";
|
|
227 String rest = "";
|
|
228 if (value.contains(" ")) {
|
|
229 int pos = value.indexOf(" ");
|
|
230 currentWord = value.substring(0, pos);
|
|
231 rest = value.substring(pos+1);
|
|
232 }
|
|
233 else {
|
|
234 currentWord = value;
|
|
235 }
|
|
236 // Output file type
|
|
237 if ("output".compareToIgnoreCase(currentWord) == 0) {
|
|
238 programOption.setInput(false);
|
|
239 int pos = rest.indexOf(" ");
|
|
240 currentWord = rest.substring(0, pos).trim();
|
|
241 rest = rest.substring(pos+1).trim();
|
|
242 }
|
|
243 // File (input or output file)
|
|
244 if ("file".compareToIgnoreCase(currentWord) == 0) {
|
|
245 programOption.setType("file");
|
|
246 // Format given by an associated option (to be found later)
|
|
247 if (rest.startsWith("in format given by ")) {
|
|
248 associatedOption.put(programOption, rest.substring(rest.indexOf("format given by ") + "format given by ".length() + 1).trim());
|
|
249 }
|
|
250 else {
|
|
251 if (! rest.startsWith("in ")) {
|
|
252 this.message = "Descriptor " + option + " does not have a proper format.";
|
|
253 return;
|
|
254 }
|
|
255 rest = rest.substring("in ".length());
|
|
256 int pos = rest.indexOf(" format");
|
|
257 if (pos == -1) {
|
|
258 this.message = "Descriptor " + option + " does not have a proper format.";
|
|
259 return;
|
|
260 }
|
|
261 programOption.setFormat(rest.substring(0, pos).trim().toLowerCase().split(" or "));
|
|
262 }
|
|
263 }
|
|
264 // Format type
|
|
265 else if (rest.endsWith("file format")) {
|
|
266 programOption.setFormat((currentWord + " " + rest.substring(0, rest.indexOf("file format"))).trim().toLowerCase().split(" or "));
|
|
267 programOption.setType("format");
|
|
268 }
|
|
269 // Choice type
|
|
270 else if ("choice".compareToIgnoreCase(currentWord) == 0) {
|
|
271 programOption.setChoices(rest.replace("(", "").replace(")", "").split(", "));
|
|
272 programOption.setType("choice");
|
|
273 }
|
|
274 // Boolean type
|
|
275 else if ("bool".compareToIgnoreCase(currentWord) == 0) {
|
|
276 programOption.setType("boolean");
|
|
277 }
|
|
278 // Other type
|
|
279 else {
|
|
280 programOption.setType(currentWord);
|
|
281 }
|
|
282 }
|
|
283 // Default value
|
|
284 else if ("default".compareToIgnoreCase(type) == 0) {
|
|
285 programOption.setDefault(value);
|
|
286 }
|
|
287 else {
|
|
288 this.message = "Do not understand option descriptor '" + inner + "'.";
|
|
289 return;
|
|
290 }
|
|
291 }
|
|
292 else {
|
|
293 // Compulsory option
|
|
294 if ("compulsory".compareToIgnoreCase(inner) == 0) {
|
|
295 programOption.setCompulsory(true);
|
|
296 }
|
|
297 else {
|
|
298 this.message = "Do not understand option descriptor '" + inner + "'.";
|
|
299 return;
|
|
300 }
|
|
301 }
|
|
302 }
|
|
303 program.addOption(programOption);
|
|
304 }
|
|
305
|
|
306 // Set associated option
|
|
307 Iterator it = associatedOption.keySet().iterator();
|
|
308 while (it.hasNext()) {
|
|
309 ProgramOption programOption = (ProgramOption) it.next();
|
|
310 programOption.setAssociatedOption(identifierToOptions.get(associatedOption.get(programOption)));
|
|
311 }
|
|
312 }
|
|
313
|
|
314 public String getMessage () {
|
|
315 return this.message;
|
|
316 }
|
|
317
|
|
318 public Program getProgram () {
|
|
319 return this.program;
|
|
320 }
|
|
321 }
|
|
322
|
|
323
|