1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.validator;
18
19 import java.io.Serializable;
20 import java.lang.reflect.InvocationTargetException;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.StringTokenizer;
30
31 import org.apache.commons.beanutils.PropertyUtils;
32 import org.apache.commons.collections.FastHashMap;
33 import org.apache.commons.validator.util.ValidatorUtils;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class Field implements Cloneable, Serializable {
49
50 private static final long serialVersionUID = -8502647722530192185L;
51
52
53
54
55
56 private static final String DEFAULT_ARG =
57 "org.apache.commons.validator.Field.DEFAULT";
58
59
60
61
62 public static final String TOKEN_INDEXED = "[]";
63
64
65
66
67 protected static final String TOKEN_START = "${";
68
69
70
71
72 protected static final String TOKEN_END = "}";
73
74
75
76
77 protected static final String TOKEN_VAR = "var:";
78
79
80
81
82 protected String property = null;
83
84
85
86
87 protected String indexedProperty = null;
88
89
90
91
92 protected String indexedListProperty = null;
93
94
95
96
97 protected String key = null;
98
99
100
101
102 protected String depends = null;
103
104
105
106
107 protected int page = 0;
108
109
110
111
112
113
114 protected boolean clientValidation = true;
115
116
117
118
119 protected int fieldOrder = 0;
120
121
122
123
124
125
126
127 private List dependencyList = Collections.synchronizedList(new ArrayList());
128
129
130
131
132 protected FastHashMap hVars = new FastHashMap();
133
134
135
136
137 protected FastHashMap hMsgs = new FastHashMap();
138
139
140
141
142
143
144
145 protected Map[] args = new Map[0];
146
147
148
149
150
151
152 public int getPage() {
153 return this.page;
154 }
155
156
157
158
159
160
161 public void setPage(int page) {
162 this.page = page;
163 }
164
165
166
167
168
169 public int getFieldOrder() {
170 return this.fieldOrder;
171 }
172
173
174
175
176
177 public void setFieldOrder(int fieldOrder) {
178 this.fieldOrder = fieldOrder;
179 }
180
181
182
183
184
185 public String getProperty() {
186 return this.property;
187 }
188
189
190
191
192
193 public void setProperty(String property) {
194 this.property = property;
195 }
196
197
198
199
200
201
202
203 public String getIndexedProperty() {
204 return this.indexedProperty;
205 }
206
207
208
209
210
211 public void setIndexedProperty(String indexedProperty) {
212 this.indexedProperty = indexedProperty;
213 }
214
215
216
217
218
219
220
221
222
223 public String getIndexedListProperty() {
224 return this.indexedListProperty;
225 }
226
227
228
229
230
231 public void setIndexedListProperty(String indexedListProperty) {
232 this.indexedListProperty = indexedListProperty;
233 }
234
235
236
237
238
239 public String getDepends() {
240 return this.depends;
241 }
242
243
244
245
246
247 public void setDepends(String depends) {
248 this.depends = depends;
249
250 this.dependencyList.clear();
251
252 StringTokenizer st = new StringTokenizer(depends, ",");
253 while (st.hasMoreTokens()) {
254 String depend = st.nextToken().trim();
255
256 if (depend != null && depend.length() > 0) {
257 this.dependencyList.add(depend);
258 }
259 }
260 }
261
262
263
264
265
266 public void addMsg(Msg msg) {
267 hMsgs.put(msg.getName(), msg);
268 }
269
270
271
272
273
274
275 public String getMsg(String key) {
276 Msg msg = getMessage(key);
277 return (msg == null) ? null : msg.getKey();
278 }
279
280
281
282
283
284
285
286 public Msg getMessage(String key) {
287 return (Msg) hMsgs.get(key);
288 }
289
290
291
292
293
294
295
296 public Map getMessages() {
297 return Collections.unmodifiableMap(hMsgs);
298 }
299
300
301
302
303
304
305
306
307 public boolean isClientValidation() {
308 return this.clientValidation;
309 }
310
311
312
313
314
315
316
317
318 public void setClientValidation(boolean clientValidation) {
319 this.clientValidation = clientValidation;
320 }
321
322
323
324
325
326
327 public void addArg(Arg arg) {
328
329 if (arg == null || arg.getKey() == null || arg.getKey().length() == 0) {
330 return;
331 }
332
333 determineArgPosition(arg);
334 ensureArgsCapacity(arg);
335
336 Map argMap = this.args[arg.getPosition()];
337 if (argMap == null) {
338 argMap = new HashMap();
339 this.args[arg.getPosition()] = argMap;
340 }
341
342 if (arg.getName() == null) {
343 argMap.put(DEFAULT_ARG, arg);
344 } else {
345 argMap.put(arg.getName(), arg);
346 }
347
348 }
349
350
351
352
353 private void determineArgPosition(Arg arg) {
354
355 int position = arg.getPosition();
356
357
358 if (position >= 0) {
359 return;
360 }
361
362
363 if (args == null || args.length == 0) {
364 arg.setPosition(0);
365 return;
366 }
367
368
369
370 String key = arg.getName() == null ? DEFAULT_ARG : arg.getName();
371 int lastPosition = -1;
372 int lastDefault = -1;
373 for (int i = 0; i < args.length; i++) {
374 if (args[i] != null && args[i].containsKey(key)) {
375 lastPosition = i;
376 }
377 if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) {
378 lastDefault = i;
379 }
380 }
381
382 if (lastPosition < 0) {
383 lastPosition = lastDefault;
384 }
385
386
387 arg.setPosition(++lastPosition);
388
389 }
390
391
392
393
394
395
396
397 private void ensureArgsCapacity(Arg arg) {
398 if (arg.getPosition() >= this.args.length) {
399 Map[] newArgs = new Map[arg.getPosition() + 1];
400 System.arraycopy(this.args, 0, newArgs, 0, this.args.length);
401 this.args = newArgs;
402 }
403 }
404
405
406
407
408
409
410
411 public Arg getArg(int position) {
412 return this.getArg(DEFAULT_ARG, position);
413 }
414
415
416
417
418
419
420
421
422
423
424
425 public Arg getArg(String key, int position) {
426 if ((position >= this.args.length) || (this.args[position] == null)) {
427 return null;
428 }
429
430 Arg arg = (Arg) args[position].get(key);
431
432
433
434 if ((arg == null) && key.equals(DEFAULT_ARG)) {
435 return null;
436 }
437
438 return (arg == null) ? this.getArg(position) : arg;
439 }
440
441
442
443
444
445
446
447
448 public Arg[] getArgs(String key){
449 Arg[] args = new Arg[this.args.length];
450
451 for (int i = 0; i < this.args.length; i++) {
452 args[i] = this.getArg(key, i);
453 }
454
455 return args;
456 }
457
458
459
460
461
462 public void addVar(Var v) {
463 this.hVars.put(v.getName(), v);
464 }
465
466
467
468
469
470
471
472
473 public void addVar(String name, String value, String jsType) {
474 this.addVar(new Var(name, value, jsType));
475 }
476
477
478
479
480
481
482 public Var getVar(String mainKey) {
483 return (Var) hVars.get(mainKey);
484 }
485
486
487
488
489
490
491 public String getVarValue(String mainKey) {
492 String value = null;
493
494 Object o = hVars.get(mainKey);
495 if (o != null && o instanceof Var) {
496 Var v = (Var) o;
497 value = v.getValue();
498 }
499
500 return value;
501 }
502
503
504
505
506
507
508 public Map getVars() {
509 return Collections.unmodifiableMap(hVars);
510 }
511
512
513
514
515
516 public String getKey() {
517 if (this.key == null) {
518 this.generateKey();
519 }
520
521 return this.key;
522 }
523
524
525
526
527
528
529 public void setKey(String key) {
530 this.key = key;
531 }
532
533
534
535
536
537
538
539 public boolean isIndexed() {
540 return ((indexedListProperty != null && indexedListProperty.length() > 0));
541 }
542
543
544
545
546 public void generateKey() {
547 if (this.isIndexed()) {
548 this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
549 } else {
550 this.key = this.property;
551 }
552 }
553
554
555
556
557
558 void process(Map globalConstants, Map constants) {
559 this.hMsgs.setFast(false);
560 this.hVars.setFast(true);
561
562 this.generateKey();
563
564
565 for (Iterator i = constants.entrySet().iterator(); i.hasNext();) {
566 Entry entry = (Entry) i.next();
567 String key = (String) entry.getKey();
568 String key2 = TOKEN_START + key + TOKEN_END;
569 String replaceValue = (String) entry.getValue();
570
571 property = ValidatorUtils.replace(property, key2, replaceValue);
572
573 processVars(key2, replaceValue);
574
575 this.processMessageComponents(key2, replaceValue);
576 }
577
578
579 for (Iterator i = globalConstants.entrySet().iterator(); i.hasNext();) {
580 Entry entry = (Entry) i.next();
581 String key = (String) entry.getKey();
582 String key2 = TOKEN_START + key + TOKEN_END;
583 String replaceValue = (String) entry.getValue();
584
585 property = ValidatorUtils.replace(property, key2, replaceValue);
586
587 processVars(key2, replaceValue);
588
589 this.processMessageComponents(key2, replaceValue);
590 }
591
592
593 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
594 String key = (String) i.next();
595 String key2 = TOKEN_START + TOKEN_VAR + key + TOKEN_END;
596 Var var = this.getVar(key);
597 String replaceValue = var.getValue();
598
599 this.processMessageComponents(key2, replaceValue);
600 }
601
602 hMsgs.setFast(true);
603 }
604
605
606
607
608 private void processVars(String key, String replaceValue) {
609 Iterator i = this.hVars.keySet().iterator();
610 while (i.hasNext()) {
611 String varKey = (String) i.next();
612 Var var = this.getVar(varKey);
613
614 var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue));
615 }
616
617 }
618
619
620
621
622 private void processMessageComponents(String key, String replaceValue) {
623 String varKey = TOKEN_START + TOKEN_VAR;
624
625 if (key != null && !key.startsWith(varKey)) {
626 for (Iterator i = hMsgs.values().iterator(); i.hasNext();) {
627 Msg msg = (Msg) i.next();
628 msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue));
629 }
630 }
631
632 this.processArg(key, replaceValue);
633 }
634
635
636
637
638
639 private void processArg(String key, String replaceValue) {
640 for (int i = 0; i < this.args.length; i++) {
641
642 Map argMap = this.args[i];
643 if (argMap == null) {
644 continue;
645 }
646
647 Iterator iter = argMap.values().iterator();
648 while (iter.hasNext()) {
649 Arg arg = (Arg) iter.next();
650
651 if (arg != null) {
652 arg.setKey(
653 ValidatorUtils.replace(arg.getKey(), key, replaceValue));
654 }
655 }
656 }
657 }
658
659
660
661
662
663
664 public boolean isDependency(String validatorName) {
665 return this.dependencyList.contains(validatorName);
666 }
667
668
669
670
671
672
673 public List getDependencyList() {
674 return Collections.unmodifiableList(this.dependencyList);
675 }
676
677
678
679
680
681 public Object clone() {
682 Field field = null;
683 try {
684 field = (Field) super.clone();
685 } catch(CloneNotSupportedException e) {
686 throw new RuntimeException(e.toString());
687 }
688
689 field.args = new Map[this.args.length];
690 for (int i = 0; i < this.args.length; i++) {
691 if (this.args[i] == null) {
692 continue;
693 }
694
695 Map argMap = new HashMap(this.args[i]);
696 Iterator iter = argMap.entrySet().iterator();
697 while (iter.hasNext()) {
698 Entry entry = (Entry) iter.next();
699 String validatorName = (String) entry.getKey();
700 Arg arg = (Arg) entry.getValue();
701 argMap.put(validatorName, arg.clone());
702 }
703 field.args[i] = argMap;
704 }
705
706 field.hVars = ValidatorUtils.copyFastHashMap(hVars);
707 field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
708
709 return field;
710 }
711
712
713
714
715
716 public String toString() {
717 StringBuffer results = new StringBuffer();
718
719 results.append("\t\tkey = " + key + "\n");
720 results.append("\t\tproperty = " + property + "\n");
721 results.append("\t\tindexedProperty = " + indexedProperty + "\n");
722 results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
723 results.append("\t\tdepends = " + depends + "\n");
724 results.append("\t\tpage = " + page + "\n");
725 results.append("\t\tfieldOrder = " + fieldOrder + "\n");
726
727 if (hVars != null) {
728 results.append("\t\tVars:\n");
729 for (Iterator i = hVars.keySet().iterator(); i.hasNext();) {
730 Object key = i.next();
731 results.append("\t\t\t");
732 results.append(key);
733 results.append("=");
734 results.append(hVars.get(key));
735 results.append("\n");
736 }
737 }
738
739 return results.toString();
740 }
741
742
743
744
745
746
747
748
749 Object[] getIndexedProperty(Object bean) throws ValidatorException {
750 Object indexedProperty = null;
751
752 try {
753 indexedProperty =
754 PropertyUtils.getProperty(bean, this.getIndexedListProperty());
755
756 } catch(IllegalAccessException e) {
757 throw new ValidatorException(e.getMessage());
758 } catch(InvocationTargetException e) {
759 throw new ValidatorException(e.getMessage());
760 } catch(NoSuchMethodException e) {
761 throw new ValidatorException(e.getMessage());
762 }
763
764 if (indexedProperty instanceof Collection) {
765 return ((Collection) indexedProperty).toArray();
766
767 } else if (indexedProperty.getClass().isArray()) {
768 return (Object[]) indexedProperty;
769
770 } else {
771 throw new ValidatorException(this.getKey() + " is not indexed");
772 }
773
774 }
775
776
777
778
779
780
781
782 private int getIndexedPropertySize(Object bean) throws ValidatorException {
783 Object indexedProperty = null;
784
785 try {
786 indexedProperty =
787 PropertyUtils.getProperty(bean, this.getIndexedListProperty());
788
789 } catch(IllegalAccessException e) {
790 throw new ValidatorException(e.getMessage());
791 } catch(InvocationTargetException e) {
792 throw new ValidatorException(e.getMessage());
793 } catch(NoSuchMethodException e) {
794 throw new ValidatorException(e.getMessage());
795 }
796
797 if (indexedProperty == null) {
798 return 0;
799 } else if (indexedProperty instanceof Collection) {
800 return ((Collection)indexedProperty).size();
801 } else if (indexedProperty.getClass().isArray()) {
802 return ((Object[])indexedProperty).length;
803 } else {
804 throw new ValidatorException(this.getKey() + " is not indexed");
805 }
806
807 }
808
809
810
811
812
813
814 private boolean validateForRule(
815 ValidatorAction va,
816 ValidatorResults results,
817 Map actions,
818 Map params,
819 int pos)
820 throws ValidatorException {
821
822 ValidatorResult result = results.getValidatorResult(this.getKey());
823 if (result != null && result.containsAction(va.getName())) {
824 return result.isValid(va.getName());
825 }
826
827 if (!this.runDependentValidators(va, results, actions, params, pos)) {
828 return false;
829 }
830
831 return va.executeValidationMethod(this, params, results, pos);
832 }
833
834
835
836
837
838
839
840
841
842
843
844 private boolean runDependentValidators(
845 ValidatorAction va,
846 ValidatorResults results,
847 Map actions,
848 Map params,
849 int pos)
850 throws ValidatorException {
851
852 List dependentValidators = va.getDependencyList();
853
854 if (dependentValidators.isEmpty()) {
855 return true;
856 }
857
858 Iterator iter = dependentValidators.iterator();
859 while (iter.hasNext()) {
860 String depend = (String) iter.next();
861
862 ValidatorAction action = (ValidatorAction) actions.get(depend);
863 if (action == null) {
864 this.handleMissingAction(depend);
865 }
866
867 if (!this.validateForRule(action, results, actions, params, pos)) {
868 return false;
869 }
870 }
871
872 return true;
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886 public ValidatorResults validate(Map params, Map actions)
887 throws ValidatorException {
888
889 if (this.getDepends() == null) {
890 return new ValidatorResults();
891 }
892
893 ValidatorResults allResults = new ValidatorResults();
894
895 Object bean = params.get(Validator.BEAN_PARAM);
896 int numberOfFieldsToValidate =
897 this.isIndexed() ? this.getIndexedPropertySize(bean) : 1;
898
899 for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) {
900
901 Iterator dependencies = this.dependencyList.iterator();
902 ValidatorResults results = new ValidatorResults();
903 while (dependencies.hasNext()) {
904 String depend = (String) dependencies.next();
905
906 ValidatorAction action = (ValidatorAction) actions.get(depend);
907 if (action == null) {
908 this.handleMissingAction(depend);
909 }
910
911 boolean good =
912 validateForRule(action, results, actions, params, fieldNumber);
913
914 if (!good) {
915 allResults.merge(results);
916 return allResults;
917 }
918 }
919 allResults.merge(results);
920 }
921
922 return allResults;
923 }
924
925
926
927
928
929
930
931 private void handleMissingAction(String name) throws ValidatorException {
932 throw new ValidatorException("No ValidatorAction named " + name
933 + " found for field " + this.getProperty());
934 }
935
936
937
938
939
940
941 protected Map getMsgMap() {
942 return hMsgs;
943 }
944
945
946
947
948
949
950 protected Map getVarMap() {
951 return hVars;
952 }
953 }
954