Clover Coverage Report - KS Common 1.1-SNAPSHOT (Aggregated)
Coverage timestamp: Thu Mar 3 2011 04:37:11 EST
../../../../../../img/srcFileCovDistChart5.png 41% of files have more coverage
406   1,050   216   11.28
276   792   0.53   18
36     6  
2    
 
  Validator       Line # 45 397 0% 215 362 48.9% 0.48870057
  Validator.BaseConstraintBean       Line # 1027 9 0% 1 0 100% 1.0
 
  (9)
 
1    /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10    * software distributed under the License is distributed on an "AS IS"
11    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12    * or implied. See the License for the specific language governing
13    * permissions and limitations under the License.
14    */
15   
16    package org.kuali.student.common.validator.old;
17   
18    import java.util.ArrayList;
19    import java.util.Collection;
20    import java.util.Date;
21    import java.util.HashMap;
22    import java.util.Iterator;
23    import java.util.List;
24    import java.util.Map;
25    import java.util.Stack;
26   
27    import org.kuali.student.common.util.MessageUtils;
28    import org.kuali.student.core.dictionary.old.dto.CaseConstraint;
29    import org.kuali.student.core.dictionary.old.dto.ConstraintDescriptor;
30    import org.kuali.student.core.dictionary.old.dto.ConstraintSelector;
31    import org.kuali.student.core.dictionary.old.dto.Field;
32    import org.kuali.student.core.dictionary.old.dto.LookupConstraint;
33    import org.kuali.student.core.dictionary.old.dto.ObjectStructure;
34    import org.kuali.student.core.dictionary.old.dto.OccursConstraint;
35    import org.kuali.student.core.dictionary.old.dto.RequireConstraint;
36    import org.kuali.student.core.dictionary.old.dto.State;
37    import org.kuali.student.core.dictionary.old.dto.Type;
38    import org.kuali.student.core.dictionary.old.dto.TypeStateCaseConstraint;
39    import org.kuali.student.core.dictionary.old.dto.ValidCharsConstraint;
40    import org.kuali.student.core.dictionary.old.dto.WhenConstraint;
41    import org.kuali.student.core.messages.dto.Message;
42    import org.kuali.student.core.messages.service.MessageService;
43    import org.kuali.student.core.validation.dto.ValidationResultInfo;
44   
 
