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