All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.com.anteros.bean.validation.extensions.MethodValidatorImpl Maven / Gradle / Ivy

There is a newer version: 1.0.18
Show newest version
/*******************************************************************************
 * Copyright 2012 Anteros Tecnologia
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package br.com.anteros.bean.validation.extensions;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import br.com.anteros.bean.validation.AnterosFactoryContext;
import br.com.anteros.bean.validation.BeanDescriptorImpl;
import br.com.anteros.bean.validation.AnterosBeanValidator;
import br.com.anteros.bean.validation.ConstraintValidation;
import br.com.anteros.bean.validation.ConstraintValidationListener;
import br.com.anteros.bean.validation.GroupValidationContext;
import br.com.anteros.bean.validation.groups.Group;
import br.com.anteros.bean.validation.groups.Groups;
import br.com.anteros.bean.validation.model.MetaBean;
import br.com.anteros.bean.validation.util.ValidationHelper;
import br.com.anteros.validation.api.ConstraintViolation;
import br.com.anteros.validation.api.ValidationException;
import br.com.anteros.validation.api.metadata.ConstraintDescriptor;

/**
 * Description: experimental implementation of method-level-validation 
*/ class MethodValidatorImpl extends AnterosBeanValidator implements MethodValidator { /** * Create a new MethodValidatorImpl instance. * * @param factoryContext */ public MethodValidatorImpl(AnterosFactoryContext factoryContext) { super(factoryContext); } /** * {@inheritDoc} */ @Override protected BeanDescriptorImpl createBeanDescriptor(MetaBean metaBean) { MethodBeanDescriptorImpl descriptor = new MethodBeanDescriptorImpl(factoryContext, metaBean); MethodValidatorMetaBeanFactory factory = new MethodValidatorMetaBeanFactory(factoryContext); factory.buildMethodDescriptor(descriptor); return descriptor; } /** * {@inheritDoc} enhancement: method-level-validation not yet completly * implemented * *
     * example:
     * 
     * public @NotNull String saveItem(@Valid @NotNull Item item, @Max(23) BigDecimal
     * 
     * 
* * spec: The constraints declarations evaluated are the constraints hosted * on the parameters of the method or constructor. If @Valid is placed on a * parameter, constraints declared on the object itself are considered. * * @throws IllegalArgumentException * enhancement: if the method does not belong to T * or if the Object[] does not match the method signature */ public Set> validateParameters(Class clazz, Method method, Object[] parameters, Class... groupArray) { MethodBeanDescriptorImpl beanDesc = (MethodBeanDescriptorImpl) getConstraintsForClass(clazz); MethodDescriptorImpl methodDescriptor = (MethodDescriptorImpl) beanDesc.getConstraintsForMethod(method); if (methodDescriptor == null) { throw new ValidationException("Method " + method + " doesn't belong to class " + clazz); } return validateParameters(methodDescriptor.getMetaBean(), methodDescriptor.getParameterDescriptors(), parameters, groupArray); } /** * {@inheritDoc} */ public Set> validateParameter(Class clazz, Method method, Object parameter, int parameterIndex, Class... groupArray) { MethodBeanDescriptorImpl beanDesc = (MethodBeanDescriptorImpl) getConstraintsForClass(clazz); MethodDescriptorImpl methodDescriptor = (MethodDescriptorImpl) beanDesc.getConstraintsForMethod(method); if (methodDescriptor == null) { throw new ValidationException("Method " + method + " doesn't belong to class " + clazz); } ParameterDescriptorImpl paramDesc = (ParameterDescriptorImpl) methodDescriptor.getParameterDescriptors().get(parameterIndex); return validateParameter(paramDesc, parameter, groupArray); } /** * {@inheritDoc} */ public Set> validateParameters(Class clazz, Constructor constructor, Object[] parameters, Class... groupArray) { MethodBeanDescriptorImpl beanDesc = (MethodBeanDescriptorImpl) getConstraintsForClass(clazz); ConstructorDescriptorImpl constructorDescriptor = (ConstructorDescriptorImpl) beanDesc.getConstraintsForConstructor(constructor); if (constructorDescriptor == null) { throw new ValidationException("Constructor " + constructor + " doesn't belong to class " + clazz); } return validateParameters(constructorDescriptor.getMetaBean(), constructorDescriptor.getParameterDescriptors(), parameters, groupArray); } /** * {@inheritDoc} */ public Set> validateParameter(Class clazz, Constructor constructor, Object parameter, int parameterIndex, Class... groupArray) { MethodBeanDescriptorImpl beanDesc = (MethodBeanDescriptorImpl) getConstraintsForClass(clazz); ConstructorDescriptorImpl constructorDescriptor = (ConstructorDescriptorImpl) beanDesc.getConstraintsForConstructor(constructor); if (constructorDescriptor == null) { throw new ValidationException("Constructor " + constructor + " doesn't belong to class " + clazz); } ParameterDescriptorImpl paramDesc = (ParameterDescriptorImpl) constructorDescriptor.getParameterDescriptors().get(parameterIndex); return validateParameter(paramDesc, parameter, groupArray); } /** * {@inheritDoc} If @Valid is placed on the method, the constraints declared * on the object itself are considered. */ @SuppressWarnings("unchecked") public Set> validateReturnedValue(Class clazz, Method method, Object returnedValue, Class... groupArray) { MethodBeanDescriptorImpl beanDesc = (MethodBeanDescriptorImpl) getConstraintsForClass(clazz); MethodDescriptorImpl methodDescriptor = (MethodDescriptorImpl) beanDesc.getConstraintsForMethod(method); if (methodDescriptor == null) { throw new ValidationException("Method " + method + " doesn't belong to class " + clazz); } final GroupValidationContext context = createContext(methodDescriptor.getMetaBean(), returnedValue, null, groupArray); validateReturnedValueInContext(context, methodDescriptor); ConstraintValidationListener result = (ConstraintValidationListener) context.getListener(); return result.getConstraintViolations(); } @SuppressWarnings("unchecked") private Set> validateParameters(MetaBean metaBean, List paramDescriptors, Object[] parameters, Class... groupArray) { if (parameters == null) throw new IllegalArgumentException("cannot validate null"); if (parameters.length > 0) { try { GroupValidationContext> context = createContext(metaBean, null, null, groupArray); for (int i = 0; i < parameters.length; i++) { ParameterDescriptorImpl paramDesc = (ParameterDescriptorImpl) paramDescriptors.get(i); context.setBean(parameters[i]); validateParameterInContext(context, paramDesc); } ConstraintValidationListener result = (ConstraintValidationListener) context.getListener(); return result.getConstraintViolations(); } catch (RuntimeException ex) { throw unrecoverableValidationError(ex, parameters); } } else { return Collections.> emptySet(); } } @SuppressWarnings("unchecked") private Set> validateParameter(ParameterDescriptorImpl paramDesc, Object parameter, Class... groupArray) { try { final GroupValidationContext context = createContext(paramDesc.getMetaBean(), parameter, null, groupArray); final ConstraintValidationListener result = (ConstraintValidationListener) context.getListener(); validateParameterInContext(context, paramDesc); return result.getConstraintViolations(); } catch (RuntimeException ex) { throw unrecoverableValidationError(ex, parameter); } } /** * validate constraints hosted on parameters of a method */ private void validateParameterInContext(GroupValidationContext context, ParameterDescriptorImpl paramDesc) { final Groups groups = context.getGroups(); for (ConstraintDescriptor consDesc : paramDesc.getConstraintDescriptors()) { ConstraintValidation validation = (ConstraintValidation) consDesc; // 1. process groups for (Group current : groups.getGroups()) { context.setCurrentGroup(current); validation.validate(context); } // 2. process sequences for (List eachSeq : groups.getSequences()) { for (Group current : eachSeq) { context.setCurrentGroup(current); validation.validate(context); /** * if one of the group process in the sequence leads to one * or more validation failure, the groups following in the * sequence must not be processed */ if (!context.getListener().isEmpty()) break; } } } if (paramDesc.isCascaded() && context.getValidatedValue() != null) { context .setMetaBean(factoryContext.getMetaBeanFinder().findForClass(context.getValidatedValue().getClass())); // 1. process groups for (Group current : groups.getGroups()) { context.setCurrentGroup(current); ValidationHelper .validateContext(context, new Jsr303ValidationCallback(context), isTreatMapsLikeBeans()); } // 2. process sequences for (List eachSeq : groups.getSequences()) { for (Group current : eachSeq) { context.setCurrentGroup(current); ValidationHelper.validateContext(context, new Jsr303ValidationCallback(context), isTreatMapsLikeBeans()); /** * if one of the group process in the sequence leads to one * or more validation failure, the groups following in the * sequence must not be processed */ if (!context.getListener().isEmpty()) break; } } } } /** * validate constraints hosted on parameters of a method */ private void validateReturnedValueInContext(GroupValidationContext context, MethodDescriptorImpl methodDescriptor) { final Groups groups = context.getGroups(); for (ConstraintDescriptor consDesc : methodDescriptor.getConstraintDescriptors()) { ConstraintValidation validation = (ConstraintValidation) consDesc; // 1. process groups for (Group current : groups.getGroups()) { context.setCurrentGroup(current); validation.validate(context); } // 2. process sequences for (List eachSeq : groups.getSequences()) { for (Group current : eachSeq) { context.setCurrentGroup(current); validation.validate(context); /** * if one of the group process in the sequence leads to one * or more validation failure, the groups following in the * sequence must not be processed */ if (!context.getListener().isEmpty()) break; } } } if (methodDescriptor.isCascaded() && context.getValidatedValue() != null) { context .setMetaBean(factoryContext.getMetaBeanFinder().findForClass(context.getValidatedValue().getClass())); // 1. process groups for (Group current : groups.getGroups()) { context.setCurrentGroup(current); ValidationHelper .validateContext(context, new Jsr303ValidationCallback(context), isTreatMapsLikeBeans()); } // 2. process sequences for (List eachSeq : groups.getSequences()) { for (Group current : eachSeq) { context.setCurrentGroup(current); ValidationHelper.validateContext(context, new Jsr303ValidationCallback(context), isTreatMapsLikeBeans()); /** * if one of the group process in the sequence leads to one * or more validation failure, the groups following in the * sequence must not be processed */ if (!context.getListener().isEmpty()) break; } } } } }