45    public class Validator {
46   
47    //TODO: Change this to 'default' when the change is made in xml
48    private static final String DEFAULT_STATE = "*";
49   
50    private static final String UNBOUNDED_CHECK = null;
51   
52    private MessageService messageService = null;
53   
54    private String messageLocaleKey = "en";
55   
56    private String messageGroupKey = "validation";
57   
58    private DateParser dateParser = new ServerDateParser();
59   
60    private boolean serverSide = true;
61   
 
62  0 toggle public MessageService getMessageService() {
63  0 return messageService;
64    }
65   
 
66  11 toggle public void setMessageService(MessageService messageService) {
67  11 this.messageService = messageService;
68    }
69   
 
70  0 toggle public String getMessageLocaleKey() {
71  0 return messageLocaleKey;
72    }
73   
 
74  0 toggle public void setMessageLocaleKey(String messageLocaleKey) {
75  0 this.messageLocaleKey = messageLocaleKey;
76    }
77   
 
78  0 toggle public String getMessageGroupKey() {
79  0 return messageGroupKey;
80    }
81   
 
82  0 toggle public void setMessageGroupKey(String messageGroupKey) {
83  0 this.messageGroupKey = messageGroupKey;
84    }
85   
 
86  9 toggle public void setDateParser(DateParser dateParser) {
87  9 this.dateParser = dateParser;
88    }
89   
90    /**
91    * @return the serverSide
92    */
 
93  0 toggle public boolean isServerSide() {
94  0 return serverSide;
95    }
96   
97    /**
98    * @param serverSide
99    * the serverSide to set
100    */
 
101  0 toggle public void setServerSide(boolean serverSide) {
102  0 this.serverSide = serverSide;
103    }
104   
105    /**
106    * @return the dateParser
107    */
 
108  0 toggle public DateParser getDateParser() {
109  0 return dateParser;
110    }
111   
112   
113   
114   
115    /**
116    * Validate Object and all its nested child objects for given type and state
117    *
118    * @param data
119    * @param objStructure
120    * @return
121    */
 
122  9 toggle public List<ValidationResultInfo> validateTypeStateObject(Object data,
123    ObjectStructure objStructure) {
124   
125  9 Stack<String> elementStack = new Stack<String>();
126  9 return validateTypeStateObject(data, objStructure, elementStack);
127    }
128   
 
129  10 toggle private List<ValidationResultInfo> validateTypeStateObject(Object data,
130    ObjectStructure objStructure, Stack<String> elementStack) {
131   
132  10 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
133   
134  10 ConstraintDataProvider dataProvider = new BeanConstraintDataProvider();
135  10 dataProvider.initialize(data);
136   
137  10 boolean isTypeStateObject = (dataProvider.hasField("type") && dataProvider
138    .hasField("state"));
139   
140    // Push object structure to the top of the stack
141  10 StringBuilder objXPathElement = new StringBuilder(dataProvider
142    .getPath());
143  10 if (null != dataProvider.getObjectId()) {
144  10 objXPathElement.append("[id='" + dataProvider.getObjectId() + "']");
145    } else {
146  0 objXPathElement.append("[id='null']");
147    }
148  10 elementStack.push(objXPathElement.toString());
149   
150    /*
151    * Do nothing if the object to be validated is not type/state or if the
152    * objectstructure with constraints is not provided
153    */
154  10 if (!isTypeStateObject || null == objStructure) {
155  0 return results;
156    }
157   
158    // Validate with the matching Type/State
159  10 List<Type> types = objStructure.getType();
160  10 for (Type t : types) {
161  10 if (t.getKey().equalsIgnoreCase(
162    (String) dataProvider.getValue("type"))) {
163  10 for (State s : t.getState()) {
164  10 if (s.getKey().equalsIgnoreCase(
165    (String) dataProvider.getValue("state"))
166    || s.getKey().equalsIgnoreCase(DEFAULT_STATE)) {
167  10 for (Field f : s.getField()) {
168  35 List<ValidationResultInfo> l = validateField(f, t,
169    s, objStructure, dataProvider, elementStack);
170  35 results.addAll(l);
171    }
172  10 break;
173    }
174    }
175  10 break;
176    }
177    }
178  10 elementStack.pop();
179   
180    /* All Field validations are returned right now */
181    // List<ValidationResultInfo> resultsBuffer = new
182    // ArrayList<ValidationResultInfo>();
183    // for (ValidationResultContainer vc : results) {
184    // if (skipFields.contains(vc.getElement()) == false) {
185    // resultsBuffer.add(vc);
186    // }
187    // }
188    // results = resultsBuffer;
189  10 return results;
190    }
191   
 
192  35 toggle public List<ValidationResultInfo> validateField(Field field, Type type,
193    State state, ObjectStructure objStruct,
194    ConstraintDataProvider dataProvider, Stack<String> elementStack) {
195   
196  35 Object value = dataProvider.getValue(field.getKey());
197  35 List<ValidationResultInfo> results = new ArrayList<ValidationResultInfo>();
198   
199  35 ConstraintDescriptor cd = field.getConstraintDescriptor();
200   
201    // Handle null values in field
202  35 if (value == null || "".equals(value.toString().trim())) {
203  19 if (isNullable(field) == false) {
204  9 ValidationResultInfo valInfo = new ValidationResultInfo(
205    getElementXpath(elementStack) + field.getKey());
206  9 valInfo.setError(getMessage("validation.required"));
207  9 results.add(valInfo);
208    }
209  19 return results;
210    }
211   
212    /*
213    * For complex object structures only the following constraints apply
214    * 1. TypeStateCase
215    * 2. MinOccurs
216    * 3. MaxOccurs
217    */
218  16 if ("complex"
219    .equalsIgnoreCase(field.getFieldDescriptor().getDataType())) {
220  1 ObjectStructure nestedObjStruct = null;
221   
222  1 if(null != field.getFieldDescriptor().getObjectStructure()) {
223  1 nestedObjStruct = field.getFieldDescriptor()
224    .getObjectStructure();
225    }
226  0 else if (hasText(field.getFieldDescriptor().getObjectStructureRef())) {
227    //TODO: Setup a mechanism to retrive referenced object structures
228    // nestedObjStruct = setupFactory.getObjectStructure(field
229    // .getFieldDescriptor().getObjectStructureRef());
230    }
231   
232  1 BaseConstraintBean bcb = new BaseConstraintBean();
233  1 if(null != cd) {
234  0 for(ConstraintSelector constraint: cd.getConstraint()) {
235  0 computeBaseConstraints(constraint, bcb, field);
236    }
237    }
238   
239  1 elementStack.push(field.getKey());
240   
241  1 if (value instanceof Collection<?>) {
242   
243  1 String xPath = getElementXpath(elementStack) + "/";
244   
245  1 for (Object o : (Collection<?>) value) {
246  1 processNestedObjectStructure(results, o, nestedObjStruct,
247    field, elementStack);
248    }
249  1 if (bcb.minOccurs > ((Collection<?>) value).size()) {
250  0 ValidationResultInfo valRes = new ValidationResultInfo(
251    xPath);
252  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), bcb.toMap()));
253  0 results.add(valRes);
254    }
255   
256  1 Integer maxOccurs = tryParse(bcb.maxOccurs);
257  1 if (maxOccurs != null
258    && maxOccurs < ((Collection<?>) value).size()) {
259  0 ValidationResultInfo valRes = new ValidationResultInfo(
260    xPath);
261  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), bcb.toMap()));
262  0 results.add(valRes);
263    }
264    } else {
265  0 if(null != value) {
266  0 processNestedObjectStructure(results, value, nestedObjStruct,
267    field, elementStack);
268    } else {
269  0 if (bcb.minOccurs != null && bcb.minOccurs > 0) {
270  0 ValidationResultInfo val = new ValidationResultInfo(
271    getElementXpath(elementStack) + "[value='null']/");
272  0 val.setError(getMessage("validation.required"));
273  0 results.add(val);
274    }
275    }
276    }
277   
278  1 elementStack.pop();
279   
280    } else { // If non complex data type
281  15 if (null != cd) {
282  15 List<ConstraintSelector> constraints = cd.getConstraint();
283   
284  15 if (value instanceof Collection<?>) {
285  0 BaseConstraintBean bcb = new BaseConstraintBean();
286  0 for (Object o : (Collection<?>) value) {
287  0 for (ConstraintSelector constraint : constraints) {
288  0 processConstraint(results, constraint, field, type,
289    state, objStruct, o, dataProvider, bcb, elementStack);
290    }
291  0 processBaseConstraints(results, bcb, field, o, elementStack);
292  0 if(!bcb.initialized) {
293  0 bcb.initialized = true;
294    }
295    }
296   
297  0 String xPath = getElementXpath(elementStack) + field.getKey() + "/";
298  0 if (bcb.minOccurs > ((Collection<?>) value).size()) {
299  0 ValidationResultInfo valRes = new ValidationResultInfo(
300    xPath);
301  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.minOccurs"), bcb.toMap()));
302  0 results.add(valRes);
303    }
304   
305  0 Integer maxOccurs = tryParse(bcb.maxOccurs);
306  0 if (maxOccurs != null
307    && maxOccurs < ((Collection<?>) value).size()) {
308  0 ValidationResultInfo valRes = new ValidationResultInfo(
309    xPath);
310  0 valRes.setError(MessageUtils.interpolate(getMessage("validation.maxOccurs"), bcb.toMap()));
311  0 results.add(valRes);
312    }
313    } else {
314  15 BaseConstraintBean bcb = new BaseConstraintBean();
315  15 for (ConstraintSelector constraint : constraints) {
316  24 processConstraint(results, constraint, field, type,
317    state, objStruct, value, dataProvider, bcb, elementStack);
318    }
319  15 processBaseConstraints(results, bcb, field, value, elementStack);
320    }
321    }
322    }
323  16 return results;
324    }
325   
 
