Skip to content

Commit

Permalink
HV-347: use the bean, which hosts the validated method as rootBean in…
Browse files Browse the repository at this point in the history
… resulting ConstraintViolation instead of the parameter bean
  • Loading branch information
gunnarmorling committed Jan 9, 2011
1 parent c198f57 commit be5e0f0
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 31 deletions.
Expand Up @@ -20,17 +20,14 @@
import java.lang.reflect.Method;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;

/**
* Provides an API for method-level validation, based on JSR 303 Appendix C ("Proposal for method-level validation")
*
* @author Gunnar Morling
*/
public interface MethodValidator {

Set<MethodConstraintViolation<?>> validateParameter(Method method, Object parameterValue, int parameterIndex, Class<?>... groups);
public <T> Set<MethodConstraintViolation<T>> validateParameter(T object, Method method, Object parameterValue, int parameterIndex, Class<?>... groups);

//getConstraintsForMethod()
}
Expand Up @@ -117,13 +117,7 @@ public static <T> ValidationContext<T> getContextForValidateValue(Class<T> rootB
);
}

public static <T> MethodValidationContext<T> getContextForValidateParameter(Method method, int parameterIndex, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory) {
return new MethodValidationContext<T>(
method, parameterIndex, null, null, messageInterpolator, constraintValidatorFactory, null
);
}

public static <T> MethodValidationContext<T> getContextForValidateCascadingParameter(Method method, int parameterIndex, T object, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) {
public static <T> MethodValidationContext<T> getContextForValidateParameter(Method method, int parameterIndex, T object, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) {
@SuppressWarnings("unchecked")
Class<T> rootBeanClass = (Class<T>) object.getClass();
return new MethodValidationContext<T>(
Expand Down
Expand Up @@ -157,15 +157,15 @@ public final <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, St
return new HashSet<ConstraintViolation<T>>( failingConstraintViolations );
}

public final Set<MethodConstraintViolation<?>> validateParameter(Method method, Object parameterValue, int parameterIndex, Class<?>... groups) {
public final <T> Set<MethodConstraintViolation<T>> validateParameter(T object, Method method, Object parameterValue, int parameterIndex, Class<?>... groups) {

if ( method == null ) {
throw new IllegalArgumentException( "The method cannot be null." );
}

GroupChain groupChain = determineGroupExecutionOrder( groups );

return validateParameter( method, parameterIndex, parameterValue, groupChain );
return validateParameter( object, method, parameterIndex, parameterValue, groupChain );
}

public final BeanDescriptor getConstraintsForClass(Class<?> clazz) {
Expand Down Expand Up @@ -680,18 +680,18 @@ private <U, V> void validateValueForGroup(
}
}

private <V> Set<MethodConstraintViolation<?>> validateParameter(Method method, int parameterIndex, V value, GroupChain groupChain) {
private <V, T> Set<MethodConstraintViolation<T>> validateParameter(T bean, Method method, int parameterIndex, V value, GroupChain groupChain) {

Set<MethodConstraintViolation<?>> constraintViolations = new HashSet<MethodConstraintViolation<?>>();
Set<MethodConstraintViolation<T>> constraintViolations = new HashSet<MethodConstraintViolation<T>>();

BeanMetaData<?> beanMetaData = getBeanMetaData( method.getDeclaringClass() );

if ( beanMetaData.defaultGroupSequenceIsRedefined() ) {
groupChain.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence() );
}

MethodValidationContext<?> context = ValidationContext.getContextForValidateParameter(
method, parameterIndex, messageInterpolator, constraintValidatorFactory
MethodValidationContext<T> context = ValidationContext.getContextForValidateParameter(
method, parameterIndex, bean, messageInterpolator, constraintValidatorFactory, getCachingTraversableResolver()
);

ValueContext<?, V> valueContext = ValueContext.getLocalExecutionContext( null, PathImpl.createRootPath() );
Expand All @@ -714,10 +714,10 @@ private <V> Set<MethodConstraintViolation<?>> validateParameter(Method method, i
if ( isCascadeRequired( method, parameterIndex ) && value != null ) {

//TODO GM: is it possible to use the existing context here?
context = ValidationContext.getContextForValidateCascadingParameter(
context = ValidationContext.getContextForValidateParameter(
method,
parameterIndex,
value,
bean,
messageInterpolator,
constraintValidatorFactory,
getCachingTraversableResolver()
Expand Down
Expand Up @@ -18,9 +18,12 @@
package org.hibernate.validator.test.engine.methodlevel;

import java.lang.reflect.Proxy;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.constraints.Min;

import org.hibernate.validator.MethodValidator;
import org.hibernate.validator.MethodConstraintViolation;
Expand Down Expand Up @@ -69,7 +72,8 @@ public void methodValidationYieldsConstraintViolation() {
assertEquals(constraintViolation.getMessage(), "may not be null");
assertEquals(constraintViolation.getMethod().getName(), "findCustomerByName");
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getRootBeanClass(), null);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
assertEquals(constraintViolation.getRootBean(), customerRepository);
}
}

Expand All @@ -89,7 +93,7 @@ public void validationOfMethodWithMultipleParameters() {
assertEquals(constraintViolation.getMessage(), "may not be null");
assertEquals(constraintViolation.getMethod().getName(), "findCustomerByAgeAndName");
assertEquals(constraintViolation.getParameterIndex(), 1);
assertEquals(constraintViolation.getRootBeanClass(), null);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
}
}

Expand All @@ -111,8 +115,8 @@ public void methodValidationWithCascadingParameter() {
assertEquals(constraintViolation.getMethod().getName(), "persistCustomer");
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getPropertyPath().toString(), "name");
assertEquals(constraintViolation.getRootBeanClass(), Customer.class);
assertEquals(constraintViolation.getRootBean(), customer);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
assertEquals(constraintViolation.getRootBean(), customerRepository);
assertEquals(constraintViolation.getLeafBean(), customer);
assertEquals(constraintViolation.getInvalidValue(), null);
}
Expand All @@ -137,8 +141,8 @@ public void methodValidationWithCascadingParameterAndCascadingConstraint() {
assertEquals(constraintViolation.getMethod().getName(), "persistCustomer");
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getPropertyPath().toString(), "address.city");
assertEquals(constraintViolation.getRootBeanClass(), Customer.class);
assertEquals(constraintViolation.getRootBean(), customer);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
assertEquals(constraintViolation.getRootBean(), customerRepository);
assertEquals(constraintViolation.getLeafBean(), address);
assertEquals(constraintViolation.getInvalidValue(), null);
}
Expand All @@ -161,7 +165,7 @@ public void constraintsAtMethodFromBaseClassAreEvaluated() {
assertEquals(constraintViolation.getMethod().getName(), "findById");
assertEquals(constraintViolation.getMethod().getDeclaringClass(), RepositoryBase.class);
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getRootBeanClass(), null);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
}
}

Expand All @@ -182,7 +186,7 @@ public void constraintsAtOverriddenMethodAreEvaluated() {
assertEquals(constraintViolation.getMethod().getName(), "foo");
assertEquals(constraintViolation.getMethod().getDeclaringClass(), CustomerRepository.class);
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getRootBeanClass(), null);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
}
}

