Clover Coverage Report - Kuali Student 1.1.1-SNAPSHOT (Aggregated)
Coverage timestamp: Wed Apr 20 2011 04:04:00 EST
../../../../../img/srcFileCovDistChart7.png 38% of files have more coverage
404   919   217   11.22
254   669   0.54   36
36     6.03  
1    
 
  DefaultValidatorImpl       Line # 44 404 0% 217 239 65.6% 0.6556196
 
  (73)
 
1    /**
2    * Copyright 2010 The Kuali Foundation Licensed under the Educational Community License, Version 2.0 (the "License"); you may
3    * not use this file except in compliance with the License. You may obtain a copy of the License at
4    * http://www.osedu.org/licenses/ECL-2.0 Unless required by applicable law or agreed to in writing, software distributed
5    * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
6    * implied. See the License for the specific language governing permissions and limitations under the License.
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  0 toggle public MessageService getMessageService() {
60  0 return messageService;
61    }
62   
 
63  8 toggle public void setMessageService(MessageService messageService) {
64  8 this.messageService = messageService;
65    }
66   
 
67  0 toggle public String getMessageLocaleKey() {
68  0 return messageLocaleKey;
69    }
70   
 
71  0 toggle public void setMessageLocaleKey(String messageLocaleKey) {
72  0 this.messageLocaleKey = messageLocaleKey;
73    }
74   
 
75  0 toggle public String getMessageGroupKey() {
76  0 return messageGroupKey;
77    }
78   
 
79  0 toggle public void setMessageGroupKey(String messageGroupKey) {
80  0 this.messageGroupKey = messageGroupKey;
81    }
82   
 
83  18 toggle public void setDateParser(DateParser dateParser) {
84  18 this.dateParser = dateParser;
85    }
86   
87    /**
88    * @return the serverSide
89    */
 
90  0 toggle public boolean isServerSide() {
91  0 return serverSide;
92    }
93   
94    /**
95    * @param serverSide
96    * the serverSide to set
97    */
 
98  0 toggle public void setServerSide(boolean serverSide) {
99  0 this.serverSide = serverSide;
100    }
101   
102    /**
103    * @return the dateParser
104    */
 
105  0 toggle public DateParser getDateParser() {
106  0 return dateParser;
107    }
108   
109    /**
110    * Validate Object and all its nested child objects for given type and state
111    *
112    * @param data
113    * @param objStructure
114    * @return
115    */
 
116  131 toggle public List<ValidationResultInfo> validateObject(Object data, ObjectStructureDefinition objStructure) {
117   
118  131 Stack<String> elementStack = new Stack<String>();
119   
120  131 return validateObject(data, objStructure, elementStack, data, objStructure, true);
121    }
122   
 
123  1564 toggle private List<ValidationResultInfo> validateObject(Object data, ObjectStructureDefinition objStructure, Stack<String> elementStack, Object rootData, ObjectStructureDefinition rootObjStructure, boolean isRoot) {
124   
125  1564 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
126   
127  1564 ConstraintDataProvider dataProvider = new BeanConstraintDataProvider();
128  1564 dataProvider.initialize(data);
129   
130    // Push object structure to the top of the stack
131  1564 StringBuilder objXPathElement = new StringBuilder(dataProvider.getPath());
132   
133  1564 if(!isRoot && !objXPathElement.toString().isEmpty()){
134  0 elementStack.push(objXPathElement.toString());
135    }
136   
137    /*
138    * Do nothing if the object to be validated is not type/state or if the objectstructure with constraints is not
139    * provided
140    */
141  1564 if (null == objStructure) {
142  25 return results;
143    }
144   
145  1539 for (FieldDefinition f : objStructure.getAttributes()) {
146  8475 List<ValidationResultInfo> l = validateField(f, objStructure, dataProvider, elementStack, rootData, rootObjStructure);
147   
148  8475 results.addAll(l);
149   
150    // Use Custom Validators
151  8475 if (f.getCustomValidatorClass() != null || f.isServerSide() && serverSide) {
152  21 Validator customValidator = validatorFactory.getValidator(f.getCustomValidatorClass());
153  21 if(customValidator==null){
154  0 throw new RuntimeException("Custom Validator "+f.getCustomValidatorClass()+" was not configured in this context");
155    }
156  21 l = customValidator.validateObject(f,data, objStructure,elementStack);
157  21 results.addAll(l);
158    }
159    }
160  1539 if(!isRoot && !objXPathElement.toString().isEmpty()){
161  0 elementStack.pop();
162    }
163   
164    /* All Field validations are returned right now */
165    // List<ValidationResultInfo> resultsBuffer = new
166    // ArrayList<ValidationResultInfo>();
167    // for (ValidationResultContainer vc : results) {
168    // if (skipFields.contains(vc.getElement()) == false) {
169    // resultsBuffer.add(vc);
170    // }
171    // }
172    // results = resultsBuffer;
173  1539 return results;
174    }
175   
 