326  19 toggle private boolean isNullable(Field field) {
327  19 ConstraintDescriptor cd = field.getConstraintDescriptor();
328  19 if (null != cd) {
329  19 List<ConstraintSelector> constraintList = cd.getConstraint();
330  19 for (ConstraintSelector cs : constraintList) {
331  19 if (cs.getMinOccurs() != null && cs.getMinOccurs() > 0) {
332  9 return false;
333    }
334    }
335    }
336  10 return true;
337    }
338   
 
339  31 toggle private Integer tryParse(String s) {
340  31 Integer result = null;
341  31 if (s != null) {
342  18 try {
343  18 result = Integer.valueOf(s);
344    } catch (NumberFormatException e) {
345    // do nothing
346    }
347    }
348  31 return result;
349    }
350   
 
351  1 toggle private void processNestedObjectStructure(
352    List<ValidationResultInfo> results, Object value,
353    ObjectStructure nestedObjStruct, Field field, Stack<String> elementStack) {
354   
355  1 results.addAll(validateTypeStateObject(value, nestedObjStruct, elementStack));
356   
357  1 ConstraintDescriptor cd = field.getConstraintDescriptor();
358  1 if (null != cd) {
359  0 ConstraintSelector cs = cd.getConstraint().get(0);
360  0 TypeStateCaseConstraint tscs = cs.getTypeStateCaseConstraint();
361  0 if (null != tscs) {
362    // ValidationResultContainer vc = new
363    // ValidationResultContainer();
364    // processTypeStateCaseConstraint(vc);
365    // results.add(vc);k
366    }
367    }
368    }
369   
 
