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;
}
}