176  8475 toggle public List<ValidationResultInfo> validateField(FieldDefinition field, ObjectStructureDefinition objStruct, ConstraintDataProvider dataProvider, Stack<String> elementStack, Object rootData, ObjectStructureDefinition rootObjectStructure) {
177   
178  8475 Object value = dataProvider.getValue(field.getName());
179  8475 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
180   
181    // Handle null values in field
182  8475 if (value == null || "".equals(value.toString().trim())) {
183  1367 processConstraint(results, field, objStruct, value, dataProvider, elementStack, rootData, rootObjectStructure);
184  1367 return results;
185    }
186   
187    /*
188    * For complex object structures only the following constraints apply 1. TypeStateCase 2. MinOccurs 3. MaxOccurs
189    */
190  7108 if (DataType.COMPLEX.equals(field.getDataType())) {
191  1246 ObjectStructureDefinition nestedObjStruct = null;
192   
193  1246 if (null != field.getDataObjectStructure()) {
194  1246 nestedObjStruct = field.getDataObjectStructure();
195    }
196   
197  1246 elementStack.push(field.getName());
198    // beanPathStack.push(field.isDynamic()?"attributes("+field.getName()+")":field.getName());
199   
200  1246 if (value instanceof Collection) {
201   
202  472 String xPathForCollection = getElementXpath(elementStack) + "/*";
203   
204  472 int i=0;
205  472 for (Object o : (Collection<?>) value) {
206  659 elementStack.push(Integer.toString(i));
207    // beanPathStack.push(!beanPathStack.isEmpty()?beanPathStack.pop():""+"["+i+"]");
208  659 processNestedObjectStructure(results, o, nestedObjStruct, field, elementStack, rootData, rootObjectStructure);
209    // beanPathStack.pop();
210    // beanPathStack.push(field.isDynamic()?"attributes("+field.getName()+")":field.getName());
211  659 elementStack.pop();
212  659 i++;
213    }
214  472 if (field.getMinOccurs() != null && field.getMinOccurs() > ((Collection<?>) value).size()) {
215  0 ValidationResultInfo valRes = new ValidationResultInfo(xPathForCollection, value);
216  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), toMap(field)));
217  0 results.add(valRes);
218    }
219   
220  472 Integer maxOccurs = tryParse(field.getMaxOccurs());
221  472 if (maxOccurs != null && maxOccurs < ((Collection<?>) value).size()) {
222  0 ValidationResultInfo valRes = new ValidationResultInfo(xPathForCollection, value);
223  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), toMap(field)));
224  0 results.add(valRes);
225    }
226    } else {
227  774 if (null != value) {
228  774 processNestedObjectStructure(results, value, nestedObjStruct, field, elementStack, rootData, rootObjectStructure);
229    } else {
230  0 if (field.getMinOccurs() != null && field.getMinOccurs() > 0) {
231  0 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack), value);
232  0 val.setError(getMessage("validation.required"));
233  0 results.add(val);
234    }
235    }
236    }
237   
238    // beanPathStack.pop();
239  1246 elementStack.pop();
240   
241    } else { // If non complex data type
242   
243  5862 if (value instanceof Collection) {
244   
245  258 if(((Collection<?>)value).isEmpty()){
246  103 processConstraint(results, field, objStruct, "", dataProvider, elementStack, rootData, rootObjectStructure);
247    }
248   
249  258 int i = 0;
250  258 for (Object o : (Collection<?>) value) {
251  316 elementStack.push(Integer.toBinaryString(i));
252    // beanPathStack.push(!beanPathStack.isEmpty()?beanPathStack.pop():""+"["+i+"]");
253  316 processConstraint(results, field, objStruct, o, dataProvider, elementStack, rootData, rootObjectStructure);
254    // beanPathStack.pop();
255    // beanPathStack.push(field.isDynamic()?"attributes("+field.getName()+")":field.getName());
256  316 elementStack.pop();
257  316 i++;
258    }
259   
260  258 String xPath = getElementXpath(elementStack) + "/" + field.getName() + "/*";
261  258 if (field.getMinOccurs() != null && field.getMinOccurs() > ((Collection<?>) value).size()) {
262  0 ValidationResultInfo valRes = new ValidationResultInfo(xPath, value);
263  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), toMap(field)));
264  0 results.add(valRes);
265    }
266   
267  258 Integer maxOccurs = tryParse(field.getMaxOccurs());
268  258 if (maxOccurs != null && maxOccurs < ((Collection<?>) value).size()) {
269  0 ValidationResultInfo valRes = new ValidationResultInfo(xPath, value);
270  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), toMap(field)));
271  0 results.add(valRes);
272    }
273    } else {
274  5604 processConstraint(results, field, objStruct, value, dataProvider, elementStack, rootData, rootObjectStructure);
275    }
276   
277    }
278  7108 return results;
279    }
280   
 