370  24 toggle private void computeBaseConstraints(ConstraintSelector constraint,
371    BaseConstraintBean bcb, Field field) {
372  24 if (null != constraint.getMinLength()) {
373  10 bcb.minLength = (bcb.minLength > constraint.getMinLength()) ? bcb.minLength
374    : constraint.getMinLength();
375    }
376   
377  24 if (null != constraint.getMinOccurs()) {
378  13 bcb.minOccurs = (bcb.minOccurs > constraint.getMinOccurs()) ? bcb.minOccurs
379    : constraint.getMinOccurs();
380    }
381   
382  24 if (null != constraint.getMinValue()) {
383  4 bcb.minValue = (null == bcb.minValue || ValidatorUtils
384    .compareValues(bcb.minValue, constraint.getMinValue(),
385    field.getFieldDescriptor().getDataType(),
386    "GREATER_THAN", dateParser)) ? constraint
387    .getMinValue() : bcb.minValue;
388    }
389   
390  24 if (null != constraint.getMaxValue()) {
391  1 bcb.maxValue = (null == bcb.maxValue || ValidatorUtils
392    .compareValues(bcb.maxValue, constraint.getMaxValue(),
393    field.getFieldDescriptor().getDataType(),
394    "LESS_THAN", dateParser)) ? constraint
395    .getMaxValue() : bcb.maxValue;
396    }
397   
398  24 if (hasText(constraint.getMaxLength())) {
399  9 Integer maxLength = tryParse(bcb.maxLength);
400  9 Integer constraintMaxLength = tryParse(constraint.getMaxLength());
401  9 if (maxLength == null) {
402  9 bcb.maxLength = constraint.getMaxLength();
403  0 } else if (constraintMaxLength != null) {
404  0 if (constraintMaxLength > maxLength) {
405  0 bcb.maxLength = constraint.getMaxLength();
406    }
407    }
408    }
409   
410  24 if (hasText(constraint.getMaxOccurs())) {
411  1 Integer maxOccurs = tryParse(bcb.maxOccurs);
412  1 Integer constraintMaxOccurs = tryParse(constraint.getMaxOccurs());
413  1 if (maxOccurs == null) {
414  1 bcb.maxOccurs = constraint.getMaxOccurs();
415  0 } else if (constraintMaxOccurs != null) {
416  0 if (constraintMaxOccurs > maxOccurs) {
417  0 bcb.maxOccurs = constraint.getMaxOccurs();
418    }
419    }
420    }
421    }
422   
 
423  24 toggle private void processConstraint(List<ValidationResultInfo> valResults,
424    ConstraintSelector constraint, Field field, Type type, State state,
425    ObjectStructure objStructure, Object value,
426    ConstraintDataProvider dataProvider, BaseConstraintBean bcb,
427    Stack<String> elementStack) {
428   
429    // If constraint is only to be processed on server side
430  24 if (hasText(constraint.getClassName()) || constraint.isServerSide()
431    && !serverSide) {
432  0 return;
433    }
434   
435  24 String elementPath = getElementXpath(elementStack) + field.getKey()
436    + "[value='" + value.toString() + "']/";
437   
438  24 if(!bcb.initialized) {
439  24 computeBaseConstraints(constraint, bcb, field);
440    }
441   
442    // Process Valid Chars
443  24 if (null != constraint.getValidChars()) {
444  9 ValidationResultInfo val = processValidCharConstraint(elementPath,
445    constraint.getValidChars(), dataProvider, value);
446  9 if (null != val) {
447  2 valResults.add(val);
448    }
449    }
450   
451    // Process Require Constraints (only if this field has value)
452  24 if (value != null && !"".equals(value.toString().trim())) {
453  24 if (null != constraint.getRequireConstraint()
454    && constraint.getRequireConstraint().size() > 0) {
455  1 for (RequireConstraint rc : constraint.getRequireConstraint()) {
456  1 ValidationResultInfo val = processRequireConstraint(
457    elementPath, rc, field, objStructure, dataProvider);
458  1 if (null != val) {
459  1 valResults.add(val);
460    }
461    }
462    }
463    }
464   
465    // Process Occurs Constraint
466  24 if (null != constraint.getOccursConstraint()
467    && constraint.getOccursConstraint().size() > 0) {
468  0 for (OccursConstraint oc : constraint.getOccursConstraint()) {
469  0 ValidationResultInfo val = processOccursConstraint(elementPath,
470    oc, field, type, state, objStructure, dataProvider);
471  0 if (null != val) {
472  0 valResults.add(val);
473    }
474    }
475    }
476   
477    // Process lookup Constraint
478  24 if (null != constraint.getLookupConstraint()
479    && constraint.getLookupConstraint().size() > 0) {
480  0 for (LookupConstraint lc : constraint.getLookupConstraint()) {
481  0 processLookupConstraint(valResults);
482    }
483    }
484   
485    // Process Case Constraint
486  24 if (null != constraint.getCaseConstraint()
487    && constraint.getCaseConstraint().size() > 0) {
488  0 for (CaseConstraint cc : constraint.getCaseConstraint()) {
489  0 processCaseConstraint(valResults, cc, field, type, state,
490    objStructure, value, dataProvider, bcb, elementStack);
491    }
492    }
493    }
494   
 
