http://git-wip-us.apache.org/repos/asf/bval/blob/92c64b3c/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java deleted file mode 100644 index d7b4640..0000000 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ClassValidator.java +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.bval.jsr; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.validation.ConstraintDeclarationException; -import javax.validation.ConstraintDefinitionException; -import javax.validation.ConstraintTarget; -import javax.validation.ConstraintViolation; -import javax.validation.ElementKind; -import javax.validation.ValidationException; -import javax.validation.executable.ExecutableValidator; -import javax.validation.groups.Default; -import javax.validation.metadata.BeanDescriptor; -import javax.validation.metadata.ConstraintDescriptor; -import javax.validation.metadata.ElementDescriptor; -import javax.validation.metadata.ParameterDescriptor; -import javax.validation.metadata.PropertyDescriptor; - -import org.apache.bval.DynamicMetaBean; -import org.apache.bval.MetaBeanFinder; -import org.apache.bval.jsr.groups.Group; -import org.apache.bval.jsr.groups.Groups; -import org.apache.bval.jsr.groups.GroupsComputer; -import org.apache.bval.jsr.util.ClassHelper; -import org.apache.bval.jsr.util.NodeImpl; -import org.apache.bval.jsr.util.PathImpl; -import org.apache.bval.jsr.util.PathNavigation; -import org.apache.bval.jsr.util.Proxies; -import org.apache.bval.jsr.util.ValidationContextTraversal; -import org.apache.bval.model.Features; -import org.apache.bval.model.FeaturesCapable; -import org.apache.bval.model.MetaBean; -import org.apache.bval.model.MetaProperty; -import org.apache.bval.model.Validation; -import org.apache.bval.util.AccessStrategy; -import org.apache.bval.util.ValidationHelper; -import org.apache.bval.util.ObjectUtils; -import org.apache.bval.util.reflection.Reflection; -import org.apache.bval.util.reflection.TypeUtils; -import org.apache.commons.weaver.privilizer.Privilizing; -import org.apache.commons.weaver.privilizer.Privilizing.CallTo; - -/** - * Objects of this class are able to validate bean instances (and the associated object graphs). - * <p/> - * Implementation is thread-safe. - * <p/> - * API class - * - * @version $Rev: 1514672 $ $Date: 2013-08-16 14:15:12 +0200 (ven., 16 août 2013) $ - * - * @author Roman Stumm - * @author Carlos Vara - */ -@Privilizing(@CallTo(Reflection.class)) -public class ClassValidator implements CascadingPropertyValidator, ExecutableValidator { - private static final Object VALIDATE_PROPERTY = new Object() { - @Override - public String toString() { - return "VALIDATE_PROPERTY"; - } - }; - - /** - * {@link ApacheFactoryContext} used - */ - protected final ApacheFactoryContext factoryContext; - - /** - * {@link GroupsComputer} used - */ - protected final GroupsComputer groupsComputer = new GroupsComputer(); - - private final MetaBeanFinder metaBeanFinder; - - /** - * Create a new ClassValidator instance. - * - * @param factoryContext - */ - public ClassValidator(ApacheFactoryContext factoryContext) { - this.factoryContext = factoryContext; - metaBeanFinder = factoryContext.getMetaBeanFinder(); - } - - // Validator implementation - // -------------------------------------------------- - - /** - * {@inheritDoc} Validates all constraints on <code>object</code>. - * - * @param object object to validate - * @param groups group or list of groups targeted for validation (default to - * {@link javax.validation.groups.Default}) - * @return constraint violations or an empty Set if none - * @throws IllegalArgumentException if object is null or if null is passed to the varargs groups - * @throws ValidationException if a non recoverable error happens during the validation - * process - */ - @Override - @SuppressWarnings("unchecked") - public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) { - notNull("validated object", object); - checkGroups(groups); - - try { - final Class<T> objectClass = (Class<T>) object.getClass(); - final MetaBean objectMetaBean = metaBeanFinder.findForClass(objectClass); - final GroupValidationContext<T> context = createContext(objectMetaBean, object, objectClass, groups); - return validateBeanWithGroups(context, context.getGroups()); - } catch (final RuntimeException ex) { - throw unrecoverableValidationError(ex, object); - } - } - - private <T> Set<ConstraintViolation<T>> validateBeanWithGroups(final GroupValidationContext<T> context, - final Groups sequence) { - final ConstraintValidationListener<T> result = context.getListener(); - - // 1. process groups - for (final Group current : sequence.getGroups()) { - context.setCurrentGroup(current); - validateBeanNet(context); - } - - // 2. process sequences - for (final List<Group> eachSeq : sequence.getSequences()) { - for (final Group current : eachSeq) { - context.setCurrentGroup(current); - validateBeanNet(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 (!result.isEmpty()) { - break; - } - } - if (!result.isEmpty()) { - break; - } - } - return result.getConstraintViolations(); - } - - /** - * {@inheritDoc} Validates all constraints placed on the property of <code>object</code> named - * <code>propertyName</code>. - * - * @param object object to validate - * @param propertyName property to validate (ie field and getter constraints). Nested - * properties may be referenced (e.g. prop[2].subpropA.subpropB) - * @param groups group or list of groups targeted for validation (default to - * {@link javax.validation.groups.Default}) - * @return constraint violations or an empty Set if none - * @throws IllegalArgumentException if <code>object</code> is null, if <code>propertyName</code> - * null, empty or not a valid object property or if null is - * passed to the varargs groups - * @throws ValidationException if a non recoverable error happens during the validation - * process - */ - @Override - public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) { - return validateProperty(object, propertyName, false, groups); - } - - /** - * {@inheritDoc} - */ - @Override - public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, boolean cascade, - Class<?>... groups) { - notNull("validated object", object); - - @SuppressWarnings("unchecked") - final Set<ConstraintViolation<T>> result = - validateValueImpl((Class<T>) object.getClass(), object, propertyName, VALIDATE_PROPERTY, cascade, groups); - return result; - } - - /** - * {@inheritDoc} Validates all constraints placed on the property named <code>propertyName</code> of the class - * <code>beanType</code> would the property value be <code>value</code> - * <p/> - * <code>ConstraintViolation</code> objects return null for {@link ConstraintViolation#getRootBean()} and - * {@link ConstraintViolation#getLeafBean()} - * - * @param beanType the bean type - * @param propertyName property to validate - * @param value property value to validate - * @param groups group or list of groups targeted for validation (default to - * {@link javax.validation.groups.Default}) - * @return constraint violations or an empty Set if none - * @throws IllegalArgumentException if <code>beanType</code> is null, if - * <code>propertyName</code> null, empty or not a valid object - * property or if null is passed to the varargs groups - * @throws ValidationException if a non recoverable error happens during the validation - * process - */ - @Override - public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, - Class<?>... groups) { - return validateValue(beanType, propertyName, value, false, groups); - } - - /** - * {@inheritDoc} - */ - @Override - public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, - boolean cascade, Class<?>... groups) { - return validateValueImpl(notNull("bean type", beanType), null, propertyName, value, cascade, groups); - } - - /** - * {@inheritDoc} Return the descriptor object describing bean constraints. The returned object (and associated - * objects including <code>ConstraintDescriptor<code>s) are immutable. - * - * @param clazz class or interface type evaluated - * @return the bean descriptor for the specified class. - * @throws IllegalArgumentException if clazz is null - * @throws ValidationException if a non recoverable error happens during the metadata - * discovery or if some constraints are invalid. - */ - @Override - public BeanDescriptor getConstraintsForClass(final Class<?> clazz) { - notNull("class", clazz); - try { - final MetaBean metaBean = metaBeanFinder.findForClass(clazz); // don't throw an exception because of a missing validator here - BeanDescriptorImpl edesc = metaBean.getFeature(JsrFeatures.Bean.BEAN_DESCRIPTOR); - if (edesc == null) { - edesc = metaBean.initFeature(JsrFeatures.Bean.BEAN_DESCRIPTOR, createBeanDescriptor(metaBean)); - } - return edesc; - } catch (final ConstraintDefinitionException definitionEx) { - throw definitionEx; - } catch (final ConstraintDeclarationException declarationEx) { - throw declarationEx; - } catch (final RuntimeException ex) { - throw new ValidationException("error retrieving constraints for " + clazz, ex); - } - } - - /** - * {@inheritDoc} Return an instance of the specified type allowing access to provider-specific APIs. If the Bean - * Validation provider implementation does not support the specified class, <code>ValidationException</code> is - * thrown. - * - * @param type the class of the object to be returned. - * @return an instance of the specified class - * @throws ValidationException if the provider does not support the call. - */ - @Override - public <T> T unwrap(Class<T> type) { - // FIXME 2011-03-27 jw: - // This code is unsecure. - // It should allow only a fixed set of classes. - // Can't fix this because don't know which classes this method should support. - - if (type.isAssignableFrom(getClass())) { - @SuppressWarnings("unchecked") - final T result = (T) this; - return result; - } - if (!(type.isInterface() || Modifier.isAbstract(type.getModifiers()))) { - return newInstance(type); - } - try { - final Class<?> cls = Reflection.toClass(type.getName() + "Impl"); - if (type.isAssignableFrom(cls)) { - @SuppressWarnings("unchecked") - final Class<? extends T> implClass = (Class<? extends T>) cls; - return newInstance(implClass); - } - } catch (ClassNotFoundException e) { - } - throw new ValidationException("Type " + type + " not supported"); - } - - @Override - public ExecutableValidator forExecutables() { - return this; - } - - private <T> T newInstance(final Class<T> cls) { - final Constructor<T> cons = Reflection.getDeclaredConstructor(cls, ApacheFactoryContext.class); - if (cons == null) { - throw new ValidationException("Cannot instantiate " + cls); - } - final boolean mustUnset = Reflection.setAccessible(cons, true); - try { - return cons.newInstance(factoryContext); - } catch (final Exception ex) { - throw new ValidationException("Cannot instantiate " + cls, ex); - } finally { - if (mustUnset) { - Reflection.setAccessible(cons, false); - } - } - } - - // Helpers - // ------------------------------------------------------------------- - - /** - * Validates a bean and all its cascaded related beans for the currently defined group. - * <p/> - * Special code is present to manage the {@link Default} group. - * - * @param context The current context of this validation call. Must have its - * {@link GroupValidationContext#getCurrentGroup()} field set. - */ - protected void validateBeanNet(GroupValidationContext<?> context) { - - // If reached a cascaded bean which is null - if (context.getBean() == null) { - return; - } - - // If reached a cascaded bean which has already been validated for the - // current group - if (!context.collectValidated()) { - return; - } - - // ### First, validate the bean - - // Default is a special case - if (context.getCurrentGroup().isDefault()) { - - List<Group> defaultGroups = expandDefaultGroup(context); - final ConstraintValidationListener<?> result = context.getListener(); - - // If the rootBean defines a GroupSequence - if (defaultGroups != null && defaultGroups.size() > 1) { - - int numViolations = result.violationsSize(); - - // Validate the bean for each group in the sequence - final Group currentGroup = context.getCurrentGroup(); - for (final Group each : defaultGroups) { - context.setCurrentGroup(each); - - // ValidationHelper.validateBean(context);, doesn't match anymore because of @ConvertGroup - validateBean(context); - - // Spec 3.4.3 - Stop validation if errors already found - if (result.violationsSize() > numViolations) { - break; - } - } - context.setCurrentGroup(currentGroup); - } else { - - // For each class in the hierarchy of classes of rootBean, - // validate the constraints defined in that class according - // to the GroupSequence defined in the same class - - // Obtain the full class hierarchy - final List<Class<?>> classHierarchy = new ArrayList<Class<?>>(); - ClassHelper.fillFullClassHierarchyAsList(classHierarchy, context.getMetaBean().getBeanClass()); - final Class<?> initialOwner = context.getCurrentOwner(); - - // For each owner in the hierarchy - for (final Class<?> owner : classHierarchy) { - - context.setCurrentOwner(owner); - - int numViolations = result.violationsSize(); - - // Obtain the group sequence of the owner, and use it for - // the constraints that belong to it - final List<Group> ownerDefaultGroups = - context.getMetaBean().getFeature("{GroupSequence:" + owner.getCanonicalName() + "}"); - for (Group each : ownerDefaultGroups) { - context.setCurrentGroup(each); - validateBean(context); - // Spec 3.4.3 - Stop validation if errors already found - if (result.violationsSize() > numViolations) { - break; - } - } - } - context.setCurrentOwner(initialOwner); - context.setCurrentGroup(Group.DEFAULT); - } - } - // if not the default group, proceed as normal - else { - validateBean(context); - } - - // ### Then, the cascaded beans (@Valid) - for (final MetaProperty prop : context.getMetaBean().getProperties()) { - final Group group = context.getCurrentGroup(); - final Group mappedGroup; - - final Object feature = prop.getFeature(JsrFeatures.Property.PropertyDescriptor); - if (feature == null) { - mappedGroup = group; - } else { - mappedGroup = PropertyDescriptorImpl.class.cast(feature).mapGroup(group); - } - - if (group == mappedGroup) { - validateCascadedBean(context, prop, null); - } else { - final Groups propertyGroup = groupsComputer.computeGroups(new Class<?>[] { mappedGroup.getGroup() }); - validateCascadedBean(context, prop, propertyGroup); - } - context.setCurrentGroup(group); - } - } - - // TODO: maybe add a GroupMapper to bval-core to ease this kind of thing and void to fork this method from ValidationHelper - private void validateBean(final GroupValidationContext<?> context) { - // execute all property level validations - for (final PropertyDescriptor prop : getConstraintsForClass(context.getMetaBean().getBeanClass()) - .getConstrainedProperties()) { - final PropertyDescriptorImpl impl = PropertyDescriptorImpl.class.cast(prop); - if (!impl.isValidated(impl)) { - checkValidationAppliesTo(impl.getConstraintDescriptors(), ConstraintTarget.PARAMETERS); - checkValidationAppliesTo(impl.getConstraintDescriptors(), ConstraintTarget.RETURN_VALUE); - impl.setValidated(impl); // we don't really care about concurrency here - } - - final MetaProperty metaProperty = context.getMetaBean().getProperty(prop.getPropertyName()); - context.setMetaProperty(metaProperty); - final Group current = context.getCurrentGroup(); - context.setCurrentGroup(impl.mapGroup(current)); - ValidationHelper.validateProperty(context); - context.setCurrentGroup(current); - } - - // execute all bean level validations - context.setMetaProperty(null); - for (final Validation validation : context.getMetaBean().getValidations()) { - if (ConstraintValidation.class.isInstance(validation)) { - final ConstraintValidation<?> constraintValidation = ConstraintValidation.class.cast(validation); - if (!constraintValidation.isValidated()) { - checkValidationAppliesTo(constraintValidation.getValidationAppliesTo(), - ConstraintTarget.PARAMETERS); - checkValidationAppliesTo(constraintValidation.getValidationAppliesTo(), - ConstraintTarget.RETURN_VALUE); - constraintValidation.setValidated(true); - } - } - validation.validate(context); - } - } - - /** - * Checks if the the meta property <code>prop</code> defines a cascaded bean, and in case it does, validates it. - * - * @param context The current validation context. - * @param prop The property to cascade from (in case it is possible). - */ - private void validateCascadedBean(final GroupValidationContext<?> context, final MetaProperty prop, - final Groups groups) { - final AccessStrategy[] access = prop.getFeature(Features.Property.REF_CASCADE); - if (access != null) { // different accesses to relation - // save old values from context - final Object bean = context.getBean(); - final MetaBean mbean = context.getMetaBean(); - // TODO implement Validation.groups support on related bean - // Class[] groups = prop.getFeature(JsrFeatures.Property.REF_GROUPS); - for (final AccessStrategy each : access) { - if (isCascadable(context, prop, each)) { - // modify context state for relationship-target bean - context.moveDown(prop, each); - // validate - if (groups == null) { - ValidationHelper.validateContext(context, new JsrValidationCallback(context), - factoryContext.isTreatMapsLikeBeans()); - } else { - ValidationHelper.validateContext(context, new ValidationHelper.ValidateCallback() { - @Override - public void validate() { - validateBeanWithGroups(context, groups); - } - }, factoryContext.isTreatMapsLikeBeans()); - } - // restore old values in context - context.moveUp(bean, mbean); - } - } - } - } - - /** - * Before accessing a related bean (marked with {@link javax.validation.Valid}), the validator has to check if it is - * reachable and cascadable. - * - * @param context The current validation context. - * @param prop The property of the related bean. - * @param access The access strategy used to get the related bean value. - * @return <code>true</code> if the validator can access the related bean, <code>false</code> otherwise. - */ - private boolean isCascadable(GroupValidationContext<?> context, MetaProperty prop, AccessStrategy access) { - - PathImpl beanPath = context.getPropertyPath(); - final NodeImpl node = new NodeImpl.PropertyNodeImpl(prop.getName()); - if (beanPath == null) { - beanPath = PathImpl.create(); - } - try { - if (!context.getTraversableResolver().isReachable(context.getBean(), node, - context.getRootMetaBean().getBeanClass(), beanPath, access.getElementType())) { - return false; - } - } catch (RuntimeException e) { - throw new ValidationException("Error in TraversableResolver.isReachable() for " + context.getBean(), e); - } - - try { - if (!context.getTraversableResolver().isCascadable(context.getBean(), node, - context.getRootMetaBean().getBeanClass(), beanPath, access.getElementType())) { - return false; - } - } catch (RuntimeException e) { - throw new ValidationException("Error TraversableResolver.isCascadable() for " + context.getBean(), e); - } - return true; - } - - /** - * in case of a default group return the list of groups for a redefined default GroupSequence - * - * @return null when no in default group or default group sequence not redefined - */ - private List<Group> expandDefaultGroup(GroupValidationContext<?> context) { - if (context.getCurrentGroup().isDefault()) { - // mention if metaBean redefines the default group - final List<Group> groupSeq = context.getMetaBean().getFeature(JsrFeatures.Bean.GROUP_SEQUENCE); - if (groupSeq != null) { - context.getGroups().assertDefaultGroupSequenceIsExpandable(groupSeq); - } - return groupSeq; - } - return null; - } - - /** - * Generate an unrecoverable validation error - * - * @param ex - * @param object - * @return a {@link RuntimeException} of the appropriate type - */ - protected static RuntimeException unrecoverableValidationError(RuntimeException ex, Object object) { - if (ex instanceof UnknownPropertyException || ex instanceof IncompatiblePropertyValueException) { - // Convert to IllegalArgumentException - return new IllegalArgumentException(ex.getMessage(), ex); - } - if (ex instanceof ValidationException) { - return ex; // do not wrap specific ValidationExceptions (or instances from subclasses) - } - String objectId; - if (object == null) { - objectId = "<null>"; - } else { - try { - objectId = object.toString(); - } catch (Exception e) { - objectId = "<unknown>"; - } - } - return new ValidationException("error during validation of " + objectId, ex); - } - - private void validatePropertyInGroup(final GroupValidationContext<?> context) { - final Runnable helper; - if (context.getMetaProperty() == null) { - helper = new Runnable() { - - @Override - public void run() { - ValidationHelper.validateBean(context); - } - }; - } else { - helper = new Runnable() { - - @Override - public void run() { - ValidationHelper.validateProperty(context); - } - }; - } - final List<Group> defaultGroups = expandDefaultGroup(context); - if (defaultGroups == null) { - helper.run(); - } else { - final Group currentGroup = context.getCurrentGroup(); - for (Group each : defaultGroups) { - context.setCurrentGroup(each); - helper.run(); - // continue validation, even if errors already found - } - context.setCurrentGroup(currentGroup); // restore - } - } - - /** - * Create a {@link GroupValidationContext}. - * - * @param <T> - * @param metaBean - * @param object - * @param objectClass - * @param groups - * @return {@link GroupValidationContext} instance - */ - protected <T> GroupValidationContext<T> createContext(MetaBean metaBean, T object, Class<T> objectClass, - Class<?>... groups) { - final ConstraintValidationListener<T> listener = new ConstraintValidationListener<T>(object, objectClass); - final GroupValidationContextImpl<T> context = new GroupValidationContextImpl<T>(listener, - factoryContext.getMessageInterpolator(), factoryContext.getTraversableResolver(), - factoryContext.getParameterNameProvider(), factoryContext.getConstraintValidatorFactory(), metaBean); - context.setBean(object, metaBean); - context.setGroups(groupsComputer.computeGroups(groups)); - return context; - } - - protected <T> GroupValidationContext<T> createInvocableContext(MetaBean metaBean, T object, Class<T> objectClass, - Class<?>... groups) { - final ConstraintValidationListener<T> listener = new ConstraintValidationListener<T>(object, objectClass); - final GroupValidationContextImpl<T> context = new GroupValidationContextImpl<T>(listener, - factoryContext.getMessageInterpolator(), factoryContext.getTraversableResolver(), - factoryContext.getParameterNameProvider(), factoryContext.getConstraintValidatorFactory(), metaBean); - context.setBean(object, metaBean); - final Groups computedGroup = groupsComputer.computeGroups(groups); - if (Collections.singletonList(Group.DEFAULT).equals(computedGroup.getGroups()) - && metaBean.getFeature(JsrFeatures.Bean.GROUP_SEQUENCE) != null) { - final Groups sequence = new Groups(); - @SuppressWarnings("unchecked") - final List<? extends Group> sequenceGroups = - List.class.cast(metaBean.getFeature(JsrFeatures.Bean.GROUP_SEQUENCE)); - sequence.getGroups().addAll(sequenceGroups); - context.setGroups(sequence); - } else { - context.setGroups(computedGroup); - } - return context; - } - - /** - * Create a {@link BeanDescriptorImpl} - * - * @param metaBean - * @return {@link BeanDescriptorImpl} instance - */ - protected BeanDescriptorImpl createBeanDescriptor(MetaBean metaBean) { - return new BeanDescriptorImpl(factoryContext, metaBean); - } - - /** - * Checks that the property name is valid according to spec Section 4.1.1 i. Throws an - * {@link IllegalArgumentException} if it is not. - * - * @param propertyName Property name to check. - */ - private void checkPropertyName(String propertyName) { - if (propertyName == null || propertyName.trim().isEmpty()) { - throw new IllegalArgumentException("Property path cannot be null or empty."); - } - } - - /** - * Checks that the groups array is valid according to spec Section 4.1.1 i. Throws an - * {@link IllegalArgumentException} if it is not. - * - * @param groups The groups to check. - */ - private void checkGroups(Class<?>[] groups) { - for (final Class<?> c : notNull("groups", groups)) { - notNull("group", c); - } - } - - @Override - public <T> Set<ConstraintViolation<T>> validateConstructorParameters(Constructor<? extends T> constructor, - Object[] parameterValues, Class<?>... gps) { - notNull("Constructor", constructor); - notNull("Groups", gps); - notNull("Parameters", parameterValues); - - final Class<?> declaringClass = constructor.getDeclaringClass(); - final ConstructorDescriptorImpl constructorDescriptor = ConstructorDescriptorImpl.class - .cast(getConstraintsForClass(declaringClass).getConstraintsForConstructor(constructor.getParameterTypes())); - if (constructorDescriptor == null) { // no constraint - return Collections.emptySet(); - } - - // sanity checks - if (!constructorDescriptor.isValidated(constructor)) { - if (parameterValues.length == 0) { - checkValidationAppliesTo(Collections.singleton(constructorDescriptor.getCrossParameterDescriptor()), - ConstraintTarget.PARAMETERS); - checkValidationAppliesTo(constructorDescriptor.getParameterDescriptors(), ConstraintTarget.PARAMETERS); - } else { - checkValidationAppliesTo(Collections.singleton(constructorDescriptor.getCrossParameterDescriptor()), - ConstraintTarget.IMPLICIT); - checkValidationAppliesTo(constructorDescriptor.getParameterDescriptors(), ConstraintTarget.IMPLICIT); - } - constructorDescriptor.setValidated(constructor); - } - - // validations - return validateInvocationParameters(constructor, parameterValues, constructorDescriptor, gps, - new NodeImpl.ConstructorNodeImpl(declaringClass.getSimpleName(), - Arrays.asList(constructor.getParameterTypes())), - null); - } - - private <T> Set<ConstraintViolation<T>> validateInvocationParameters(final Member invocable, - final Object[] parameterValues, final InvocableElementDescriptor constructorDescriptor, final Class<?>[] gps, - final NodeImpl rootNode, final Object rootBean) { - final Set<ConstraintViolation<T>> violations = new HashSet<ConstraintViolation<T>>(); - - @SuppressWarnings("unchecked") - final GroupValidationContext<ConstraintValidationListener<?>> parametersContext = createInvocableContext( - constructorDescriptor.getMetaBean(), rootBean, Class.class.cast(invocable.getDeclaringClass()), gps); - - @SuppressWarnings("unchecked") - final GroupValidationContext<Object> crossParameterContext = createContext(constructorDescriptor.getMetaBean(), - rootBean, Class.class.cast(invocable.getDeclaringClass()), gps); - - if (rootBean == null) { - final Constructor<?> m = Constructor.class.cast(invocable); - parametersContext.setConstructor(m); - crossParameterContext.setConstructor(m); - } else { // could be more sexy but that's ok for now - final Method m = Method.class.cast(invocable); - parametersContext.setMethod(m); - crossParameterContext.setMethod(m); - } - - final Groups groups = parametersContext.getGroups(); - - final List<ParameterDescriptor> parameterDescriptors = constructorDescriptor.getParameterDescriptors(); - final ElementDescriptorImpl crossParamDescriptor = - ElementDescriptorImpl.class.cast(constructorDescriptor.getCrossParameterDescriptor()); - final Set<ConstraintDescriptor<?>> crossParamConstraints = crossParamDescriptor.getConstraintDescriptors(); - - crossParameterContext.setBean(parameterValues); - crossParameterContext.moveDown(rootNode); - crossParameterContext.moveDown("<cross-parameter>"); - crossParameterContext.setKind(ElementKind.CROSS_PARAMETER); - - parametersContext.moveDown(rootNode); - parametersContext.setParameters(parameterValues); - - for (final Group current : groups.getGroups()) { - for (int i = 0; i < parameterValues.length; i++) { - final ParameterDescriptorImpl paramDesc = - ParameterDescriptorImpl.class.cast(parameterDescriptors.get(i)); - parametersContext.setBean(parameterValues[i]); - parametersContext.moveDown(new NodeImpl.ParameterNodeImpl(paramDesc.getName(), i)); - for (final ConstraintDescriptor<?> constraintDescriptor : paramDesc.getConstraintDescriptors()) { - final ConstraintValidation<?> validation = ConstraintValidation.class.cast(constraintDescriptor); - parametersContext.setCurrentGroup(paramDesc.mapGroup(current)); - validation.validateGroupContext(parametersContext); - } - parametersContext.moveUp(null, null); - } - - for (final ConstraintDescriptor<?> d : crossParamConstraints) { - final ConstraintValidation<?> validation = ConstraintValidation.class.cast(d); - crossParameterContext.setCurrentGroup(crossParamDescriptor.mapGroup(current)); - validation.validateGroupContext(crossParameterContext); - } - - if (gps.length == 0 && parametersContext.getListener().getConstraintViolations().size() - + crossParameterContext.getListener().getConstraintViolations().size() > 0) { - break; - } - } - - for (final Group current : groups.getGroups()) { - for (int i = 0; i < parameterValues.length; i++) { - final ParameterDescriptorImpl paramDesc = - ParameterDescriptorImpl.class.cast(parameterDescriptors.get(i)); - if (paramDesc.isCascaded() && parameterValues[i] != null) { - parametersContext.setBean(parameterValues[i]); - parametersContext.moveDown(new NodeImpl.ParameterNodeImpl(paramDesc.getName(), i)); - initMetaBean(parametersContext, factoryContext.getMetaBeanFinder(), parameterValues[i].getClass()); - parametersContext.setCurrentGroup(paramDesc.mapGroup(current)); - ValidationHelper.validateContext(parametersContext, new JsrValidationCallback(parametersContext), - factoryContext.isTreatMapsLikeBeans()); - parametersContext.moveUp(null, null); - } - } - } - - for (final List<Group> eachSeq : groups.getSequences()) { - for (final Group current : eachSeq) { - for (int i = 0; i < parameterValues.length; i++) { - final ParameterDescriptorImpl paramDesc = - ParameterDescriptorImpl.class.cast(parameterDescriptors.get(i)); - parametersContext.setBean(parameterValues[i]); - parametersContext.moveDown(new NodeImpl.ParameterNodeImpl(paramDesc.getName(), i)); - for (final ConstraintDescriptor<?> constraintDescriptor : paramDesc.getConstraintDescriptors()) { - final ConstraintValidation<?> validation = - ConstraintValidation.class.cast(constraintDescriptor); - parametersContext.setCurrentGroup(paramDesc.mapGroup(current)); - validation.validateGroupContext(parametersContext); - } - parametersContext.moveUp(null, null); - } - - for (final ConstraintDescriptor<?> d : crossParamConstraints) { - final ConstraintValidation<?> validation = ConstraintValidation.class.cast(d); - crossParameterContext.setCurrentGroup(crossParamDescriptor.mapGroup(current)); - validation.validateGroupContext(crossParameterContext); - } - - if (parametersContext.getListener().getConstraintViolations().size() - + crossParameterContext.getListener().getConstraintViolations().size() > 0) { - break; - } - } - - for (final Group current : eachSeq) { - for (int i = 0; i < parameterValues.length; i++) { - final ParameterDescriptorImpl paramDesc = - ParameterDescriptorImpl.class.cast(parameterDescriptors.get(i)); - if (paramDesc.isCascaded() && parameterValues[i] != null) { - parametersContext.setBean(parameterValues[i]); - parametersContext.moveDown(new NodeImpl.ParameterNodeImpl(paramDesc.getName(), i)); - initMetaBean(parametersContext, factoryContext.getMetaBeanFinder(), - parameterValues[i].getClass()); - parametersContext.setCurrentGroup(paramDesc.mapGroup(current)); - ValidationHelper.validateContext(parametersContext, - new JsrValidationCallback(parametersContext), factoryContext.isTreatMapsLikeBeans()); - parametersContext.moveUp(null, null); - } - } - } - } - if (constructorDescriptor.isCascaded()) { - if (parametersContext.getValidatedValue() != null) { - initMetaBean(parametersContext, factoryContext.getMetaBeanFinder(), - parametersContext.getValidatedValue().getClass()); - - for (final Group current : groups.getGroups()) { - parametersContext.setCurrentGroup(constructorDescriptor.mapGroup(current)); - ValidationHelper.validateContext(parametersContext, new JsrValidationCallback(parametersContext), - factoryContext.isTreatMapsLikeBeans()); - } - for (final List<Group> eachSeq : groups.getSequences()) { - for (final Group current : eachSeq) { - parametersContext.setCurrentGroup(constructorDescriptor.mapGroup(current)); - ValidationHelper.validateContext(parametersContext, - new JsrValidationCallback(parametersContext), factoryContext.isTreatMapsLikeBeans()); - if (!parametersContext.getListener().isEmpty()) { - break; - } - } - } - } - if (crossParameterContext.getValidatedValue() != null) { - initMetaBean(crossParameterContext, factoryContext.getMetaBeanFinder(), - crossParameterContext.getValidatedValue().getClass()); - - for (final Group current : groups.getGroups()) { - crossParameterContext.setCurrentGroup(constructorDescriptor.mapGroup(current)); - ValidationHelper.validateContext(crossParameterContext, - new JsrValidationCallback(crossParameterContext), factoryContext.isTreatMapsLikeBeans()); - } - for (final List<Group> eachSeq : groups.getSequences()) { - for (final Group current : eachSeq) { - crossParameterContext.setCurrentGroup(constructorDescriptor.mapGroup(current)); - ValidationHelper.validateContext(crossParameterContext, - new JsrValidationCallback(crossParameterContext), factoryContext.isTreatMapsLikeBeans()); - if (!crossParameterContext.getListener().isEmpty()) { - break; - } - } - } - } - } - - @SuppressWarnings("unchecked") - final Set<ConstraintViolation<T>> parameterViolations = - Set.class.cast(parametersContext.getListener().getConstraintViolations()); - violations.addAll(parameterViolations); - @SuppressWarnings("unchecked") - final Set<ConstraintViolation<T>> crossParameterViolations = - Set.class.cast(crossParameterContext.getListener().getConstraintViolations()); - violations.addAll(crossParameterViolations); - - return violations; - } - - private static void checkValidationAppliesTo(final Collection<? extends ElementDescriptor> descriptors, - final ConstraintTarget forbidden) { - for (final ElementDescriptor descriptor : descriptors) { - for (final ConstraintDescriptor<?> consDesc : descriptor.getConstraintDescriptors()) { - checkValidationAppliesTo(consDesc.getValidationAppliesTo(), forbidden); - } - } - } - - private static void checkValidationAppliesTo(final Set<ConstraintDescriptor<?>> constraintDescriptors, - final ConstraintTarget forbidden) { - for (final ConstraintDescriptor<?> descriptor : constraintDescriptors) { - checkValidationAppliesTo(descriptor.getValidationAppliesTo(), forbidden); - } - } - - private static void checkValidationAppliesTo(final ConstraintTarget configured, final ConstraintTarget forbidden) { - if (forbidden.equals(configured)) { - throw new ConstraintDeclarationException(forbidden.name() + " forbidden here"); - } - } - - @Override - public <T> Set<ConstraintViolation<T>> validateConstructorReturnValue(final Constructor<? extends T> constructor, - final T createdObject, final Class<?>... gps) { - notNull("Constructor", constructor); - notNull("Returned value", createdObject); - - final Class<? extends T> declaringClass = constructor.getDeclaringClass(); - final ConstructorDescriptorImpl methodDescriptor = ConstructorDescriptorImpl.class - .cast(getConstraintsForClass(declaringClass).getConstraintsForConstructor(constructor.getParameterTypes())); - if (methodDescriptor == null) { - throw new ValidationException("Constructor " + constructor + " doesn't belong to class " + declaringClass); - } - - return validateReturnedValue( - new NodeImpl.ConstructorNodeImpl(declaringClass.getSimpleName(), - Arrays.asList(constructor.getParameterTypes())), - createdObject, declaringClass, methodDescriptor, gps, null); - } - - private <T> Set<ConstraintViolation<T>> validateReturnedValue(final NodeImpl rootNode, final T createdObject, - final Class<?> clazz, final InvocableElementDescriptor methodDescriptor, final Class<?>[] gps, - final Object rootBean) { - final ElementDescriptorImpl returnedValueDescriptor = - ElementDescriptorImpl.class.cast(methodDescriptor.getReturnValueDescriptor()); - final Set<ConstraintDescriptor<?>> returnedValueConstraints = - returnedValueDescriptor.getConstraintDescriptors(); - - @SuppressWarnings("unchecked") - final GroupValidationContext<T> context = createInvocableContext(methodDescriptor.getMetaBean(), createdObject, - Class.class.cast(Proxies.classFor(clazz)), gps); - context.moveDown(rootNode); - context.moveDown(new NodeImpl.ReturnValueNodeImpl()); - context.setReturnValue(rootBean); - - final Groups groups = context.getGroups(); - - for (final Group current : groups.getGroups()) { - for (final ConstraintDescriptor<?> d : returnedValueConstraints) { - final ConstraintValidation<?> validation = ConstraintValidation.class.cast(d); - context.setCurrentGroup(returnedValueDescriptor.mapGroup(current)); - validation.validateGroupContext(context); - } - if (gps.length == 0 && !context.getListener().getConstraintViolations().isEmpty()) { - break; - } - } - - int currentViolationNumber = context.getListener().getConstraintViolations().size(); - for (final Group current : groups.getGroups()) { - if (returnedValueDescriptor.isCascaded() && context.getValidatedValue() != null) { - context.setBean(createdObject); - initMetaBean(context, factoryContext.getMetaBeanFinder(), context.getValidatedValue().getClass()); - - context.setCurrentGroup(methodDescriptor.mapGroup(current)); - ValidationHelper.validateContext(context, new JsrValidationCallback(context), - factoryContext.isTreatMapsLikeBeans()); - - if (currentViolationNumber < context.getListener().getConstraintViolations().size()) { - break; - } - } - } - - for (final List<Group> eachSeq : groups.getSequences()) { - for (final Group current : eachSeq) { - for (final ConstraintDescriptor<?> d : returnedValueConstraints) { - final ConstraintValidation<?> validation = ConstraintValidation.class.cast(d); - context.setCurrentGroup(current); - validation.validateGroupContext(context); - } - if (!context.getListener().getConstraintViolations().isEmpty()) { - break; - } - } - - currentViolationNumber = context.getListener().getConstraintViolations().size(); - for (final Group current : eachSeq) { - if (returnedValueDescriptor.isCascaded() && context.getValidatedValue() != null) { - context.setBean(createdObject); - initMetaBean(context, factoryContext.getMetaBeanFinder(), context.getValidatedValue().getClass()); - - context.setCurrentGroup(methodDescriptor.mapGroup(current)); - ValidationHelper.validateContext(context, new JsrValidationCallback(context), - factoryContext.isTreatMapsLikeBeans()); - - if (currentViolationNumber < context.getListener().getConstraintViolations().size()) { - break; - } - } - } - } - - return context.getListener().getConstraintViolations(); - } - - @Override - public <T> Set<ConstraintViolation<T>> validateParameters(T object, Method method, Object[] parameterValues, - Class<?>... groups) { - notNull("Object", object); - notNull("Parameters", parameterValues); - notNull("Method", method); - notNull("Groups", groups); - for (final Class<?> g : groups) { - notNull("Each group", g); - } - - final MethodDescriptorImpl methodDescriptor = findMethodDescriptor(object, method); - if (methodDescriptor == null - || !(methodDescriptor.hasConstrainedParameters() || methodDescriptor.hasConstrainedReturnValue())) { // no constraint - return Collections.emptySet(); - } - - if (!methodDescriptor.isValidated(method)) { - if (method.getParameterTypes().length == 0) { - checkValidationAppliesTo(Collections.singleton(methodDescriptor.getCrossParameterDescriptor()), - ConstraintTarget.PARAMETERS); - checkValidationAppliesTo(methodDescriptor.getParameterDescriptors(), ConstraintTarget.PARAMETERS); - } else if (!Void.TYPE.equals(method.getReturnType())) { - checkValidationAppliesTo(Collections.singleton(methodDescriptor.getCrossParameterDescriptor()), - ConstraintTarget.IMPLICIT); - checkValidationAppliesTo(methodDescriptor.getParameterDescriptors(), ConstraintTarget.IMPLICIT); - } - methodDescriptor.setValidated(method); - } - return validateInvocationParameters(method, parameterValues, methodDescriptor, groups, - new NodeImpl.MethodNodeImpl(method.getName(), Arrays.asList(method.getParameterTypes())), object); - } - - private static <T> T notNull(final String entity, final T shouldntBeNull) { - if (shouldntBeNull == null) { - throw new IllegalArgumentException(entity + " cannot be null"); - } - return shouldntBeNull; - } - - /** - * {@inheritDoc} - */ - @Override - public <T> Set<ConstraintViolation<T>> validateReturnValue(T object, Method method, Object returnValue, - Class<?>... groups) { - notNull("object", object); - notNull("method", method); - notNull("groups", groups); - - final MethodDescriptorImpl methodDescriptor = findMethodDescriptor(object, method); - if (methodDescriptor == null) { - throw new ValidationException("Method " + method + " doesn't belong to class " + object.getClass()); - } - - if (method.getReturnType() == Void.TYPE) { - checkValidationAppliesTo(methodDescriptor.getReturnValueDescriptor().getConstraintDescriptors(), - ConstraintTarget.RETURN_VALUE); - } - - @SuppressWarnings("unchecked") - final Set<ConstraintViolation<T>> result = Set.class.cast(validateReturnedValue( - new NodeImpl.MethodNodeImpl(method.getName(), Arrays.asList(method.getParameterTypes())), returnValue, - object.getClass(), methodDescriptor, groups, object)); - return result; - } - - private <T> MethodDescriptorImpl findMethodDescriptor(final T object, final Method method) { - return MethodDescriptorImpl.class - .cast(BeanDescriptorImpl.class.cast(getConstraintsForClass(Proxies.classFor(method.getDeclaringClass()))) - .getInternalConstraintsForMethod(method.getName(), method.getParameterTypes())); - } - - private <T> void initMetaBean(final GroupValidationContext<T> context, final MetaBeanFinder metaBeanFinder, - final Class<?> directValueClass) { - if (directValueClass.isArray()) { - context.setMetaBean(metaBeanFinder.findForClass(directValueClass.getComponentType())); - return; - } - if (Collection.class.isAssignableFrom(directValueClass)) { - final Collection<?> coll = Collection.class.cast(context.getValidatedValue()); - if (!coll.isEmpty()) { - context.setMetaBean(metaBeanFinder.findForClass(coll.iterator().next().getClass())); - return; - } - } - if (Map.class.isAssignableFrom(directValueClass)) { - final Map<?, ?> m = Map.class.cast(context.getValidatedValue()); - if (!m.isEmpty()) { - context.setMetaBean(metaBeanFinder.findForClass(m.values().iterator().next().getClass())); - return; - } - } - context.setMetaBean(metaBeanFinder.findForClass(directValueClass)); - } - - /** - * Dispatches a call from {@link #validate()} to {@link ClassValidator#validateBeanNet(GroupValidationContext)} with - * the current context set. - */ - protected class JsrValidationCallback implements ValidationHelper.ValidateCallback { - - private final GroupValidationContext<?> context; - - public JsrValidationCallback(GroupValidationContext<?> context) { - this.context = context; - } - - @Override - public void validate() { - validateBeanNet(context); - } - - } - - /** - * Create a {@link ValidationContextTraversal} instance for this {@link ClassValidator}. - * - * @param validationContext - * @return {@link ValidationContextTraversal} - */ - protected ValidationContextTraversal createValidationContextTraversal(GroupValidationContext<?> validationContext) { - return new ValidationContextTraversal(validationContext); - } - - /** - * Implement {@link #validateProperty(Object, String, boolean, Class[])} } and - * {@link #validateValue(Class, String, Object, boolean, Class...)}. - * - * @param <T> - * @param beanType - * @param object - * @param propertyName - * @param value - * @param cascade - * @param groups - * @return {@link ConstraintViolation} {@link Set} - */ - private <T> Set<ConstraintViolation<T>> validateValueImpl(Class<T> beanType, T object, String propertyName, - Object value, final boolean cascade, Class<?>... groups) { - - assert (object == null) ^ (value == VALIDATE_PROPERTY); - checkPropertyName(propertyName); - checkGroups(groups); - - try { - final MetaBean initialMetaBean = new DynamicMetaBean(metaBeanFinder); - initialMetaBean.setBeanClass(beanType); - GroupValidationContext<T> context = createContext(initialMetaBean, object, beanType, groups); - ValidationContextTraversal contextTraversal = createValidationContextTraversal(context); - PathNavigation.navigate(propertyName, contextTraversal); - - MetaProperty prop = context.getMetaProperty(); - boolean fixed = false; - if (value != VALIDATE_PROPERTY) { - assert !context.getPropertyPath().isRootPath(); - if (prop == null && value != null) { - context.setMetaBean(metaBeanFinder.findForClass(value.getClass())); - } - if (!cascade) { - //TCK doesn't care what type a property is if there are no constraints to validate: - FeaturesCapable meta = prop == null ? context.getMetaBean() : prop; - - Validation[] validations = meta.getValidations(); - if (validations == null || validations.length == 0) { - return Collections.<ConstraintViolation<T>> emptySet(); - } - } - if (!TypeUtils.isAssignable(value == null ? null : value.getClass(), contextTraversal.getType())) { - throw new IncompatiblePropertyValueException(String.format( - "%3$s is not a valid value for property %2$s of type %1$s", beanType, propertyName, value)); - } - if (prop == null) { - context.setBean(value); - } else { - context.setFixedValue(value); - fixed = true; - } - } - boolean doCascade = cascade && (prop == null || prop.getMetaBean() != null); - - Object bean = context.getBean(); - - ConstraintValidationListener<T> result = context.getListener(); - Groups sequence = context.getGroups(); - - // 1. process groups - - for (Group current : sequence.getGroups()) { - context.setCurrentGroup(current); - - if (!doCascade || prop != null) { - validatePropertyInGroup(context); - } - if (doCascade) { - contextTraversal.moveDownIfNecessary(); - if (context.getMetaBean() instanceof DynamicMetaBean) { - context.setMetaBean(context.getMetaBean().resolveMetaBean( - ObjectUtils.defaultIfNull(context.getBean(), contextTraversal.getRawType()))); - } - validateBeanNet(context); - if (prop != null) { - context.moveUp(bean, prop.getParentMetaBean()); - context.setMetaProperty(prop); - if (fixed) { - context.setFixedValue(value); - } - } - } - } - - // 2. process sequences - - int groupViolations = result.getConstraintViolations().size(); - - outer: for (List<Group> eachSeq : sequence.getSequences()) { - for (Group current : eachSeq) { - context.setCurrentGroup(current); - - if (!doCascade || prop != null) { - validatePropertyInGroup(context); - } - if (doCascade) { - contextTraversal.moveDownIfNecessary(); - if (context.getMetaBean() instanceof DynamicMetaBean) { - context.setMetaBean(context.getMetaBean().resolveMetaBean( - ObjectUtils.defaultIfNull(context.getBean(), contextTraversal.getRawType()))); - } - validateBeanNet(context); - if (prop != null) { - context.moveUp(bean, prop.getParentMetaBean()); - context.setMetaProperty(prop); - if (fixed) { - context.setFixedValue(value); - } - } - } - /** - * 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 (result.getConstraintViolations().size() > groupViolations) - break outer; - } - } - return result.getConstraintViolations(); - } catch (RuntimeException ex) { - throw unrecoverableValidationError(ex, ObjectUtils.defaultIfNull(object, value)); - } - } -}
http://git-wip-us.apache.org/repos/asf/bval/blob/92c64b3c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java index 28379b7..e412c30 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintCached.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; http://git-wip-us.apache.org/repos/asf/bval/blob/92c64b3c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java deleted file mode 100644 index c4c9d99..0000000 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintDescriptorImpl.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.bval.jsr; - -import javax.validation.ConstraintTarget; -import javax.validation.Payload; -import javax.validation.metadata.ConstraintDescriptor; -import javax.validation.metadata.ValidateUnwrappedValue; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Immutable, {@link Serializable} {@link ConstraintDescriptor} implementation. - * - * User: roman.stumm<br> - * Date: 22.04.2010<br> - * Time: 10:21:23<br> - */ -public class ConstraintDescriptorImpl<T extends Annotation> implements ConstraintDescriptor<T>, Serializable { - /** Serialization version */ - private static final long serialVersionUID = 1L; - - private final T annotation; - private final Set<Class<?>> groups; - private final Set<Class<? extends javax.validation.Payload>> payload; - private final List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> constraintValidatorClasses; - private final Map<String, Object> attributes; - private final Set<ConstraintDescriptor<?>> composingConstraints; - private final boolean reportAsSingleViolation; - private final ConstraintTarget validationAppliesTo; - private final String template; - private final int hashCode; - - /** - * Create a new ConstraintDescriptorImpl instance. - * - * @param descriptor - */ - public ConstraintDescriptorImpl(final ConstraintDescriptor<T> descriptor) { - this(descriptor.getAnnotation(), descriptor.getGroups(), descriptor.getPayload(), - descriptor.getConstraintValidatorClasses(), descriptor.getAttributes(), - descriptor.getComposingConstraints(), descriptor.isReportAsSingleViolation(), - descriptor.getValidationAppliesTo(), descriptor.getMessageTemplate()); - } - - /** - * Create a new ConstraintDescriptorImpl instance. - * - * @param annotation - * @param groups - * @param payload - * @param constraintValidatorClasses - * @param attributes - * @param composingConstraints - * @param reportAsSingleViolation - */ - public ConstraintDescriptorImpl(T annotation, Set<Class<?>> groups, - Set<Class<? extends javax.validation.Payload>> payload, - List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> constraintValidatorClasses, - Map<String, Object> attributes, Set<ConstraintDescriptor<?>> composingConstraints, - boolean reportAsSingleViolation, ConstraintTarget validationAppliesTo, String messageTemplate) { - this.annotation = annotation; - this.groups = groups; - this.payload = payload; - this.constraintValidatorClasses = constraintValidatorClasses; - this.attributes = attributes; - this.composingConstraints = composingConstraints; - this.reportAsSingleViolation = reportAsSingleViolation; - this.validationAppliesTo = validationAppliesTo; - this.template = messageTemplate; - this.hashCode = computeHashCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public T getAnnotation() { - return annotation; - } - - @Override - public String getMessageTemplate() { - return template; - } - - /** - * {@inheritDoc} - */ - @Override - public Set<Class<?>> getGroups() { - return groups; - } - - /** - * {@inheritDoc} - */ - @Override - public Set<Class<? extends Payload>> getPayload() { - return payload; - } - - @Override - public ConstraintTarget getValidationAppliesTo() { - return validationAppliesTo; - } - - /** - * {@inheritDoc} - */ - @Override - public List<java.lang.Class<? extends javax.validation.ConstraintValidator<T, ?>>> getConstraintValidatorClasses() { - return constraintValidatorClasses; - } - - /** - * {@inheritDoc} - */ - @Override - public Map<String, Object> getAttributes() { - return attributes; - } - - /** - * {@inheritDoc} - */ - @Override - public Set<ConstraintDescriptor<?>> getComposingConstraints() { - return composingConstraints; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isReportAsSingleViolation() { - return reportAsSingleViolation; - } - - /** - * generated equals on all fields except hashCode - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ConstraintDescriptorImpl<?> that = (ConstraintDescriptorImpl<?>) o; - - if (reportAsSingleViolation != that.reportAsSingleViolation) { - return false; - } - if (annotation != null ? !annotation.equals(that.annotation) : that.annotation != null) { - return false; - } - if (groups != null ? !groups.equals(that.groups) : that.groups != null) { - return false; - } - if (payload != null ? !payload.equals(that.payload) : that.payload != null) { - return false; - } - if (constraintValidatorClasses != null ? !constraintValidatorClasses.equals(that.constraintValidatorClasses) - : that.constraintValidatorClasses != null) { - return false; - } - if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) { - return false; - } - if (composingConstraints != null ? !composingConstraints.equals(that.composingConstraints) - : that.composingConstraints != null) { - return false; - } - if (validationAppliesTo != that.validationAppliesTo) { - return false; - } - return template != null ? template.equals(that.template) : that.template == null; - - } - - @Override - public int hashCode() { - return hashCode; - } - - /** - * generated hashCode on all fields except hashCode - */ - private int computeHashCode() { - int result = annotation != null ? annotation.hashCode() : 0; - result = 31 * result + (groups != null ? groups.hashCode() : 0); - result = 31 * result + (payload != null ? payload.hashCode() : 0); - result = 31 * result + (constraintValidatorClasses != null ? constraintValidatorClasses.hashCode() : 0); - result = 31 * result + (attributes != null ? attributes.hashCode() : 0); - result = 31 * result + (composingConstraints != null ? composingConstraints.hashCode() : 0); - result = 31 * result + (reportAsSingleViolation ? 1 : 0); - result = 31 * result + (validationAppliesTo != null ? validationAppliesTo.hashCode() : 0); - result = 31 * result + (template != null ? template.hashCode() : 0); - return result; - } - - @Override - public ValidateUnwrappedValue getValueUnwrapping() { - // TODO Auto-generated method stub - return null; - } - - @Override - public <U> U unwrap(Class<U> arg0) { - // TODO Auto-generated method stub - return null; - } -} http://git-wip-us.apache.org/repos/asf/bval/blob/92c64b3c/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java deleted file mode 100644 index 57680d7..0000000 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConstraintFinderImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.bval.jsr; - -import org.apache.bval.jsr.groups.Group; -import org.apache.bval.jsr.groups.Groups; -import org.apache.bval.jsr.groups.GroupsComputer; -import org.apache.bval.model.MetaBean; - -import javax.validation.metadata.ConstraintDescriptor; -import javax.validation.metadata.ElementDescriptor; -import javax.validation.metadata.ElementDescriptor.ConstraintFinder; -import javax.validation.metadata.Scope; -import java.lang.annotation.ElementType; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -/** - * Description: Implementation of the fluent {@link ConstraintFinder} interface.<br/> - */ -final class ConstraintFinderImpl implements ElementDescriptor.ConstraintFinder { - private final MetaBean metaBean; - private final Set<Scope> findInScopes; - private Set<ConstraintValidation<?>> constraintDescriptors; - - /** - * Create a new ConstraintFinderImpl instance. - * - * @param metaBean - * @param constraintDescriptors - */ - ConstraintFinderImpl(MetaBean metaBean, Set<ConstraintValidation<?>> constraintDescriptors) { - this.metaBean = metaBean; - this.constraintDescriptors = constraintDescriptors; - this.findInScopes = new HashSet<Scope>(Arrays.asList(Scope.values())); - } - - /** - * {@inheritDoc} - */ - @Override - public ElementDescriptor.ConstraintFinder unorderedAndMatchingGroups(Class<?>... groups) { - final Set<ConstraintValidation<?>> matchingDescriptors = - new HashSet<ConstraintValidation<?>>(constraintDescriptors.size()); - final Groups groupChain = new GroupsComputer().computeGroups(groups); - for (Group group : groupChain.getGroups()) { - if (group.isDefault()) { - // If group is default, check if it gets redefined - for (Group defaultGroupMember : metaBean.<List<Group>> getFeature(JsrFeatures.Bean.GROUP_SEQUENCE)) { - for (ConstraintValidation<?> descriptor : constraintDescriptors) { - if (isInScope(descriptor) && isInGroup(descriptor, defaultGroupMember)) { - matchingDescriptors.add(descriptor); - } - } - } - } else { - for (ConstraintValidation<?> descriptor : constraintDescriptors) { - if (isInScope(descriptor) && isInGroup(descriptor, group)) { - matchingDescriptors.add(descriptor); - } - } - } - } - return thisWith(matchingDescriptors); - } - - /** - * {@inheritDoc} - */ - @Override - public ElementDescriptor.ConstraintFinder lookingAt(Scope scope) { - if (scope == Scope.LOCAL_ELEMENT) { - findInScopes.remove(Scope.HIERARCHY); - for (Iterator<ConstraintValidation<?>> it = constraintDescriptors.iterator(); it.hasNext();) { - if (!it.next().getOwner().equals(metaBean.getBeanClass())) { - it.remove(); - } - } - } - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public ElementDescriptor.ConstraintFinder declaredOn(ElementType... elementTypes) { - final Set<ConstraintValidation<?>> matchingDescriptors = - new HashSet<ConstraintValidation<?>>(constraintDescriptors.size()); - for (ElementType each : elementTypes) { - for (ConstraintValidation<?> descriptor : constraintDescriptors) { - if (isInScope(descriptor) && isAtElement(descriptor, each)) { - matchingDescriptors.add(descriptor); - } - } - } - return thisWith(matchingDescriptors); - } - - private boolean isAtElement(ConstraintValidation<?> descriptor, ElementType each) { - return descriptor.getAccess().getElementType() == each; - } - - private boolean isInScope(ConstraintValidation<?> descriptor) { - if (findInScopes.size() == Scope.values().length) { - return true; // all scopes - } - if (metaBean != null) { - final boolean isOwner = descriptor.getOwner().equals(metaBean.getBeanClass()); - for (Scope scope : findInScopes) { - switch (scope) { - case LOCAL_ELEMENT: - if (isOwner) { - return true; - } - break; - case HIERARCHY: - if (!isOwner) { - return true; - } - break; - } - } - } - return false; - } - - private boolean isInGroup(ConstraintValidation<?> descriptor, Group group) { - return descriptor.getGroups().contains(group.getGroup()); - } - - private ElementDescriptor.ConstraintFinder thisWith(Set<ConstraintValidation<?>> matchingDescriptors) { - constraintDescriptors = matchingDescriptors; - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public Set<ConstraintDescriptor<?>> getConstraintDescriptors() { - if (constraintDescriptors.isEmpty()) { - return Collections.emptySet(); - } - return Collections.<ConstraintDescriptor<?>> unmodifiableSet(constraintDescriptors); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasConstraints() { - return !constraintDescriptors.isEmpty(); - } -}