281  5399 toggle protected Integer tryParse(String s) {
282  5399 Integer result = null;
283  5399 if (s != null) {
284  5315 try {
285  5315 result = Integer.valueOf(s);
286    } catch (NumberFormatException e) {
287    // do nothing
288    }
289    }
290  5399 return result;
291    }
292   
 
293  1433 toggle protected void processNestedObjectStructure(List<ValidationResultInfo> results, Object value, ObjectStructureDefinition nestedObjStruct, FieldDefinition field, Stack<String> elementStack, Object rootData, ObjectStructureDefinition rootObjStructure) {
294   
295  1433 results.addAll(validateObject(value, nestedObjStruct, elementStack, rootData, rootObjStructure, false));
296   
297    }
298   
 
299  7390 toggle protected void processConstraint(List<ValidationResultInfo> valResults, FieldDefinition field, ObjectStructureDefinition objStructure, Object value, ConstraintDataProvider dataProvider, Stack<String> elementStack, Object rootData, ObjectStructureDefinition rootObjStructure) {
300   
301    // Process Case Constraint
302    // Case Constraint are only evaluated on the field. Nested case constraints are currently ignored
303  7390 Constraint caseConstraint = processCaseConstraint(valResults, field, objStructure, value, dataProvider, elementStack, rootData, rootObjStructure);
304   
305  7390 Constraint constraint = (null != caseConstraint) ? caseConstraint : field;
306   
307  7390 processBaseConstraints(valResults, constraint, field.getDataType(), field.getName(), value, elementStack);
308   
309    // Stop other checks if value is null
310  7390 if (value == null || "".equals(value.toString().trim())) {
311  1470 return;
312    }
313   
314  5920 String elementPath = getElementXpath(elementStack) + "/" + field.getName();
315   
316    // Process Valid Chars
317  5920 if (null != constraint.getValidChars()) {
318  2266 ValidationResultInfo val = processValidCharConstraint(elementPath, constraint.getValidChars(), dataProvider, value);
319  2266 if (null != val) {
320  16 valResults.add(val);
321    }
322    }
323   
324    // Process Require Constraints (only if this field has value)
325  5920 if (value != null && !"".equals(value.toString().trim())) {
326  5920 if (null != constraint.getRequireConstraint() && constraint.getRequireConstraint().size() > 0) {
327  134 for (RequiredConstraint rc : constraint.getRequireConstraint()) {
328  134 ValidationResultInfo val = processRequireConstraint(elementPath, rc, field, objStructure, dataProvider);
329  134 if (null != val) {
330  5 valResults.add(val);
331    }
332    }
333    }
334    }
335   
336    // Process Occurs Constraint
337  5920 if (null != constraint.getOccursConstraint() && constraint.getOccursConstraint().size() > 0) {
338  0 for (MustOccurConstraint oc : constraint.getOccursConstraint()) {
339  0 ValidationResultInfo val = processOccursConstraint(elementPath, oc, field, objStructure, dataProvider);
340  0 if (null != val) {
341  0 valResults.add(val);
342    }
343    }
344    }
345   
346    // Process lookup Constraint
347  5920 if (null != constraint.getLookupDefinition()) {
348  210 processLookupConstraint(valResults, constraint.getLookupDefinition(), field, elementStack, dataProvider);
349    }
350    }
351   
 
