- It forces the developer to create the Validator using a predefined schema
- The Validator had to implement a new interface (ClassAwareValidator)
With that idea in my mind and, by the way, with the intention of also solving the points above I started working a little more with the code already available. The goals were:
- Define a generic Validator that could check any object
- But not all objects should be checked by it
- The Validator could be used to check just a field or the whole object
- The Validator should be usable in AJAX (with DWR)
- The Validator should work side by side with other Validators in the system
- The Validator should support Spring MVC forms
public @interface StringConstraint {
public boolean required() default true;
public String regexp() default "";
public int maxLength() default 0;
}
@Target(ElementType.FIELD)
public @interface IntegerConstraint {
public boolean required() default true;
public int minValue() default 0;
public int maxValue() default 0;
}
- The string annotation can be applied to any field and it will check that the field is not null, it matches a regular expression and it does not span over a number of characters.
- The integer annotation defines a minimum and maximum values for the field
Class extends Annotation> validAnnotation = null;
if (field != null)
for (Annotation annotation: field.getAnnotations())
if (validAnnotation == null)
if (validAnnotations.contains(annotation.annotationType()))
validAnnotation = annotation.annotationType();
return validAnnotation;
}
public boolean supports(Class aClass) {
boolean supports = false;
if ((aClass != null) & (validAnnotations != null)) {
for (Field field : aClass.getDeclaredFields())
if (!supports) supports |= (getValidationAnnotation(field) != null);
}
return supports;
}
if ((object == null) | (errors == null))
throw new IllegalArgumentException();
if (!this.supports(object.getClass()))
throw new IllegalArgumentException();
for (Field field : object.getClass().getDeclaredFields())
validateField(field, object, errors);
}
protected void validateFieldAsString(Field field, Object object, Errors errors) {
StringConstraint req = field.getAnnotation(StringConstraint.class);
if (req.required() && validateNull(field, object))
errors.rejectValue(field.getName(), errorCodes[0]);
field.setAccessible(true);
stringField = field.get(object).toString();
if ((stringField != null) & (req.regexp().length() > 0)) {
Pattern pattern = Pattern.compile(req.regexp());
Matcher matcher = pattern.matcher(stringField);
if (!matcher.matches())
errors.rejectValue(field.getName(), errorCodes[1], req.regexp());
}
if ((stringField != null) & (req.maxLength() > 0)) {
if (stringField.length() > req.maxLength())
errors.rejectValue(
field.getName(),
errorCodes[3],
Integer.toString(req.maxLength()));
}
}
Validator validValidator = null;
if (clazz != null) {
for (Validator validator : this.validators)
if ((validValidator == null) && (validator.supports(clazz)))
validValidator = validator;
}
return validValidator;
}
public String validateField(String fieldName, String fieldValue) throws Exception {
String message = null;
if ((fieldName == null) || (fieldName.indexOf(".") < 0))
throw new DWRBindException(fieldName);
String className = fieldName.substring(0, fieldName.lastIndexOf("."));
Class> clazz = this.getClassFromName(className);
Validator validator = this.getValidator(clazz);
if (validator != null) {
String field = fieldName.substring(fieldName.lastIndexOf(".") + 1);
String capitalizedField = StringUtils.capitalize(field);
Object formBackingObject = clazz.newInstance();
Field f = clazz.getDeclaredField(field);
Object value = this.getValueObject(f.getType(), fieldValue);
f.setAccessible(true);
f.set(formBackingObject, value);
Errors errors = validateObject(formBackingObject);
FieldError error = errors.getFieldError(field);
if (error != null) message = error.getCode();
}
return message;
}
public Errors validateObject(Object object) throws Exception {
Errors errors = null;
if (object != null) {
Validator validator = this.getValidator(object.getClass());
if (validator != null) {
errors = new DirectFieldBindingResult(object, "command");
Class[] validationArgs = new Class[] { Object.class, Errors.class };
String methodName = "validate";
Method method = validator.getClass().getMethod(methodName, validationArgs);
if (method != null)
method.invoke(validator, new Object[] { object, errors });
}
}
return errors;
}