Expand All @@ -203,7 +207,7 @@ public void validFromOverriddenMethodIsEvaluated() {
assertEquals(constraintViolation.getMethod().getName(), "bar");
assertEquals(constraintViolation.getMethod().getDeclaringClass(), CustomerRepository.class);
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getRootBeanClass(), Customer.class);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
assertEquals(constraintViolation.getPropertyPath().toString(), "name");
}
}
Expand All @@ -225,7 +229,7 @@ public void constraintsAtOverridingMethodAreEvaluated() {
assertEquals(constraintViolation.getMethod().getName(), "foo");
assertEquals(constraintViolation.getMethod().getDeclaringClass(), CustomerRepository.class);
assertEquals(constraintViolation.getParameterIndex(), 0);
assertEquals(constraintViolation.getRootBeanClass(), null);
assertEquals(constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class);
}
}

Expand Down
Expand Up @@ -49,8 +49,9 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl

for (int i = 0; i < args.length; i++) {

Set<MethodConstraintViolation<?>> constraintViolations = validator.validateParameter(method, args[i], i);

Set<MethodConstraintViolation<Object>> constraintViolations =
validator.validateParameter(wrapped, method, args[i], i);

if(!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(new HashSet<ConstraintViolation<?>>(constraintViolations));
}
Expand Down

0 comments on commit be5e0f0

Please sign in to comment.