352  134 toggle protected ValidationResultInfo processRequireConstraint(String element, RequiredConstraint constraint, FieldDefinition field, ObjectStructureDefinition objStructure, ConstraintDataProvider dataProvider) {
353   
354  134 ValidationResultInfo val = null;
355   
356  134 String fieldName = constraint.getFieldPath();// TODO parse fieldname from here
357  134 Object fieldValue = dataProvider.getValue(fieldName);
358   
359  134 boolean result = true;
360   
361  134 if (fieldValue instanceof java.lang.String) {
362  130 result = hasText((String) fieldValue);
363  4 } else if (fieldValue instanceof Collection) {
364  0 result = (((Collection<?>) fieldValue).size() > 0);
365    } else {
366  4 result = (null != fieldValue) ? true : false;
367    }
368   
369  134 if (!result) {
370  5 Map<String, Object> rMap = new HashMap<String, Object>();
371  5 rMap.put("field1", field.getName());
372  5 rMap.put("field2", fieldName);
373  5 val = new ValidationResultInfo(element, fieldValue);
374  5 val.setError(MessageUtils.interpolate(getMessage("validation.requiresField"), rMap));
375    }
376   
377  134 return val;
378    }
379   
380    /**
381    * Process caseConstraint tag and sets any of the base constraint items if any of the when condition matches
382    *
383    * @param constraint
384    * @param caseConstraint
385    * @param field
386    */
 
387  7390 toggle protected Constraint processCaseConstraint(List<ValidationResultInfo> valResults, FieldDefinition field, ObjectStructureDefinition objStructure, Object value, ConstraintDataProvider dataProvider, Stack<String> elementStack, Object rootData, ObjectStructureDefinition rootObjStructure) {
388   
389  7390 CaseConstraint constraint = field.getCaseConstraint();
390   
391  7390 if (null == constraint) {
392  7114 return null;
393    }
394   
395  276 String operator = (hasText(constraint.getOperator())) ? constraint.getOperator() : "EQUALS";
396  276 FieldDefinition caseField = null;
397  276 boolean absolutePath = false;
398  276 if(hasText(constraint.getFieldPath())){
399  276 if(constraint.getFieldPath().startsWith("/")){
400  6 absolutePath = true;
401  6 caseField = ValidatorUtils.getField(constraint.getFieldPath().substring(1), rootObjStructure);
402    }else{
403  270 caseField = ValidatorUtils.getField(constraint.getFieldPath(), objStructure);
404    }
405    }
406   
407    // TODO: What happens when the field is not in the dataProvider?
408  276 Object fieldValue = value;
409  276 if(caseField!=null){
410  236 if(absolutePath){
411  6 try {
412  6 fieldValue = PropertyUtils.getNestedProperty(rootData, constraint.getFieldPath().substring(1));
413    } catch (IllegalAccessException e) {
414    } catch (InvocationTargetException e) {
415    } catch (NoSuchMethodException e) {
416    }
417    }else{
418  230 fieldValue = dataProvider.getValue(caseField.getName());
419    }
420    }
421  276 DataType fieldDataType = (null != caseField ? caseField.getDataType():null);
422   
423    // If fieldValue is null then skip Case check
424  276 if(null == fieldValue) {
425  47 return null;
426    }
427   
428    // Extract value for field Key
429  229 for (WhenConstraint wc : constraint.getWhenConstraint()) {
430   
431  276 if(hasText(wc.getValuePath())){
432  0 Object whenValue = null;
433  0 if(wc.getValuePath().startsWith("/")){
434  0 try {
435  0 whenValue = PropertyUtils.getNestedProperty(rootData, wc.getValuePath().substring(1));
436    } catch (IllegalAccessException e) {
437    } catch (InvocationTargetException e) {
438    } catch (NoSuchMethodException e) {
439    }
440    }else{
441  0 whenValue = dataProvider.getValue(wc.getValuePath());
442    }
443  0 if (ValidatorUtils.compareValues(fieldValue, whenValue, fieldDataType, operator, constraint.isCaseSensitive(), dateParser) && null != wc.getConstraint()) {
444  0 return wc.getConstraint();
445    }
446    }else{
447  276 List<Object> whenValueList = wc.getValues();
448   
449  276 for (Object whenValue : whenValueList) {
450  776 if (ValidatorUtils.compareValues(fieldValue, whenValue, fieldDataType, operator, constraint.isCaseSensitive(), dateParser) && null != wc.getConstraint()) {
451  56 return wc.getConstraint();
452    }
453    }
454    }
455    }
456   
457  173 return null;
458    }
459   
 
