Developer Legacy

Special Validators on Fields

Question

Is it possible to have a special Validator on a field, like a Date Validator?

Answer

Yes, thanks to the JCRNodeValidator, you can define in spring a validator for special types e.g:

 <bean  class="org.jahia.services.content.decorator.validation.JCRNodeValidatorDefinition">
     <property name="validators">
         <map>
             <entry key="jnt:validatorExample"  value="org.jahia.modules.validatorexample.validator.MyNodeValidator" />
         </map>
     </property>
</bean>  

This MyNodeValidator class have to implement getter methods for the fields which should be checked (e.g. fieldname Date (needs getDate() method)). this method has to return the Validator and in the notation above the method you can define a Validator Interface, also you can specify in the notation some parameters like the daterange:

 public MyNodeValidator(JCRNodeWrapper myNode) {
  this.myNode = myNode;
 }
 @DateValidator(pastMonth = 0, futureMonth = 12)
 public MyNodeValidator getDate() {
  return this; 
        } 

The interface is simple, there you can specify also the Error message for the validator:

@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = MyDateValidator.class)
@Documented
public @interface DateValidator {
    Class<?>[] groups() default {};

    String message() default "{javax.validation.constraints.date.outofrange}";

    Class<? extends Payload>[] payload() default {};

    int futureMonth();
    
    int pastMonth();
}
 

And last you have to implement the validor function itself, if it returns false, the error message is shown:

public class MyDateValidator implements ConstraintValidator<DateValidator, Object> {

 private int pastMonth;
 private int futureMonth;
 @Override
 public void initialize(DateValidator constraintAnnotation) {
  this.pastMonth = constraintAnnotation.pastMonth();
  this.futureMonth = constraintAnnotation.futureMonth();
  
 }

 @Override
 public boolean isValid(Object val, ConstraintValidatorContext arg1) {
  MyNodeValidator validator = null;
  if(val != null && val instanceof MyNodeValidator) {
   validator = (MyNodeValidator)val;
  } else {
   return false;
  }
  
  try {
      Calendar myDate = validator.getMyDate();
      Calendar past = Calendar.getInstance();
      past.add(Calendar.MONTH, (pastMonth * -1));
      Calendar future = Calendar.getInstance();
      future.add(Calendar.MONTH, futureMonth);
      if (myDate.before(past) || myDate.after(future)) {
       return false;
      }
      return true;
  } catch (RepositoryException ex) {
   ex.printStackTrace();
  }
  
  return false;
 }
}