495  1 toggle private ValidationResultInfo processRequireConstraint(String element,
496    RequireConstraint constraint, Field field,
497    ObjectStructure objStructure, ConstraintDataProvider dataProvider) {
498   
499  1 ValidationResultInfo val = null;
500   
501  1 String fieldName = constraint.getField();
502  1 Object fieldValue = dataProvider.getValue(fieldName);
503   
504  1 boolean result = true;
505   
506  1 if (fieldValue instanceof java.lang.String) {
507  1 result = hasText((String) fieldValue);
508  0 } else if (fieldValue instanceof Collection<?>) {
509  0 result = (((Collection<?>) fieldValue).size() > 0);
510    } else {
511  0 result = (null != fieldValue) ? true : false;
512    }
513   
514  1 if (!result) {
515  1 Map<String, Object> rMap = new HashMap<String, Object>();
516  1 rMap.put("field1", field.getKey());
517  1 rMap.put("field2", fieldName);
518  1 val = new ValidationResultInfo(element);
519  1 val.setError(MessageUtils.interpolate(
520    getMessage("validation.requiresField"), rMap));
521    }
522   
523  1 return val;
524    }
525   
526    /**
527    * Process caseConstraint tag and sets any of the base constraint items if
528    * any of the when condition matches
529    *
530    * @param bcb
531    * @param caseConstraint
532    * @param field
533    */
 
534  0 toggle private void processCaseConstraint(List<ValidationResultInfo> valResults,
535    CaseConstraint constraint, Field field, Type type, State state,
536    ObjectStructure objStructure, Object value,
537    ConstraintDataProvider dataProvider, BaseConstraintBean bcb,
538    Stack<String> elementStack) {
539   
540  0 String operator = (hasText(constraint.getOperator())) ? constraint
541    .getOperator() : "EQUALS";
542  0 Field caseField = (hasText(constraint.getField())) ? ValidatorUtils
543    .getField(constraint.getField(), objStructure, type.getKey(),
544    state.getKey()) : null;
545   
546    // TODO: What happens when the field is not in the dataProvider?
547  0 Object fieldValue = (null != caseField) ? dataProvider
548    .getValue(caseField.getKey()) : value;
549   
550    // Extract value for field Key
551  0 for (WhenConstraint wc : constraint.getWhenConstraint()) {
552  0 String whenValue = wc.getValue();
553   
554  0 if (ValidatorUtils.compareValues(fieldValue, whenValue, caseField
555    .getFieldDescriptor().getDataType(), operator, dateParser)) {
556  0 processConstraint(valResults, wc.getConstraint(), field, type,
557    state, objStructure, value, dataProvider, bcb,
558    elementStack);
559    }
560    }
561    }
562   
 
563  9 toggle private ValidationResultInfo processValidCharConstraint(String element,
564    ValidCharsConstraint vcConstraint,
565    ConstraintDataProvider dataProvider, Object value) {
566   
567  9 ValidationResultInfo val = null;
568   
569  9 StringBuilder fieldValue = new StringBuilder();
570  9 String validChars = vcConstraint.getValue();
571  9 String fields = vcConstraint.getFields();
572   
573  9 if (hasText(fields)) {
574  0 String separator = vcConstraint.getSeparator();
575  0 String[] fieldNameList = fields.split(",");
576   
577  0 int sz = fieldNameList.length;
578   
579  0 for (String fieldName : fieldNameList) {
580  0 Object v = dataProvider.getValue(fieldName);
581  0 fieldValue.append(ValidatorUtils.getString(v));
582   
583  0 if (--sz > 0) {
584  0 fieldValue.append(separator);
585    }
586    }
587    } else {
588  9 fieldValue.append(ValidatorUtils.getString(value));
589    }
590   
591  9 int typIdx = validChars.indexOf(":");
592  9 String processorType = "regex";
593  9 if (-1 == typIdx) {
594  0 validChars = "[" + validChars + "]*";
595    } else {
596  9 processorType = validChars.substring(0, typIdx);
597  9 validChars = validChars.substring(typIdx + 1);
598    }
599   
600    // TODO: Allow different processing based on the label
601  9 if ("regex".equalsIgnoreCase(processorType)) {
602    // if (!Pattern.matches(validChars, fieldValue.toString())) {
603  9 if (fieldValue == null) {
604  0 val = new ValidationResultInfo(element);
605  0 val.setError(getMessage("validation.validCharsFailed"));
606  9 } else if (fieldValue != null
607    && !fieldValue.toString().matches(validChars)) {
608  2 val = new ValidationResultInfo(element);
609  2 val.setError(getMessage("validation.validCharsFailed"));
610    }
611    }
612   
613  9 return val;
614    }
615   
616    /**
617    * Computes if all the filed required in the occurs clause are between the
618    * min and max
619    *
620    * @param valResults
621    * @param constraint
622    * @param field
623    * @param type
624    * @param state
625    * @param objStructure
626    * @param dataProvider
627    * @return
628    */
 
629  0 toggle private ValidationResultInfo processOccursConstraint(String element,
630    OccursConstraint constraint, Field field, Type type, State state,
631    ObjectStructure objStructure, ConstraintDataProvider dataProvider) {
632   
633  0 boolean result = false;
634  0 int trueCount = 0;
635   
636  0 ValidationResultInfo val = null;
637   
638  0 for (RequireConstraint rc : constraint.getRequire()) {
639  0 trueCount += (processRequireConstraint("", rc, field, objStructure,
640    dataProvider) != null) ? 1 : 0;
641    }
642   
643  0 for (OccursConstraint oc : constraint.getOccurs()) {
644  0 trueCount += (processOccursConstraint("", oc, field, type, state,
645    objStructure, dataProvider) != null) ? 1 : 0;
646    }
647   
648  0 result = (trueCount >= constraint.getMin() && trueCount <= constraint
649    .getMax()) ? true : false;
650   
651  0 if (!result) {
652  0 val = new ValidationResultInfo(element);
653  0 val.setError(getMessage("validation.occurs"));
654    }
655   
656  0 return val;
657    }
658   
659    // TODO: Implement lookup constraint
 