460  2528 toggle public ValidationResultInfo processValidCharConstraint(String element, ValidCharsConstraint vcConstraint, ConstraintDataProvider dataProvider, Object value) {
461   
462  2528 ValidationResultInfo val = null;
463   
464  2528 StringBuilder fieldValue = new StringBuilder();
465  2528 String validChars = vcConstraint.getValue();
466   
467  2528 fieldValue.append(ValidatorUtils.getString(value));
468   
469  2528 int typIdx = validChars.indexOf(":");
470  2528 String processorType = "regex";
471  2528 if (-1 == typIdx) {
472  0 validChars = "[" + validChars + "]*";
473    } else {
474  2528 processorType = validChars.substring(0, typIdx);
475  2528 validChars = validChars.substring(typIdx + 1);
476    }
477   
478  2528 if ("regex".equalsIgnoreCase(processorType)) {
479  2528 if (fieldValue == null || !fieldValue.toString().matches(validChars)) {
480  129 val = new ValidationResultInfo(element, fieldValue);
481  129 if(vcConstraint.getLabelKey()!=null){
482  87 val.setError(getMessage(vcConstraint.getLabelKey()));
483    }else{
484  42 val.setError(getMessage("validation.validCharsFailed"));
485    }
486    }
487    }
488   
489  2528 return val;
490    }
491   
492    /**
493    * Computes if all the filed required in the occurs clause are between the min and max
494    *
495    * @param valResults
496    * @param constraint
497    * @param field
498    * @param type
499    * @param state
500    * @param objStructure
501    * @param dataProvider
502    * @return
503    */
 
504  0 toggle protected ValidationResultInfo processOccursConstraint(String element, MustOccurConstraint constraint, FieldDefinition field, ObjectStructureDefinition objStructure, ConstraintDataProvider dataProvider) {
505   
506  0 boolean result = false;
507  0 int trueCount = 0;
508   
509  0 ValidationResultInfo val = null;
510   
511  0 for (RequiredConstraint rc : constraint.getRequiredFields()) {
512  0 trueCount += (processRequireConstraint("", rc, field, objStructure, dataProvider) != null) ? 1 : 0;
513    }
514   
515  0 for (MustOccurConstraint oc : constraint.getOccurs()) {
516  0 trueCount += (processOccursConstraint("", oc, field, objStructure, dataProvider) != null) ? 1 : 0;
517    }
518   
519  0 result = (trueCount >= constraint.getMin() && trueCount <= constraint.getMax()) ? true : false;
520   
521  0 if (!result) {
522    // TODO: figure out what data should go here instead of null
523  0 val = new ValidationResultInfo(element, null);
524  0 val.setError(getMessage("validation.occurs"));
525    }
526   
527  0 return val;
528    }
529   
530    // TODO: Implement lookup constraint
 
531  210 toggle protected void processLookupConstraint(List<ValidationResultInfo> valResults, LookupConstraint lookupConstraint, FieldDefinition field, Stack<String> elementStack, ConstraintDataProvider dataProvider) {
532  210 if (lookupConstraint == null) {
533  0 return;
534    }
535   
536    // Create search params based on the param mapping
537  210 List<SearchParam> params = new ArrayList<SearchParam>();
538  210 Object fieldValue = null;
539  210 for (CommonLookupParam paramMapping : lookupConstraint.getParams()) {
540  336 SearchParam param = new SearchParam();
541   
542  336 param.setKey(paramMapping.getKey());
543   
544    // If the value of the search param comes form another field then get it
545  336 if (paramMapping.getFieldPath() != null && !paramMapping.getFieldPath().isEmpty()) {
546  36 fieldValue = dataProvider.getValue(paramMapping.getFieldPath());
547  36 if (fieldValue instanceof String) {
548  2 param.setValue((String) fieldValue);
549  34 } else if (fieldValue instanceof List<?>) {
550  34 param.setValue((List<String>) fieldValue);
551    }
552  300 } else if (paramMapping.getDefaultValueString() != null) {
553  76 param.setValue(paramMapping.getDefaultValueString());
554    } else {
555  224 param.setValue(paramMapping.getDefaultValueList());
556    }
557  336 params.add(param);
558    }
559   
560  210 SearchRequest searchRequest = new SearchRequest();
561  210 searchRequest.setMaxResults(1);
562  210 searchRequest.setStartAt(0);
563  210 searchRequest.setNeededTotalResults(false);
564  210 searchRequest.setSearchKey(lookupConstraint.getSearchTypeId());
565  210 searchRequest.setParams(params);
566   
567  210 SearchResult searchResult = null;
568  210 try {
569  210 searchResult = searchDispatcher.dispatchSearch(searchRequest);
570    } catch (Exception e) {
571  0 LOG.info("Error calling Search", e);
572    }
573  210 if (searchResult == null || searchResult.getRows() == null || searchResult.getRows().isEmpty()) {
574  2 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack) + "/" + field.getName(), fieldValue);
575  2 val.setError(getMessage("validation.lookup"));
576  2 valResults.add(val);
577    }
578    }
579   
 
