1
2
3
4
5
6
7
8
9 package org.kuali.student.common.validator;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Date;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Stack;
19
20 import org.apache.log4j.Logger;
21 import org.kuali.student.common.util.MessageUtils;
22 import org.kuali.student.core.dictionary.dto.CaseConstraint;
23 import org.kuali.student.core.dictionary.dto.CommonLookupParam;
24 import org.kuali.student.core.dictionary.dto.Constraint;
25 import org.kuali.student.core.dictionary.dto.DataType;
26 import org.kuali.student.core.dictionary.dto.FieldDefinition;
27 import org.kuali.student.core.dictionary.dto.LookupConstraint;
28 import org.kuali.student.core.dictionary.dto.MustOccurConstraint;
29 import org.kuali.student.core.dictionary.dto.ObjectStructureDefinition;
30 import org.kuali.student.core.dictionary.dto.RequiredConstraint;
31 import org.kuali.student.core.dictionary.dto.ValidCharsConstraint;
32 import org.kuali.student.core.dictionary.dto.WhenConstraint;
33 import org.kuali.student.core.messages.dto.Message;
34 import org.kuali.student.core.messages.service.MessageService;
35 import org.kuali.student.core.search.dto.SearchParam;
36 import org.kuali.student.core.search.dto.SearchRequest;
37 import org.kuali.student.core.search.dto.SearchResult;
38 import org.kuali.student.core.search.service.SearchDispatcher;
39 import org.kuali.student.core.validation.dto.ValidationResultInfo;
40
41 public class DefaultValidatorImpl extends BaseAbstractValidator {
42 final static Logger LOG = Logger.getLogger(DefaultValidatorImpl.class);
43
44 private MessageService messageService = null;
45
46 private SearchDispatcher searchDispatcher;
47
48 private String messageLocaleKey = "en";
49
50 private String messageGroupKey = "validation";
51
52 private DateParser dateParser = new ServerDateParser();
53
54 private boolean serverSide = true;
55
56 public MessageService getMessageService() {
57 return messageService;
58 }
59
60 public void setMessageService(MessageService messageService) {
61 this.messageService = messageService;
62 }
63
64 public String getMessageLocaleKey() {
65 return messageLocaleKey;
66 }
67
68 public void setMessageLocaleKey(String messageLocaleKey) {
69 this.messageLocaleKey = messageLocaleKey;
70 }
71
72 public String getMessageGroupKey() {
73 return messageGroupKey;
74 }
75
76 public void setMessageGroupKey(String messageGroupKey) {
77 this.messageGroupKey = messageGroupKey;
78 }
79
80 public void setDateParser(DateParser dateParser) {
81 this.dateParser = dateParser;
82 }
83
84
85
86
87 public boolean isServerSide() {
88 return serverSide;
89 }
90
91
92
93
94
95 public void setServerSide(boolean serverSide) {
96 this.serverSide = serverSide;
97 }
98
99
100
101
102 public DateParser getDateParser() {
103 return dateParser;
104 }
105
106
107
108
109
110
111
112
113 public List<ValidationResultInfo> validateObject(Object data, ObjectStructureDefinition objStructure) {
114
115 Stack<String> elementStack = new Stack<String>();
116 return validateObject(data, objStructure, elementStack, true);
117 }
118
119 private List<ValidationResultInfo> validateObject(Object data, ObjectStructureDefinition objStructure, Stack<String> elementStack, boolean isRoot) {
120
121 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
122
123 ConstraintDataProvider dataProvider = new BeanConstraintDataProvider();
124 dataProvider.initialize(data);
125
126
127 StringBuilder objXPathElement = new StringBuilder(dataProvider.getPath());
128
129 if(!isRoot && !objXPathElement.toString().isEmpty()){
130 elementStack.push(objXPathElement.toString());
131 }
132
133
134
135
136
137 if (null == objStructure) {
138 return results;
139 }
140
141 for (FieldDefinition f : objStructure.getAttributes()) {
142 List<ValidationResultInfo> l = validateField(f, objStructure, dataProvider, elementStack);
143
144 results.addAll(l);
145
146
147 if (f.getCustomValidatorClass() != null || f.isServerSide() && serverSide) {
148 Validator customValidator = validatorFactory.getValidator(f.getCustomValidatorClass());
149 if(customValidator==null){
150 throw new RuntimeException("Custom Validator "+f.getCustomValidatorClass()+" was not configured in this context");
151 }
152 l = customValidator.validateObject(f,data, objStructure,elementStack);
153 results.addAll(l);
154 }
155 }
156 if(!isRoot && !objXPathElement.toString().isEmpty()){
157 elementStack.pop();
158 }
159
160
161
162
163
164
165
166
167
168
169 return results;
170 }
171
172 public List<ValidationResultInfo> validateField(FieldDefinition field, ObjectStructureDefinition objStruct, ConstraintDataProvider dataProvider, Stack<String> elementStack) {
173
174 Object value = dataProvider.getValue(field.getName());
175 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
176
177
178 if (value == null || "".equals(value.toString().trim())) {
179 processConstraint(results, field, objStruct, value, dataProvider, elementStack);
180 return results;
181 }
182
183
184
185
186 if (DataType.COMPLEX.equals(field.getDataType())) {
187 ObjectStructureDefinition nestedObjStruct = null;
188
189 if (null != field.getDataObjectStructure()) {
190 nestedObjStruct = field.getDataObjectStructure();
191 }
192
193 elementStack.push(field.getName());
194
195 if (value instanceof Collection) {
196
197 String xPathForCollection = getElementXpath(elementStack) + "/*";
198
199 int i=0;
200 for (Object o : (Collection<?>) value) {
201 elementStack.push(Integer.toString(i));
202 processNestedObjectStructure(results, o, nestedObjStruct, field, elementStack);
203 elementStack.pop();
204 i++;
205 }
206 if (field.getMinOccurs() != null && field.getMinOccurs() > ((Collection<?>) value).size()) {
207 ValidationResultInfo valRes = new ValidationResultInfo(xPathForCollection, value);
208 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), toMap(field)));
209 results.add(valRes);
210 }
211
212 Integer maxOccurs = tryParse(field.getMaxOccurs());
213 if (maxOccurs != null && maxOccurs < ((Collection<?>) value).size()) {
214 ValidationResultInfo valRes = new ValidationResultInfo(xPathForCollection, value);
215 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), toMap(field)));
216 results.add(valRes);
217 }
218 } else {
219 if (null != value) {
220 processNestedObjectStructure(results, value, nestedObjStruct, field, elementStack);
221 } else {
222 if (field.getMinOccurs() != null && field.getMinOccurs() > 0) {
223 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack), value);
224 val.setError(getMessage("validation.required"));
225 results.add(val);
226 }
227 }
228 }
229
230 elementStack.pop();
231
232 } else {
233
234 if (value instanceof Collection) {
235
236 if(((Collection<?>)value).isEmpty()){
237 processConstraint(results, field, objStruct, "", dataProvider, elementStack);
238 }
239
240 int i = 0;
241 for (Object o : (Collection<?>) value) {
242 elementStack.push(Integer.toBinaryString(i));
243 processConstraint(results, field, objStruct, o, dataProvider, elementStack);
244 elementStack.pop();
245 i++;
246 }
247
248 String xPath = getElementXpath(elementStack) + "/" + field.getName() + "/*";
249 if (field.getMinOccurs() != null && field.getMinOccurs() > ((Collection<?>) value).size()) {
250 ValidationResultInfo valRes = new ValidationResultInfo(xPath, value);
251 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), toMap(field)));
252 results.add(valRes);
253 }
254
255 Integer maxOccurs = tryParse(field.getMaxOccurs());
256 if (maxOccurs != null && maxOccurs < ((Collection<?>) value).size()) {
257 ValidationResultInfo valRes = new ValidationResultInfo(xPath, value);
258 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), toMap(field)));
259 results.add(valRes);
260 }
261 } else {
262 processConstraint(results, field, objStruct, value, dataProvider, elementStack);
263 }
264
265 }
266 return results;
267 }
268
269 protected Integer tryParse(String s) {
270 Integer result = null;
271 if (s != null) {
272 try {
273 result = Integer.valueOf(s);
274 } catch (NumberFormatException e) {
275
276 }
277 }
278 return result;
279 }
280
281 protected void processNestedObjectStructure(List<ValidationResultInfo> results, Object value, ObjectStructureDefinition nestedObjStruct, FieldDefinition field, Stack<String> elementStack) {
282
283 results.addAll(validateObject(value, nestedObjStruct, elementStack, false));
284
285 }
286
287 protected void processConstraint(List<ValidationResultInfo> valResults, FieldDefinition field, ObjectStructureDefinition objStructure, Object value, ConstraintDataProvider dataProvider, Stack<String> elementStack) {
288
289
290
291 Constraint caseConstraint = processCaseConstraint(valResults, field, objStructure, value, dataProvider, elementStack);
292
293 Constraint constraint = (null != caseConstraint) ? caseConstraint : field;
294
295 processBaseConstraints(valResults, constraint, field.getDataType(), field.getName(), value, elementStack);
296
297
298 if (value == null || "".equals(value.toString().trim())) {
299 return;
300 }
301
302 String elementPath = getElementXpath(elementStack) + "/" + field.getName();
303
304
305 if (null != constraint.getValidChars()) {
306 ValidationResultInfo val = processValidCharConstraint(elementPath, constraint.getValidChars(), dataProvider, value);
307 if (null != val) {
308 valResults.add(val);
309 }
310 }
311
312
313 if (value != null && !"".equals(value.toString().trim())) {
314 if (null != constraint.getRequireConstraint() && constraint.getRequireConstraint().size() > 0) {
315 for (RequiredConstraint rc : constraint.getRequireConstraint()) {
316 ValidationResultInfo val = processRequireConstraint(elementPath, rc, field, objStructure, dataProvider);
317 if (null != val) {
318 valResults.add(val);
319 }
320 }
321 }
322 }
323
324
325 if (null != constraint.getOccursConstraint() && constraint.getOccursConstraint().size() > 0) {
326 for (MustOccurConstraint oc : constraint.getOccursConstraint()) {
327 ValidationResultInfo val = processOccursConstraint(elementPath, oc, field, objStructure, dataProvider);
328 if (null != val) {
329 valResults.add(val);
330 }
331 }
332 }
333
334
335 if (null != constraint.getLookupDefinition()) {
336 processLookupConstraint(valResults, constraint.getLookupDefinition(), field, elementStack, dataProvider);
337 }
338 }
339
340 protected ValidationResultInfo processRequireConstraint(String element, RequiredConstraint constraint, FieldDefinition field, ObjectStructureDefinition objStructure, ConstraintDataProvider dataProvider) {
341
342 ValidationResultInfo val = null;
343
344 String fieldName = constraint.getFieldPath();
345 Object fieldValue = dataProvider.getValue(fieldName);
346
347 boolean result = true;
348
349 if (fieldValue instanceof java.lang.String) {
350 result = hasText((String) fieldValue);
351 } else if (fieldValue instanceof Collection) {
352 result = (((Collection<?>) fieldValue).size() > 0);
353 } else {
354 result = (null != fieldValue) ? true : false;
355 }
356
357 if (!result) {
358 Map<String, Object> rMap = new HashMap<String, Object>();
359 rMap.put("field1", field.getName());
360 rMap.put("field2", fieldName);
361 val = new ValidationResultInfo(element, fieldValue);
362 val.setError(MessageUtils.interpolate(getMessage("validation.requiresField"), rMap));
363 }
364
365 return val;
366 }
367
368
369
370
371
372
373
374
375 protected Constraint processCaseConstraint(List<ValidationResultInfo> valResults, FieldDefinition field, ObjectStructureDefinition objStructure, Object value, ConstraintDataProvider dataProvider, Stack<String> elementStack) {
376
377 CaseConstraint constraint = field.getCaseConstraint();
378
379 if (null == constraint) {
380 return null;
381 }
382
383 String operator = (hasText(constraint.getOperator())) ? constraint.getOperator() : "EQUALS";
384 FieldDefinition caseField = (hasText(constraint.getFieldPath())) ? ValidatorUtils.getField(constraint.getFieldPath(), objStructure) : null;
385
386
387 Object fieldValue = (null != caseField) ? dataProvider.getValue(caseField.getName()) : value;
388 DataType fieldDataType = (null != caseField ? caseField.getDataType():null);
389
390
391 if(null == fieldValue) {
392 return null;
393 }
394
395
396 for (WhenConstraint wc : constraint.getWhenConstraint()) {
397
398 List<Object> whenValueList = wc.getValues();
399
400 for (Object whenValue : whenValueList) {
401 if (ValidatorUtils.compareValues(fieldValue, whenValue, fieldDataType, operator, constraint.isCaseSensitive(), dateParser) && null != wc.getConstraint()) {
402 return wc.getConstraint();
403 }
404 }
405 }
406
407 return null;
408 }
409
410 protected ValidationResultInfo processValidCharConstraint(String element, ValidCharsConstraint vcConstraint, ConstraintDataProvider dataProvider, Object value) {
411
412 ValidationResultInfo val = null;
413
414 StringBuilder fieldValue = new StringBuilder();
415 String validChars = vcConstraint.getValue();
416
417 fieldValue.append(ValidatorUtils.getString(value));
418
419 int typIdx = validChars.indexOf(":");
420 String processorType = "regex";
421 if (-1 == typIdx) {
422 validChars = "[" + validChars + "]*";
423 } else {
424 processorType = validChars.substring(0, typIdx);
425 validChars = validChars.substring(typIdx + 1);
426 }
427
428 if ("regex".equalsIgnoreCase(processorType)) {
429 if (fieldValue == null || !fieldValue.toString().matches(validChars)) {
430 val = new ValidationResultInfo(element, fieldValue);
431 if(vcConstraint.getLabelKey()!=null){
432 val.setError(getMessage(vcConstraint.getLabelKey()));
433 }else{
434 val.setError(getMessage("validation.validCharsFailed"));
435 }
436 }
437 }
438
439 return val;
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454 protected ValidationResultInfo processOccursConstraint(String element, MustOccurConstraint constraint, FieldDefinition field, ObjectStructureDefinition objStructure, ConstraintDataProvider dataProvider) {
455
456 boolean result = false;
457 int trueCount = 0;
458
459 ValidationResultInfo val = null;
460
461 for (RequiredConstraint rc : constraint.getRequiredFields()) {
462 trueCount += (processRequireConstraint("", rc, field, objStructure, dataProvider) != null) ? 1 : 0;
463 }
464
465 for (MustOccurConstraint oc : constraint.getOccurs()) {
466 trueCount += (processOccursConstraint("", oc, field, objStructure, dataProvider) != null) ? 1 : 0;
467 }
468
469 result = (trueCount >= constraint.getMin() && trueCount <= constraint.getMax()) ? true : false;
470
471 if (!result) {
472
473 val = new ValidationResultInfo(element, null);
474 val.setError(getMessage("validation.occurs"));
475 }
476
477 return val;
478 }
479
480
481 protected void processLookupConstraint(List<ValidationResultInfo> valResults, LookupConstraint lookupConstraint, FieldDefinition field, Stack<String> elementStack, ConstraintDataProvider dataProvider) {
482 if (lookupConstraint == null) {
483 return;
484 }
485
486
487 List<SearchParam> params = new ArrayList<SearchParam>();
488 Object fieldValue = null;
489 for (CommonLookupParam paramMapping : lookupConstraint.getParams()) {
490 SearchParam param = new SearchParam();
491
492 param.setKey(paramMapping.getKey());
493
494
495 if (paramMapping.getFieldPath() != null && !paramMapping.getFieldPath().isEmpty()) {
496 fieldValue = dataProvider.getValue(paramMapping.getFieldPath());
497 if (fieldValue instanceof String) {
498 param.setValue((String) fieldValue);
499 } else if (fieldValue instanceof List<?>) {
500 param.setValue((List<String>) fieldValue);
501 }
502 } else if (paramMapping.getDefaultValueString() != null) {
503 param.setValue(paramMapping.getDefaultValueString());
504 } else {
505 param.setValue(paramMapping.getDefaultValueList());
506 }
507 params.add(param);
508 }
509
510 SearchRequest searchRequest = new SearchRequest();
511 searchRequest.setMaxResults(1);
512 searchRequest.setStartAt(0);
513 searchRequest.setNeededTotalResults(false);
514 searchRequest.setSearchKey(lookupConstraint.getSearchTypeId());
515 searchRequest.setParams(params);
516
517 SearchResult searchResult = null;
518 try {
519 searchResult = searchDispatcher.dispatchSearch(searchRequest);
520 } catch (Exception e) {
521 LOG.info("Error calling Search", e);
522 }
523 if (searchResult == null || searchResult.getRows() == null || searchResult.getRows().isEmpty()) {
524 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack) + "/" + field.getName(), fieldValue);
525 val.setError(getMessage("validation.lookup"));
526 valResults.add(val);
527 }
528 }
529
530 protected void processBaseConstraints(List<ValidationResultInfo> valResults, Constraint constraint, DataType dataType, String name, Object value, Stack<String> elementStack) {
531
532 if (value == null || "".equals(value.toString().trim())) {
533 if (constraint.getMinOccurs() != null && constraint.getMinOccurs() > 0) {
534 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack) + "/" + name, value);
535 val.setError(getMessage("validation.required"));
536 valResults.add(val);
537 }
538 return;
539 }
540
541 String elementPath = getElementXpath(elementStack) + "/" + name;
542
543 if (DataType.STRING.equals(dataType)) {
544 validateString(value, constraint, elementPath, valResults);
545 } else if (DataType.INTEGER.equals(dataType)) {
546 validateInteger(value, constraint, elementPath, valResults);
547 } else if (DataType.LONG.equals(dataType)) {
548 validateLong(value, constraint, elementPath, valResults);
549 } else if (DataType.DOUBLE.equals(dataType)) {
550 validateDouble(value, constraint, elementPath, valResults);
551 } else if (DataType.FLOAT.equals(dataType)) {
552 validateFloat(value, constraint, elementPath, valResults);
553 } else if (DataType.BOOLEAN.equals(dataType)) {
554 validateBoolean(value, constraint, elementPath, valResults);
555 } else if (DataType.DATE.equals(dataType)) {
556 validateDate(value, constraint, elementPath, valResults, dateParser);
557 }
558 }
559
560 protected void validateBoolean(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
561 if (!(value instanceof Boolean)) {
562 try {
563 Boolean.valueOf(value.toString());
564 } catch (Exception e) {
565 ValidationResultInfo val = new ValidationResultInfo(element, value);
566 val.setError(getMessage("validation.mustBeBoolean"));
567 results.add(val);
568 }
569 }
570 }
571
572 protected void validateDouble(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
573 Double v = null;
574
575 ValidationResultInfo val = new ValidationResultInfo(element, value);
576
577 if (value instanceof Number) {
578 v = ((Number) value).doubleValue();
579 } else {
580 try {
581 v = Double.valueOf(value.toString());
582 } catch (Exception e) {
583 val.setError(getMessage("validation.mustBeDouble"));
584 }
585 }
586
587 if (val.isOk()) {
588 Double maxValue = ValidatorUtils.getDouble(constraint.getInclusiveMax());
589 Double minValue = ValidatorUtils.getDouble(constraint.getExclusiveMin());
590
591 if (maxValue != null && minValue != null) {
592
593 if (v > maxValue || v < minValue) {
594 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
595 }
596 } else if (maxValue != null) {
597 if (v > maxValue) {
598 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
599 }
600 } else if (minValue != null) {
601 if (v < minValue) {
602 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
603 }
604 }
605 }
606
607 if (!val.isOk()) {
608 results.add(val);
609 }
610 }
611
612 protected void validateFloat(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
613 Float v = null;
614
615 ValidationResultInfo val = new ValidationResultInfo(element, value);
616 if (value instanceof Number) {
617 v = ((Number) value).floatValue();
618 } else {
619 try {
620 v = Float.valueOf(value.toString());
621 } catch (Exception e) {
622 val.setError(getMessage("validation.mustBeFloat"));
623 }
624 }
625
626 if (val.isOk()) {
627 Float maxValue = ValidatorUtils.getFloat(constraint.getInclusiveMax());
628 Float minValue = ValidatorUtils.getFloat(constraint.getExclusiveMin());
629
630 if (maxValue != null && minValue != null) {
631
632 if (v > maxValue || v < minValue) {
633 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
634 }
635 } else if (maxValue != null) {
636 if (v > maxValue) {
637 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
638 }
639 } else if (minValue != null) {
640 if (v < minValue) {
641 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
642 }
643 }
644 }
645
646 if (!val.isOk()) {
647 results.add(val);
648 }
649 }
650
651 protected void validateLong(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
652 Long v = null;
653
654 ValidationResultInfo val = new ValidationResultInfo(element, value);
655 if (value instanceof Number) {
656 v = ((Number) value).longValue();
657 } else {
658 try {
659 v = Long.valueOf(value.toString());
660 } catch (Exception e) {
661 val.setError(getMessage("validation.mustBeLong"));
662 }
663 }
664
665 if (val.isOk()) {
666 Long maxValue = ValidatorUtils.getLong(constraint.getInclusiveMax());
667 Long minValue = ValidatorUtils.getLong(constraint.getExclusiveMin());
668
669 if (maxValue != null && minValue != null) {
670
671 if (v > maxValue || v < minValue) {
672 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
673 }
674 } else if (maxValue != null) {
675 if (v > maxValue) {
676 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
677 }
678 } else if (minValue != null) {
679 if (v < minValue) {
680 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
681 }
682 }
683 }
684
685 if (!val.isOk()) {
686 results.add(val);
687 }
688
689 }
690
691 protected void validateInteger(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
692 Integer v = null;
693
694 ValidationResultInfo val = new ValidationResultInfo(element, value);
695
696 if (value instanceof Number) {
697 v = ((Number) value).intValue();
698 } else {
699 try {
700 v = Integer.valueOf(value.toString());
701 } catch (Exception e) {
702 val.setError(getMessage("validation.mustBeInteger"));
703 }
704 }
705
706 if (val.isOk()) {
707 Integer maxValue = ValidatorUtils.getInteger(constraint.getInclusiveMax());
708 Integer minValue = ValidatorUtils.getInteger(constraint.getExclusiveMin());
709
710 if (maxValue != null && minValue != null) {
711
712 if (v > maxValue || v < minValue) {
713 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
714 }
715 } else if (maxValue != null) {
716 if (v > maxValue) {
717 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
718 }
719 } else if (minValue != null) {
720 if (v < minValue) {
721 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
722 }
723 }
724 }
725
726 if (!val.isOk()) {
727 results.add(val);
728 }
729 }
730
731 protected void validateDate(Object value, Constraint constraint, String element, List<ValidationResultInfo> results, DateParser dateParser) {
732 ValidationResultInfo val = new ValidationResultInfo(element, value);
733
734 Date v = null;
735
736 if (value instanceof Date) {
737 v = (Date) value;
738 } else {
739 try {
740 v = dateParser.parseDate(value.toString());
741 } catch (Exception e) {
742 val.setError(getMessage("validation.mustBeDate"));
743 }
744 }
745
746 if (val.isOk()) {
747 Date maxValue = ValidatorUtils.getDate(constraint.getInclusiveMax(), dateParser);
748 Date minValue = ValidatorUtils.getDate(constraint.getExclusiveMin(), dateParser);
749
750 if (maxValue != null && minValue != null) {
751
752 if (v.getTime() > maxValue.getTime() || v.getTime() < minValue.getTime()) {
753 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
754 }
755 } else if (maxValue != null) {
756 if (v.getTime() > maxValue.getTime()) {
757 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
758 }
759 } else if (minValue != null) {
760 if (v.getTime() < minValue.getTime()) {
761 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
762 }
763 }
764 }
765
766 if (!val.isOk()) {
767 results.add(val);
768 }
769 }
770
771 protected void validateString(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
772
773 if (value == null) {
774 value = "";
775 }
776 String s = value.toString().trim();
777
778 ValidationResultInfo val = new ValidationResultInfo(element, value);
779
780 Integer maxLength = tryParse(constraint.getMaxLength());
781 if (maxLength != null && constraint.getMinLength() != null && constraint.getMinLength() > 0) {
782 if (s.length() > maxLength || s.length() < constraint.getMinLength()) {
783 val.setError(MessageUtils.interpolate(getMessage("validation.lengthOutOfRange"), toMap(constraint)));
784 }
785 } else if (maxLength != null) {
786 if (s.length() > Integer.parseInt(constraint.getMaxLength())) {
787 val.setError(MessageUtils.interpolate(getMessage("validation.maxLengthFailed"), toMap(constraint)));
788 }
789 } else if (constraint.getMinLength() != null && constraint.getMinLength() > 0) {
790 if (s.length() < constraint.getMinLength()) {
791 val.setError(MessageUtils.interpolate(getMessage("validation.minLengthFailed"), toMap(constraint)));
792 }
793 }
794
795 if (!val.isOk()) {
796 results.add(val);
797 }
798 }
799
800 protected String getMessage(String messageId) {
801 if (null == messageService) {
802 return messageId;
803 }
804
805 Message msg = messageService.getMessage(messageLocaleKey, messageGroupKey, messageId);
806
807 return msg.getValue();
808 }
809
810 protected String getElementXpath(Stack<String> elementStack) {
811 StringBuilder xPath = new StringBuilder();
812 Iterator<String> itr = elementStack.iterator();
813 while (itr.hasNext()) {
814 xPath.append(itr.next());
815 if(itr.hasNext()){
816 xPath.append("/");
817 }
818 }
819
820 return xPath.toString();
821 }
822
823
824
825
826 protected boolean hasText(String string) {
827
828 if (string == null || string.length() < 1) {
829 return false;
830 }
831 int stringLength = string.length();
832
833 for (int i = 0; i < stringLength; i++) {
834 char currentChar = string.charAt(i);
835 if (' ' != currentChar || '\t' != currentChar || '\n' != currentChar) {
836 return true;
837 }
838 }
839
840 return false;
841 }
842
843 protected Map<String, Object> toMap(Constraint c) {
844 Map<String, Object> result = new HashMap<String, Object>();
845 result.put("minOccurs", c.getMinOccurs());
846 result.put("maxOccurs", c.getMaxOccurs());
847 result.put("minLength", c.getMinLength());
848 result.put("maxLength", c.getMaxLength());
849 result.put("minValue", c.getExclusiveMin());
850 result.put("maxValue", c.getInclusiveMax());
851
852
853 return result;
854 }
855
856 public SearchDispatcher getSearchDispatcher() {
857 return searchDispatcher;
858 }
859
860 public void setSearchDispatcher(SearchDispatcher searchDispatcher) {
861 this.searchDispatcher = searchDispatcher;
862 }
863
864 @Override
865 public List<ValidationResultInfo> validateObject(FieldDefinition field,
866 Object o, ObjectStructureDefinition objStructure,Stack<String> elementStack) {
867 return null;
868 }
869 }