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