/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.testutils;
import static org.hibernate.validator.internal.util.Contracts.assertNotNull;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Locale;
import javax.validation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstructorDescriptor;
import javax.validation.metadata.MethodDescriptor;
import javax.validation.metadata.ParameterDescriptor;
import javax.validation.metadata.PropertyDescriptor;
import javax.validation.metadata.ReturnValueDescriptor;
import javax.validation.spi.ValidationProvider;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext;
import org.hibernate.validator.internal.engine.DefaultClockProvider;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.hibernate.validator.testutil.DummyTraversableResolver;
import org.hibernate.validator.testutil.ValidationInvocationHandler;
/**
* A helper providing useful functions for setting up validators.
*
* @author Hardy Ferentschik
* @author Gunnar Morling
* @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI
*/
public final class ValidatorUtil {
/**
* Private constructor in order to avoid instantiation.
*/
private ValidatorUtil() {
}
/**
* Returns a configured instance of {@code Validator}. This validator is configured to use a
* {@link DummyTraversableResolver}. This method also sets the default locale to english.
*
* @return an instance of {@code Validator}.
*/
public static Validator getValidator() {
final Configuration<HibernateValidatorConfiguration> configuration = getConfiguration();
configuration.traversableResolver( new DummyTraversableResolver() );
return configuration.buildValidatorFactory().getValidator();
}
/**
* Returns the {@code Configuration} object for Hibernate Validator. This method also sets the default locale to
* english.
*
* @return an instance of {@code Configuration} for Hibernate Validator.
*/
public static HibernateValidatorConfiguration getConfiguration() {
return getConfiguration( HibernateValidator.class, Locale.ENGLISH );
}
/**
* Returns the {@code Configuration} object for Hibernate Validator. This method also sets the default locale to
* the given locale.
*
* @param locale The default locale to set.
*
* @return an instance of {@code Configuration} for Hibernate Validator.
*/
public static HibernateValidatorConfiguration getConfiguration(Locale locale) {
return getConfiguration( HibernateValidator.class, locale );
}
/**
* Returns the {@code Configuration} object for the given validation provider type. This method also sets the
* default locale to english.
*
* @param type The validation provider type.
*
* @return an instance of {@code Configuration}.
*/
public static <T extends Configuration<T>, U extends ValidationProvider<T>> T getConfiguration(Class<U> type) {
return getConfiguration( type, Locale.ENGLISH );
}
/**
* Returns the {@code Configuration} object for the given validation provider type. This method also sets the
* default locale to the given locale.
*
* @param type The validation provider type.
* @param locale The default locale to set.
*
* @return an instance of {@code Configuration}.
*/
public static <T extends Configuration<T>, U extends ValidationProvider<T>> T getConfiguration(Class<U> type, Locale locale) {
Locale.setDefault( locale );
return Validation.byProvider( type ).configure();
}
/**
* Returns the {@code PropertyDescriptor} corresponding to the property contained in the given class.
*
* @param clazz The class containing the given property.
* @param property The property name.
*
* @return an instance of {@code PropertyDescriptor} or {@code null} if does not exists or has no constraint.
*
* @see javax.validation.metadata.BeanDescriptor#getConstraintsForProperty(String)
*/
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String property) {
return getValidator().getConstraintsForClass( clazz ).getConstraintsForProperty( property );
}
/**
* Returns the {@code BeanDescriptor} corresponding to the given type.
*
* @param clazz The type.
*
* @return an instance of {@code BeanDescriptor} for the given type, never {@code null}
*/
public static BeanDescriptor getBeanDescriptor(Class<?> clazz) {
return getValidator().getConstraintsForClass( clazz );
}
/**
* Returns the {@code MethodDescriptor} for the given method signature in the given class.
*
* @param clazz The class.
* @param methodName The method name.
* @param parameterTypes The method parameter types.
*
* @return an instance of {@code MethodDescriptor} for the given method signature or {@code null} if no such method exists.
*/
public static MethodDescriptor getMethodDescriptor(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
return getBeanDescriptor( clazz ).getConstraintsForMethod( methodName, parameterTypes );
}
/**
* Returns the {@code ConstructorDescriptor} for the given constructor signature in the given class.
*
* @param clazz The class.
* @param parameterTypes The constructor parameter types.
*
* @return an instance of {@code ConstructorDescriptor} for the given constructor signature or {@code null} if no such constructor exists.
*/
public static ConstructorDescriptor getConstructorDescriptor(Class<?> clazz, Class<?>... parameterTypes) {
return getBeanDescriptor( clazz ).getConstraintsForConstructor( parameterTypes );
}
/**
* Returns the {@code ParameterDescriptor} for the parameter at the given index within the method, corresponding to
* the given signature, within the given class.
*
* @param clazz The class.
* @param methodName The method name.
* @param parameterTypes The method parameter types.
* @param parameterIndex The parameter index.
*
* @return an instance of {@code ParameterDescriptor}.
*/
public static ParameterDescriptor getParameterDescriptor(Class<?> clazz, String methodName, Class<?>[] parameterTypes, int parameterIndex) {
final MethodDescriptor methodDescriptor = getMethodDescriptor(
clazz,
methodName,
parameterTypes
);
assertNotNull(
methodDescriptor,
"No method with the given signature is declared in " + clazz + " or its super class"
);
return methodDescriptor.getParameterDescriptors().get( parameterIndex );
}
/**
* Returns the {@code ReturnValueDescriptor} for the given method signature in the given class.
*
* @param clazz The class.
* @param methodName The method name.
* @param parameterTypes The method parameter types.
*
* @return an instance of {@code ReturnValueDescriptor} for the given method signature or {@code null} if no such method exists.
*/
public static ReturnValueDescriptor getMethodReturnValueDescriptor(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
MethodDescriptor methodDescriptor = getBeanDescriptor( clazz ).getConstraintsForMethod(
methodName,
parameterTypes
);
return methodDescriptor != null ? methodDescriptor.getReturnValueDescriptor() : null;
}
@SuppressWarnings("unchecked")
public static <T, I extends T> T getValidatingProxy(I implementor,
Class<?>[] interfaces,
Validator executableValidator,
Class<?>... validationGroups) {
InvocationHandler handler = new ValidationInvocationHandler(
implementor, executableValidator, validationGroups
);
return (T) Proxy.newProxyInstance(
implementor.getClass().getClassLoader(),
interfaces,
handler
);
}
/**
* Creates a proxy for the given object which performs a validation of the given object's method constraints upon method invocation.
*
* @param <T> The type to which the proxy shall be casted. Must be an interface.
* @param <I> The type of the object to be proxied.
* @param implementor The object to be proxied.
* @param executableValidator The validator to use for method validation.
* @param validationGroups Optionally the groups which shall be evaluated.
*
* @return A proxy performing an automatic method validation.
*/
public static <T, I extends T> T getValidatingProxy(I implementor, Validator executableValidator, Class<?>... validationGroups) {
return getValidatingProxy(
implementor,
implementor.getClass().getInterfaces(),
executableValidator,
validationGroups
);
}
public static HibernateConstraintValidatorContext getConstraintValidatorContext() {
return new ConstraintValidatorContextImpl( null, DefaultClockProvider.INSTANCE, null, null );
}
}