580  7390 toggle protected void processBaseConstraints(List<ValidationResultInfo> valResults, Constraint constraint, DataType dataType, String name, Object value, Stack<String> elementStack) {
581   
582  7390 if (value == null || "".equals(value.toString().trim())) {
583  1470 if (constraint.getMinOccurs() != null && constraint.getMinOccurs() > 0) {
584  65 ValidationResultInfo val = new ValidationResultInfo(getElementXpath(elementStack) + "/" + name, value);
585  65 val.setError(getMessage("validation.required"));
586  65 valResults.add(val);
587    }
588  1470 return;
589    }
590   
591  5920 String elementPath = getElementXpath(elementStack) + "/" + name;
592   
593  5920 if (DataType.STRING.equals(dataType)) {
594  4669 validateString(value, constraint, elementPath, valResults);
595  1251 } else if (DataType.INTEGER.equals(dataType)) {
596  143 validateInteger(value, constraint, elementPath, valResults);
597  1108 } else if (DataType.LONG.equals(dataType)) {
598  43 validateLong(value, constraint, elementPath, valResults);
599  1065 } else if (DataType.DOUBLE.equals(dataType)) {
600  1 validateDouble(value, constraint, elementPath, valResults);
601  1064 } else if (DataType.FLOAT.equals(dataType)) {
602  0 validateFloat(value, constraint, elementPath, valResults);
603  1064 } else if (DataType.BOOLEAN.equals(dataType)) {
604  87 validateBoolean(value, constraint, elementPath, valResults);
605  977 } else if (DataType.DATE.equals(dataType)) {
606  977 validateDate(value, constraint, elementPath, valResults, dateParser);
607    }
608    }
609   
 
610  87 toggle protected void validateBoolean(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
611  87 if (!(value instanceof Boolean)) {
612  0 try {
613  0 Boolean.valueOf(value.toString());
614    } catch (Exception e) {
615  0 ValidationResultInfo val = new ValidationResultInfo(element, value);
616  0 val.setError(getMessage("validation.mustBeBoolean"));
617  0 results.add(val);
618    }
619    }
620    }
621   
 
622  1 toggle protected void validateDouble(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
623  1 Double v = null;
624   
625  1 ValidationResultInfo val = new ValidationResultInfo(element, value);
626   
627  1 if (value instanceof Number) {
628  1 v = ((Number) value).doubleValue();
629    } else {
630  0 try {
631  0 v = Double.valueOf(value.toString());
632    } catch (Exception e) {
633  0 val.setError(getMessage("validation.mustBeDouble"));
634    }
635    }
636   
637  1 if (val.isOk()) {
638  1 Double maxValue = ValidatorUtils.getDouble(constraint.getInclusiveMax());
639  1 Double minValue = ValidatorUtils.getDouble(constraint.getExclusiveMin());
640   
641  1 if (maxValue != null && minValue != null) {
642    // validate range
643  1 if (v > maxValue || v < minValue) {
644  1 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
645    }
646  0 } else if (maxValue != null) {
647  0 if (v > maxValue) {
648  0 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
649    }
650  0 } else if (minValue != null) {
651  0 if (v < minValue) {
652  0 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
653    }
654    }
655    }
656   
657  1 if (!val.isOk()) {
658  1 results.add(val);
659    }
660    }
661   
 