660  0 toggle private void processLookupConstraint(List<ValidationResultInfo> valResults) {
661    }
662   
663    // TODO: Implement TypeStateCase constraint
 
664  0 toggle private void processTypeStateCaseConstraint(
665    List<ValidationResultInfo> valResults) {
666    }
667   
 
668  15 toggle private void processBaseConstraints(List<ValidationResultInfo> valResults,
669    BaseConstraintBean bcb, Field field, Object value,
670    Stack<String> elementStack) {
671   
672  15 String dataType = field.getFieldDescriptor().getDataType();
673   
674  15 if (value == null || "".equals(value.toString().trim())) {
675  0 if (bcb.minOccurs != null && bcb.minOccurs > 0) {
676  0 ValidationResultInfo val = new ValidationResultInfo(
677    getElementXpath(elementStack) + field.getKey()
678    + "[value='null']/");
679  0 val.setError(getMessage("validation.required"));
680  0 valResults.add(val);
681  0 return;
682    }
683    }
684   
685  15 String elementPath = getElementXpath(elementStack) + field.getKey()
686    + "[value='" + value.toString() + "']/";
687   
688  15 if ("string".equalsIgnoreCase(dataType)) {
689  10 validateString(value, bcb, elementPath, valResults);
690  5 } else if ("integer".equalsIgnoreCase(dataType)) {
691  1 validateInteger(value, bcb, elementPath, valResults);
692  4 } else if ("long".equalsIgnoreCase(dataType)) {
693  0 validateLong(value, bcb, elementPath, valResults);
694  4 } else if ("double".equalsIgnoreCase(dataType)) {
695  1 validateDouble(value, bcb, elementPath, valResults);
696  3 } else if ("float".equalsIgnoreCase(dataType)) {
697  0 validateFloat(value, bcb, elementPath, valResults);
698  3 } else if ("boolean".equalsIgnoreCase(dataType)) {
699  0 validateBoolean(value, bcb, elementPath, valResults);
700  3 } else if ("date".equalsIgnoreCase(dataType)) {
701  3 validateDate(value, bcb, elementPath, valResults, dateParser);
702    }
703    }
704   
 
705  0 toggle private void validateBoolean(Object value, BaseConstraintBean bcb,
706    String element, List<ValidationResultInfo> results) {
707  0 if (!(value instanceof Boolean)) {
708  0 try {
709  0 Boolean.valueOf(value.toString());
710    } catch (Exception e) {
711  0 ValidationResultInfo val = new ValidationResultInfo(element);
712  0 val.setError(getMessage("validation.mustBeBoolean"));
713  0 results.add(val);
714    }
715    }
716    }
717   
 
718  1 toggle private void validateDouble(Object value, BaseConstraintBean bcb,
719    String element, List<ValidationResultInfo> results) {
720  1 Double v = null;
721   
722  1 ValidationResultInfo val = new ValidationResultInfo(element);
723   
724  1 if (value instanceof Number) {
725  1 v = ((Number) value).doubleValue();
726    } else {
727  0 try {
728  0 v = Double.valueOf(value.toString());
729    } catch (Exception e) {
730  0 val.setError(getMessage("validation.mustBeDouble"));
731    }
732    }
733   
734  1 if (val.isOk()) {
735  1 Double maxValue = ValidatorUtils.getDouble(bcb.maxValue);
736  1 Double minValue = ValidatorUtils.getDouble(bcb.minValue);
737   
738  1 if (maxValue != null && minValue != null) {
739    // validate range
740  1 if (v > maxValue || v < minValue) {
741  1 val.setError(MessageUtils.interpolate(
742    getMessage("validation.outOfRange"), bcb.toMap()));
743    }
744  0 } else if (maxValue != null) {
745  0 if (v > maxValue) {
746  0 val.setError(MessageUtils.interpolate(
747    getMessage("validation.maxValueFailed"), bcb
748    .toMap()));
749    }
750  0 } else if (minValue != null) {
751  0 if (v < minValue) {
752  0 val.setError(MessageUtils.interpolate(
753    getMessage("validation.minValueFailed"), bcb
754    .toMap()));
755    }
756    }
757    }
758   
759  1 if (!val.isOk()) {
760  1 results.add(val);
761    }
762    }
763   
 
