Author: hardy.ferentschik
Date: 2009-06-16 12:16:48 -0400 (Tue, 16 Jun 2009)
New Revision: 16798
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
Removed:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/metadata/
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
Log:
Also introduced metadata package in validator implementation (mirrowring the api)
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,30 +0,0 @@
-package org.hibernate.validation.engine;
-
-import java.util.Set;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class BeanDescriptorImpl<T> extends ElementDescriptorImpl implements
BeanDescriptor {
- private final BeanMetaData<T> metadataBean;
-
- public BeanDescriptorImpl(BeanMetaData<T> metadataBean) {
- super( metadataBean.getBeanClass() );
- this.metadataBean = metadataBean;
- }
-
- public boolean isBeanConstrained() {
- return metadataBean.getConstrainedProperties().size() > 0;
- }
-
- public PropertyDescriptor getConstraintsForProperty(String propertyName) {
- return metadataBean.getPropertyDescriptor( propertyName );
- }
-
- public Set<PropertyDescriptor> getConstrainedProperties() {
- return metadataBean.getConstrainedProperties();
- }
-}
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,75 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
-import java.util.List;
-import java.util.Set;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * Interface defining the meta data about the constraints defined in a given bean.
- *
- * @author Hardy Ferentschik
- */
-public interface BeanMetaData<T> {
-
- /**
- * @return the class of the bean.
- */
- Class<T> getBeanClass();
-
- /**
- * @return an instance of <code>ElementDescriptor</code> describing the bean
this meta data applies for.
- */
- BeanDescriptor getBeanDescriptor();
-
- /**
- * @return A list of all cascaded methods and fields (methods/fields annotated with
@Valid).
- */
- List<Member> getCascadedMembers();
-
- /**
- * @return A map mapping defined group sequences to a list of groups.
- */
- List<Class<?>> getDefaultGroupSequence();
-
- /**
- * @return A list of <code>MetaConstraint</code> instances encapsulating the
information of all the constraints
- * defined on the bean.
- */
- List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList();
-
- /**
- * Return <code>PropertyDescriptor</code> for the given property.
- *
- * @param property the property for which to retrieve the descriptor.
- *
- * @return Returns the <code>PropertyDescriptor</code> for the given
property or <code>null</code> in case the
- * property does not have a descriptor.
- */
- PropertyDescriptor getPropertyDescriptor(String property);
-
- /**
- * @return the property descriptors having at least one constraint defined or which are
marked
- * as cascaded (@Valid).
- */
- Set<PropertyDescriptor> getConstrainedProperties();
-}
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,48 +0,0 @@
-// $Id:$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Cache for created instances of <code>BeanMetaData</code>.
- *
- * @author Hardy Ferentschik
- */
-public class BeanMetaDataCache {
- /**
- * A map for the meta data for each entity. The key is the class and the value the bean
meta data for this
- * entity.
- */
- private Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders = new
ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>(
- 10
- );
-
- @SuppressWarnings("unchecked")
- public <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
- if ( beanClass == null ) {
- throw new IllegalArgumentException( "Class cannot be null" );
- }
- return ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
- }
-
- public <T> void addBeanMetaData(Class<T> beanClass,
BeanMetaDataImpl<T> metaData) {
- metadataProviders.put( beanClass, metaData );
- }
-}
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,389 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.validation.GroupSequence;
-import javax.validation.Valid;
-import javax.validation.ValidationException;
-import javax.validation.groups.Default;
-import javax.validation.metadata.BeanDescriptor;
-import javax.validation.metadata.PropertyDescriptor;
-
-import org.slf4j.Logger;
-
-import org.hibernate.validation.engine.xml.AnnotationIgnores;
-import org.hibernate.validation.util.LoggerFactory;
-import org.hibernate.validation.util.ReflectionHelper;
-
-
-/**
- * This class encapsulates all meta data needed for validation. Implementations of {@code
Validator} interface can
- * instantiate an instance of this class and delegate the metadata extraction to it.
- *
- * @author Hardy Ferentschik
- */
-
-public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
-
- private static final Logger log = LoggerFactory.make();
-
- /**
- * The root bean class for this validator.
- */
- private final Class<T> beanClass;
-
- /**
- * The main element descriptor for <code>beanClass</code>.
- */
- private BeanDescriptorImpl<T> beanDescriptor;
-
- /**
- * List of constraints.
- */
- private List<MetaConstraint<T, ? extends Annotation>> metaConstraintList =
new ArrayList<MetaConstraint<T, ? extends Annotation>>();
-
- /**
- * List of cascaded members.
- */
- private List<Member> cascadedMembers = new ArrayList<Member>();
-
- /**
- * Maps field and method names to their <code>ElementDescriptorImpl</code>.
- */
- private Map<String, PropertyDescriptor> propertyDescriptors = new
HashMap<String, PropertyDescriptor>();
-
- /**
- * Maps group sequences to the list of group/sequences.
- */
- private List<Class<?>> defaultGroupSequence = new
ArrayList<Class<?>>();
-
- /**
- * Object keeping track of all constraints.
- */
- private final ConstraintHelper constraintHelper;
-
-
- public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
- this(
- beanClass,
- constraintHelper,
- new AnnotationIgnores()
- );
- }
-
- public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper,
AnnotationIgnores annotationIgnores) {
- this.beanClass = beanClass;
- this.constraintHelper = constraintHelper;
- createMetaData( annotationIgnores );
- }
-
- public Class<T> getBeanClass() {
- return beanClass;
- }
-
- public BeanDescriptor getBeanDescriptor() {
- return beanDescriptor;
- }
-
- public List<Member> getCascadedMembers() {
- return Collections.unmodifiableList( cascadedMembers );
- }
-
- public List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList()
{
- return Collections.unmodifiableList( metaConstraintList );
- }
-
- public void addMetaConstraint(MetaConstraint<T, ? extends Annotation>
metaConstraint) {
- metaConstraintList.add( metaConstraint );
- }
-
- public void addCascadedMember(Member member) {
- cascadedMembers.add( member );
- }
-
- public PropertyDescriptor getPropertyDescriptor(String property) {
- return propertyDescriptors.get( property );
- }
-
- public List<Class<?>> getDefaultGroupSequence() {
- return Collections.unmodifiableList( defaultGroupSequence );
- }
-
- public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
- defaultGroupSequence = new ArrayList<Class<?>>();
- for ( Class<?> group : groupSequence ) {
- if ( group.getName().equals( beanClass.getName() ) ) {
- defaultGroupSequence.add( Default.class );
- }
- else if ( group.getName().equals( Default.class.getName() ) ) {
- throw new ValidationException( "'Default.class' cannot appear in default
group sequence list." );
- }
- else {
- defaultGroupSequence.add( group );
- }
- }
- if ( log.isTraceEnabled() ) {
- log.trace(
- "Members of the default group sequence for bean {} are: {}",
- beanClass.getName(),
- defaultGroupSequence
- );
- }
- }
-
- public Set<PropertyDescriptor> getConstrainedProperties() {
- return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>(
propertyDescriptors.values() ) );
- }
-
- /**
- * Create bean desciptor, find all classes/subclasses/interfaces which have to be taken
in consideration
- * for this validator and create meta data.
- *
- * @param annotationIgnores Datastructure keeping track on which annotation should be
ignored.
- */
- private void createMetaData(AnnotationIgnores annotationIgnores) {
- beanDescriptor = new BeanDescriptorImpl<T>( this );
- initDefaultGroupSequence();
- List<Class> classes = new ArrayList<Class>();
- computeClassHierarchy( beanClass, classes );
- for ( Class current : classes ) {
- initClass( current, annotationIgnores );
- }
- }
-
- /**
- * Get all superclasses and interfaces recursively.
- *
- * @param clazz The class to start the search with.
- * @param classes List of classes to which to add all found super classes and
interfaces.
- */
- private void computeClassHierarchy(Class clazz, List<Class> classes) {
- if ( log.isTraceEnabled() ) {
- log.trace( "Processing: {}", clazz );
- }
- for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
- if ( classes.contains( current ) ) {
- return;
- }
- classes.add( current );
- for ( Class currentInterface : current.getInterfaces() ) {
- computeClassHierarchy( currentInterface, classes );
- }
- }
- }
-
- private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
- initClassConstraints( clazz, annotationIgnores );
- initMethodConstraints( clazz, annotationIgnores );
- initFieldConstraints( clazz, annotationIgnores );
- }
-
- /**
- * Checks whether there is a default group sequence defined for this class.
- * See HV-113.
- */
- private void initDefaultGroupSequence() {
- List<Class<?>> groupSequence = new ArrayList<Class<?>>();
- GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class
);
- if ( groupSequenceAnnotation == null ) {
- groupSequence.add( beanClass );
- }
- else {
- groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
- }
- setDefaultGroupSequence( groupSequence );
- }
-
- private void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
- for ( Field field : clazz.getDeclaredFields() ) {
- List<ConstraintDescriptorImpl<?>> fieldMetadata = findConstraints( field
);
- for ( ConstraintDescriptorImpl<?> constraintDescription : fieldMetadata ) {
- if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
- break;
- }
- ReflectionHelper.setAccessibility( field );
- MetaConstraint<T, ?> metaConstraint = createMetaConstraint( field,
constraintDescription );
- metaConstraintList.add( metaConstraint );
- }
- if ( field.isAnnotationPresent( Valid.class ) ) {
- ReflectionHelper.setAccessibility( field );
- cascadedMembers.add( field );
- addPropertyDescriptorForMember( field );
- }
- }
- }
-
- private void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
- for ( Method method : clazz.getDeclaredMethods() ) {
- List<ConstraintDescriptorImpl<?>> methodMetadata = findConstraints( method
);
- for ( ConstraintDescriptorImpl<?> constraintDescription : methodMetadata ) {
- if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
- break;
- }
- ReflectionHelper.setAccessibility( method );
- MetaConstraint<T, ?> metaConstraint = createMetaConstraint( method,
constraintDescription );
- metaConstraintList.add( metaConstraint );
- }
- if ( method.isAnnotationPresent( Valid.class ) ) {
- ReflectionHelper.setAccessibility( method );
- cascadedMembers.add( method );
- addPropertyDescriptorForMember( method );
- }
- }
- }
-
- private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
- String name = ReflectionHelper.getPropertyName( member );
- PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get(
- name
- );
- if ( propertyDescriptor == null ) {
- propertyDescriptor = new PropertyDescriptorImpl(
- ReflectionHelper.getType( member ),
- ( ( AnnotatedElement ) member ).isAnnotationPresent( Valid.class ),
- name
- );
- propertyDescriptors.put( name, propertyDescriptor );
- }
- return propertyDescriptor;
- }
-
- private void initClassConstraints(Class<?> clazz, AnnotationIgnores
annotationIgnores) {
- if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
- return;
- }
- List<ConstraintDescriptorImpl<?>> classMetadata =
findClassLevelConstraints( clazz );
- for ( ConstraintDescriptorImpl<?> constraintDescription : classMetadata ) {
- MetaConstraint<T, ?> metaConstraint = createMetaConstraint(
constraintDescription );
- metaConstraintList.add( metaConstraint );
- }
- }
-
- private <A extends Annotation> MetaConstraint<T, ?>
createMetaConstraint(ConstraintDescriptorImpl<A> descriptor) {
- return new MetaConstraint<T, A>( beanClass, descriptor );
- }
-
- private <A extends Annotation> MetaConstraint<T, ?>
createMetaConstraint(Member m, ConstraintDescriptorImpl<A> descriptor) {
- return new MetaConstraint<T, A>( m, beanClass, descriptor );
- }
-
- /**
- * Examines the given annotation to see whether it is a single or multi valued
constraint annotation.
- *
- * @param clazz the class we are currently processing.
- * @param annotation The annotation to examine.
- *
- * @return A list of constraint descriptors or the empty list in case
<code>annotation</code> is neither a
- * single nor multi value annotation.
- */
- private <A extends Annotation> List<ConstraintDescriptorImpl<?>>
findConstraintAnnotations(Class<?> clazz, A annotation) {
- List<ConstraintDescriptorImpl<?>> constraintDescriptors = new
ArrayList<ConstraintDescriptorImpl<?>>();
-
- List<Annotation> constraints = new ArrayList<Annotation>();
- if ( constraintHelper.isConstraintAnnotation( annotation ) ||
- constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
- constraints.add( annotation );
- }
-
- // check if we have a multi value constraint
- constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) );
-
- for ( Annotation constraint : constraints ) {
- final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
clazz, constraint );
- constraintDescriptors.add( constraintDescriptor );
- }
- return constraintDescriptors;
- }
-
- @SuppressWarnings("unchecked")
- private <A extends Annotation> ConstraintDescriptorImpl
buildConstraintDescriptor(Class<?> clazz, A annotation) {
- ConstraintDescriptorImpl constraintDescriptor;
- if ( clazz.isInterface() ) {
- constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper,
clazz );
- }
- else {
- constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper );
- }
- return constraintDescriptor;
- }
-
- /**
- * Finds all constraint annotations defined for the given class and returns them in a
list of
- * constraint descriptors.
- *
- * @param beanClass The class to check for constraints annotations.
- *
- * @return A list of constraint descriptors for all constraint specified on the given
class.
- */
- private List<ConstraintDescriptorImpl<?>>
findClassLevelConstraints(Class<?> beanClass) {
- List<ConstraintDescriptorImpl<?>> metadata = new
ArrayList<ConstraintDescriptorImpl<?>>();
- for ( Annotation annotation : beanClass.getAnnotations() ) {
- metadata.addAll( findConstraintAnnotations( beanClass, annotation ) );
- }
- for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
- beanDescriptor.addConstraintDescriptor( constraintDescriptor );
- }
- return metadata;
- }
-
-
- /**
- * Finds all constraint annotations defined for the given field/method and returns them
in a list of
- * constraint descriptors.
- *
- * @param member The fiels or method to check for constraints annotations.
- *
- * @return A list of constraint descriptors for all constraint specified for the given
field or method.
- */
- private List<ConstraintDescriptorImpl<?>> findConstraints(Member member) {
- assert member instanceof Field || member instanceof Method;
-
- List<ConstraintDescriptorImpl<?>> metadata = new
ArrayList<ConstraintDescriptorImpl<?>>();
- for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) {
- metadata.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation )
);
- }
-
- String name = ReflectionHelper.getPropertyName( member );
- for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
- if ( member instanceof Method && name == null ) { // can happen if member is a
Method which does not follow the bean convention
- throw new ValidationException(
- "Annotated methods must follow the JavaBeans naming convention. " +
member.getName() + "() does not."
- );
- }
- PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get( name );
- if ( propertyDescriptor == null ) {
- propertyDescriptor = addPropertyDescriptorForMember( member );
- }
- propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
- }
- return metadata;
- }
-}
\ No newline at end of file
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConfigurationImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -34,8 +34,8 @@
import org.slf4j.Logger;
import org.hibernate.validation.engine.resolver.DefaultTraversableResolver;
-import org.hibernate.validation.engine.xml.ValidationBootstrapParameters;
-import org.hibernate.validation.engine.xml.ValidationXmlParser;
+import org.hibernate.validation.xml.ValidationBootstrapParameters;
+import org.hibernate.validation.xml.ValidationXmlParser;
import org.hibernate.validation.util.LoggerFactory;
import org.hibernate.validation.util.Version;
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,384 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.validation.Constraint;
-import javax.validation.ConstraintDefinitionException;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.ConstraintValidator;
-import javax.validation.OverridesAttribute;
-import javax.validation.ReportAsSingleViolation;
-import javax.validation.ValidationException;
-import javax.validation.groups.Default;
-
-import org.slf4j.Logger;
-
-import org.hibernate.validation.util.LoggerFactory;
-import org.hibernate.validation.util.ReflectionHelper;
-import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
-import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
-
-/**
- * Describe a single constraint (including it's composing constraints).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class ConstraintDescriptorImpl<T extends Annotation> implements
ConstraintDescriptor<T> {
- private static final Logger log = LoggerFactory.make();
- private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1;
-
- /**
- * The actual constraint annotation.
- */
- private final T annotation;
-
- /**
- * The set of classes implementing the validation for this constraint. See also
- * <code>ConstraintValidator</code> resolution algorithm.
- */
- private final List<Class<? extends ConstraintValidator<T, ?>>>
constraintValidatorDefinitonClasses = new ArrayList<Class<? extends
ConstraintValidator<T, ?>>>();
-
- /**
- * The groups for which to apply this constraint.
- */
- private final Set<Class<?>> groups = new HashSet<Class<?>>();
-
- /**
- * The constraint parameters as map. The key is the paramter name and the value the
- * parameter value as specified in the constraint.
- */
- private final Map<String, Object> attributes;
-
- /**
- * The composing constraints for this constraints.
- */
- private final Set<ConstraintDescriptor<?>> composingConstraints = new
HashSet<ConstraintDescriptor<?>>();
-
- /**
- * Flag indicating if in case of a composing constraint a single error or multiple
errors should be raised.
- */
- private final boolean isReportAsSingleInvalidConstraint;
-
- /**
- * Handle to the builtin constraint implementations.
- */
- private final ConstraintHelper constraintHelper;
-
- public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper,
Class<?> implicitGroup) {
- this( annotation, constraintHelper );
- this.groups.add( implicitGroup );
- }
-
-
- public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper) {
- this.annotation = annotation;
- this.attributes = getAnnotationParameters( annotation );
- this.constraintHelper = constraintHelper;
-
- this.isReportAsSingleInvalidConstraint =
annotation.annotationType().isAnnotationPresent(
- ReportAsSingleViolation.class
- );
-
- Class<?>[] groupsFromAnnotation = ReflectionHelper.getAnnotationParameter(
- annotation, "groups", Class[].class
- );
- if ( groupsFromAnnotation.length == 0 ) {
- groups.add( Default.class );
- }
- else {
- this.groups.addAll( Arrays.asList( groupsFromAnnotation ) );
- }
-
- findConstraintValidatorClasses();
- Map<ClassIndexWrapper, Map<String, Object>> overrideParameters =
parseOverrideParameters();
- parseComposingConstraints( overrideParameters );
- }
-
- private void findConstraintValidatorClasses() {
- if ( constraintHelper.containsConstraintValidatorDefinition(
annotation.annotationType() ) ) {
- for ( Class<? extends ConstraintValidator<? extends Annotation, ?>>
validator : constraintHelper
- .getConstraintValidatorDefinition( annotation.annotationType() ) ) {
- constraintValidatorDefinitonClasses.add( ( Class<? extends
ConstraintValidator<T, ?>> ) validator );
- }
- return;
- }
-
- List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraintDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<?
extends Annotation, ?>>>();
- if ( constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
- constraintDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints(
annotation.annotationType() ) );
- }
- else {
- final Class<? extends Annotation> annotationType = annotation.annotationType();
- Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
- .getAnnotation( Constraint.class )
- .validatedBy();
- constraintDefinitonClasses.addAll( Arrays.asList( validatedBy ) );
- }
-
- constraintHelper.addConstraintValidatorDefinition(
- annotation.annotationType(), constraintDefinitonClasses
- );
-
- for ( Class<? extends ConstraintValidator<? extends Annotation, ?>>
validator : constraintDefinitonClasses ) {
- @SuppressWarnings("unchecked")
- Class<? extends ConstraintValidator<T, ?>> safeValidator = ( Class<?
extends ConstraintValidator<T, ?>> ) validator;
- constraintValidatorDefinitonClasses.add( safeValidator );
- }
- }
-
- public T getAnnotation() {
- return annotation;
- }
-
- public Set<Class<?>> getGroups() {
- return Collections.unmodifiableSet( groups );
- }
-
- public List<Class<? extends ConstraintValidator<T, ?>>>
getConstraintValidatorClasses() {
- return Collections.unmodifiableList( constraintValidatorDefinitonClasses );
- }
-
- public Map<String, Object> getAttributes() {
- return Collections.unmodifiableMap( attributes );
- }
-
- public Set<ConstraintDescriptor<?>> getComposingConstraints() {
- return Collections.unmodifiableSet( composingConstraints );
- }
-
- public boolean isReportAsSingleViolation() {
- return isReportAsSingleInvalidConstraint;
- }
-
- @Override
- public String toString() {
- return "ConstraintDescriptorImpl{" +
- "annotation=" + annotation +
- ", constraintValidatorDefinitonClasses=" +
constraintValidatorDefinitonClasses.toString() +
- ", groups=" + groups +
- ", attributes=" + attributes +
- ", composingConstraints=" + composingConstraints +
- ", isReportAsSingleInvalidConstraint=" + isReportAsSingleInvalidConstraint
+
- '}';
- }
-
- private Map<String, Object> getAnnotationParameters(Annotation annotation) {
- Method[] declaredMethods = annotation.annotationType().getDeclaredMethods();
- Map<String, Object> parameters = new HashMap<String, Object>(
declaredMethods.length );
- for ( Method m : declaredMethods ) {
- try {
- parameters.put( m.getName(), m.invoke( annotation ) );
- }
- catch ( IllegalAccessException e ) {
- throw new ValidationException( "Unable to read annotation attributes: " +
annotation.getClass(), e );
- }
- catch ( InvocationTargetException e ) {
- throw new ValidationException( "Unable to read annotation attributes: " +
annotation.getClass(), e );
- }
- }
- return Collections.unmodifiableMap( parameters );
- }
-
- private Object getMethodValue(Annotation annotation, Method m) {
- Object value;
- try {
- value = m.invoke( annotation );
- }
- // should never happen
- catch ( IllegalAccessException e ) {
- throw new ValidationException( "Unable to retrieve annotation parameter
value." );
- }
- catch ( InvocationTargetException e ) {
- throw new ValidationException( "Unable to retrieve annotation parameter
value." );
- }
- return value;
- }
-
- private Map<ClassIndexWrapper, Map<String, Object>>
parseOverrideParameters() {
- Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new
HashMap<ClassIndexWrapper, Map<String, Object>>();
- for ( Method m : annotation.annotationType().getMethods() ) {
- if ( m.getAnnotation( OverridesAttribute.class ) != null ) {
- addOverrideAttributes(
- overrideParameters, m, m.getAnnotation( OverridesAttribute.class )
- );
- }
- else if ( m.getAnnotation( OverridesAttribute.List.class ) != null ) {
- addOverrideAttributes(
- overrideParameters,
- m,
- m.getAnnotation( OverridesAttribute.List.class ).value()
- );
- }
- }
- return overrideParameters;
- }
-
- private void addOverrideAttributes(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters, Method m, OverridesAttribute... attributes) {
-
- Object value = getMethodValue( annotation, m );
- for ( OverridesAttribute overridesAttribute : attributes ) {
- ensureAttributeIsOverridable( m, overridesAttribute );
-
- ClassIndexWrapper wrapper = new ClassIndexWrapper(
- overridesAttribute.constraint(), overridesAttribute.constraintIndex()
- );
- Map<String, Object> map = overrideParameters.get( wrapper );
- if ( map == null ) {
- map = new HashMap<String, Object>();
- overrideParameters.put( wrapper, map );
- }
- map.put( overridesAttribute.name(), value );
- }
- }
-
- private void ensureAttributeIsOverridable(Method m, OverridesAttribute
overridesAttribute) {
- try {
- Class<?> returnTypeOfOverridenConstraint = overridesAttribute.constraint()
- .getMethod( overridesAttribute.name() )
- .getReturnType();
- if ( !returnTypeOfOverridenConstraint.equals( m.getReturnType() ) ) {
- String message = "The overiding type of a composite constraint must be identical
to the overwridden one. Expected " + returnTypeOfOverridenConstraint
- .getName() + " found " + m.getReturnType();
- throw new ConstraintDefinitionException( message );
- }
- }
- catch ( NoSuchMethodException nsme ) {
- throw new ConstraintDefinitionException(
- "Overriden constraint does not define an attribute with name " +
overridesAttribute.name()
- );
- }
- }
-
- private void parseComposingConstraints(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters) {
- for ( Annotation declaredAnnotation :
annotation.annotationType().getDeclaredAnnotations() ) {
- if ( constraintHelper.isConstraintAnnotation( declaredAnnotation )
- || constraintHelper.isBuiltinConstraint( declaredAnnotation.annotationType() ) ) {
- ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
- declaredAnnotation, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX
- );
- composingConstraints.add( descriptor );
- log.debug( "Adding composing constraint: " + descriptor );
- }
- else if ( constraintHelper.isMultiValueConstraint( declaredAnnotation ) ) {
- List<Annotation> multiValueConstraints =
constraintHelper.getMultiValueConstraints( declaredAnnotation );
- int index = 1;
- for ( Annotation constraintAnnotation : multiValueConstraints ) {
- ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
- constraintAnnotation, overrideParameters, index
- );
- composingConstraints.add( descriptor );
- log.debug( "Adding composing constraint: " + descriptor );
- index++;
- }
- }
- }
- }
-
- private <U extends Annotation> ConstraintDescriptorImpl<U>
createComposingConstraintDescriptor(U declaredAnnotation, Map<ClassIndexWrapper,
Map<String, Object>> overrideParameters, int index) {
- //TODO don't quite understand this warning
- //TODO assuming U.getClass() returns Class<U>
- @SuppressWarnings("unchecked")
- final Class<U> annotationType = ( Class<U> )
declaredAnnotation.annotationType();
- return createComposingConstraintDescriptor(
- overrideParameters,
- index,
- declaredAnnotation,
- annotationType
- );
- }
-
- private <U extends Annotation> ConstraintDescriptorImpl<U>
createComposingConstraintDescriptor(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters, int index, U constraintAnnotation, Class<U>
annotationType) {
- // use a annotation proxy
- AnnotationDescriptor<U> annotationDescriptor = new
AnnotationDescriptor<U>(
- annotationType, getAnnotationParameters( constraintAnnotation )
- );
-
- // get the right override parameters
- Map<String, Object> overrides = overrideParameters.get(
- new ClassIndexWrapper(
- annotationType, index
- )
- );
- if ( overrides != null ) {
- for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
- annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
- }
- }
-
- // groups get inherited from the parent
- annotationDescriptor.setValue( "groups", groups.toArray( new Class<?>[]
{ } ) );
-
- U annotationProxy = AnnotationFactory.create( annotationDescriptor );
- return new ConstraintDescriptorImpl<U>(
- annotationProxy, constraintHelper
- );
- }
-
- /**
- * A wrapper class to keep track for which compposing constraints (class and index) a
given attribute override applies to.
- */
- private class ClassIndexWrapper {
- final Class<?> clazz;
- final int index;
-
- ClassIndexWrapper(Class<?> clazz, int index) {
- this.clazz = clazz;
- this.index = index;
- }
-
- @Override
- public boolean equals(Object o) {
- if ( this == o ) {
- return true;
- }
- if ( o == null || getClass() != o.getClass() ) {
- return false;
- }
-
- ClassIndexWrapper that = ( ClassIndexWrapper ) o;
-
- if ( index != that.index ) {
- return false;
- }
- if ( clazz != null ? !clazz.equals( that.clazz ) : that.clazz != null ) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = clazz != null ? clazz.hashCode() : 0;
- result = 31 * result + index;
- return result;
- }
- }
-}
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,335 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.validation.Constraint;
-import javax.validation.ConstraintDefinitionException;
-import javax.validation.ConstraintValidator;
-import javax.validation.ValidationException;
-import javax.validation.constraints.AssertFalse;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.DecimalMax;
-import javax.validation.constraints.DecimalMin;
-import javax.validation.constraints.Digits;
-import javax.validation.constraints.Future;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Null;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Size;
-
-import org.hibernate.validation.constraints.impl.AssertFalseValidator;
-import org.hibernate.validation.constraints.impl.AssertTrueValidator;
-import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForString;
-import org.hibernate.validation.constraints.impl.DecimalMinValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DecimalMinValidatorForString;
-import org.hibernate.validation.constraints.impl.DigitsValidatorForNumber;
-import org.hibernate.validation.constraints.impl.DigitsValidatorForString;
-import org.hibernate.validation.constraints.impl.FutureValidatorForCalendar;
-import org.hibernate.validation.constraints.impl.FutureValidatorForDate;
-import org.hibernate.validation.constraints.impl.MaxValidatorForNumber;
-import org.hibernate.validation.constraints.impl.MaxValidatorForString;
-import org.hibernate.validation.constraints.impl.MinValidatorForNumber;
-import org.hibernate.validation.constraints.impl.MinValidatorForString;
-import org.hibernate.validation.constraints.impl.NotNullValidator;
-import org.hibernate.validation.constraints.impl.NullValidator;
-import org.hibernate.validation.constraints.impl.PastValidatorForCalendar;
-import org.hibernate.validation.constraints.impl.PastValidatorForDate;
-import org.hibernate.validation.constraints.impl.PatternValidator;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArray;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfBoolean;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfByte;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfChar;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfDouble;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfFloat;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfInt;
-import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfLong;
-import org.hibernate.validation.constraints.impl.SizeValidatorForCollection;
-import org.hibernate.validation.constraints.impl.SizeValidatorForMap;
-import org.hibernate.validation.constraints.impl.SizeValidatorForString;
-import org.hibernate.validation.util.ReflectionHelper;
-
-/**
- * Keeps track of builtin constraints and their validator implementations, as well as
already resolved validator definitions.
- *
- * @author Hardy Ferentschik
- * @author Alaa Nassef
- */
-public class ConstraintHelper {
-
- private final static Map<Class<? extends Annotation>, List<Class<?
extends ConstraintValidator<?, ?>>>> builtinConstraints =
- new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<?, ?>>>>();
-
- static {
- List<Class<? extends ConstraintValidator<?, ?>>> constraintList =
- new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
- constraintList.add( AssertFalseValidator.class );
- builtinConstraints.put( AssertFalse.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( AssertTrueValidator.class );
- builtinConstraints.put( AssertTrue.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( DecimalMaxValidatorForNumber.class );
- constraintList.add( DecimalMaxValidatorForString.class );
- builtinConstraints.put( DecimalMax.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( DecimalMinValidatorForNumber.class );
- constraintList.add( DecimalMinValidatorForString.class );
- builtinConstraints.put( DecimalMin.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( DigitsValidatorForString.class );
- constraintList.add( DigitsValidatorForNumber.class );
- builtinConstraints.put( Digits.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( FutureValidatorForCalendar.class );
- constraintList.add( FutureValidatorForDate.class );
- builtinConstraints.put( Future.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( MaxValidatorForNumber.class );
- constraintList.add( MaxValidatorForString.class );
- builtinConstraints.put( Max.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( MinValidatorForNumber.class );
- constraintList.add( MinValidatorForString.class );
- builtinConstraints.put( Min.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( NotNullValidator.class );
- builtinConstraints.put( NotNull.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( NullValidator.class );
- builtinConstraints.put( Null.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( PastValidatorForCalendar.class );
- constraintList.add( PastValidatorForDate.class );
- builtinConstraints.put( Past.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( PatternValidator.class );
- builtinConstraints.put( Pattern.class, constraintList );
-
- constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
- constraintList.add( SizeValidatorForString.class );
- constraintList.add( SizeValidatorForCollection.class );
- constraintList.add( SizeValidatorForArray.class );
- constraintList.add( SizeValidatorForMap.class );
- constraintList.add( SizeValidatorForArraysOfBoolean.class );
- constraintList.add( SizeValidatorForArraysOfByte.class );
- constraintList.add( SizeValidatorForArraysOfChar.class );
- constraintList.add( SizeValidatorForArraysOfDouble.class );
- constraintList.add( SizeValidatorForArraysOfFloat.class );
- constraintList.add( SizeValidatorForArraysOfInt.class );
- constraintList.add( SizeValidatorForArraysOfLong.class );
- builtinConstraints.put( Size.class, constraintList );
- }
-
- private final Map<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<? extends Annotation, ?>>>>
constraintValidatorDefinitons =
- new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<? extends Annotation, ?>>>>();
-
- public List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> getBuiltInConstraints(Class<? extends Annotation> annotationType) {
- final List<Class<? extends ConstraintValidator<?, ?>>> builtInList =
getBuiltInFromAnnotationType(
- annotationType
- );
-
- if ( builtInList == null || builtInList.size() == 0 ) {
- throw new ValidationException( "Unable to find constraints for " +
annotationType );
- }
- List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraints =
- new ArrayList<Class<? extends ConstraintValidator<? extends Annotation,
?>>>( builtInList.size() );
- for ( Class<? extends ConstraintValidator<?, ?>> validatorClass :
builtInList ) {
- //safe cause all CV for a given annotation A are CV<A, ?>
- @SuppressWarnings("unchecked")
- Class<ConstraintValidator<? extends Annotation, ?>> safeValdiatorClass = (
Class<ConstraintValidator<? extends Annotation, ?>> ) validatorClass;
- constraints.add( safeValdiatorClass );
- }
-
- return constraints;
- }
-
- private List<Class<? extends ConstraintValidator<?, ?>>>
getBuiltInFromAnnotationType(Class<? extends Annotation> annotationType) {
- return builtinConstraints.get( annotationType );
- }
-
- public boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {
- return builtinConstraints.containsKey( annotationType );
- }
-
- /**
- * Checks whether a given annotation is a multi value constraint or not.
- *
- * @param annotation the annotation to check.
- *
- * @return <code>true</code> if the specified annotation is a multi value
constraints, <code>false</code>
- * otherwise.
- */
- public boolean isMultiValueConstraint(Annotation annotation) {
- boolean isMultiValueConstraint = false;
- try {
- Method m = annotation.getClass().getMethod( "value" );
- Class returnType = m.getReturnType();
- if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
- Annotation[] annotations = ( Annotation[] ) m.invoke( annotation );
- for ( Annotation a : annotations ) {
- if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) {
- isMultiValueConstraint = true;
- }
- else {
- isMultiValueConstraint = false;
- break;
- }
- }
- }
- }
- catch ( NoSuchMethodException nsme ) {
- // ignore
- }
- catch ( IllegalAccessException iae ) {
- // ignore
- }
- catch ( InvocationTargetException ite ) {
- // ignore
- }
- return isMultiValueConstraint;
- }
-
-
- /**
- * Checks whether a given annotation is a multi value constraint and returns the
contained constraints if so.
- *
- * @param annotation the annotation to check.
- *
- * @return A list of constraint annotations or the empty list if
<code>annotation</code> is not a multi constraint
- * annotation.
- */
- public <A extends Annotation> List<Annotation> getMultiValueConstraints(A
annotation) {
- List<Annotation> annotationList = new ArrayList<Annotation>();
- try {
- Method m = annotation.getClass().getMethod( "value" );
- Class returnType = m.getReturnType();
- if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
- Annotation[] annotations = ( Annotation[] ) m.invoke( annotation );
- for ( Annotation a : annotations ) {
- if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) {
- annotationList.add( a );
- }
- }
- }
- }
- catch ( NoSuchMethodException nsme ) {
- // ignore
- }
- catch ( IllegalAccessException iae ) {
- // ignore
- }
- catch ( InvocationTargetException ite ) {
- // ignore
- }
- return annotationList;
- }
-
- /**
- * Checks whether the specified annotation is a valid constraint annotation. A
constraint annotations has to
- * fulfill the following conditions:
- * <ul>
- * <li>Has to contain a <code>ConstraintValidator</code>
implementation.</li>
- * <li>Defines a message parameter.</li>
- * <li>Defines a group parameter.</li>
- * </ul>
- *
- * @param annotation The annotation to test.
- *
- * @return <code>true</code> if the annotation fulfills the above condtions,
<code>false</code> otherwise.
- */
- public boolean isConstraintAnnotation(Annotation annotation) {
-
- Constraint constraint = annotation.annotationType()
- .getAnnotation( Constraint.class );
- if ( constraint == null ) {
- return false;
- }
-
- try {
- ReflectionHelper.getAnnotationParameter( annotation, "message", String.class
);
- }
- catch ( Exception e ) {
- String msg = annotation.annotationType().getName() + " contains Constraint
annotation, but does " +
- "not contain a message parameter.";
- throw new ConstraintDefinitionException( msg );
- }
-
- try {
- Class<?>[] defaultGroups = ( Class<?>[] ) annotation.annotationType()
- .getMethod( "groups" )
- .getDefaultValue();
- if ( defaultGroups.length != 0 ) {
- String msg = annotation.annotationType()
- .getName() + " contains Constraint annotation, but the groups " +
- "paramter default value is not empty.";
- throw new ConstraintDefinitionException( msg );
- }
- }
- catch ( NoSuchMethodException nsme ) {
- String msg = annotation.annotationType().getName() + " contains Constraint
annotation, but does " +
- "not contain a groups parameter.";
- throw new ConstraintDefinitionException( msg );
- }
-
- Method[] methods = annotation.getClass().getMethods();
- for ( Method m : methods ) {
- if ( m.getName().startsWith( "valid" ) ) {
- String msg = "Parameters starting with 'valid' are not allowed in a
constraint.";
- throw new ConstraintDefinitionException( msg );
- }
- }
- return true;
- }
-
- public List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> getConstraintValidatorDefinition(Class<? extends Annotation>
annotationClass) {
- if ( annotationClass == null ) {
- throw new IllegalArgumentException( "Class cannot be null" );
- }
- return constraintValidatorDefinitons.get( annotationClass );
- }
-
- public <A extends Annotation> void addConstraintValidatorDefinition(Class<A>
annotationClass, List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> definitionClasses) {
- constraintValidatorDefinitons.put( annotationClass, definitionClasses );
- }
-
- public boolean containsConstraintValidatorDefinition(Class<? extends Annotation>
annotationClass) {
- return constraintValidatorDefinitons.containsKey( annotationClass );
- }
-}
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintTree.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -36,6 +36,8 @@
import org.hibernate.validation.util.LoggerFactory;
import org.hibernate.validation.util.ValidatorTypeHelper;
+import org.hibernate.validation.engine.ExecutionContext;
+import org.hibernate.validation.engine.ConstraintValidatorContextImpl;
/**
* Due to constraint conposition a single constraint annotation can lead to a whole
constraint tree beeing validated.
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,64 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.metadata.ElementDescriptor;
-
-/**
- * Describe a validated element (class, field or property).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class ElementDescriptorImpl implements ElementDescriptor {
- private final Class<?> type;
- private final Set<ConstraintDescriptor<?>> constraintDescriptors = new
HashSet<ConstraintDescriptor<?>>();
-
- public ElementDescriptorImpl(Class<?> type) {
- this.type = type;
- }
-
- public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) {
- constraintDescriptors.add( constraintDescriptor );
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean hasConstraints() {
- return constraintDescriptors.size() != 0;
- }
-
- /**
- * {@inheritDoc}
- */
- public Class<?> getType() {
- return type;
- }
-
- /**
- * {@inheritDoc}
- */
- public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
- return Collections.unmodifiableSet( constraintDescriptors );
- }
-}
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ExecutionContext.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -35,6 +35,7 @@
import javax.validation.TraversableResolver;
import org.hibernate.validation.util.IdentitySet;
+import org.hibernate.validation.metadata.MetaConstraint;
/**
* Context object keeping track of all processed objects and failing constraints.
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,176 +0,0 @@
-// $Id$// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import javax.validation.metadata.ConstraintDescriptor;
-import javax.validation.ConstraintViolation;
-
-import org.hibernate.validation.util.ReflectionHelper;
-
-/**
- * Instances of this class abstract the constraint type (class, method or field
constraint) and gives access to
- * meta data about the constraint. This allows a unified handling of constraints in the
validator imlpementation.
- *
- * @author Hardy Ferentschik
- */
-public class MetaConstraint<T, A extends Annotation> {
-
- /**
- * The constraint tree created from the constraint annotation.
- */
- private final ConstraintTree<A> constraintTree;
-
- /**
- * The member the constraint was defined on.
- */
- private final Member member;
-
- /**
- * The JavaBeans name for this constraint.
- */
- private final String propertyName;
-
- /**
- * Describes on which level (<code>TYPE</code>,
<code>METHOD</code>, <code>FIELD</code>) the constraint was
- * defined on.
- */
- private final ElementType elementType;
-
- /**
- * The class of the bean hosting this constraint.
- */
- private final Class<T> beanClass;
-
- public MetaConstraint(Class<T> beanClass, ConstraintDescriptor<A>
constraintDescriptor) {
- this.elementType = ElementType.TYPE;
- this.member = null;
- this.propertyName = "";
- this.beanClass = beanClass;
- constraintTree = new ConstraintTree<A>( constraintDescriptor );
- }
-
- public MetaConstraint(Member member, Class<T> beanClass,
ConstraintDescriptor<A> constraintDescriptor) {
- if ( member instanceof Method ) {
- this.elementType = ElementType.METHOD;
- }
- else if ( member instanceof Field ) {
- this.elementType = ElementType.FIELD;
- }
- else {
- throw new IllegalArgumentException( "Non allowed member type: " + member );
- }
- this.member = member;
- this.propertyName = ReflectionHelper.getPropertyName( member );
- this.beanClass = beanClass;
- constraintTree = new ConstraintTree<A>( constraintDescriptor );
- }
-
-
- /**
- * @return Returns the list of groups this constraint is part of. This might include the
default group even when
- * it is not explicitly specified, but part of the redefined default group list
of the hosting bean.
- */
- public Set<Class<?>> getGroupList() {
- return constraintTree.getDescriptor().getGroups();
- }
-
- public ConstraintDescriptor getDescriptor() {
- return constraintTree.getDescriptor();
- }
-
- public Class<T> getBeanClass() {
- return beanClass;
- }
-
- public String getPropertyName() {
- return propertyName;
- }
-
- public ElementType getElementType() {
- return elementType;
- }
-
- public ConstraintTree getConstraintTree() {
- return constraintTree;
- }
-
- public <T> boolean validateConstraint(ExecutionContext<T> executionContext)
{
- final Object leafBeanInstance = executionContext.peekCurrentBean();
- Object value = getValue( leafBeanInstance );
- List<ConstraintViolation<T>> constraintViolations = new
ArrayList<ConstraintViolation<T>>();
- constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext,
constraintViolations );
- if ( constraintViolations.size() > 0 ) {
- executionContext.addConstraintFailures( constraintViolations );
- return false;
- }
- return true;
- }
-
- public <T> boolean validateConstraint(Object value, ExecutionContext<T>
executionContext) {
- List<ConstraintViolation<T>> constraintViolations = new
ArrayList<ConstraintViolation<T>>();
- constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext,
constraintViolations );
- if ( constraintViolations.size() > 0 ) {
- executionContext.addConstraintFailures( constraintViolations );
- return false;
- }
- return true;
- }
-
- private Type typeOfAnnoatedElement() {
- Type t;
- switch ( elementType ) {
- case TYPE: {
- t = beanClass;
- break;
- }
- default: {
- t = ReflectionHelper.typeOf( member );
- if ( t instanceof Class && ((Class) t).isPrimitive()) {
- t = ReflectionHelper.boxedTyp( t );
- }
- }
- }
- return t;
- }
-
- /**
- * @param o the object from which to retrieve the value.
- *
- * @return Returns the value for this constraint from the specified object. Depending on
the type either the value itself
- * is returned of method or field access is used to access the value.
- */
- private Object getValue(Object o) {
- switch ( elementType ) {
- case TYPE: {
- return o;
- }
- default: {
- return ReflectionHelper.getValue( member, o );
- }
- }
- }
-}
Deleted:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -1,52 +0,0 @@
-// $Id$
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2008, Red Hat Middleware LLC, and individual contributors
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* 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 org.hibernate.validation.engine;
-
-import javax.validation.metadata.PropertyDescriptor;
-
-/**
- * Describe a validated element (class, field or property).
- *
- * @author Emmanuel Bernard
- * @author Hardy Ferentschik
- */
-public class PropertyDescriptorImpl extends ElementDescriptorImpl implements
PropertyDescriptor {
- private final boolean cascaded;
- private final String property;
-
-
- public PropertyDescriptorImpl(Class<?> returnType, boolean cascaded, String
property) {
- super( returnType );
- this.cascaded = cascaded;
- this.property = property;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isCascaded() {
- return cascaded;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getPropertyName() {
- return property;
- }
-}
\ No newline at end of file
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorContextImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -6,6 +6,9 @@
import javax.validation.Validator;
import javax.validation.ValidatorContext;
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.ConstraintHelper;
+
/**
* @author Emmanuel Bernard
* @author Hardy Ferentschik
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -30,8 +30,12 @@
import javax.validation.ValidationException;
import javax.validation.spi.ConfigurationState;
-import org.hibernate.validation.engine.xml.AnnotationIgnores;
-import org.hibernate.validation.engine.xml.XmlMappingParser;
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.xml.XmlMappingParser;
+import org.hibernate.validation.metadata.BeanMetaDataImpl;
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
/**
* Factory returning initialized <code>Validator</code> instances.
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -47,6 +47,11 @@
import org.hibernate.validation.util.LoggerFactory;
import org.hibernate.validation.util.PropertyPath;
import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.BeanMetaData;
+import org.hibernate.validation.metadata.BeanMetaDataImpl;
+import org.hibernate.validation.metadata.BeanMetaDataCache;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
/**
* The main Bean Validation class. This is the core processing class of Hibernate
Validator.
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/AnnotationIgnores.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,119 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+
+/**
+ * This class instantiated during the parsing of the XML configuration data and keeps
+ * track of the annotations which should be ignored.
+ *
+ * @author Hardy Ferentschik
+ */
+public class AnnotationIgnores {
+
+ private static final Logger log = LoggerFactory.make();
+
+ /**
+ * Keeps track whether the 'ignore-annotations' flag is set on bean level in the
xml configuration. If 'ignore-annotations'
+ * is not specified <code>false</code> is the default.
+ */
+ private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new
HashMap<Class<?>, Boolean>();
+
+ /**
+ * Keeps track of explicitly excluded members (fields and properties) for a given class.
If a member appears in
+ * the list mapped to a given class 'ignore-annotations' was explicitly set to
<code>true</code> in the configuration
+ * for this class.
+ */
+ private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember =
new HashMap<Class<?>, List<Member>>();
+
+ private final List<Class<?>> ignoreAnnotationOnClass = new
ArrayList<Class<?>>();
+
+ public void setDefaultIgnoreAnnotation(Class<?> clazz, Boolean b) {
+ if ( b == null ) {
+ ignoreAnnotationDefaults.put( clazz, Boolean.FALSE );
+ }
+ else {
+ ignoreAnnotationDefaults.put( clazz, b );
+ }
+ }
+
+ public boolean getDefaultIgnoreAnnotation(Class<?> clazz) {
+ return ignoreAnnotationDefaults.containsKey( clazz ) &&
ignoreAnnotationDefaults.get( clazz );
+ }
+
+ public void setIgnoreAnnotationsOnMember(Member member) {
+ Class<?> beanClass = member.getDeclaringClass();
+ if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
+ List<Member> tmpList = new ArrayList<Member>();
+ tmpList.add( member );
+ ignoreAnnotationOnMember.put( beanClass, tmpList );
+ }
+ else {
+ ignoreAnnotationOnMember.get( beanClass ).add( member );
+ }
+ }
+
+ public boolean isIgnoreAnnotations(Member member) {
+ boolean ignoreAnnotation;
+ Class<?> clazz = member.getDeclaringClass();
+ List<Member> ignoreAnnotationForMembers = ignoreAnnotationOnMember.get( clazz );
+ if ( ignoreAnnotationForMembers == null || !ignoreAnnotationForMembers.contains( member
) ) {
+ ignoreAnnotation = getDefaultIgnoreAnnotation( clazz );
+ }
+ else {
+ ignoreAnnotation = ignoreAnnotationForMembers.contains( member );
+ }
+ if ( ignoreAnnotation ) {
+ logMessage( member, clazz );
+ }
+ return ignoreAnnotation;
+ }
+
+ private void logMessage(Member member, Class<?> clazz) {
+ String type;
+ if ( member instanceof Field ) {
+ type = "Field";
+ }
+ else {
+ type = "Property";
+ }
+ log.debug( type + " level annotations are getting ignored for " +
clazz.getName() + "." + member.getName() );
+ }
+
+ public void setIgnoreAnnotationsOnClass(Class<?> clazz) {
+ ignoreAnnotationOnClass.add( clazz );
+ }
+
+ public boolean isIgnoreAnnotations(Class<?> clazz) {
+ boolean ignoreAnnotation = ignoreAnnotationOnClass.contains( clazz ) ||
getDefaultIgnoreAnnotation( clazz );
+ if ( log.isDebugEnabled() && ignoreAnnotation ) {
+ log.debug( "Class level annotation are getting ignored for " +
clazz.getName() );
+ }
+ return ignoreAnnotation;
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanDescriptorImpl.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,30 @@
+package org.hibernate.validation.metadata;
+
+import java.util.Set;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+/**
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class BeanDescriptorImpl<T> extends ElementDescriptorImpl implements
BeanDescriptor {
+ private final BeanMetaData<T> metadataBean;
+
+ public BeanDescriptorImpl(BeanMetaData<T> metadataBean) {
+ super( metadataBean.getBeanClass() );
+ this.metadataBean = metadataBean;
+ }
+
+ public boolean isBeanConstrained() {
+ return metadataBean.getConstrainedProperties().size() > 0;
+ }
+
+ public PropertyDescriptor getConstraintsForProperty(String propertyName) {
+ return metadataBean.getPropertyDescriptor( propertyName );
+ }
+
+ public Set<PropertyDescriptor> getConstrainedProperties() {
+ return metadataBean.getConstrainedProperties();
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,77 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.util.List;
+import java.util.Set;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.hibernate.validation.metadata.MetaConstraint;
+
+/**
+ * Interface defining the meta data about the constraints defined in a given bean.
+ *
+ * @author Hardy Ferentschik
+ */
+public interface BeanMetaData<T> {
+
+ /**
+ * @return the class of the bean.
+ */
+ Class<T> getBeanClass();
+
+ /**
+ * @return an instance of <code>ElementDescriptor</code> describing the bean
this meta data applies for.
+ */
+ BeanDescriptor getBeanDescriptor();
+
+ /**
+ * @return A list of all cascaded methods and fields (methods/fields annotated with
@Valid).
+ */
+ List<Member> getCascadedMembers();
+
+ /**
+ * @return A map mapping defined group sequences to a list of groups.
+ */
+ List<Class<?>> getDefaultGroupSequence();
+
+ /**
+ * @return A list of <code>MetaConstraint</code> instances encapsulating the
information of all the constraints
+ * defined on the bean.
+ */
+ List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList();
+
+ /**
+ * Return <code>PropertyDescriptor</code> for the given property.
+ *
+ * @param property the property for which to retrieve the descriptor.
+ *
+ * @return Returns the <code>PropertyDescriptor</code> for the given
property or <code>null</code> in case the
+ * property does not have a descriptor.
+ */
+ PropertyDescriptor getPropertyDescriptor(String property);
+
+ /**
+ * @return the property descriptors having at least one constraint defined or which are
marked
+ * as cascaded (@Valid).
+ */
+ Set<PropertyDescriptor> getConstrainedProperties();
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataCache.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,48 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Cache for created instances of <code>BeanMetaData</code>.
+ *
+ * @author Hardy Ferentschik
+ */
+public class BeanMetaDataCache {
+ /**
+ * A map for the meta data for each entity. The key is the class and the value the bean
meta data for this
+ * entity.
+ */
+ private Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders = new
ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>(
+ 10
+ );
+
+ @SuppressWarnings("unchecked")
+ public <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T> beanClass) {
+ if ( beanClass == null ) {
+ throw new IllegalArgumentException( "Class cannot be null" );
+ }
+ return ( BeanMetaDataImpl<T> ) metadataProviders.get( beanClass );
+ }
+
+ public <T> void addBeanMetaData(Class<T> beanClass,
BeanMetaDataImpl<T> metaData) {
+ metadataProviders.put( beanClass, metaData );
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,390 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.GroupSequence;
+import javax.validation.Valid;
+import javax.validation.ValidationException;
+import javax.validation.groups.Default;
+import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.MetaConstraint;
+
+
+/**
+ * This class encapsulates all meta data needed for validation. Implementations of {@code
Validator} interface can
+ * instantiate an instance of this class and delegate the metadata extraction to it.
+ *
+ * @author Hardy Ferentschik
+ */
+
+public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
+
+ private static final Logger log = LoggerFactory.make();
+
+ /**
+ * The root bean class for this validator.
+ */
+ private final Class<T> beanClass;
+
+ /**
+ * The main element descriptor for <code>beanClass</code>.
+ */
+ private BeanDescriptorImpl<T> beanDescriptor;
+
+ /**
+ * List of constraints.
+ */
+ private List<MetaConstraint<T, ? extends Annotation>> metaConstraintList =
new ArrayList<MetaConstraint<T, ? extends Annotation>>();
+
+ /**
+ * List of cascaded members.
+ */
+ private List<Member> cascadedMembers = new ArrayList<Member>();
+
+ /**
+ * Maps field and method names to their <code>ElementDescriptorImpl</code>.
+ */
+ private Map<String, PropertyDescriptor> propertyDescriptors = new
HashMap<String, PropertyDescriptor>();
+
+ /**
+ * Maps group sequences to the list of group/sequences.
+ */
+ private List<Class<?>> defaultGroupSequence = new
ArrayList<Class<?>>();
+
+ /**
+ * Object keeping track of all constraints.
+ */
+ private final ConstraintHelper constraintHelper;
+
+
+ public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
+ this(
+ beanClass,
+ constraintHelper,
+ new AnnotationIgnores()
+ );
+ }
+
+ public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper,
AnnotationIgnores annotationIgnores) {
+ this.beanClass = beanClass;
+ this.constraintHelper = constraintHelper;
+ createMetaData( annotationIgnores );
+ }
+
+ public Class<T> getBeanClass() {
+ return beanClass;
+ }
+
+ public BeanDescriptor getBeanDescriptor() {
+ return beanDescriptor;
+ }
+
+ public List<Member> getCascadedMembers() {
+ return Collections.unmodifiableList( cascadedMembers );
+ }
+
+ public List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList()
{
+ return Collections.unmodifiableList( metaConstraintList );
+ }
+
+ public void addMetaConstraint(MetaConstraint<T, ? extends Annotation>
metaConstraint) {
+ metaConstraintList.add( metaConstraint );
+ }
+
+ public void addCascadedMember(Member member) {
+ cascadedMembers.add( member );
+ }
+
+ public PropertyDescriptor getPropertyDescriptor(String property) {
+ return propertyDescriptors.get( property );
+ }
+
+ public List<Class<?>> getDefaultGroupSequence() {
+ return Collections.unmodifiableList( defaultGroupSequence );
+ }
+
+ public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
+ defaultGroupSequence = new ArrayList<Class<?>>();
+ for ( Class<?> group : groupSequence ) {
+ if ( group.getName().equals( beanClass.getName() ) ) {
+ defaultGroupSequence.add( Default.class );
+ }
+ else if ( group.getName().equals( Default.class.getName() ) ) {
+ throw new ValidationException( "'Default.class' cannot appear in default
group sequence list." );
+ }
+ else {
+ defaultGroupSequence.add( group );
+ }
+ }
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ "Members of the default group sequence for bean {} are: {}",
+ beanClass.getName(),
+ defaultGroupSequence
+ );
+ }
+ }
+
+ public Set<PropertyDescriptor> getConstrainedProperties() {
+ return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>(
propertyDescriptors.values() ) );
+ }
+
+ /**
+ * Create bean desciptor, find all classes/subclasses/interfaces which have to be taken
in consideration
+ * for this validator and create meta data.
+ *
+ * @param annotationIgnores Datastructure keeping track on which annotation should be
ignored.
+ */
+ private void createMetaData(AnnotationIgnores annotationIgnores) {
+ beanDescriptor = new BeanDescriptorImpl<T>( this );
+ initDefaultGroupSequence();
+ List<Class> classes = new ArrayList<Class>();
+ computeClassHierarchy( beanClass, classes );
+ for ( Class current : classes ) {
+ initClass( current, annotationIgnores );
+ }
+ }
+
+ /**
+ * Get all superclasses and interfaces recursively.
+ *
+ * @param clazz The class to start the search with.
+ * @param classes List of classes to which to add all found super classes and
interfaces.
+ */
+ private void computeClassHierarchy(Class clazz, List<Class> classes) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "Processing: {}", clazz );
+ }
+ for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
+ if ( classes.contains( current ) ) {
+ return;
+ }
+ classes.add( current );
+ for ( Class currentInterface : current.getInterfaces() ) {
+ computeClassHierarchy( currentInterface, classes );
+ }
+ }
+ }
+
+ private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
+ initClassConstraints( clazz, annotationIgnores );
+ initMethodConstraints( clazz, annotationIgnores );
+ initFieldConstraints( clazz, annotationIgnores );
+ }
+
+ /**
+ * Checks whether there is a default group sequence defined for this class.
+ * See HV-113.
+ */
+ private void initDefaultGroupSequence() {
+ List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+ GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class
);
+ if ( groupSequenceAnnotation == null ) {
+ groupSequence.add( beanClass );
+ }
+ else {
+ groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
+ }
+ setDefaultGroupSequence( groupSequence );
+ }
+
+ private void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
+ for ( Field field : clazz.getDeclaredFields() ) {
+ List<ConstraintDescriptorImpl<?>> fieldMetadata = findConstraints( field
);
+ for ( ConstraintDescriptorImpl<?> constraintDescription : fieldMetadata ) {
+ if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
+ break;
+ }
+ ReflectionHelper.setAccessibility( field );
+ MetaConstraint<T, ?> metaConstraint = createMetaConstraint( field,
constraintDescription );
+ metaConstraintList.add( metaConstraint );
+ }
+ if ( field.isAnnotationPresent( Valid.class ) ) {
+ ReflectionHelper.setAccessibility( field );
+ cascadedMembers.add( field );
+ addPropertyDescriptorForMember( field );
+ }
+ }
+ }
+
+ private void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
+ for ( Method method : clazz.getDeclaredMethods() ) {
+ List<ConstraintDescriptorImpl<?>> methodMetadata = findConstraints( method
);
+ for ( ConstraintDescriptorImpl<?> constraintDescription : methodMetadata ) {
+ if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
+ break;
+ }
+ ReflectionHelper.setAccessibility( method );
+ MetaConstraint<T, ?> metaConstraint = createMetaConstraint( method,
constraintDescription );
+ metaConstraintList.add( metaConstraint );
+ }
+ if ( method.isAnnotationPresent( Valid.class ) ) {
+ ReflectionHelper.setAccessibility( method );
+ cascadedMembers.add( method );
+ addPropertyDescriptorForMember( method );
+ }
+ }
+ }
+
+ private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
+ String name = ReflectionHelper.getPropertyName( member );
+ PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get(
+ name
+ );
+ if ( propertyDescriptor == null ) {
+ propertyDescriptor = new PropertyDescriptorImpl(
+ ReflectionHelper.getType( member ),
+ ( ( AnnotatedElement ) member ).isAnnotationPresent( Valid.class ),
+ name
+ );
+ propertyDescriptors.put( name, propertyDescriptor );
+ }
+ return propertyDescriptor;
+ }
+
+ private void initClassConstraints(Class<?> clazz, AnnotationIgnores
annotationIgnores) {
+ if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
+ return;
+ }
+ List<ConstraintDescriptorImpl<?>> classMetadata =
findClassLevelConstraints( clazz );
+ for ( ConstraintDescriptorImpl<?> constraintDescription : classMetadata ) {
+ MetaConstraint<T, ?> metaConstraint = createMetaConstraint(
constraintDescription );
+ metaConstraintList.add( metaConstraint );
+ }
+ }
+
+ private <A extends Annotation> MetaConstraint<T, ?>
createMetaConstraint(ConstraintDescriptorImpl<A> descriptor) {
+ return new MetaConstraint<T, A>( beanClass, descriptor );
+ }
+
+ private <A extends Annotation> MetaConstraint<T, ?>
createMetaConstraint(Member m, ConstraintDescriptorImpl<A> descriptor) {
+ return new MetaConstraint<T, A>( m, beanClass, descriptor );
+ }
+
+ /**
+ * Examines the given annotation to see whether it is a single or multi valued
constraint annotation.
+ *
+ * @param clazz the class we are currently processing.
+ * @param annotation The annotation to examine.
+ *
+ * @return A list of constraint descriptors or the empty list in case
<code>annotation</code> is neither a
+ * single nor multi value annotation.
+ */
+ private <A extends Annotation> List<ConstraintDescriptorImpl<?>>
findConstraintAnnotations(Class<?> clazz, A annotation) {
+ List<ConstraintDescriptorImpl<?>> constraintDescriptors = new
ArrayList<ConstraintDescriptorImpl<?>>();
+
+ List<Annotation> constraints = new ArrayList<Annotation>();
+ if ( constraintHelper.isConstraintAnnotation( annotation ) ||
+ constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
+ constraints.add( annotation );
+ }
+
+ // check if we have a multi value constraint
+ constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) );
+
+ for ( Annotation constraint : constraints ) {
+ final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
clazz, constraint );
+ constraintDescriptors.add( constraintDescriptor );
+ }
+ return constraintDescriptors;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <A extends Annotation> ConstraintDescriptorImpl
buildConstraintDescriptor(Class<?> clazz, A annotation) {
+ ConstraintDescriptorImpl constraintDescriptor;
+ if ( clazz.isInterface() ) {
+ constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper,
clazz );
+ }
+ else {
+ constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper );
+ }
+ return constraintDescriptor;
+ }
+
+ /**
+ * Finds all constraint annotations defined for the given class and returns them in a
list of
+ * constraint descriptors.
+ *
+ * @param beanClass The class to check for constraints annotations.
+ *
+ * @return A list of constraint descriptors for all constraint specified on the given
class.
+ */
+ private List<ConstraintDescriptorImpl<?>>
findClassLevelConstraints(Class<?> beanClass) {
+ List<ConstraintDescriptorImpl<?>> metadata = new
ArrayList<ConstraintDescriptorImpl<?>>();
+ for ( Annotation annotation : beanClass.getAnnotations() ) {
+ metadata.addAll( findConstraintAnnotations( beanClass, annotation ) );
+ }
+ for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+ beanDescriptor.addConstraintDescriptor( constraintDescriptor );
+ }
+ return metadata;
+ }
+
+
+ /**
+ * Finds all constraint annotations defined for the given field/method and returns them
in a list of
+ * constraint descriptors.
+ *
+ * @param member The fiels or method to check for constraints annotations.
+ *
+ * @return A list of constraint descriptors for all constraint specified for the given
field or method.
+ */
+ private List<ConstraintDescriptorImpl<?>> findConstraints(Member member) {
+ assert member instanceof Field || member instanceof Method;
+
+ List<ConstraintDescriptorImpl<?>> metadata = new
ArrayList<ConstraintDescriptorImpl<?>>();
+ for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) {
+ metadata.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation )
);
+ }
+
+ String name = ReflectionHelper.getPropertyName( member );
+ for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+ if ( member instanceof Method && name == null ) { // can happen if member is a
Method which does not follow the bean convention
+ throw new ValidationException(
+ "Annotated methods must follow the JavaBeans naming convention. " +
member.getName() + "() does not."
+ );
+ }
+ PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get( name );
+ if ( propertyDescriptor == null ) {
+ propertyDescriptor = addPropertyDescriptorForMember( member );
+ }
+ propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
+ }
+ return metadata;
+ }
+}
\ No newline at end of file
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,384 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintValidator;
+import javax.validation.OverridesAttribute;
+import javax.validation.ReportAsSingleViolation;
+import javax.validation.ValidationException;
+import javax.validation.groups.Default;
+import javax.validation.metadata.ConstraintDescriptor;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+
+/**
+ * Describe a single constraint (including it's composing constraints).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class ConstraintDescriptorImpl<T extends Annotation> implements
ConstraintDescriptor<T> {
+ private static final Logger log = LoggerFactory.make();
+ private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1;
+
+ /**
+ * The actual constraint annotation.
+ */
+ private final T annotation;
+
+ /**
+ * The set of classes implementing the validation for this constraint. See also
+ * <code>ConstraintValidator</code> resolution algorithm.
+ */
+ private final List<Class<? extends ConstraintValidator<T, ?>>>
constraintValidatorDefinitonClasses = new ArrayList<Class<? extends
ConstraintValidator<T, ?>>>();
+
+ /**
+ * The groups for which to apply this constraint.
+ */
+ private final Set<Class<?>> groups = new HashSet<Class<?>>();
+
+ /**
+ * The constraint parameters as map. The key is the paramter name and the value the
+ * parameter value as specified in the constraint.
+ */
+ private final Map<String, Object> attributes;
+
+ /**
+ * The composing constraints for this constraints.
+ */
+ private final Set<ConstraintDescriptor<?>> composingConstraints = new
HashSet<ConstraintDescriptor<?>>();
+
+ /**
+ * Flag indicating if in case of a composing constraint a single error or multiple
errors should be raised.
+ */
+ private final boolean isReportAsSingleInvalidConstraint;
+
+ /**
+ * Handle to the builtin constraint implementations.
+ */
+ private final ConstraintHelper constraintHelper;
+
+ public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper,
Class<?> implicitGroup) {
+ this( annotation, constraintHelper );
+ this.groups.add( implicitGroup );
+ }
+
+
+ public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper) {
+ this.annotation = annotation;
+ this.attributes = getAnnotationParameters( annotation );
+ this.constraintHelper = constraintHelper;
+
+ this.isReportAsSingleInvalidConstraint =
annotation.annotationType().isAnnotationPresent(
+ ReportAsSingleViolation.class
+ );
+
+ Class<?>[] groupsFromAnnotation = ReflectionHelper.getAnnotationParameter(
+ annotation, "groups", Class[].class
+ );
+ if ( groupsFromAnnotation.length == 0 ) {
+ groups.add( Default.class );
+ }
+ else {
+ this.groups.addAll( Arrays.asList( groupsFromAnnotation ) );
+ }
+
+ findConstraintValidatorClasses();
+ Map<ClassIndexWrapper, Map<String, Object>> overrideParameters =
parseOverrideParameters();
+ parseComposingConstraints( overrideParameters );
+ }
+
+ private void findConstraintValidatorClasses() {
+ if ( constraintHelper.containsConstraintValidatorDefinition(
annotation.annotationType() ) ) {
+ for ( Class<? extends ConstraintValidator<? extends Annotation, ?>>
validator : constraintHelper
+ .getConstraintValidatorDefinition( annotation.annotationType() ) ) {
+ constraintValidatorDefinitonClasses.add( ( Class<? extends
ConstraintValidator<T, ?>> ) validator );
+ }
+ return;
+ }
+
+ List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraintDefinitonClasses = new ArrayList<Class<? extends ConstraintValidator<?
extends Annotation, ?>>>();
+ if ( constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) {
+ constraintDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints(
annotation.annotationType() ) );
+ }
+ else {
+ final Class<? extends Annotation> annotationType = annotation.annotationType();
+ Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
+ .getAnnotation( Constraint.class )
+ .validatedBy();
+ constraintDefinitonClasses.addAll( Arrays.asList( validatedBy ) );
+ }
+
+ constraintHelper.addConstraintValidatorDefinition(
+ annotation.annotationType(), constraintDefinitonClasses
+ );
+
+ for ( Class<? extends ConstraintValidator<? extends Annotation, ?>>
validator : constraintDefinitonClasses ) {
+ @SuppressWarnings("unchecked")
+ Class<? extends ConstraintValidator<T, ?>> safeValidator = ( Class<?
extends ConstraintValidator<T, ?>> ) validator;
+ constraintValidatorDefinitonClasses.add( safeValidator );
+ }
+ }
+
+ public T getAnnotation() {
+ return annotation;
+ }
+
+ public Set<Class<?>> getGroups() {
+ return Collections.unmodifiableSet( groups );
+ }
+
+ public List<Class<? extends ConstraintValidator<T, ?>>>
getConstraintValidatorClasses() {
+ return Collections.unmodifiableList( constraintValidatorDefinitonClasses );
+ }
+
+ public Map<String, Object> getAttributes() {
+ return Collections.unmodifiableMap( attributes );
+ }
+
+ public Set<ConstraintDescriptor<?>> getComposingConstraints() {
+ return Collections.unmodifiableSet( composingConstraints );
+ }
+
+ public boolean isReportAsSingleViolation() {
+ return isReportAsSingleInvalidConstraint;
+ }
+
+ @Override
+ public String toString() {
+ return "ConstraintDescriptorImpl{" +
+ "annotation=" + annotation +
+ ", constraintValidatorDefinitonClasses=" +
constraintValidatorDefinitonClasses.toString() +
+ ", groups=" + groups +
+ ", attributes=" + attributes +
+ ", composingConstraints=" + composingConstraints +
+ ", isReportAsSingleInvalidConstraint=" + isReportAsSingleInvalidConstraint
+
+ '}';
+ }
+
+ private Map<String, Object> getAnnotationParameters(Annotation annotation) {
+ Method[] declaredMethods = annotation.annotationType().getDeclaredMethods();
+ Map<String, Object> parameters = new HashMap<String, Object>(
declaredMethods.length );
+ for ( Method m : declaredMethods ) {
+ try {
+ parameters.put( m.getName(), m.invoke( annotation ) );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new ValidationException( "Unable to read annotation attributes: " +
annotation.getClass(), e );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new ValidationException( "Unable to read annotation attributes: " +
annotation.getClass(), e );
+ }
+ }
+ return Collections.unmodifiableMap( parameters );
+ }
+
+ private Object getMethodValue(Annotation annotation, Method m) {
+ Object value;
+ try {
+ value = m.invoke( annotation );
+ }
+ // should never happen
+ catch ( IllegalAccessException e ) {
+ throw new ValidationException( "Unable to retrieve annotation parameter
value." );
+ }
+ catch ( InvocationTargetException e ) {
+ throw new ValidationException( "Unable to retrieve annotation parameter
value." );
+ }
+ return value;
+ }
+
+ private Map<ClassIndexWrapper, Map<String, Object>>
parseOverrideParameters() {
+ Map<ClassIndexWrapper, Map<String, Object>> overrideParameters = new
HashMap<ClassIndexWrapper, Map<String, Object>>();
+ for ( Method m : annotation.annotationType().getMethods() ) {
+ if ( m.getAnnotation( OverridesAttribute.class ) != null ) {
+ addOverrideAttributes(
+ overrideParameters, m, m.getAnnotation( OverridesAttribute.class )
+ );
+ }
+ else if ( m.getAnnotation( OverridesAttribute.List.class ) != null ) {
+ addOverrideAttributes(
+ overrideParameters,
+ m,
+ m.getAnnotation( OverridesAttribute.List.class ).value()
+ );
+ }
+ }
+ return overrideParameters;
+ }
+
+ private void addOverrideAttributes(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters, Method m, OverridesAttribute... attributes) {
+
+ Object value = getMethodValue( annotation, m );
+ for ( OverridesAttribute overridesAttribute : attributes ) {
+ ensureAttributeIsOverridable( m, overridesAttribute );
+
+ ClassIndexWrapper wrapper = new ClassIndexWrapper(
+ overridesAttribute.constraint(), overridesAttribute.constraintIndex()
+ );
+ Map<String, Object> map = overrideParameters.get( wrapper );
+ if ( map == null ) {
+ map = new HashMap<String, Object>();
+ overrideParameters.put( wrapper, map );
+ }
+ map.put( overridesAttribute.name(), value );
+ }
+ }
+
+ private void ensureAttributeIsOverridable(Method m, OverridesAttribute
overridesAttribute) {
+ try {
+ Class<?> returnTypeOfOverridenConstraint = overridesAttribute.constraint()
+ .getMethod( overridesAttribute.name() )
+ .getReturnType();
+ if ( !returnTypeOfOverridenConstraint.equals( m.getReturnType() ) ) {
+ String message = "The overiding type of a composite constraint must be identical
to the overwridden one. Expected " + returnTypeOfOverridenConstraint
+ .getName() + " found " + m.getReturnType();
+ throw new ConstraintDefinitionException( message );
+ }
+ }
+ catch ( NoSuchMethodException nsme ) {
+ throw new ConstraintDefinitionException(
+ "Overriden constraint does not define an attribute with name " +
overridesAttribute.name()
+ );
+ }
+ }
+
+ private void parseComposingConstraints(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters) {
+ for ( Annotation declaredAnnotation :
annotation.annotationType().getDeclaredAnnotations() ) {
+ if ( constraintHelper.isConstraintAnnotation( declaredAnnotation )
+ || constraintHelper.isBuiltinConstraint( declaredAnnotation.annotationType() ) ) {
+ ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
+ declaredAnnotation, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX
+ );
+ composingConstraints.add( descriptor );
+ log.debug( "Adding composing constraint: " + descriptor );
+ }
+ else if ( constraintHelper.isMultiValueConstraint( declaredAnnotation ) ) {
+ List<Annotation> multiValueConstraints =
constraintHelper.getMultiValueConstraints( declaredAnnotation );
+ int index = 1;
+ for ( Annotation constraintAnnotation : multiValueConstraints ) {
+ ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
+ constraintAnnotation, overrideParameters, index
+ );
+ composingConstraints.add( descriptor );
+ log.debug( "Adding composing constraint: " + descriptor );
+ index++;
+ }
+ }
+ }
+ }
+
+ private <U extends Annotation> ConstraintDescriptorImpl<U>
createComposingConstraintDescriptor(U declaredAnnotation, Map<ClassIndexWrapper,
Map<String, Object>> overrideParameters, int index) {
+ //TODO don't quite understand this warning
+ //TODO assuming U.getClass() returns Class<U>
+ @SuppressWarnings("unchecked")
+ final Class<U> annotationType = ( Class<U> )
declaredAnnotation.annotationType();
+ return createComposingConstraintDescriptor(
+ overrideParameters,
+ index,
+ declaredAnnotation,
+ annotationType
+ );
+ }
+
+ private <U extends Annotation> ConstraintDescriptorImpl<U>
createComposingConstraintDescriptor(Map<ClassIndexWrapper, Map<String,
Object>> overrideParameters, int index, U constraintAnnotation, Class<U>
annotationType) {
+ // use a annotation proxy
+ AnnotationDescriptor<U> annotationDescriptor = new
AnnotationDescriptor<U>(
+ annotationType, getAnnotationParameters( constraintAnnotation )
+ );
+
+ // get the right override parameters
+ Map<String, Object> overrides = overrideParameters.get(
+ new ClassIndexWrapper(
+ annotationType, index
+ )
+ );
+ if ( overrides != null ) {
+ for ( Map.Entry<String, Object> entry : overrides.entrySet() ) {
+ annotationDescriptor.setValue( entry.getKey(), entry.getValue() );
+ }
+ }
+
+ // groups get inherited from the parent
+ annotationDescriptor.setValue( "groups", groups.toArray( new Class<?>[]
{ } ) );
+
+ U annotationProxy = AnnotationFactory.create( annotationDescriptor );
+ return new ConstraintDescriptorImpl<U>(
+ annotationProxy, constraintHelper
+ );
+ }
+
+ /**
+ * A wrapper class to keep track for which compposing constraints (class and index) a
given attribute override applies to.
+ */
+ private class ClassIndexWrapper {
+ final Class<?> clazz;
+ final int index;
+
+ ClassIndexWrapper(Class<?> clazz, int index) {
+ this.clazz = clazz;
+ this.index = index;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ( this == o ) {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() ) {
+ return false;
+ }
+
+ ClassIndexWrapper that = ( ClassIndexWrapper ) o;
+
+ if ( index != that.index ) {
+ return false;
+ }
+ if ( clazz != null ? !clazz.equals( that.clazz ) : that.clazz != null ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = clazz != null ? clazz.hashCode() : 0;
+ result = 31 * result + index;
+ return result;
+ }
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintHelper.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ConstraintHelper.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,335 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintValidator;
+import javax.validation.ValidationException;
+import javax.validation.constraints.AssertFalse;
+import javax.validation.constraints.AssertTrue;
+import javax.validation.constraints.DecimalMax;
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.Digits;
+import javax.validation.constraints.Future;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Null;
+import javax.validation.constraints.Past;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+import org.hibernate.validation.constraints.impl.AssertFalseValidator;
+import org.hibernate.validation.constraints.impl.AssertTrueValidator;
+import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DecimalMaxValidatorForString;
+import org.hibernate.validation.constraints.impl.DecimalMinValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DecimalMinValidatorForString;
+import org.hibernate.validation.constraints.impl.DigitsValidatorForNumber;
+import org.hibernate.validation.constraints.impl.DigitsValidatorForString;
+import org.hibernate.validation.constraints.impl.FutureValidatorForCalendar;
+import org.hibernate.validation.constraints.impl.FutureValidatorForDate;
+import org.hibernate.validation.constraints.impl.MaxValidatorForNumber;
+import org.hibernate.validation.constraints.impl.MaxValidatorForString;
+import org.hibernate.validation.constraints.impl.MinValidatorForNumber;
+import org.hibernate.validation.constraints.impl.MinValidatorForString;
+import org.hibernate.validation.constraints.impl.NotNullValidator;
+import org.hibernate.validation.constraints.impl.NullValidator;
+import org.hibernate.validation.constraints.impl.PastValidatorForCalendar;
+import org.hibernate.validation.constraints.impl.PastValidatorForDate;
+import org.hibernate.validation.constraints.impl.PatternValidator;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArray;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfBoolean;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfByte;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfChar;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfDouble;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfFloat;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfInt;
+import org.hibernate.validation.constraints.impl.SizeValidatorForArraysOfLong;
+import org.hibernate.validation.constraints.impl.SizeValidatorForCollection;
+import org.hibernate.validation.constraints.impl.SizeValidatorForMap;
+import org.hibernate.validation.constraints.impl.SizeValidatorForString;
+import org.hibernate.validation.util.ReflectionHelper;
+
+/**
+ * Keeps track of builtin constraints and their validator implementations, as well as
already resolved validator definitions.
+ *
+ * @author Hardy Ferentschik
+ * @author Alaa Nassef
+ */
+public class ConstraintHelper {
+
+ private final static Map<Class<? extends Annotation>, List<Class<?
extends ConstraintValidator<?, ?>>>> builtinConstraints =
+ new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<?, ?>>>>();
+
+ static {
+ List<Class<? extends ConstraintValidator<?, ?>>> constraintList =
+ new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
+ constraintList.add( AssertFalseValidator.class );
+ builtinConstraints.put( AssertFalse.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( AssertTrueValidator.class );
+ builtinConstraints.put( AssertTrue.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( DecimalMaxValidatorForNumber.class );
+ constraintList.add( DecimalMaxValidatorForString.class );
+ builtinConstraints.put( DecimalMax.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( DecimalMinValidatorForNumber.class );
+ constraintList.add( DecimalMinValidatorForString.class );
+ builtinConstraints.put( DecimalMin.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( DigitsValidatorForString.class );
+ constraintList.add( DigitsValidatorForNumber.class );
+ builtinConstraints.put( Digits.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( FutureValidatorForCalendar.class );
+ constraintList.add( FutureValidatorForDate.class );
+ builtinConstraints.put( Future.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( MaxValidatorForNumber.class );
+ constraintList.add( MaxValidatorForString.class );
+ builtinConstraints.put( Max.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( MinValidatorForNumber.class );
+ constraintList.add( MinValidatorForString.class );
+ builtinConstraints.put( Min.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( NotNullValidator.class );
+ builtinConstraints.put( NotNull.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( NullValidator.class );
+ builtinConstraints.put( Null.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( PastValidatorForCalendar.class );
+ constraintList.add( PastValidatorForDate.class );
+ builtinConstraints.put( Past.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( PatternValidator.class );
+ builtinConstraints.put( Pattern.class, constraintList );
+
+ constraintList = new ArrayList<Class<? extends ConstraintValidator<?,
?>>>();
+ constraintList.add( SizeValidatorForString.class );
+ constraintList.add( SizeValidatorForCollection.class );
+ constraintList.add( SizeValidatorForArray.class );
+ constraintList.add( SizeValidatorForMap.class );
+ constraintList.add( SizeValidatorForArraysOfBoolean.class );
+ constraintList.add( SizeValidatorForArraysOfByte.class );
+ constraintList.add( SizeValidatorForArraysOfChar.class );
+ constraintList.add( SizeValidatorForArraysOfDouble.class );
+ constraintList.add( SizeValidatorForArraysOfFloat.class );
+ constraintList.add( SizeValidatorForArraysOfInt.class );
+ constraintList.add( SizeValidatorForArraysOfLong.class );
+ builtinConstraints.put( Size.class, constraintList );
+ }
+
+ private final Map<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<? extends Annotation, ?>>>>
constraintValidatorDefinitons =
+ new ConcurrentHashMap<Class<? extends Annotation>, List<Class<? extends
ConstraintValidator<? extends Annotation, ?>>>>();
+
+ public List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> getBuiltInConstraints(Class<? extends Annotation> annotationType) {
+ final List<Class<? extends ConstraintValidator<?, ?>>> builtInList =
getBuiltInFromAnnotationType(
+ annotationType
+ );
+
+ if ( builtInList == null || builtInList.size() == 0 ) {
+ throw new ValidationException( "Unable to find constraints for " +
annotationType );
+ }
+ List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraints =
+ new ArrayList<Class<? extends ConstraintValidator<? extends Annotation,
?>>>( builtInList.size() );
+ for ( Class<? extends ConstraintValidator<?, ?>> validatorClass :
builtInList ) {
+ //safe cause all CV for a given annotation A are CV<A, ?>
+ @SuppressWarnings("unchecked")
+ Class<ConstraintValidator<? extends Annotation, ?>> safeValdiatorClass = (
Class<ConstraintValidator<? extends Annotation, ?>> ) validatorClass;
+ constraints.add( safeValdiatorClass );
+ }
+
+ return constraints;
+ }
+
+ private List<Class<? extends ConstraintValidator<?, ?>>>
getBuiltInFromAnnotationType(Class<? extends Annotation> annotationType) {
+ return builtinConstraints.get( annotationType );
+ }
+
+ public boolean isBuiltinConstraint(Class<? extends Annotation> annotationType) {
+ return builtinConstraints.containsKey( annotationType );
+ }
+
+ /**
+ * Checks whether a given annotation is a multi value constraint or not.
+ *
+ * @param annotation the annotation to check.
+ *
+ * @return <code>true</code> if the specified annotation is a multi value
constraints, <code>false</code>
+ * otherwise.
+ */
+ public boolean isMultiValueConstraint(Annotation annotation) {
+ boolean isMultiValueConstraint = false;
+ try {
+ Method m = annotation.getClass().getMethod( "value" );
+ Class returnType = m.getReturnType();
+ if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
+ Annotation[] annotations = ( Annotation[] ) m.invoke( annotation );
+ for ( Annotation a : annotations ) {
+ if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) {
+ isMultiValueConstraint = true;
+ }
+ else {
+ isMultiValueConstraint = false;
+ break;
+ }
+ }
+ }
+ }
+ catch ( NoSuchMethodException nsme ) {
+ // ignore
+ }
+ catch ( IllegalAccessException iae ) {
+ // ignore
+ }
+ catch ( InvocationTargetException ite ) {
+ // ignore
+ }
+ return isMultiValueConstraint;
+ }
+
+
+ /**
+ * Checks whether a given annotation is a multi value constraint and returns the
contained constraints if so.
+ *
+ * @param annotation the annotation to check.
+ *
+ * @return A list of constraint annotations or the empty list if
<code>annotation</code> is not a multi constraint
+ * annotation.
+ */
+ public <A extends Annotation> List<Annotation> getMultiValueConstraints(A
annotation) {
+ List<Annotation> annotationList = new ArrayList<Annotation>();
+ try {
+ Method m = annotation.getClass().getMethod( "value" );
+ Class returnType = m.getReturnType();
+ if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
+ Annotation[] annotations = ( Annotation[] ) m.invoke( annotation );
+ for ( Annotation a : annotations ) {
+ if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) {
+ annotationList.add( a );
+ }
+ }
+ }
+ }
+ catch ( NoSuchMethodException nsme ) {
+ // ignore
+ }
+ catch ( IllegalAccessException iae ) {
+ // ignore
+ }
+ catch ( InvocationTargetException ite ) {
+ // ignore
+ }
+ return annotationList;
+ }
+
+ /**
+ * Checks whether the specified annotation is a valid constraint annotation. A
constraint annotations has to
+ * fulfill the following conditions:
+ * <ul>
+ * <li>Has to contain a <code>ConstraintValidator</code>
implementation.</li>
+ * <li>Defines a message parameter.</li>
+ * <li>Defines a group parameter.</li>
+ * </ul>
+ *
+ * @param annotation The annotation to test.
+ *
+ * @return <code>true</code> if the annotation fulfills the above condtions,
<code>false</code> otherwise.
+ */
+ public boolean isConstraintAnnotation(Annotation annotation) {
+
+ Constraint constraint = annotation.annotationType()
+ .getAnnotation( Constraint.class );
+ if ( constraint == null ) {
+ return false;
+ }
+
+ try {
+ ReflectionHelper.getAnnotationParameter( annotation, "message", String.class
);
+ }
+ catch ( Exception e ) {
+ String msg = annotation.annotationType().getName() + " contains Constraint
annotation, but does " +
+ "not contain a message parameter.";
+ throw new ConstraintDefinitionException( msg );
+ }
+
+ try {
+ Class<?>[] defaultGroups = ( Class<?>[] ) annotation.annotationType()
+ .getMethod( "groups" )
+ .getDefaultValue();
+ if ( defaultGroups.length != 0 ) {
+ String msg = annotation.annotationType()
+ .getName() + " contains Constraint annotation, but the groups " +
+ "paramter default value is not empty.";
+ throw new ConstraintDefinitionException( msg );
+ }
+ }
+ catch ( NoSuchMethodException nsme ) {
+ String msg = annotation.annotationType().getName() + " contains Constraint
annotation, but does " +
+ "not contain a groups parameter.";
+ throw new ConstraintDefinitionException( msg );
+ }
+
+ Method[] methods = annotation.getClass().getMethods();
+ for ( Method m : methods ) {
+ if ( m.getName().startsWith( "valid" ) ) {
+ String msg = "Parameters starting with 'valid' are not allowed in a
constraint.";
+ throw new ConstraintDefinitionException( msg );
+ }
+ }
+ return true;
+ }
+
+ public List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> getConstraintValidatorDefinition(Class<? extends Annotation>
annotationClass) {
+ if ( annotationClass == null ) {
+ throw new IllegalArgumentException( "Class cannot be null" );
+ }
+ return constraintValidatorDefinitons.get( annotationClass );
+ }
+
+ public <A extends Annotation> void addConstraintValidatorDefinition(Class<A>
annotationClass, List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> definitionClasses) {
+ constraintValidatorDefinitons.put( annotationClass, definitionClasses );
+ }
+
+ public boolean containsConstraintValidatorDefinition(Class<? extends Annotation>
annotationClass) {
+ return constraintValidatorDefinitons.containsKey( annotationClass );
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ElementDescriptorImpl.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,64 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+
+/**
+ * Describe a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class ElementDescriptorImpl implements ElementDescriptor {
+ private final Class<?> type;
+ private final Set<ConstraintDescriptor<?>> constraintDescriptors = new
HashSet<ConstraintDescriptor<?>>();
+
+ public ElementDescriptorImpl(Class<?> type) {
+ this.type = type;
+ }
+
+ public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) {
+ constraintDescriptors.add( constraintDescriptor );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasConstraints() {
+ return constraintDescriptors.size() != 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class<?> getType() {
+ return type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
+ return Collections.unmodifiableSet( constraintDescriptors );
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaConstraint.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/MetaConstraint.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,178 @@
+// $Id$// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.ConstraintViolation;
+
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.engine.ConstraintTree;
+import org.hibernate.validation.engine.ExecutionContext;
+
+/**
+ * Instances of this class abstract the constraint type (class, method or field
constraint) and gives access to
+ * meta data about the constraint. This allows a unified handling of constraints in the
validator imlpementation.
+ *
+ * @author Hardy Ferentschik
+ */
+public class MetaConstraint<T, A extends Annotation> {
+
+ /**
+ * The constraint tree created from the constraint annotation.
+ */
+ private final ConstraintTree<A> constraintTree;
+
+ /**
+ * The member the constraint was defined on.
+ */
+ private final Member member;
+
+ /**
+ * The JavaBeans name for this constraint.
+ */
+ private final String propertyName;
+
+ /**
+ * Describes on which level (<code>TYPE</code>,
<code>METHOD</code>, <code>FIELD</code>) the constraint was
+ * defined on.
+ */
+ private final ElementType elementType;
+
+ /**
+ * The class of the bean hosting this constraint.
+ */
+ private final Class<T> beanClass;
+
+ public MetaConstraint(Class<T> beanClass, ConstraintDescriptor<A>
constraintDescriptor) {
+ this.elementType = ElementType.TYPE;
+ this.member = null;
+ this.propertyName = "";
+ this.beanClass = beanClass;
+ constraintTree = new ConstraintTree<A>( constraintDescriptor );
+ }
+
+ public MetaConstraint(Member member, Class<T> beanClass,
ConstraintDescriptor<A> constraintDescriptor) {
+ if ( member instanceof Method ) {
+ this.elementType = ElementType.METHOD;
+ }
+ else if ( member instanceof Field ) {
+ this.elementType = ElementType.FIELD;
+ }
+ else {
+ throw new IllegalArgumentException( "Non allowed member type: " + member );
+ }
+ this.member = member;
+ this.propertyName = ReflectionHelper.getPropertyName( member );
+ this.beanClass = beanClass;
+ constraintTree = new ConstraintTree<A>( constraintDescriptor );
+ }
+
+
+ /**
+ * @return Returns the list of groups this constraint is part of. This might include the
default group even when
+ * it is not explicitly specified, but part of the redefined default group list
of the hosting bean.
+ */
+ public Set<Class<?>> getGroupList() {
+ return constraintTree.getDescriptor().getGroups();
+ }
+
+ public ConstraintDescriptor getDescriptor() {
+ return constraintTree.getDescriptor();
+ }
+
+ public Class<T> getBeanClass() {
+ return beanClass;
+ }
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ public ElementType getElementType() {
+ return elementType;
+ }
+
+ public ConstraintTree getConstraintTree() {
+ return constraintTree;
+ }
+
+ public <T> boolean validateConstraint(ExecutionContext<T> executionContext)
{
+ final Object leafBeanInstance = executionContext.peekCurrentBean();
+ Object value = getValue( leafBeanInstance );
+ List<ConstraintViolation<T>> constraintViolations = new
ArrayList<ConstraintViolation<T>>();
+ constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext,
constraintViolations );
+ if ( constraintViolations.size() > 0 ) {
+ executionContext.addConstraintFailures( constraintViolations );
+ return false;
+ }
+ return true;
+ }
+
+ public <T> boolean validateConstraint(Object value, ExecutionContext<T>
executionContext) {
+ List<ConstraintViolation<T>> constraintViolations = new
ArrayList<ConstraintViolation<T>>();
+ constraintTree.validateConstraints( value, typeOfAnnoatedElement(), executionContext,
constraintViolations );
+ if ( constraintViolations.size() > 0 ) {
+ executionContext.addConstraintFailures( constraintViolations );
+ return false;
+ }
+ return true;
+ }
+
+ private Type typeOfAnnoatedElement() {
+ Type t;
+ switch ( elementType ) {
+ case TYPE: {
+ t = beanClass;
+ break;
+ }
+ default: {
+ t = ReflectionHelper.typeOf( member );
+ if ( t instanceof Class && ((Class) t).isPrimitive()) {
+ t = ReflectionHelper.boxedTyp( t );
+ }
+ }
+ }
+ return t;
+ }
+
+ /**
+ * @param o the object from which to retrieve the value.
+ *
+ * @return Returns the value for this constraint from the specified object. Depending on
the type either the value itself
+ * is returned of method or field access is used to access the value.
+ */
+ private Object getValue(Object o) {
+ switch ( elementType ) {
+ case TYPE: {
+ return o;
+ }
+ default: {
+ return ReflectionHelper.getValue( member, o );
+ }
+ }
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/PropertyDescriptorImpl.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/PropertyDescriptorImpl.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,52 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.metadata;
+
+import javax.validation.metadata.PropertyDescriptor;
+
+/**
+ * Describe a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class PropertyDescriptorImpl extends ElementDescriptorImpl implements
PropertyDescriptor {
+ private final boolean cascaded;
+ private final String property;
+
+
+ public PropertyDescriptorImpl(Class<?> returnType, boolean cascaded, String
property) {
+ super( returnType );
+ this.cascaded = cascaded;
+ this.property = property;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isCascaded() {
+ return cascaded;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getPropertyName() {
+ return property;
+ }
+}
\ No newline at end of file
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/ValidationBootstrapParameters.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationBootstrapParameters.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,41 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.xml;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class ValidationBootstrapParameters {
+ public ConstraintValidatorFactory constraintValidatorFactory;
+ public MessageInterpolator messageInterpolator;
+ public TraversableResolver traversableResolver;
+ public ValidationProvider provider;
+ public Class<? extends ValidationProvider<?>> providerClass = null;
+ public final Map<String, String> configProperties = new HashMap<String,
String>();
+ public final Set<InputStream> mappings = new HashSet<InputStream>();
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/ValidationXmlParser.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/ValidationXmlParser.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,255 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.xml;
+
+import java.io.InputStream;
+import java.net.URL;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
+import javax.validation.spi.ValidationProvider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.slf4j.Logger;
+import org.xml.sax.SAXException;
+
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.xml.PropertyType;
+import org.hibernate.validation.xml.ValidationConfigType;
+
+/**
+ * Parser for <i>validation.xml</i> using JAXB.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ValidationXmlParser {
+
+ private static final Logger log = LoggerFactory.make();
+ private static final String VALIDATION_XML_FILE = "META-INF/validation.xml";
+ private static final String VALIDATION_CONFIGURATION_XSD =
"META-INF/validation-configuration-1.0.xsd";
+
+
+ /**
+ * Tries to check whether a validation.xml file exists and parses it using JAXB.
+ *
+ * @return The parameters parsed out of <i>validation.xml</i> wrapped in an
instance of <code>ConfigurationImpl.ValidationBootstrapParameters</code>.
+ */
+ public ValidationBootstrapParameters parseValidationXml() {
+ ValidationConfigType config = getValidationConfig();
+ ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters();
+ if ( config != null ) {
+ // collect the paramters from the xml file
+ setProviderClassFromXml( config, xmlParameters );
+ setMessageInterpolatorFromXml( config, xmlParameters );
+ setTraversableResolverFromXml( config, xmlParameters );
+ setConstraintFactoryFromXml( config, xmlParameters );
+ setMappingStreamsFromXml( config, xmlParameters );
+ setPropertiesFromXml( config, xmlParameters );
+ }
+ return xmlParameters;
+ }
+
+ private void setConstraintFactoryFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParameters) {
+ String constraintFactoryClass = config.getConstraintValidatorFactory();
+ if ( constraintFactoryClass != null ) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<ConstraintValidatorFactory> clazz = (
Class<ConstraintValidatorFactory> ) ReflectionHelper.classForName(
+ constraintFactoryClass, this.getClass()
+ );
+ xmlParameters.constraintValidatorFactory = clazz.newInstance();
+ log.info( "Using {} as constraint factory.", constraintFactoryClass );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException(
+ "Unable to instantiate constraint factory class " +
constraintFactoryClass + ".", e
+ );
+ }
+ catch ( InstantiationException e ) {
+ throw new ValidationException(
+ "Unable to instantiate constraint factory class " +
constraintFactoryClass + ".", e
+ );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new ValidationException(
+ "Unable to instantiate constraint factory class " +
constraintFactoryClass + ".", e
+ );
+ }
+ }
+ }
+
+ private void setPropertiesFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParameters) {
+ for ( PropertyType property : config.getProperty() ) {
+ if ( log.isDebugEnabled() ) {
+ log.debug(
+ "Found property '{}' with value '{}' in
validation.xml.",
+ property.getName(),
+ property.getValue()
+ );
+ }
+ xmlParameters.configProperties.put( property.getName(), property.getValue() );
+ }
+ }
+
+ private void setMappingStreamsFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParameters) {
+ for ( JAXBElement<String> mappingFileName : config.getConstraintMapping() ) {
+ if ( log.isDebugEnabled() ) {
+ log.debug(
+ "Trying to open input stream for {}.", mappingFileName.getValue()
+ );
+ }
+ InputStream in = getInputStreamForPath( mappingFileName.getValue() );
+ if ( in == null ) {
+ throw new ValidationException( "Unable to open input stream for mapping file
" + mappingFileName.getValue() + "." );
+ }
+ xmlParameters.mappings.add( in );
+ }
+ }
+
+ private void setMessageInterpolatorFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParameters) {
+ String messageInterpolatorClass = config.getMessageInterpolator();
+ if ( messageInterpolatorClass != null ) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<MessageInterpolator> clazz = ( Class<MessageInterpolator> )
ReflectionHelper.classForName(
+ messageInterpolatorClass, this.getClass()
+ );
+ xmlParameters.messageInterpolator = clazz.newInstance();
+ log.info( "Using {} as message interpolator.", messageInterpolatorClass );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException(
+ "Unable to instantiate message interpolator class " +
messageInterpolatorClass + ".", e
+ );
+ }
+ catch ( InstantiationException e ) {
+ throw new ValidationException(
+ "Unable to instantiate message interpolator class " +
messageInterpolatorClass + ".", e
+ );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new ValidationException(
+ "Unable to instantiate message interpolator class " +
messageInterpolatorClass + ".", e
+ );
+ }
+ }
+ }
+
+ private void setTraversableResolverFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParameters) {
+ String traversableResolverClass = config.getTraversableResolver();
+ if ( traversableResolverClass != null ) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<TraversableResolver> clazz = ( Class<TraversableResolver> )
ReflectionHelper.classForName(
+ traversableResolverClass, this.getClass()
+ );
+ xmlParameters.traversableResolver = clazz.newInstance();
+ log.info( "Using {} as traversable resolver.", traversableResolverClass );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException(
+ "Unable to instantiate traversable resolver class " +
traversableResolverClass + ".", e
+ );
+ }
+ catch ( InstantiationException e ) {
+ throw new ValidationException(
+ "Unable to instantiate traversable resolver class " +
traversableResolverClass + ".", e
+ );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new ValidationException(
+ "Unable to instantiate traversable resolver class " +
traversableResolverClass + ".", e
+ );
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void setProviderClassFromXml(ValidationConfigType config,
ValidationBootstrapParameters xmlParamters) {
+ String providerClassName = config.getDefaultProvider();
+ if ( providerClassName != null ) {
+ try {
+ xmlParamters.providerClass = ( Class<? extends ValidationProvider<?>> )
ReflectionHelper.classForName(
+ providerClassName, this.getClass()
+ );
+ log.info( "Using {} as validation provider.", providerClassName );
+ }
+ catch ( Exception e ) {
+ throw new ValidationException( "Unable to instantiate validation provider class
" + providerClassName + "." );
+ }
+ }
+ }
+
+ private ValidationConfigType getValidationConfig() {
+ InputStream inputStream = getInputStreamForPath( VALIDATION_XML_FILE );
+ if ( inputStream == null ) {
+ log.info( "No {} found. Using annotation based configuration only!",
VALIDATION_XML_FILE );
+ return null;
+ }
+
+ log.info( "{} found.", VALIDATION_XML_FILE );
+
+ ValidationConfigType validationConfig;
+ Schema schema = getValidationConfigurationSchema();
+ try {
+ JAXBContext jc = JAXBContext.newInstance( ValidationConfigType.class );
+ Unmarshaller unmarshaller = jc.createUnmarshaller();
+ unmarshaller.setSchema( schema );
+ StreamSource stream = new StreamSource( inputStream );
+ JAXBElement<ValidationConfigType> root = unmarshaller.unmarshal( stream,
ValidationConfigType.class );
+ validationConfig = root.getValue();
+ }
+ catch ( JAXBException e ) {
+ log.error( "Error parsing validation.xml: {}", e.getMessage() );
+ throw new ValidationException( "Unable to parse " + VALIDATION_XML_FILE );
+ }
+ return validationConfig;
+ }
+
+ private InputStream getInputStreamForPath(String path) {
+ // try the context class loader first
+ InputStream inputStream =
Thread.currentThread().getContextClassLoader().getResourceAsStream( path );
+
+ // try the current class loader
+ if ( inputStream == null ) {
+ inputStream = this.getClass().getResourceAsStream( path );
+ }
+ return inputStream;
+ }
+
+ private Schema getValidationConfigurationSchema() {
+ URL schemaUrl = this.getClass().getClassLoader().getResource(
VALIDATION_CONFIGURATION_XSD );
+ SchemaFactory sf = SchemaFactory.newInstance(
javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
+ Schema schema = null;
+ try {
+ schema = sf.newSchema( schemaUrl );
+ }
+ catch ( SAXException e ) {
+ log.warn( "Unable to create schema for {}: {}",
VALIDATION_CONFIGURATION_XSD, e.getMessage() );
+ }
+ return schema;
+ }
+}
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
(from rev 16797,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/xml/XmlMappingParser.java)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -0,0 +1,620 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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 org.hibernate.validation.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ValidationException;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.slf4j.Logger;
+import org.xml.sax.SAXException;
+
+import org.hibernate.validation.metadata.ConstraintDescriptorImpl;
+import org.hibernate.validation.metadata.MetaConstraint;
+import org.hibernate.validation.metadata.ConstraintHelper;
+import org.hibernate.validation.metadata.AnnotationIgnores;
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+import org.hibernate.validation.xml.AnnotationType;
+import org.hibernate.validation.xml.BeanType;
+import org.hibernate.validation.xml.ClassType;
+import org.hibernate.validation.xml.ConstraintDefinitionType;
+import org.hibernate.validation.xml.ConstraintMappingsType;
+import org.hibernate.validation.xml.ConstraintType;
+import org.hibernate.validation.xml.ElementType;
+import org.hibernate.validation.xml.FieldType;
+import org.hibernate.validation.xml.GetterType;
+import org.hibernate.validation.xml.GroupSequenceType;
+import org.hibernate.validation.xml.GroupsType;
+import org.hibernate.validation.xml.ValidatedByType;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class XmlMappingParser {
+
+ private static final Logger log = LoggerFactory.make();
+ private static final String VALIDATION_MAPPING_XSD =
"META-INF/validation-mapping-1.0.xsd";
+ private static final String MESSAGE_PARAM = "message";
+ private static final String GROUPS_PARAM = "groups";
+ private static final String PACKAGE_SEPERATOR = ".";
+
+ private final Set<Class<?>> processedClasses = new
HashSet<Class<?>>();
+ private final ConstraintHelper constraintHelper;
+ private final AnnotationIgnores annotationIgnores;
+ private final Map<Class<?>, List<MetaConstraint<?, ? extends
Annotation>>> constraintMap;
+ private final Map<Class<?>, List<Member>> cascadedMembers;
+ private final Map<Class<?>, List<Class<?>>> defaultSequences;
+
+ public XmlMappingParser(ConstraintHelper constraintHelper) {
+ this.constraintHelper = constraintHelper;
+ this.annotationIgnores = new AnnotationIgnores();
+ this.constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ?
extends Annotation>>>();
+ this.cascadedMembers = new HashMap<Class<?>, List<Member>>();
+ this.defaultSequences = new HashMap<Class<?>,
List<Class<?>>>();
+ }
+
+ public void parse(Set<InputStream> mappingStreams) {
+ for ( InputStream in : mappingStreams ) {
+ try {
+ ConstraintMappingsType mapping = getValidationConfig( in );
+ parseConstraintDefinitions( mapping.getConstraintDefinition() );
+ String defaultPackage = mapping.getDefaultPackage();
+ for ( BeanType bean : mapping.getBean() ) {
+ Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
+ checkClassHasNotBeenProcessed( processedClasses, beanClass );
+ annotationIgnores.setDefaultIgnoreAnnotation( beanClass, bean.isIgnoreAnnotations()
);
+ parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
+ parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage );
+ parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage );
+ processedClasses.add( beanClass );
+ }
+ }
+ finally {
+ try {
+ in.close();
+ }
+ catch ( IOException e ) {
+ log.warn( "Error closing input stream: {}", e.getMessage() );
+ }
+ }
+ }
+ }
+
+ public Set<Class<?>> getProcessedClasses() {
+ return processedClasses;
+ }
+
+ public AnnotationIgnores getAnnotationIgnores() {
+ return annotationIgnores;
+ }
+
+ public <T> List<MetaConstraint<T, ? extends Annotation>>
getConstraintsForClass(Class<T> beanClass) {
+ List<MetaConstraint<T, ? extends Annotation>> list = new
ArrayList<MetaConstraint<T, ? extends Annotation>>();
+ if ( constraintMap.containsKey( beanClass ) ) {
+ for ( MetaConstraint<?, ? extends Annotation> metaConstraint :
constraintMap.get( beanClass ) ) {
+ @SuppressWarnings( "unchecked") // safe cast since the list of meta
constraints is always specific to the bean type
+ MetaConstraint<T, ? extends Annotation> boundMetaConstraint = (
MetaConstraint<T, ? extends Annotation> ) metaConstraint;
+ list.add( boundMetaConstraint );
+ }
+ return list;
+ }
+ else {
+ return Collections.emptyList();
+ }
+ }
+
+ public List<Member> getCascadedMembersForClass(Class<?> beanClass) {
+ if ( cascadedMembers.containsKey( beanClass ) ) {
+ return cascadedMembers.get( beanClass );
+ }
+ else {
+ return Collections.emptyList();
+ }
+ }
+
+ public List<Class<?>> getDefaultSequenceForClass(Class<?> beanClass)
{
+ if ( defaultSequences.containsKey( beanClass ) ) {
+ return defaultSequences.get( beanClass );
+ }
+ else {
+ return Collections.emptyList();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void parseConstraintDefinitions(List<ConstraintDefinitionType>
constraintDefinitionList) {
+ for ( ConstraintDefinitionType constraintDefinition : constraintDefinitionList ) {
+ String annotationClassName = constraintDefinition.getAnnotation();
+ Class<? extends Annotation> annotationClass;
+ try {
+ annotationClass = ( Class<? extends Annotation> )
ReflectionHelper.classForName(
+ annotationClassName, this.getClass()
+ );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException( "Unable to load class " +
annotationClassName );
+ }
+
+ if ( !annotationClass.isAnnotation() ) {
+ throw new ValidationException( annotationClassName + " is not an
annotation" );
+ }
+
+ ValidatedByType validatedByType = constraintDefinition.getValidatedBy();
+ List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraintValidatorClasses = new ArrayList<Class<? extends ConstraintValidator<?
extends Annotation, ?>>>();
+ if ( validatedByType.isIncludeExistingValidators() != null &&
validatedByType.isIncludeExistingValidators() ) {
+ constraintValidatorClasses.addAll( findConstraintValidatorClasses( annotationClass )
);
+ }
+ for ( JAXBElement<String> validatorClassName : validatedByType.getValue() ) {
+ Class<? extends ConstraintValidator<?, ?>> validatorClass;
+ try {
+ validatorClass = ( Class<? extends ConstraintValidator<?, ?>> )
ReflectionHelper.classForName(
+ validatorClassName.getValue(),
+ this.getClass()
+ );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException( "Unable to load class " +
validatorClassName );
+ }
+
+ if ( !ConstraintValidator.class.isAssignableFrom( validatorClass ) ) {
+ throw new ValidationException( validatorClass + " is not a constraint validator
class" );
+ }
+
+ constraintValidatorClasses.add( validatorClass );
+ }
+ constraintHelper.addConstraintValidatorDefinition(
+ annotationClass, constraintValidatorClasses
+ );
+ }
+ }
+
+ private List<Class<? extends ConstraintValidator<? extends Annotation,
?>>> findConstraintValidatorClasses(Class<? extends Annotation>
annotationType) {
+ List<Class<? extends ConstraintValidator<? extends Annotation, ?>>>
constraintValidatorDefinitonClasses = new ArrayList<Class<? extends
ConstraintValidator<? extends Annotation, ?>>>();
+ if ( constraintHelper.isBuiltinConstraint( annotationType ) ) {
+ constraintValidatorDefinitonClasses.addAll( constraintHelper.getBuiltInConstraints(
annotationType ) );
+ }
+ else {
+ Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
+ .getAnnotation( Constraint.class )
+ .validatedBy();
+ for ( Class<? extends ConstraintValidator<?, ?>> validator : validatedBy )
{
+ //FIXME does this create a CCE at runtime?
+ //FIXME if yes wrap into VE, if no we need to test the type here
+ //Once resolved,we can @SuppressWarning("unchecked") on the cast
+ Class<? extends ConstraintValidator<? extends Annotation, ?>>
safeValidator = validator;
+ constraintValidatorDefinitonClasses.add( safeValidator );
+ }
+ }
+ return constraintValidatorDefinitonClasses;
+ }
+
+ private void checkClassHasNotBeenProcessed(Set<Class<?>> processedClasses,
Class<?> beanClass) {
+ if ( processedClasses.contains( beanClass ) ) {
+ throw new ValidationException( beanClass.getName() + " has already be configured
in xml." );
+ }
+ }
+
+ private void parseFieldLevelOverrides(List<FieldType> fields, Class<?>
beanClass, String defaultPackage) {
+ for ( FieldType fieldType : fields ) {
+ String fieldName = fieldType.getName();
+ if ( !ReflectionHelper.containsField( beanClass, fieldName ) ) {
+ throw new ValidationException( beanClass.getName() + " does not contain the
fieldType " + fieldName );
+ }
+ Field field = ReflectionHelper.getField( beanClass, fieldName );
+
+ // ignore annotations
+ boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false :
fieldType.isIgnoreAnnotations();
+ if ( ignoreFieldAnnotation ) {
+ annotationIgnores.setIgnoreAnnotationsOnMember( field );
+ }
+
+ // valid
+ if ( fieldType.getValid() != null ) {
+ addCascadedMember( beanClass, field );
+ }
+
+ // constraints
+ for ( ConstraintType constraint : fieldType.getConstraint() ) {
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+ constraint, beanClass, field, defaultPackage
+ );
+ addMetaConstraint( beanClass, metaConstraint );
+ }
+ }
+ }
+
+ private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?>
beanClass, String defaultPackage) {
+ for ( GetterType getterType : getters ) {
+ String getterName = getterType.getName();
+ if ( !ReflectionHelper.containsMethod( beanClass, getterName ) ) {
+ throw new ValidationException( beanClass.getName() + " does not contain the
property " + getterName );
+ }
+ Method method = ReflectionHelper.getMethod( beanClass, getterName );
+
+ // ignore annotations
+ boolean ignoreGetterAnnotation = getterType.isIgnoreAnnotations() == null ? false :
getterType.isIgnoreAnnotations();
+ if ( ignoreGetterAnnotation ) {
+ annotationIgnores.setIgnoreAnnotationsOnMember( method );
+ }
+
+ // valid
+ if ( getterType.getValid() != null ) {
+ addCascadedMember( beanClass, method );
+ }
+
+ // constraints
+ for ( ConstraintType constraint : getterType.getConstraint() ) {
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+ constraint, beanClass, method, defaultPackage
+ );
+ addMetaConstraint( beanClass, metaConstraint );
+ }
+ }
+ }
+
+ private void parseClassLevelOverrides(ClassType classType, Class<?> beanClass,
String defaultPackage) {
+ if ( classType == null ) {
+ return;
+ }
+
+ // ignore annotation
+ boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false :
classType.isIgnoreAnnotations();
+ if ( ignoreClassAnnotation ) {
+ annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
+ }
+
+ // group sequence
+ List<Class<?>> groupSequence = createGroupSequence(
classType.getGroupSequence(), defaultPackage );
+ if ( !groupSequence.isEmpty() ) {
+ defaultSequences.put( beanClass, groupSequence );
+ }
+
+ // constraints
+ for ( ConstraintType constraint : classType.getConstraint() ) {
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint,
beanClass, null, defaultPackage );
+ addMetaConstraint( beanClass, metaConstraint );
+ }
+ }
+
+ private void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?>
metaConstraint) {
+ if ( constraintMap.containsKey( beanClass ) ) {
+ constraintMap.get( beanClass ).add( metaConstraint );
+ }
+ else {
+ List<MetaConstraint<?, ? extends Annotation>> constraintList = new
ArrayList<MetaConstraint<?, ? extends Annotation>>();
+ constraintList.add( metaConstraint );
+ constraintMap.put( beanClass, constraintList );
+ }
+ }
+
+ private void addCascadedMember(Class<?> beanClass, Member member) {
+ if ( cascadedMembers.containsKey( beanClass ) ) {
+ cascadedMembers.get( beanClass ).add( member );
+ }
+ else {
+ List<Member> tmpList = new ArrayList<Member>();
+ tmpList.add( member );
+ cascadedMembers.put( beanClass, tmpList );
+ }
+ }
+
+ private List<Class<?>> createGroupSequence(GroupSequenceType
groupSequenceType, String defaultPackage) {
+ List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+ for ( JAXBElement<String> groupName : groupSequenceType.getValue() ) {
+ Class<?> group = getClass( groupName.getValue(), defaultPackage );
+ groupSequence.add( group );
+ }
+ return groupSequence;
+ }
+
+ private <A extends Annotation, T> MetaConstraint<?, ?>
createMetaConstraint(ConstraintType constraint, Class<T> beanClass, Member member,
String defaultPackage) {
+ @SuppressWarnings("unchecked")
+ Class<A> annotationClass = ( Class<A> ) getClass(
constraint.getAnnotation(), defaultPackage );
+ AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>(
annotationClass );
+
+ if ( constraint.getMessage() != null ) {
+ annotationDescriptor.setValue( MESSAGE_PARAM, constraint.getMessage() );
+ }
+ annotationDescriptor.setValue( GROUPS_PARAM, getGroups( constraint.getGroups(),
defaultPackage ) );
+
+ for ( ElementType elementType : constraint.getElement() ) {
+ String name = elementType.getName();
+ checkNameIsValid( name );
+ Class<?> returnType = getAnnotationParamterType( annotationClass, name );
+ Object elementValue = getElementValue( elementType, returnType );
+ annotationDescriptor.setValue( name, elementValue );
+ }
+
+ A annotation = AnnotationFactory.create( annotationDescriptor );
+ ConstraintDescriptorImpl<A> constraintDescriptor = new
ConstraintDescriptorImpl<A>(
+ annotation, constraintHelper
+ );
+
+ MetaConstraint<T, A> metaConstraint;
+ if ( member == null ) {
+ metaConstraint = new MetaConstraint<T, A>( beanClass, constraintDescriptor );
+ }
+ else {
+ metaConstraint = new MetaConstraint<T, A>( member, beanClass,
constraintDescriptor );
+ }
+ return metaConstraint;
+ }
+
+ private <A extends Annotation> Class<?>
getAnnotationParamterType(Class<A> annotationClass, String name) {
+ Method m;
+ try {
+ m = annotationClass.getMethod( name );
+ }
+ catch ( NoSuchMethodException e ) {
+ throw new ValidationException( "Annotation of type " +
annotationClass.getName() + " does not contain a paramter " + name +
"." );
+ }
+ return m.getReturnType();
+ }
+
+ private Object getElementValue(ElementType elementType, Class<?> returnType) {
+ removeEmptyContentElements( elementType );
+
+ boolean isArray = returnType.isArray();
+ if ( !isArray ) {
+ if ( elementType.getContent().size() != 1 ) {
+ throw new ValidationException( "Attempt to specify an array where single value
is expected." );
+ }
+ return getSingleValue( elementType.getContent().get( 0 ), returnType );
+ }
+ else {
+ List<Object> values = new ArrayList<Object>();
+ for ( Serializable s : elementType.getContent() ) {
+ values.add( getSingleValue( s, returnType.getComponentType() ) );
+ }
+ return values.toArray( ( Object[] ) Array.newInstance( returnType.getComponentType(),
values.size() ) );
+ }
+ }
+
+ private void removeEmptyContentElements(ElementType elementType) {
+ List<Serializable> contentToDelete = new ArrayList<Serializable>();
+ for ( Serializable content : elementType.getContent() ) {
+ if ( content instanceof String && ( ( String ) content ).matches( "[\\n
].*" ) ) {
+ contentToDelete.add( content );
+ }
+ }
+ elementType.getContent().removeAll( contentToDelete );
+ }
+
+ private Object getSingleValue(Serializable serializable, Class<?> returnType) {
+
+ Object returnValue;
+ if ( serializable instanceof String ) {
+ String value = ( String ) serializable;
+ returnValue = convertStringToReturnType( returnType, value );
+ }
+ else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable
).getDeclaredType()
+ .equals( String.class ) ) {
+ JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+ String value = ( String ) elem.getValue();
+ returnValue = convertStringToReturnType( returnType, value );
+ }
+ else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable
).getDeclaredType()
+ .equals( AnnotationType.class ) ) {
+ JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+ AnnotationType annotationType = ( AnnotationType ) elem.getValue();
+ try {
+ @SuppressWarnings("unchecked")
+ Class<Annotation> annotationClass = ( Class<Annotation> ) returnType;
+ returnValue = createAnnotation( annotationType, annotationClass );
+ }
+ catch ( ClassCastException e ) {
+ throw new ValidationException( "Unexpected paramter value" );
+ }
+ }
+ else {
+ throw new ValidationException( "Unexpected paramter value" );
+ }
+ return returnValue;
+
+ }
+
+ private <A extends Annotation> Annotation createAnnotation(AnnotationType
annotationType, Class<A> returnType) {
+ AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>(
returnType );
+ for ( ElementType elementType : annotationType.getElement() ) {
+ String name = elementType.getName();
+ Class<?> paramterType = getAnnotationParamterType( returnType, name );
+ Object elementValue = getElementValue( elementType, paramterType );
+ annotationDescriptor.setValue( name, elementValue );
+ }
+ return AnnotationFactory.create( annotationDescriptor );
+ }
+
+ private Object convertStringToReturnType(Class<?> returnType, String value) {
+ Object returnValue;
+ if ( returnType.getName().equals( byte.class.getName() ) ) {
+ try {
+ returnValue = Byte.parseByte( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid byte format", e );
+ }
+ }
+ else if ( returnType.getName().equals( short.class.getName() ) ) {
+ try {
+ returnValue = Short.parseShort( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid short format", e );
+ }
+ }
+ else if ( returnType.getName().equals( int.class.getName() ) ) {
+ try {
+ returnValue = Integer.parseInt( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid int format", e );
+ }
+ }
+ else if ( returnType.getName().equals( long.class.getName() ) ) {
+ try {
+ returnValue = Long.parseLong( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid long format", e );
+ }
+ }
+ else if ( returnType.getName().equals( float.class.getName() ) ) {
+ try {
+ returnValue = Float.parseFloat( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid float format", e );
+ }
+ }
+ else if ( returnType.getName().equals( double.class.getName() ) ) {
+ try {
+ returnValue = Double.parseDouble( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid double format", e );
+ }
+ }
+ else if ( returnType.getName().equals( boolean.class.getName() ) ) {
+ returnValue = Boolean.parseBoolean( value );
+ }
+ else if ( returnType.getName().equals( char.class.getName() ) ) {
+ if ( value.length() != 1 ) {
+ throw new ValidationException( "Invalid char value: " + value );
+ }
+ returnValue = value.charAt( 0 );
+ }
+ else if ( returnType.getName().equals( String.class.getName() ) ) {
+ returnValue = value;
+ }
+ else if ( returnType.getName().equals( Class.class.getName() ) ) {
+ try {
+ returnValue = ReflectionHelper.classForName( value, this.getClass() );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException( "Unable to instantiate class: " + value );
+ }
+ }
+ else {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<Enum> enumClass = ( Class<Enum> ) returnType;
+ returnValue = Enum.valueOf( enumClass, value );
+ }
+ catch ( ClassCastException e ) {
+ throw new ValidationException( "Invalid return type: " + returnType +
". Should be a enumeration type." );
+ }
+ }
+ return returnValue;
+ }
+
+ private void checkNameIsValid(String name) {
+ if ( MESSAGE_PARAM.equals( name ) || GROUPS_PARAM.equals( name ) ) {
+ throw new ValidationException( MESSAGE_PARAM + " and " + GROUPS_PARAM +
" are reserved paramter names." );
+ }
+ }
+
+ private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
+ if ( groupsType == null ) {
+ return new Class[] { };
+ }
+
+ List<Class<?>> groupList = new ArrayList<Class<?>>();
+ for ( JAXBElement<String> groupClass : groupsType.getValue() ) {
+ groupList.add( getClass( groupClass.getValue(), defaultPackage ) );
+ }
+ return groupList.toArray( new Class[groupList.size()] );
+ }
+
+ private Class<?> getClass(String clazz, String defaultPackage) {
+ String fullyQualifiedClass;
+ if ( isQualifiedClass( clazz ) ) {
+ fullyQualifiedClass = clazz;
+ }
+ else {
+ fullyQualifiedClass = defaultPackage + PACKAGE_SEPERATOR + clazz;
+ }
+ try {
+ return ReflectionHelper.classForName( fullyQualifiedClass, this.getClass() );
+ }
+ catch ( Exception e ) {
+ throw new ValidationException( "Unable to instantiate class " +
fullyQualifiedClass );
+ }
+ }
+
+ private boolean isQualifiedClass(String clazz) {
+ return clazz.contains( PACKAGE_SEPERATOR );
+ }
+
+ private ConstraintMappingsType getValidationConfig(InputStream in) {
+ ConstraintMappingsType constraintMappings;
+ Schema schema = getMappingSchema();
+ try {
+ JAXBContext jc = JAXBContext.newInstance( ConstraintMappingsType.class );
+ Unmarshaller unmarshaller = jc.createUnmarshaller();
+ unmarshaller.setSchema( schema );
+ StreamSource stream = new StreamSource( in );
+ JAXBElement<ConstraintMappingsType> root = unmarshaller.unmarshal( stream,
ConstraintMappingsType.class );
+ constraintMappings = root.getValue();
+ }
+ catch ( JAXBException e ) {
+ String msg = "Error parsing mapping file.";
+ log.error( msg );
+ throw new ValidationException( msg, e );
+ }
+ return constraintMappings;
+ }
+
+ private Schema getMappingSchema() {
+ URL schemaUrl = this.getClass().getClassLoader().getResource( VALIDATION_MAPPING_XSD
);
+ SchemaFactory sf = SchemaFactory.newInstance(
javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
+ Schema schema = null;
+ try {
+ schema = sf.newSchema( schemaUrl );
+ }
+ catch ( SAXException e ) {
+ log.warn( "Unable to create schema for {}: {}", VALIDATION_MAPPING_XSD,
e.getMessage() );
+ }
+ return schema;
+ }
+}
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ConstraintHelperTest.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -29,6 +29,7 @@
import org.testng.annotations.Test;
import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.metadata.ConstraintHelper;
/**
* @author Hardy Ferentschik
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java 2009-06-16
15:29:59 UTC (rev 16797)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolatorTest.java 2009-06-16
16:16:48 UTC (rev 16798)
@@ -35,6 +35,8 @@
import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
+import org.hibernate.validation.metadata.ConstraintDescriptorImpl;
+import org.hibernate.validation.metadata.ConstraintHelper;
/**
* Tests for message resolution.
Modified: validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml 2009-06-16 15:29:59
UTC (rev 16797)
+++ validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml 2009-06-16 16:16:48
UTC (rev 16798)
@@ -10,10 +10,10 @@
<package
name="org.hibernate.validation.engine.constraintcomposition"/>
<package
name="org.hibernate.validation.engine.graphnavigation"/>
<package name="org.hibernate.validation.engine.groups"/>
- <package name="org.hibernate.validation.engine.metadata"/>
+ <package name="org.hibernate.validation.metadata"/>
<package
name="org.hibernate.validation.engine.inheritance"/>
<package name="org.hibernate.validation.engine.resolver"/>
- <package name="org.hibernate.validation.engine.xml"/>
+ <package name="org.hibernate.validation.xml"/>
<package name="org.hibernate.validation.util"/>
<package
name="org.hibernate.validation.util.annotationfactory"/>
</packages>