662  0 toggle protected void validateFloat(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
663  0 Float v = null;
664   
665  0 ValidationResultInfo val = new ValidationResultInfo(element, value);
666  0 if (value instanceof Number) {
667  0 v = ((Number) value).floatValue();
668    } else {
669  0 try {
670  0 v = Float.valueOf(value.toString());
671    } catch (Exception e) {
672  0 val.setError(getMessage("validation.mustBeFloat"));
673    }
674    }
675   
676  0 if (val.isOk()) {
677  0 Float maxValue = ValidatorUtils.getFloat(constraint.getInclusiveMax());
678  0 Float minValue = ValidatorUtils.getFloat(constraint.getExclusiveMin());
679   
680  0 if (maxValue != null && minValue != null) {
681    // validate range
682  0 if (v > maxValue || v < minValue) {
683  0 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
684    }
685  0 } else if (maxValue != null) {
686  0 if (v > maxValue) {
687  0 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
688    }
689  0 } else if (minValue != null) {
690  0 if (v < minValue) {
691  0 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
692    }
693    }
694    }
695   
696  0 if (!val.isOk()) {
697  0 results.add(val);
698    }
699    }
700   
 
701  43 toggle protected void validateLong(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
702  43 Long v = null;
703   
704  43 ValidationResultInfo val = new ValidationResultInfo(element, value);
705  43 if (value instanceof Number) {
706  43 v = ((Number) value).longValue();
707    } else {
708  0 try {
709  0 v = Long.valueOf(value.toString());
710    } catch (Exception e) {
711  0 val.setError(getMessage("validation.mustBeLong"));
712    }
713    }
714   
715  43 if (val.isOk()) {
716  43 Long maxValue = ValidatorUtils.getLong(constraint.getInclusiveMax());
717  43 Long minValue = ValidatorUtils.getLong(constraint.getExclusiveMin());
718   
719  43 if (maxValue != null && minValue != null) {
720    // validate range
721  0 if (v > maxValue || v < minValue) {
722  0 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
723    }
724  43 } else if (maxValue != null) {
725  0 if (v > maxValue) {
726  0 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
727    }
728  43 } else if (minValue != null) {
729  0 if (v < minValue) {
730  0 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
731    }
732    }
733    }
734   
735  43 if (!val.isOk()) {
736  0 results.add(val);
737    }
738   
739    }
740   
 
741  143 toggle protected void validateInteger(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
742  143 Integer v = null;
743   
744  143 ValidationResultInfo val = new ValidationResultInfo(element, value);
745   
746  143 if (value instanceof Number) {
747  143 v = ((Number) value).intValue();
748    } else {
749  0 try {
750  0 v = Integer.valueOf(value.toString());
751    } catch (Exception e) {
752  0 val.setError(getMessage("validation.mustBeInteger"));
753    }
754    }
755   
756  143 if (val.isOk()) {
757  143 Integer maxValue = ValidatorUtils.getInteger(constraint.getInclusiveMax());
758  143 Integer minValue = ValidatorUtils.getInteger(constraint.getExclusiveMin());
759   
760  143 if (maxValue != null && minValue != null) {
761    // validate range
762  24 if (v > maxValue || v < minValue) {
763  0 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
764    }
765  119 } else if (maxValue != null) {
766  0 if (v > maxValue) {
767  0 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
768    }
769  119 } else if (minValue != null) {
770  0 if (v < minValue) {
771  0 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
772    }
773    }
774    }
775   
776  143 if (!val.isOk()) {
777  0 results.add(val);
778    }
779    }
780   
 
781  977 toggle protected void validateDate(Object value, Constraint constraint, String element, List<ValidationResultInfo> results, DateParser dateParser) {
782  977 ValidationResultInfo val = new ValidationResultInfo(element, value);
783   
784  977 Date v = null;
785   
786  977 if (value instanceof Date) {
787  977 v = (Date) value;
788    } else {
789  0 try {
790  0 v = dateParser.parseDate(value.toString());
791    } catch (Exception e) {
792  0 val.setError(getMessage("validation.mustBeDate"));
793    }
794    }
795   
796  977 if (val.isOk()) {
797  977 Date maxValue = ValidatorUtils.getDate(constraint.getInclusiveMax(), dateParser);
798  977 Date minValue = ValidatorUtils.getDate(constraint.getExclusiveMin(), dateParser);
799   
800  977 if (maxValue != null && minValue != null) {
801    // validate range
802  0 if (v.getTime() > maxValue.getTime() || v.getTime() < minValue.getTime()) {
803  0 val.setError(MessageUtils.interpolate(getMessage("validation.outOfRange"), toMap(constraint)));
804    }
805  977 } else if (maxValue != null) {
806  0 if (v.getTime() > maxValue.getTime()) {
807  0 val.setError(MessageUtils.interpolate(getMessage("validation.maxValueFailed"), toMap(constraint)));
808    }
809  977 } else if (minValue != null) {
810  5 if (v.getTime() < minValue.getTime()) {
811  1 val.setError(MessageUtils.interpolate(getMessage("validation.minValueFailed"), toMap(constraint)));
812    }
813    }
814    }
815   
816  977 if (!val.isOk()) {
817  1 results.add(val);
818    }
819    }
820   
 