764  0 toggle private void validateFloat(Object value, BaseConstraintBean bcb,
765    String element, List<ValidationResultInfo> results) {
766  0 Float v = null;
767   
768  0 ValidationResultInfo val = new ValidationResultInfo(element);
769  0 if (value instanceof Number) {
770  0 v = ((Number) value).floatValue();
771    } else {
772  0 try {
773  0 v = Float.valueOf(value.toString());
774    } catch (Exception e) {
775  0 val.setError(getMessage("validation.mustBeFloat"));
776    }
777    }
778   
779  0 if (val.isOk()) {
780  0 Float maxValue = ValidatorUtils.getFloat(bcb.maxValue);
781  0 Float minValue = ValidatorUtils.getFloat(bcb.minValue);
782   
783  0 if (maxValue != null && minValue != null) {
784    // validate range
785  0 if (v > maxValue || v < minValue) {
786  0 val.setError(MessageUtils.interpolate(
787    getMessage("validation.outOfRange"), bcb.toMap()));
788    }
789  0 } else if (maxValue != null) {
790  0 if (v > maxValue) {
791  0 val.setError(MessageUtils.interpolate(
792    getMessage("validation.maxValueFailed"), bcb
793    .toMap()));
794    }
795  0 } else if (minValue != null) {
796  0 if (v < minValue) {
797  0 val.setError(MessageUtils.interpolate(
798    getMessage("validation.minValueFailed"), bcb
799    .toMap()));
800    }
801    }
802    }
803   
804  0 if (!val.isOk()) {
805  0 results.add(val);
806    }
807    }
808   
 
809  0 toggle private void validateLong(Object value, BaseConstraintBean bcb,
810    String element, List<ValidationResultInfo> results) {
811  0 Long v = null;
812   
813  0 ValidationResultInfo val = new ValidationResultInfo(element);
814  0 if (value instanceof Number) {
815  0 v = ((Number) value).longValue();
816    } else {
817  0 try {
818  0 v = Long.valueOf(value.toString());
819    } catch (Exception e) {
820  0 val.setError(getMessage("validation.mustBeLong"));
821    }
822    }
823   
824  0 if (val.isOk()) {
825  0 Long maxValue = ValidatorUtils.getLong(bcb.maxValue);
826  0 Long minValue = ValidatorUtils.getLong(bcb.minValue);
827   
828  0 if (maxValue != null && minValue != null) {
829    // validate range
830  0 if (v > maxValue || v < minValue) {
831  0 val.setError(MessageUtils.interpolate(
832    getMessage("validation.outOfRange"), bcb.toMap()));
833    }
834  0 } else if (maxValue != null) {
835  0 if (v > maxValue) {
836  0 val.setError(MessageUtils.interpolate(
837    getMessage("validation.maxValueFailed"), bcb
838    .toMap()));
839    }
840  0 } else if (minValue != null) {
841  0 if (v < minValue) {
842  0 val.setError(MessageUtils.interpolate(
843    getMessage("validation.minValueFailed"), bcb
844    .toMap()));
845    }
846    }
847    }
848   
849  0 if (!val.isOk()) {
850  0 results.add(val);
851    }
852   
853    }
854   
 
855  1 toggle private void validateInteger(Object value, BaseConstraintBean bcb,
856    String element, List<ValidationResultInfo> results) {
857  1 Integer v = null;
858   
859  1 ValidationResultInfo val = new ValidationResultInfo(element);
860   
861  1 if (value instanceof Number) {
862  0 v = ((Number) value).intValue();
863    } else {
864  1 try {
865  1 v = Integer.valueOf(value.toString());
866    } catch (Exception e) {
867  1 val.setError(getMessage("validation.mustBeInteger"));
868    }
869    }
870   
871  1 if (val.isOk()) {
872  0 Integer maxValue = ValidatorUtils.getInteger(bcb.maxValue);
873  0 Integer minValue = ValidatorUtils.getInteger(bcb.minValue);
874   
875  0 if (maxValue != null && minValue != null) {
876    // validate range
877  0 if (v > maxValue || v < minValue) {
878  0 val.setError(MessageUtils.interpolate(
879    getMessage("validation.outOfRange"), bcb.toMap()));
880    }
881  0 } else if (maxValue != null) {
882  0 if (v > maxValue) {
883  0 val.setError(MessageUtils.interpolate(
884    getMessage("validation.maxValueFailed"), bcb
885    .toMap()));
886    }
887  0 } else if (minValue != null) {
888  0 if (v < minValue) {
889  0 val.setError(MessageUtils.interpolate(
890    getMessage("validation.minValueFailed"), bcb
891    .toMap()));
892    }
893    }
894    }
895   
896  1 if (!val.isOk()) {
897  1 results.add(val);
898    }
899    }
900   
 
