
org.richfaces.validator.BeanValidatorServiceImpl Maven / Gradle / Ivy
/**
*
*/
package org.richfaces.validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.el.ELException;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.ElementDescriptor.ConstraintFinder;
import javax.validation.metadata.PropertyDescriptor;
import org.richfaces.el.ValueDescriptor;
import org.richfaces.el.ValueExpressionAnalayser;
import com.google.common.collect.ImmutableSet;
/**
* @author asmirnov
*
*/
public class BeanValidatorServiceImpl implements BeanValidatorService {
private static final Collection HIDDEN_PARAMS = ImmutableSet.of("message","payload","groups");
private static final String FACES_CONTEXT_IS_NULL = "Faces context is null";
private static final String INPUT_PARAMETERS_IS_NOT_CORRECT = "Input parameters is not correct.";
private static final Class>[] DEFAULT_GROUP={};
private final ValueExpressionAnalayser analayser;
private final BeanValidatorFactory validatorFactory;
public BeanValidatorServiceImpl(ValueExpressionAnalayser analayser, BeanValidatorFactory validatorFactory) {
this.analayser = analayser;
this.validatorFactory = validatorFactory;
}
/*
* (non-Javadoc)
*
* @see org.richfaces.validator.BeanValidatorService#getConstrains(javax.faces.context.FacesContext,
* javax.el.ValueExpression, java.lang.Class>[])
*/
public Collection getConstrains(FacesContext context, ValueExpression expression,
Class>... groups) {
try {
ValueDescriptor propertyDescriptor = analayser.getPropertyDescriptor(context, expression);
if (propertyDescriptor == null) {
return Collections.emptySet();
}
return processBeanAttribute(context, propertyDescriptor, groups);
} catch (ELException e) {
return Collections.emptySet();
}
}
private Validator getValidator(FacesContext context) {
return validatorFactory.getValidator(context);
}
Collection processBeanAttribute(FacesContext context, ValueDescriptor descriptor,
Class>... groups) {
PropertyDescriptor constraintsForProperty =
getValidator(context).getConstraintsForClass(descriptor.getBeanType()).getConstraintsForProperty(
descriptor.getName());
if (null != constraintsForProperty) {
ConstraintFinder propertyConstraints = constraintsForProperty.findConstraints();
if (null != groups && groups.length > 0) {
// Filter groups, if required
propertyConstraints = propertyConstraints.unorderedAndMatchingGroups(groups);
}
Set> constraints = propertyConstraints // or the requested list of groups)
.getConstraintDescriptors();
// ContextHolder is an arbitrary object, it will depend on the implementation
Set descriptors = new HashSet(constraints.size());
processConstraints(context, constraints, descriptors);
return descriptors;
} else {
return Collections.emptySet();
}
}
void processConstraints(FacesContext context, Set> constraints,
Collection descriptors) {
for (ConstraintDescriptor> cd : constraints) {
Annotation a = cd.getAnnotation();
Map parameters = cd.getAttributes();
// TODO if cd.isReportedAsSingleConstraint() make sure than only the root constraint raises an error message
// if one or several of the composing constraints are invalid)
FacesMessage message = validatorFactory.interpolateMessage(context, cd);
Class extends Annotation> validatorClass = findAnnotationClass(a);
BeanValidatorDescriptor beanValidatorDescriptor = new BeanValidatorDescriptor(validatorClass, message);
for (Map.Entry entry : parameters.entrySet()) {
String key = entry.getKey();
if (!HIDDEN_PARAMS.contains(key)) {
Object value = entry.getValue();
try {
Method method = validatorClass.getDeclaredMethod(key);
Object defaultValue = method.getDefaultValue();
if(!value.equals(defaultValue)){
beanValidatorDescriptor.addParameter(key, value);
}
} catch (SecurityException e) {
beanValidatorDescriptor.addParameter(key, value);
} catch (NoSuchMethodException e) {
beanValidatorDescriptor.addParameter(key, value);
}
}
}
beanValidatorDescriptor.makeImmutable();
descriptors.add(beanValidatorDescriptor);
processConstraints(context, cd.getComposingConstraints(), descriptors); // process the composing constraints
}
}
private Class extends Annotation> findAnnotationClass(Annotation a) {
Class extends Annotation> annotationClass = a.getClass();
// RF-10311, Hibernate validator wraps annotation class with proxy;
if (!annotationClass.isAnnotation()) {
Class>[] interfaces = annotationClass.getInterfaces();
for (Class> implemented : interfaces) {
if (implemented.isAnnotation()) {
annotationClass = (Class extends Annotation>) implemented;
}
}
}
return annotationClass;
}
public Collection validateExpression(FacesContext context, ValueExpression expression, Object newValue,
Class>... groups) {
if (null == context) {
throw new FacesException(INPUT_PARAMETERS_IS_NOT_CORRECT);
}
Collection validationMessages = null;
if (null != expression) {
ValueDescriptor valueDescriptor;
try {
valueDescriptor = analayser.updateValueAndGetPropertyDescriptor(context, expression, newValue);
} catch (ELException e) {
throw new FacesException(e);
}
if (valueDescriptor != null) {
validationMessages = validate(context, valueDescriptor.getBeanType(), valueDescriptor.getName(), newValue, groups);
}
}
if (validationMessages == null) {
validationMessages = Collections.emptySet();
}
return validationMessages;
}
/**
* Class for identify validator instance by locale
*
* @author amarkhel
*
*/
protected static class ValidatorKey {
private final Class extends Object> validatableClass;
private final Locale locale;
/**
* Constructor for ValidatorKey object
*
* @param validatableClass
* - class to validate
* @param locale
* - User locale to determine Resource bundle, used during validation process
*/
public ValidatorKey(Class extends Object> validatableClass, Locale locale) {
this.validatableClass = validatableClass;
this.locale = locale;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.locale == null) ? 0 : this.locale.hashCode());
result = prime * result + ((this.validatableClass == null) ? 0 : this.validatableClass.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ValidatorKey other = (ValidatorKey) obj;
if (this.locale == null) {
if (other.locale != null) {
return false;
}
} else if (!this.locale.equals(other.locale)) {
return false;
}
if (this.validatableClass == null) {
if (other.validatableClass != null) {
return false;
}
} else if (!this.validatableClass.equals(other.validatableClass)) {
return false;
}
return true;
}
}
protected Collection validate(FacesContext facesContext, Class> beanType, String property, Object value,
Class>[] groups) {
@SuppressWarnings("unchecked")
Set> constrains =
getValidator(facesContext).validateValue((Class
© 2015 - 2025 Weber Informatics LLC | Privacy Policy