821  4669 toggle protected void validateString(Object value, Constraint constraint, String element, List<ValidationResultInfo> results) {
822   
823  4669 if (value == null) {
824  0 value = "";
825    }
826  4669 String s = value.toString().trim();
827   
828  4669 ValidationResultInfo val = new ValidationResultInfo(element, value);
829   
830  4669 Integer maxLength = tryParse(constraint.getMaxLength());
831  4669 if (maxLength != null && constraint.getMinLength() != null && constraint.getMinLength() > 0) {
832  2661 if (s.length() > maxLength || s.length() < constraint.getMinLength()) {
833  22 val.setError(MessageUtils.interpolate(getMessage("validation.lengthOutOfRange"), toMap(constraint)));
834    }
835  2008 } else if (maxLength != null) {
836  1927 if (s.length() > Integer.parseInt(constraint.getMaxLength())) {
837  1 val.setError(MessageUtils.interpolate(getMessage("validation.maxLengthFailed"), toMap(constraint)));
838    }
839  81 } else if (constraint.getMinLength() != null && constraint.getMinLength() > 0) {
840  1 if (s.length() < constraint.getMinLength()) {
841  1 val.setError(MessageUtils.interpolate(getMessage("validation.minLengthFailed"), toMap(constraint)));
842    }
843    }
844   
845  4669 if (!val.isOk()) {
846  24 results.add(val);
847    }
848    }
849   
 
850  229 toggle protected String getMessage(String messageId) {
851  229 if (null == messageService) {
852  229 return messageId;
853    }
854   
855  0 Message msg = messageService.getMessage(messageLocaleKey, messageGroupKey, messageId);
856   
857  0 return msg.getValue();
858    }
859   
 
860  12639 toggle protected String getElementXpath(Stack<String> elementStack) {
861  12639 StringBuilder xPath = new StringBuilder();
862  12639 Iterator<String> itr = elementStack.iterator();
863  74296 while (itr.hasNext()) {
864  61657 xPath.append(itr.next());
865  61657 if(itr.hasNext()){
866  50388 xPath.append("/");
867    }
868    }
869   
870  12639 return xPath.toString();
871    }
872   
873    /*
874    * Homemade has text so we dont need outside libs.
875    */
 
876  958 toggle protected boolean hasText(String string) {
877   
878  958 if (string == null || string.length() < 1) {
879  277 return false;
880    }
881  681 int stringLength = string.length();
882   
883  681 for (int i = 0; i < stringLength; i++) {
884  681 char currentChar = string.charAt(i);
885  681 if (' ' != currentChar || '\t' != currentChar || '\n' != currentChar) {
886  681 return true;
887    }
888    }
889   
890  0 return false;
891    }
892   
 
893  28 toggle protected Map<String, Object> toMap(Constraint c) {
894  28 Map<String, Object> result = new HashMap<String, Object>();
895  28 result.put("minOccurs", c.getMinOccurs());
896  28 result.put("maxOccurs", c.getMaxOccurs());
897  28 result.put("minLength", c.getMinLength());
898  28 result.put("maxLength", c.getMaxLength());
899  28 result.put("minValue", c.getExclusiveMin());
900  28 result.put("maxValue", c.getInclusiveMax());
901    // result.put("dataType", c.getDataType());
902   
903  28 return result;
904    }
905   
 
906  0 toggle public SearchDispatcher getSearchDispatcher() {
907  0 return searchDispatcher;
908    }
909   
 
910  12 toggle public void setSearchDispatcher(SearchDispatcher searchDispatcher) {
911  12 this.searchDispatcher = searchDispatcher;
912    }
913   
 
914  0 toggle @Override
915    public List<ValidationResultInfo> validateObject(FieldDefinition field,
916    Object o, ObjectStructureDefinition objStructure,Stack<String> elementStack) {
917  0 return null;
918    }
919    }