1 package net.sourceforge.argval.impl;
2
3
4 import java.io.File;
5 import java.net.MalformedURLException;
6 import java.net.URI;
7 import java.net.URISyntaxException;
8 import java.net.URL;
9 import java.text.DateFormat;
10 import java.text.ParseException;
11 import java.text.SimpleDateFormat;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Properties;
19 import java.util.Set;
20
21 import net.sourceforge.argval.ArgumentValidation;
22 import net.sourceforge.argval.lang.SystemConstants;
23 import net.sourceforge.argval.utils.StringUtil;
24
25 import org.apache.oro.text.regex.MalformedPatternException;
26 import org.apache.oro.text.regex.Pattern;
27 import org.apache.oro.text.regex.PatternCompiler;
28 import org.apache.oro.text.regex.PatternMatcher;
29 import org.apache.oro.text.regex.Perl5Compiler;
30 import org.apache.oro.text.regex.Perl5Matcher;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 public class ArgumentValidationImpl implements ArgumentValidation {
187
188 transient static Logger logger = LoggerFactory.getLogger(ArgumentValidationImpl.class);
189
190
191 private final static String SEPARATOR = System.getProperty(SystemConstants.LINE_SEPARATOR);
192
193 private List<String> errorList;
194
195 private Map<String, DateFormat> dateFormatMap;
196
197
198 private Map<String, Pattern> patternMap;
199
200
201
202 private PatternMatcher matcher;
203
204 private String validationTypeName = ArgumentValidation.VALIDATION_TYPE_NAME_ARGUMENT;
205
206
207 public ArgumentValidationImpl() {
208 this((String)null);
209 }
210
211 public ArgumentValidationImpl(String validationTypeName) {
212 super();
213 validationTypeName = polish(validationTypeName);
214
215 if (validationTypeName != null) {
216 this.validationTypeName = validationTypeName;
217 }
218 else {
219 this.validationTypeName = ArgumentValidation.VALIDATION_TYPE_NAME_ARGUMENT;
220 }
221 errorList = new ArrayList<String>();
222 dateFormatMap = new HashMap<String, DateFormat>();
223 patternMap = new HashMap<String, Pattern>();
224 }
225
226
227
228
229
230
231
232
233
234 public ArgumentValidationImpl(Map<String, String> patternMap) {
235 this(patternMap, new Perl5Compiler(), new Perl5Matcher());
236 }
237 public ArgumentValidationImpl(Map<String, String> patternMap, String validationTypeName) {
238 this(patternMap, new Perl5Compiler(), new Perl5Matcher(), validationTypeName);
239 }
240
241 public ArgumentValidationImpl(Map<String, String> patternMap, Map<String, String> dateFormatMap) {
242 this(patternMap, new Perl5Compiler(), new Perl5Matcher(), dateFormatMap);
243 }
244 public ArgumentValidationImpl(Map<String, String> patternMap, Map<String, String> dateFormatMap, String validationTypeName) {
245 this(patternMap, new Perl5Compiler(), new Perl5Matcher(), dateFormatMap, validationTypeName);
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 public ArgumentValidationImpl(Map<String, String> patternMap, PatternCompiler compiler, PatternMatcher matcher) {
270 this(patternMap, compiler, matcher, new HashMap<String, String>());
271 }
272 public ArgumentValidationImpl(Map<String, String> patternMap, PatternCompiler compiler, PatternMatcher matcher,
273 String validationTypeName) {
274 this(patternMap, compiler, matcher, new HashMap<String, String>(), validationTypeName);
275 }
276
277 public ArgumentValidationImpl(Map<String, String> patternMap,
278 PatternCompiler compiler, PatternMatcher matcher, Map<String, String> dateFormatMap) {
279 this(patternMap, compiler, matcher, dateFormatMap, null);
280 }
281
282
283
284
285
286
287
288
289
290 public ArgumentValidationImpl(Map<String, String> patternMap,
291 PatternCompiler compiler, PatternMatcher matcher, Map<String, String> dateFormatMap,
292 String validationTypeName) {
293 this();
294 if (patternMap == null) {
295 throw new IllegalArgumentException("Argument 'patternMap' should not be null.");
296 }
297 if (compiler == null) {
298 throw new IllegalArgumentException("Argument 'compiler' should not be null.");
299 }
300 if (matcher == null) {
301 throw new IllegalArgumentException("Argument 'matcher' should not be null.");
302 }
303 if (dateFormatMap == null) {
304 throw new IllegalArgumentException("Argument 'dateFormatMap' should not be null.");
305 }
306
307 validationTypeName = polish(validationTypeName);
308 if (validationTypeName == null) {
309 validationTypeName = ArgumentValidation.VALIDATION_TYPE_NAME_ARGUMENT;
310 }
311
312
313 this.matcher = matcher;
314
315 for (Iterator<String> iter = patternMap.keySet().iterator(); iter.hasNext();) {
316 String patternName = (String)iter.next();
317 String regExpStr = (String)patternMap.get(patternName);
318 try {
319 Pattern pattern = compiler.compile(regExpStr);
320 this.patternMap.put(patternName, pattern);
321 logger.debug("Created Pattern instance '" + patternName + "' with reg exp '" + regExpStr + "'.");
322 }
323 catch (MalformedPatternException mpe) {
324 logger.error("The pattern '" + patternName + "' with regular expression '" + regExpStr + "' is not correct.", mpe);
325 }
326 }
327
328 for (Iterator<String> iter = dateFormatMap.keySet().iterator(); iter.hasNext();) {
329 String dateFormatName = (String)iter.next();
330 String datePattern = (String)dateFormatMap.get(dateFormatName);
331 try {
332 DateFormat dateFormat = new SimpleDateFormat(datePattern);
333 this.dateFormatMap.put(dateFormatName, dateFormat);
334 logger.debug("Created DateFormat instance '" + dateFormatName + "' with simple date pattern '" + datePattern + "'.");
335 }
336 catch (NullPointerException npe) {
337 logger.error("The date format name '" + dateFormatName + "' with simple date pattern '" + datePattern + "' is not correct.", npe);
338 }
339 catch (IllegalArgumentException iae) {
340 logger.error("The date format name '" + dateFormatName + "' with simple date pattern '" + datePattern + "' is not correct.", iae);
341 }
342 }
343 }
344
345
346
347
348
349
350
351
352
353
354
355 public ArgumentValidationImpl(Properties properties, PatternCompiler compiler, PatternMatcher matcher) {
356 this(new PropertiesConfigurationManager().createPatternMap(properties), compiler, matcher, new PropertiesConfigurationManager().createDateFormatMap(properties));
357 }
358
359
360
361
362
363 public String getMessage() {
364 if (errorList.size() == 0) {
365 return null;
366 }
367 StringBuffer strBuf = new StringBuffer();
368 boolean isFirst = true;
369 Iterator<String> iter = errorList.iterator();
370 while (iter.hasNext()) {
371 strBuf.append(isFirst ? "" : SEPARATOR ).append(iter.next());
372 isFirst = false;
373 }
374
375 return strBuf.toString();
376 }
377
378
379
380
381
382 public boolean containsIllegalArgument() {
383 return errorList.size() > 0;
384 }
385
386
387
388
389
390 public IllegalArgumentException createIllegalArgumentException() {
391 return new IllegalArgumentException(getMessage());
392 }
393
394
395
396
397
398 public boolean isValidWhenNotNull(String argumentName, Object argumentValue) {
399 if (argumentValue == null) {
400 addError(argumentName, "should not be null.");
401 return false;
402 }
403 return true;
404 }
405
406 public boolean isValidWhenNotNullInCollection(String argumentName, Collection<?> argumentValue) {
407 if (isValidWhenNotNull(argumentName, argumentValue)) {
408 Object[] argValueArray = argumentValue.toArray(new Object[argumentValue.size()]);
409 for (int index = 0; index < argValueArray.length; index++) {
410 if (argValueArray[index] == null) {
411 return false;
412 }
413 }
414 return true;
415 }
416 return false;
417 }
418
419
420
421
422
423
424 public void addError(String argumentName, String message) {
425 errorList.add(validationTypeName + " '" + argumentName + "' " + message);
426 }
427
428 public void addError(String argumentName, String key, String message) {
429 errorList.add(validationTypeName + " '" + argumentName + "[" + key + "]' " + message);
430 }
431
432
433
434
435 public boolean isValidWhenBoolean(String argumentName, String argumentValue) {
436 if (isValidWhenNotNull(argumentName, argumentValue)) {
437 if (Boolean.FALSE.toString().toLowerCase().equals(argumentValue.toLowerCase())
438 || Boolean.TRUE.toString().toLowerCase().equals(argumentValue.toLowerCase())) {
439 return true;
440 }
441 else {
442 addError(argumentName, "should be a boolean.");
443 }
444 }
445 return false;
446 }
447
448
449
450
451
452 public boolean isValidWhenInteger(String argumentName, String argumentValue) {
453 try {
454 Integer.parseInt(argumentValue);
455 }
456 catch (NumberFormatException nfe) {
457 addError(argumentName, "should be a number which can be parsed into an Integer.");
458 return false;
459 }
460 return true;
461 }
462
463
464
465
466
467 public boolean isValidWhenLong(String argumentName, String argumentValue) {
468 try {
469 Long.parseLong(argumentValue);
470 }
471 catch (NumberFormatException nfe) {
472 addError(argumentName, "should be a number which can be parsed into a Long.");
473 return false;
474 }
475 return true;
476 }
477
478
479
480
481
482 public boolean isValidWhenDirectory(String argumentName, String argumentValue) {
483 if (! isValidWhenNotNull(argumentName, argumentValue)) {
484 return false;
485 }
486 return isValidWhenDirectory(argumentName, new File(argumentValue));
487 }
488 public boolean isValidWhenDirectory(String argumentName, File argumentValue) {
489 if (! isValidWhenNotNull(argumentName, argumentValue)) {
490 return false;
491 }
492 if (! argumentValue.isDirectory() || ! argumentValue.exists()) {
493 addError(argumentName, "with value '" + argumentValue + "' should be an existing path.");
494 return false;
495 }
496 return true;
497 }
498
499
500
501
502
503 public boolean isValidWhenFile(String argumentName, String argumentValue) {
504 if (! isValidWhenNotNull(argumentName, argumentValue)) {
505 return false;
506 }
507 return isValidWhenFile(argumentName, new File(argumentValue));
508 }
509 public boolean isValidWhenFile(String argumentName, File argumentValue) {
510 if (! isValidWhenNotNull(argumentName, argumentValue)) {
511 return false;
512 }
513 if (! argumentValue.isFile() || ! argumentValue.exists()) {
514 addError(argumentName, "with value '" + argumentValue + "' should be an existing file.");
515 return false;
516 }
517 return true;
518 }
519
520
521
522
523
524 public boolean isValidWhenUrl(String argumentName, String argumentValue) {
525 try {
526 new URL(argumentValue);
527 }
528 catch (MalformedURLException murle) {
529 addError(argumentName, "with value '" + argumentValue + "' is not a valid url.");
530 return false;
531 }
532 return true;
533 }
534
535
536 public boolean isValidWhenUri(String argumentName, String argumentValue) {
537 try {
538 new URI(argumentValue);
539 }
540 catch (URISyntaxException urise) {
541 addError(argumentName, "with value '" + argumentValue + "' is not a valid uri.");
542 return false;
543 }
544 return true;
545 }
546
547
548
549
550
551 public boolean isValidWhenInSet(String argumentName, String argumentValue, Set<String> argumentSet) {
552 if (isValidWhenNotNull(argumentName, argumentValue)) {
553 if (! argumentSet.contains(argumentValue)) {
554 StringBuffer strBuf = new StringBuffer();
555 strBuf.append(validationTypeName).append(" '").append(argumentName).append("' with value '").append(argumentValue);
556 strBuf.append("' should contain one of the following values { ");
557 boolean isFirst = true;
558 Iterator<String> iter = argumentSet.iterator();
559 while (iter.hasNext()) {
560 strBuf.append((isFirst) ? "'" : "', '");
561 strBuf.append(iter.next().toString());
562 isFirst = false;
563 }
564 if (!isFirst) {
565 strBuf.append("'");
566 }
567 strBuf.append(" }.");
568 errorList.add(strBuf.toString());
569 return false;
570 }
571 return true;
572 }
573 return false;
574 }
575
576
577
578 public boolean isValidWhenNotInSet(String argumentName, String argumentValue, Set<String> argumentSet) {
579 if (isValidWhenNotNull(argumentName, argumentValue)) {
580 if (argumentSet.contains(argumentValue)) {
581 StringBuffer strBuf = new StringBuffer();
582 strBuf.append(validationTypeName).append(" '").append(argumentName).append("' with value '").append(argumentValue);
583 strBuf.append("' should not be contained by the given set.");
584 errorList.add(strBuf.toString());
585 return false;
586 }
587 return true;
588 }
589 return false;
590 }
591
592
593 public boolean isValidCollectionWhenNoNulls(String argumentName, Collection<?> argumentValue) {
594 if (isValidWhenNotNull(argumentName, argumentValue)) {
595 if (argumentValue.size() > 0) {
596 Object[] argumentValueArray = argumentValue.toArray();
597 StringBuilder builder = new StringBuilder();
598 for (int index = 0; index < argumentValueArray.length; index++) {
599 Object element = argumentValueArray[index];
600 if (element instanceof String) {
601 String elementStr = polish((String)element);
602 if (elementStr == null) {
603 if (builder.length() > 0) {
604 builder.append(", ");
605 }
606 builder.append(index);
607 }
608 }
609 else if (element == null) {
610 if (builder.length() > 0) {
611 builder.append(", ");
612 }
613 builder.append(index);
614 }
615 }
616 if (builder.length() > 0) {
617 addError(argumentName , "is expected to have no null elements. Found null on following elements '"
618 + builder + "'.");
619 return false;
620 }
621 }
622 return true;
623 }
624 return false;
625 }
626
627
628 public boolean isValidCollectionWhenMinElements(String argumentName, Collection<?> argumentValue, int minElements) {
629 if (isValidWhenNotNull(argumentName, argumentValue)) {
630 if (argumentValue.size() < minElements) {
631 addError(argumentName, "is expected to have at least " + minElements + " element(s).");
632 return false;
633 }
634 return true;
635 }
636 return false;
637 }
638
639
640
641
642
643 public boolean isValidWhenGreaterThen(String argumentName, int argumentValue, int value) {
644 if (argumentValue > value) {
645 return true;
646 }
647 StringBuffer strBuf = new StringBuffer();
648 strBuf.append(validationTypeName).append(" '").append(argumentName).append("' should have at least a value of '")
649 .append(argumentValue).append("'. The given value is '")
650 .append(argumentValue).append("'.");
651 errorList.add(strBuf.toString());
652 return false;
653 }
654
655
656
657
658
659 public boolean isValidStringMinLength(String argumentName, String argumentValue, int minLength) {
660 if (isValidWhenNotNull(argumentName, argumentValue)) {
661 if (argumentValue.length() < minLength) {
662 createErrorInLength(argumentName, argumentValue, minLength, "a minimal");
663 return false;
664 }
665 }
666 return true;
667 }
668
669
670
671
672
673 public boolean isValidStringMaxLength(String argumentName, String argumentValue, int maxLength) {
674 if (isValidWhenNotNull(argumentName, argumentValue)) {
675 if (argumentValue.length() > maxLength) {
676 createErrorInLength(argumentName, argumentValue, maxLength, "a maximal");
677 return false;
678 }
679 }
680 return true;
681 }
682
683
684
685
686
687 public boolean isValidStringLength(String argumentName, String argumentValue, int length) {
688 if (isValidWhenNotNull(argumentName, argumentValue)) {
689 if (argumentValue.length() != length) {
690 createErrorInLength(argumentName, argumentValue, length, "an exact");
691 return false;
692 }
693 }
694 return true;
695 }
696
697
698
699
700
701 public boolean isValidStringMinAndMaxLength(String argumentName, String argumentValue, int minLength, int maxLength) {
702 if (isValidWhenNotNull(argumentName, argumentValue)) {
703 if (argumentValue.length() < minLength) {
704 createErrorInLength(argumentName, argumentValue, minLength, "a minimal");
705 return false;
706 }
707 else if (argumentValue.length() > maxLength) {
708 createErrorInLength(argumentName, argumentValue, maxLength, "a maximal");
709 return false;
710 }
711 }
712 return true;
713 }
714
715
716
717
718
719 public boolean isValidMatchingDateFormat(String argumentName, String argumentValue, DateFormat dateFormat) {
720 if (! isValidWhenNotNull(argumentName, argumentValue)) {
721 return false;
722 }
723 try {
724 dateFormat.parse(argumentValue);
725 }
726 catch (ParseException e) {
727
728 addError(argumentName, "with value '" + argumentValue
729 + "' does not match the given date format pattern '"
730 + ((dateFormat instanceof SimpleDateFormat)
731 ? ((SimpleDateFormat)dateFormat).toPattern() : dateFormat.toString())
732 + "'.");
733 return false;
734 }
735
736 return true;
737 }
738
739
740
741
742
743 public boolean isValidMatchingDateFormat(String argumentName, String argumentValue, String dateFormatName) {
744 if (dateFormatName != null && ! dateFormatMap.keySet().contains(dateFormatName)) {
745 throw new IllegalArgumentException("There is no date format known with the name '" + dateFormatName + "'.");
746 }
747 DateFormat dateFormat = (DateFormat)dateFormatMap.get(dateFormatName);
748
749 logger.debug((dateFormat != null) ? "Date format '" + dateFormatName + "' is available as '"
750 + ((dateFormat instanceof SimpleDateFormat)
751 ? ((SimpleDateFormat)dateFormat).toPattern() : dateFormat.toString())
752 + "'" : "No date format available.");
753
754 return isValidMatchingDateFormat(argumentName, argumentValue, dateFormat);
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772 }
773
774
775
776
777
778 public boolean isValidMatchingPattern(String argumentName, String argumentValue, String patternName) {
779 if (patternName != null && ! patternMap.keySet().contains(patternName)) {
780 throw new IllegalArgumentException("There is no pattern known with the name '" + patternName + "'.");
781 }
782 Pattern pattern = (Pattern)patternMap.get(patternName);
783 logger.debug((pattern != null) ? "Pattern '" + patternName + "' is available as '" + pattern.getPattern() + "'" : "No pattern available.");
784
785 if (! isValidWhenNotNull(argumentName, argumentValue)) {
786 return false;
787 }
788 if (! matcher.matches(argumentValue, pattern)) {
789 errorList.add("Argument '" + argumentName + "' with value '" + argumentValue
790 + "' does not match the given regular expression pattern '"
791 + pattern.getPattern() + "'.");
792 return false;
793 }
794
795 return true;
796 }
797
798
799
800
801
802
803
804
805
806
807 private void createErrorInLength(String argumentName, String argumentValue, int theLength, String lengthConditionStr) {
808 StringBuffer strBuf = new StringBuffer();
809 strBuf.append(validationTypeName).append(" '").append(argumentName).append("' should have ").append(lengthConditionStr);
810 strBuf.append(" length of '").append(theLength).append("'. The given value has a length of '");
811 strBuf.append(argumentValue.length()).append("'.");
812 errorList.add(strBuf.toString());
813 }
814
815
816
817
818
819 public void addError(String error) {
820 error = ArgumentValidationImpl.polish(error);
821 if (error == null) {
822 return;
823 }
824 errorList.add(error);
825 }
826
827
828
829
830
831 public Set<String> getPatternNames() {
832 return patternMap.keySet();
833 }
834
835
836
837
838
839 public Map<String, String> getPattern() {
840 Map<String, String> patternMap = new HashMap<String, String>();
841 for (Iterator<String> iter = this.patternMap.keySet().iterator(); iter.hasNext(); ) {
842 String patternName = (String)iter.next();
843 patternMap.put(patternName, ((Pattern)this.patternMap.get(patternName)).getPattern());
844 }
845 return patternMap;
846 }
847
848
849
850
851
852 public Pattern getPattern(String patternName) {
853 if (! patternMap.containsKey(patternName)) {
854 throw new IllegalArgumentException("Argument 'patternName' with the value '"
855 + patternName + "' is not known.");
856 }
857 return (Pattern)patternMap.get(patternName);
858 }
859
860
861
862
863
864 public String getRegularExpression(String patternName) {
865 if (! patternMap.containsKey(patternName)) {
866 throw new IllegalArgumentException("Argument 'patternName' with the value '"
867 + patternName + "' is not known.");
868 }
869 return ((Pattern)patternMap.get(patternName)).getPattern();
870 }
871
872
873
874
875
876
877
878
879
880
881 public static String polish(String text) {
882 if (text == null) {
883 return null;
884 }
885 text = text.trim();
886
887 if (text.length() == 0) {
888 return null;
889 }
890 return text;
891 }
892
893
894
895
896
897
898
899
900 public static String polishToLower(String text) {
901 text = ArgumentValidationImpl.polish(text);
902 return text == null ? null : text.toLowerCase();
903 }
904
905
906
907
908
909
910
911
912 public static String polishToUpper(String text) {
913 text = ArgumentValidationImpl.polish(text);
914 return text == null ? null : text.toUpperCase();
915 }
916
917 public boolean isValidNotNullForKey(String argumentName, Map<String, String> argumentValueMap, String key) {
918 String value = StringUtil.polish(argumentValueMap.get(key));
919 if (value == null) {
920 addError(argumentName, key, "should not be null.");
921 return false;
922 }
923 return true;
924 }
925
926 }