org.richfaces.validator.BeanValidatorServiceImpl Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
/**
*
*/
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.base.Strings;
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, String message,
Class>... groups) {
try {
ValueDescriptor propertyDescriptor = analayser.getPropertyDescriptor(context, expression);
if (propertyDescriptor == null) {
return Collections.emptySet();
}
return processBeanAttribute(context, propertyDescriptor, message, groups);
} catch (ELException e) {
return Collections.emptySet();
}
}
private Validator getValidator(FacesContext context) {
return validatorFactory.getValidator(context);
}
Collection processBeanAttribute(FacesContext context, ValueDescriptor descriptor, String msg,
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
FacesMessage message = Strings.isNullOrEmpty(msg) ? null : new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
return processConstraints(context, constraints, message);
} else {
return Collections.emptySet();
}
}
Collection processConstraints(FacesContext context, Set> constraints,
FacesMessage msg) {
Set descriptors = new HashSet(constraints.size());
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 = null == msg ? validatorFactory.interpolateMessage(context, cd) : msg;
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);
descriptors.addAll(processConstraints(context, cd.getComposingConstraints(), msg)); // process the composing
// constraints
}
return descriptors;
}
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