901  3 toggle private void validateDate(Object value, BaseConstraintBean bcb,
902    String element, List<ValidationResultInfo> results,
903    DateParser dateParser) {
904  3 ValidationResultInfo val = new ValidationResultInfo(element);
905   
906  3 Date v = null;
907   
908  3 if (value instanceof Date) {
909  3 v = (Date) value;
910    } else {
911  0 try {
912  0 v = dateParser.parseDate(value.toString());
913    } catch (Exception e) {
914  0 val.setError(getMessage("validation.mustBeDate"));
915    }
916    }
917   
918  3 if (val.isOk()) {
919  3 Date maxValue = ValidatorUtils.getDate(bcb.maxValue, dateParser);
920  3 Date minValue = ValidatorUtils.getDate(bcb.minValue, dateParser);
921   
922  3 if (maxValue != null && minValue != null) {
923    // validate range
924  0 if (v.getTime() > maxValue.getTime()
925    || v.getTime() < minValue.getTime()) {
926  0 val.setError(MessageUtils.interpolate(
927    getMessage("validation.outOfRange"), bcb.toMap()));
928    }
929  3 } else if (maxValue != null) {
930  0 if (v.getTime() > maxValue.getTime()) {
931  0 val.setError(MessageUtils.interpolate(
932    getMessage("validation.maxValueFailed"), bcb
933    .toMap()));
934    }
935  3 } else if (minValue != null) {
936  3 if (v.getTime() < minValue.getTime()) {
937  1 val.setError(MessageUtils.interpolate(
938    getMessage("validation.minValueFailed"), bcb
939    .toMap()));
940    }
941    }
942    }
943   
944  3 if (!val.isOk()) {
945  1 results.add(val);
946    }
947    }
948   
 
949  10 toggle private void validateString(Object value, BaseConstraintBean bcb,
950    String element, List<ValidationResultInfo> results) {
951   
952  10 if (value == null) {
953  0 value = "";
954    }
955  10 String s = value.toString().trim();
956   
957  10 ValidationResultInfo val = new ValidationResultInfo(element);
958   
959  10 Integer maxLength = tryParse(bcb.maxLength);
960  10 if (maxLength != null && bcb.minLength > 0) {
961  7 if (s.length() > maxLength || s.length() < bcb.minLength) {
962  1 val
963    .setError(MessageUtils.interpolate(
964    getMessage("validation.lengthOutOfRange"), bcb
965    .toMap()));
966    }
967  3 } else if (maxLength != null) {
968  1 if (s.length() > Integer.parseInt(bcb.maxLength)) {
969  1 val.setError(MessageUtils.interpolate(
970    getMessage("validation.maxLengthFailed"), bcb.toMap()));
971    }
972  2 } else if (bcb.minLength > 0) {
973  1 if (s.length() < bcb.minLength) {
974  1 val.setError(MessageUtils.interpolate(
975    getMessage("validation.minLengthFailed"), bcb.toMap()));
976    }
977    }
978   
979  10 if (!val.isOk()) {
980  3 results.add(val);
981    }
982    }
983   
 
984  18 toggle private String getMessage(String messageId) {
985  18 if (null == messageService) {
986  18 return messageId;
987    }
988   
989  0 Message msg = messageService.getMessage(messageLocaleKey,
990    messageGroupKey, messageId);
991   
992  0 return msg.getValue();
993    }
994   
 
995  49 toggle private String getElementXpath(Stack<String> elementStack) {
996  49 StringBuilder xPath = new StringBuilder();
997  49 xPath.append("/");
998  49 Iterator<String> itr = elementStack.iterator();
999  107 while (itr.hasNext()) {
1000  58 xPath.append(itr.next() + "/");
1001    }
1002   
1003  49 return xPath.toString();
1004    }
1005   
1006    /*
1007    * Homemade has text so we dont need outside libs.
1008    */
 
1009  82 toggle private boolean hasText(String string) {
1010   
1011  82 if (string == null || string.length() < 1) {
1012  72 return false;
1013    }
1014  10 int stringLength = string.length();
1015   
1016  10 for (int i = 0; i < stringLength; i++) {
1017  10 char currentChar = string.charAt(i);
1018  10 if (' ' != currentChar || '\t' != currentChar
1019    || '\n' != currentChar) {
1020  10 return true;
1021    }
1022    }
1023   
1024  0 return false;
1025    }
1026   
 
1027    private static class BaseConstraintBean {
1028    public boolean initialized = false;
1029    public Integer minOccurs = 0;
1030    public String maxOccurs = UNBOUNDED_CHECK;
1031    public Integer minLength = 0;
1032    public String maxLength = UNBOUNDED_CHECK;
1033    public String dataType = null;
1034    public String minValue = null;
1035    public String maxValue = null;
1036   
 
1037  5 toggle public Map<String, Object> toMap() {
1038  5 Map<String, Object> result = new HashMap<String, Object>();
1039  5 result.put("minOccurs", minOccurs);
1040  5 result.put("maxOccurs", maxOccurs);
1041  5 result.put("minLength", minLength);
1042  5 result.put("maxLength", maxLength);
1043  5 result.put("minValue", minValue);
1044  5 result.put("maxValue", maxValue);
1045  5 result.put("dataType", dataType);
1046   
1047  5 return result;
1048    }
1049    }
1050    }