1
2
3
4
5
6
7
8
9
10
11
12 package org.hyphenType.lexerparser;
13
14 import java.io.File;
15 import java.lang.reflect.Array;
16 import java.lang.reflect.Method;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.hyphenType.datastructure.Options;
24 import org.hyphenType.datastructure.annotations.InputChannel;
25 import org.hyphenType.datastructure.lexer.LexToken;
26 import org.hyphenType.datastructure.lexer.option.LexOption;
27 import org.hyphenType.datastructure.lexer.option.LexOptionMapValue;
28 import org.hyphenType.datastructure.lexer.option.LexOptionValue;
29 import org.hyphenType.datastructure.lexer.simple.LexArgument;
30 import org.hyphenType.datastructure.parser.StructureArgument;
31 import org.hyphenType.datastructure.parser.option.StructureOption;
32 import org.hyphenType.datastructure.parser.option.StructureOptionArgument;
33 import org.hyphenType.datastructure.parser.option.StructureOptionMapValue;
34 import org.hyphenType.datastructure.parser.option.StructureOptionValue;
35 import org.hyphenType.datastructure.parser.simple.StructureSimpleArgument;
36 import org.hyphenType.input.StandardUserInput;
37 import org.hyphenType.input.UserInput;
38 import org.hyphenType.input.UserInputException;
39 import org.hyphenType.lexerparser.exceptions.MandatoryMapValueNotFoundException;
40 import org.hyphenType.lexerparser.exceptions.MandatorySimpleArgumentNotFoundException;
41 import org.hyphenType.lexerparser.exceptions.MandatoryValueNotFoundException;
42 import org.hyphenType.lexerparser.exceptions.OptionValuesException;
43 import org.hyphenType.lexerparser.exceptions.RegexMismatchException;
44 import org.hyphenType.lexerparser.exceptions.StringParseException;
45 import org.hyphenType.lexerparser.exceptions.StringParsingErrorException;
46 import org.hyphenType.util.soc.StringObjectConversion;
47 import org.hyphenType.util.soc.StringParsingError;
48
49
50
51
52
53
54
55
56
57 public class OptionValues<T extends Options<?>> {
58
59
60
61
62
63
64 private HashMap<Method, Object> map = new HashMap<Method, Object>();
65
66
67
68
69 private List<LexToken> unusedTokens = new ArrayList<LexToken>();
70
71
72
73
74 private LexerParser<T> lexPar;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public OptionValues(final List<LexToken> tokens, final LexerParser<T> parser) throws StringParsingErrorException, MandatoryValueNotFoundException, RegexMismatchException, StringParseException, MandatoryMapValueNotFoundException, MandatorySimpleArgumentNotFoundException {
96 this(tokens, parser, new StandardUserInput());
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 @SuppressWarnings("unchecked")
121 public OptionValues(final List<LexToken> tokens, final LexerParser<T> parser, final UserInput userInput) throws StringParsingErrorException, MandatoryValueNotFoundException, RegexMismatchException, StringParseException, MandatoryMapValueNotFoundException, MandatorySimpleArgumentNotFoundException {
122
123 int simpleArgumentIndex = 0;
124
125 this.lexPar = parser;
126
127 LexTokenStream lts = new LexTokenStream(tokens);
128
129 a: while (lts.hasFutureToken()) {
130
131 LexToken token = lts.consume();
132
133 if (token instanceof LexOption) {
134 LexOption lexOption = (LexOption) token;
135 StructureOption option = parser.searchOption(lexOption.value);
136
137 if (option == null) {
138 unusedTokens.add(lexOption);
139 continue a;
140 }
141 if (map.containsKey(option.method)) {
142 int x = (Integer) map.get(option.method);
143 x++;
144 map.put(option.method, x);
145 } else {
146 map.put(option.method, new Integer(1));
147 }
148
149 if (option.value != null) {
150 if (lts.hasFutureToken() && lts.futureToken() != null && lts.futureToken() instanceof LexOptionValue) {
151 String value = lts.consume().value;
152 try {
153 Object convertedValue;
154 if(option.value.arrayUseFileSeparator) {
155 convertedValue = StringObjectConversion.fromString(option.value.method.getReturnType(), value, true, File.pathSeparator);
156 } else {
157 convertedValue = StringObjectConversion.fromString(option.value.method.getReturnType(), value, true, option.value.arraySeparator);
158 }
159
160
161
162 if(option.value.method.getReturnType().isArray()) {
163 List list = new ArrayList();
164 for(int i=0; i<Array.getLength(convertedValue); i++) {
165 list.add(Array.get(convertedValue, i));
166 }
167 convertedValue = list;
168 }
169 map.put(option.value.method, convertedValue);
170 } catch (StringParsingError e) {
171 throw new StringParsingErrorException(e, lexPar.getOptionsInterface(), value, option.value.method.getReturnType());
172 }
173 } else if (option.value.mandatory) {
174 throw new MandatoryValueNotFoundException(lexPar.getOptionsInterface(), option.value.name, token.value);
175 }
176 }
177
178 if (option.map != null) {
179 if (lts.futureToken() != null && lts.futureToken() instanceof LexOptionMapValue) {
180
181 String value = lts.consume().value;
182 String k = value.substring(0, value.indexOf(lexPar.getArgsObject().equals()));
183 Object v;
184 try {
185 v = StringObjectConversion.fromString(option.map.valueType, value.substring(value.indexOf(parser.getArgsObject().equals()) + 1, value.length()));
186 } catch (StringParsingError e) {
187 throw new StringParsingErrorException(e, lexPar.getOptionsInterface(), value, option.map.valueType);
188 }
189
190 if (map.containsKey(option.map.method)) {
191 Map m = (Map) map.get(option.map.method);
192 m.put(k, v);
193 } else {
194 Map m = new HashMap();
195 m.put(k, v);
196 map.put(option.map.method, m);
197 }
198 } else if (option.map.mandatory) {
199 throw new MandatoryMapValueNotFoundException(lexPar.getOptionsInterface(), option.map.keyName, parser.getArgsObject().equals(), option.map.valueName, token.value);
200 }
201 }
202
203 for (StructureOptionArgument optionArgument : option.arguments) {
204 if (lts.hasFutureToken() && lts.futureToken() instanceof LexArgument) {
205
206 if (optionArgument.method.getReturnType().isArray()) {
207 Object v = checkConvert(optionArgument.method.getReturnType().getComponentType(), optionArgument.getName(), lts.consume().value, optionArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
208 registerOptionArgument(optionArgument, v);
209 while (lts.hasFutureToken() && lts.futureToken() instanceof LexArgument && check(lts.futureToken().value, optionArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen())) {
210 v = checkConvert(optionArgument.method.getReturnType().getComponentType(), optionArgument.getName(), lts.consume().value, optionArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
211 registerOptionArgument(optionArgument, v);
212 }
213 } else {
214 Object v = checkConvert(optionArgument.method.getReturnType(), optionArgument.getName(), lts.consume().value, optionArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
215 registerOptionArgument(optionArgument, v);
216 }
217 } else if (optionArgument.isMandatory()) {
218
219 try {
220 if (optionArgument.method.getReturnType().isArray()) {
221 Object[] inputs = userInput.readArray(optionArgument, lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
222 for (Object input : inputs) {
223 registerOptionArgument(optionArgument, input);
224 }
225 } else {
226 Object input = userInput.readString(optionArgument, lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
227 registerOptionArgument(optionArgument, input);
228 }
229 } catch (UserInputException e) {
230 throw new MandatoryValueNotFoundException(lexPar.getOptionsInterface(), optionArgument.getName(), option.alternatives.toString());
231 }
232 }
233 }
234
235 } else if (token instanceof LexArgument) {
236
237 LexArgument lexArgument = (LexArgument) token;
238
239 if (simpleArgumentIndex == parser.getSimpleArguments().size()) {
240 unusedTokens.add(token);
241 } else {
242
243 StructureSimpleArgument simpleArgument = parser.getSimpleArguments().get(simpleArgumentIndex);
244
245 if (!simpleArgument.getChannels().contains(InputChannel.ARGUMENT)) {
246 unusedTokens.add(token);
247 continue a;
248 }
249
250 if (simpleArgument.method.getReturnType().isArray()) {
251 List list;
252
253 if (!map.containsKey(simpleArgument.method)) {
254 list = new ArrayList();
255 } else {
256 list = (List) map.get(simpleArgument.method);
257 }
258
259 Object v = checkConvert(simpleArgument.method.getReturnType().getComponentType(), simpleArgument.getName(), lexArgument.value, simpleArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
260 list.add(v);
261 while (lts.hasFutureToken() && lts.futureToken() instanceof LexArgument && check(lts.futureToken().value, simpleArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen())) {
262 v = checkConvert(simpleArgument.method.getReturnType().getComponentType(), simpleArgument.getName(), lts.consume().value, simpleArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
263 list.add(v);
264 }
265
266 if (!map.containsKey(simpleArgument.method)) {
267 map.put(simpleArgument.method, list);
268 }
269 } else {
270 Object v = checkConvert(simpleArgument.method.getReturnType(), simpleArgument.getName(), lexArgument.value, simpleArgument.getRegex(), lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
271 map.put(simpleArgument.method, v);
272 }
273 simpleArgumentIndex++;
274 }
275 } else {
276 unusedTokens.add(token);
277 }
278 }
279
280
281
282
283
284
285 if (simpleArgumentIndex != parser.getSimpleArguments().size()) {
286 for (; simpleArgumentIndex < parser.getSimpleArguments().size(); simpleArgumentIndex++) {
287 StructureSimpleArgument simpleArgument = parser.getSimpleArguments().get(simpleArgumentIndex);
288 if (simpleArgument.isMandatory()) {
289
290
291
292
293
294
295
296 try {
297 if (simpleArgument.method.getReturnType().isArray()) {
298 Object[] inputs = userInput.readArray(simpleArgument, lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
299 for (Object input : inputs) {
300 registerOptionArgument(simpleArgument, input);
301 }
302 } else {
303 Object input = userInput.readString(simpleArgument, lexPar.getArgsObject().singleHyphen(), lexPar.getArgsObject().doubleHyphen());
304 registerOptionArgument(simpleArgument, input);
305 }
306 continue;
307 } catch (UserInputException e) {
308 throw new MandatorySimpleArgumentNotFoundException(e, lexPar.getOptionsInterface(), simpleArgument.getName());
309 }
310 }
311 }
312 }
313
314
315
316
317
318
319 for (Method method : map.keySet()) {
320 if (method.getReturnType().isArray()) {
321 List list = (List) map.get(method);
322
323 Object array = Array.newInstance(method.getReturnType().getComponentType(), list.size());
324 for (int i = 0; i < list.size(); i++) {
325 if (method.getReturnType().getComponentType().isPrimitive()) {
326 Array.set(array, i, StringObjectConversion.toPrimitive(method.getReturnType().getComponentType(), list.get(i)));
327 } else {
328 Array.set(array, i, method.getReturnType().getComponentType().cast(list.get(i)));
329 }
330 }
331
332 map.put(method, array);
333 }
334 }
335 }
336
337
338
339
340
341
342
343
344
345 @SuppressWarnings("unchecked")
346 private void registerOptionArgument(final StructureArgument optionArgument, final Object value) {
347
348 if (optionArgument.method.getReturnType().isArray()) {
349 if (map.containsKey(optionArgument.method)) {
350 List list = (List) map.get(optionArgument.method);
351 list.add(value);
352 } else {
353 List list = new ArrayList();
354 list.add(value);
355 map.put(optionArgument.method, list);
356 }
357 } else {
358 map.put(optionArgument.method, value);
359 }
360 }
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 private boolean check(final String value, final String regex, final String singleHyphen, final String doubleHyphen) {
378 String transformedRegex = regex.replace("\\h", singleHyphen);
379 transformedRegex = transformedRegex.replace("\\H", doubleHyphen);
380 return value.matches(transformedRegex);
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 private <Z> Z checkConvert(final Class<Z> clazz, final String name, final String value, final String regex, final String singleHyphen, final String doubleHyphen) throws RegexMismatchException, StringParseException {
405 if (!check(value, regex, singleHyphen, doubleHyphen)) {
406 throw new RegexMismatchException(lexPar.getOptionsInterface(), value, name, regex);
407 }
408 try {
409 return StringObjectConversion.fromString(clazz, value);
410 } catch (StringParsingError e) {
411 throw new StringParseException(e, lexPar.getOptionsInterface(), value);
412 }
413 }
414
415
416
417
418
419
420 public final int getParsedOptionValue(final StructureOption option) {
421 if (option == null) {
422 System.out.println("Ugh!");
423 }
424 if (map.containsKey(option.method)) {
425 return (Integer) map.get(option.method);
426 } else {
427 return 0;
428 }
429 }
430
431
432
433
434
435
436 @SuppressWarnings("unchecked")
437 public final Map getOptionMapValue(final StructureOptionMapValue optionMapValue) {
438 return (Map) map.get(optionMapValue.method);
439 }
440
441
442
443
444
445
446 public final Object getOptionValue(final StructureOptionValue optionValue) {
447 return map.get(optionValue.method);
448 }
449
450
451
452
453
454
455 public final Object getSimpleArgumentValue(final StructureSimpleArgument argument) {
456 if (argument == null) {
457 System.out.println("Ugh!");
458 }
459 if (map.containsKey(argument.method)) {
460 return map.get(argument.method);
461 } else {
462 if(argument.method.getReturnType().isArray()) {
463 return Array.newInstance(argument.method.getReturnType().getComponentType(), 0);
464 }
465 if(argument.method.getReturnType().equals(boolean.class) && argument.method.getReturnType().equals(Boolean.class)) {
466 return false;
467 }
468 if(argument.method.getReturnType().equals(int.class) && argument.method.getReturnType().equals(Integer.class)) {
469 return 0;
470 }
471
472 return null;
473 }
474 }
475
476
477
478
479 public final List<LexToken> unusedArguments() {
480 return Collections.unmodifiableList(unusedTokens);
481 }
482
483
484
485
486
487
488 public final Object getValue(final Method method) {
489 if (lexPar.searchElement(method) instanceof StructureOption) {
490 Object obj = map.get(method);
491 int n;
492 if (obj == null) {
493 n = 0;
494 } else {
495 n = (Integer) map.get(method);
496 }
497 if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)) {
498 return n > 0;
499 } else if (method.getReturnType().equals(int.class) || method.getReturnType().equals(Integer.class)) {
500 return n;
501 }
502 }
503
504 return map.get(method);
505 }
506
507 @Override
508 public final int hashCode() {
509 return toString().hashCode();
510 }
511
512 @Override
513 public final String toString() {
514 String result = "[";
515 for (Method method : map.keySet()) {
516 if (method.getReturnType().isArray()) {
517 result += String.format("%s=[", method.getName());
518 Object array = map.get(method);
519 for (int i = 0; i < Array.getLength(array); i++) {
520 result += String.format("%s, ", method.getName(), Array.get(array, i));
521 }
522 if (Array.getLength(array) > 0) {
523 result = result.substring(0, result.length() - 2);
524 }
525 result += "], ";
526 } else {
527 result += String.format("%s=%s, ", method.getName(), map.get(method));
528 }
529 }
530 result += "unusedTokens=" + unusedTokens.toString() + "]";
531 return result;
532 }
533 }