Author: hardy.ferentschik
Date: 2009-04-08 08:48:10 -0400 (Wed, 08 Apr 2009)
New Revision: 16279
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
Log:
HV-112
Added a new class for taking care of the annotation ignores.
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -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.engine;
+
+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;
+ }
+}
Property changes on:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified:
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-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -90,32 +90,18 @@
*/
private final ConstraintHelper constraintHelper;
- private Map<Class<?>, Boolean> ignoreAnnotationDefaults;
- private Map<Class<?>, List<Member>> ignoreAnnotationOnMember;
- private List<Class<?>> ignoreAnnotationOnClass;
-
public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
this(
beanClass,
constraintHelper,
- new HashMap<Class<?>, Boolean>(),
- new ArrayList<Class<?>>(),
- new HashMap<Class<?>, List<Member>>()
+ new AnnotationIgnores()
);
}
- public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper,
Map<Class<?>, Boolean> ignoreAnnotationDefaults, List<Class<?>>
ignoreAnnotationOnClass, Map<Class<?>, List<Member>>
ignoreAnnotationOnMember) {
+ public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper,
AnnotationIgnores annotationIgnores) {
this.beanClass = beanClass;
this.constraintHelper = constraintHelper;
- this.ignoreAnnotationDefaults = ignoreAnnotationDefaults;
- this.ignoreAnnotationOnClass = ignoreAnnotationOnClass;
- this.ignoreAnnotationOnMember = ignoreAnnotationOnMember;
-
- createMetaData();
-
- this.ignoreAnnotationDefaults = null;
- this.ignoreAnnotationOnClass = null;
- this.ignoreAnnotationOnMember = null;
+ createMetaData( annotationIgnores );
}
public Class<T> getBeanClass() {
@@ -153,14 +139,16 @@
/**
* 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() {
+ private void createMetaData(AnnotationIgnores annotationIgnores) {
beanDescriptor = new BeanDescriptorImpl<T>( this );
initDefaultGroupSequence( beanClass );
List<Class> classes = new ArrayList<Class>();
computeClassHierarchy( beanClass, classes );
for ( Class current : classes ) {
- initClass( current );
+ initClass( current, annotationIgnores );
}
}
@@ -185,10 +173,10 @@
}
}
- private void initClass(Class clazz) {
- initClassConstraints( clazz );
- initMethodConstraints( clazz );
- initFieldConstraints( clazz );
+ private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
+ initClassConstraints( clazz, annotationIgnores );
+ initMethodConstraints( clazz, annotationIgnores );
+ initFieldConstraints( clazz, annotationIgnores );
}
/**
@@ -225,11 +213,11 @@
}
}
- private <A extends Annotation> void initFieldConstraints(Class clazz) {
+ private <A extends Annotation> void initFieldConstraints(Class clazz,
AnnotationIgnores annotationIgnores) {
for ( Field field : clazz.getDeclaredFields() ) {
List<ConstraintDescriptorImpl> fieldMetadata = findConstraints( field );
for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
- if ( checkSkipAnnotationProcessing( clazz, field ) ) {
+ if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
break;
}
ReflectionHelper.setAccessibility( field );
@@ -246,11 +234,11 @@
}
}
- private <A extends Annotation> void initMethodConstraints(Class clazz) {
+ private <A extends Annotation> void initMethodConstraints(Class clazz,
AnnotationIgnores annotationIgnores) {
for ( Method method : clazz.getDeclaredMethods() ) {
List<ConstraintDescriptorImpl> methodMetadata = findConstraints( method );
for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
- if ( checkSkipAnnotationProcessing( clazz, method ) ) {
+ if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
break;
}
ReflectionHelper.setAccessibility( method );
@@ -267,29 +255,6 @@
}
}
- private boolean checkSkipAnnotationProcessing(Class clazz, Member member) {
- List<Member> ignoreAnnotationForFields = ignoreAnnotationOnMember.get( clazz );
- boolean ignoreAnnotation;
- if ( ignoreAnnotationForFields == null || !ignoreAnnotationForFields.contains( member )
) {
- ignoreAnnotation = ignoreAnnotationDefaults.containsKey( clazz ) &&
ignoreAnnotationDefaults.get( clazz );
- }
- else {
- ignoreAnnotation = ignoreAnnotationForFields.contains( member );
- }
- if ( ignoreAnnotation ) {
- String type;
- if ( member instanceof Field ) {
- type = "Field";
- }
- else {
- type = "Property";
- }
- log.debug( type + " level annotations are getting ignored for " +
clazz.getName() + "." + member.getName() );
- return true;
- }
- return false;
- }
-
private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
String name = ReflectionHelper.getPropertyName( member );
PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get(
@@ -306,10 +271,8 @@
return propertyDescriptor;
}
- private <A extends Annotation> void initClassConstraints(Class clazz) {
- if ( ignoreAnnotationOnClass.contains( clazz ) ||
- ( ignoreAnnotationDefaults.containsKey( clazz ) &&
ignoreAnnotationDefaults.get( clazz ) ) ) {
- log.debug( "Class level annotation are getting ignored for " +
clazz.getName() );
+ private <A extends Annotation> void initClassConstraints(Class clazz,
AnnotationIgnores annotationIgnores) {
+ if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
return;
}
List<ConstraintDescriptorImpl> classMetadata = findClassLevelConstraints( clazz
);
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-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -81,16 +81,17 @@
private final ConstraintHelper constraintHelper = new ConstraintHelper();
private static final String PACKAGE_SEPERATOR = ".";
- private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new
HashMap<Class<?>, Boolean>();
- private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember =
new HashMap<Class<?>, List<Member>>();
- private final List<Class<?>> ignoreAnnotationOnClass = new
ArrayList<Class<?>>();
- private final Map<Class<?>, List<MetaConstraint<?, ?>>>
constraintMap = new HashMap<Class<?>, List<MetaConstraint<?,
?>>>();
+ private AnnotationIgnores annotationIgnores;
+ private Map<Class<?>, List<MetaConstraint<?, ?>>>
constraintMap;
public ValidatorFactoryImpl(ConfigurationState configurationState) {
this.messageInterpolator = configurationState.getMessageInterpolator();
this.constraintValidatorFactory = configurationState.getConstraintValidatorFactory();
this.traversableResolver = configurationState.getTraversableResolver();
+ annotationIgnores = new AnnotationIgnores();
+ constraintMap = new HashMap<Class<?>, List<MetaConstraint<?,
?>>>();
+
parseMappingFiles( configurationState.getMappingStreams() );
initBeanMetaData();
}
@@ -140,8 +141,7 @@
for ( BeanType bean : mappings.getBean() ) {
Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
checkClassHasNotBeenProcessed( processedClasses, beanClass );
- Boolean ignoreAnnotations = bean.isIgnoreAnnotations() == null ? false :
bean.isIgnoreAnnotations();
- ignoreAnnotationDefaults.put( beanClass, ignoreAnnotations );
+ annotationIgnores.setDefaultIgnoreAnnotation( beanClass, bean.isIgnoreAnnotations()
);
parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage );
parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage );
@@ -174,7 +174,7 @@
Field field = ReflectionHelper.getField( beanClass, fieldName );
boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false :
fieldType.isIgnoreAnnotations();
if ( ignoreFieldAnnotation ) {
- addMemberToIgnoreList( beanClass, field );
+ annotationIgnores.setIgnoreAnnotationsOnMember( field );
}
for ( ConstraintType constraint : fieldType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
@@ -185,17 +185,6 @@
}
}
- private void addMemberToIgnoreList(Class<?> beanClass, Member member) {
- if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
- List<Member> ignoredAnnotationOnMember = new ArrayList<Member>();
- ignoredAnnotationOnMember.add( member );
- ignoreAnnotationOnMember.put( beanClass, ignoredAnnotationOnMember );
- }
- else {
- ignoreAnnotationOnMember.get( beanClass ).add( member );
- }
- }
-
private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?>
beanClass, String defaultPackage) {
for ( GetterType getter : getters ) {
String getterName = getter.getName();
@@ -205,7 +194,7 @@
Method method = ReflectionHelper.getMethod( beanClass, getterName );
boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false :
getter.isIgnoreAnnotations();
if ( ignoreGetterAnnotation ) {
- addMemberToIgnoreList( beanClass, method );
+ annotationIgnores.setIgnoreAnnotationsOnMember( method );
}
for ( ConstraintType constraint : getter.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
@@ -222,7 +211,7 @@
}
boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false :
classType.isIgnoreAnnotations();
if ( ignoreClassAnnotation ) {
- ignoreAnnotationOnClass.add( beanClass );
+ annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
}
for ( ConstraintType constraint : classType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint,
beanClass, null, defaultPackage );
@@ -466,13 +455,7 @@
private void initBeanMetaData() {
for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry :
constraintMap.entrySet() ) {
- BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl(
- entry.getKey(),
- constraintHelper,
- ignoreAnnotationDefaults,
- ignoreAnnotationOnClass,
- ignoreAnnotationOnMember
- );
+ BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(),
constraintHelper, annotationIgnores );
for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
metaData.addMetaConstraint( metaConstraint );
}
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java 2009-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -42,7 +42,6 @@
PatternValidator constraint = new PatternValidator();
constraint.initialize( p );
-
assertTrue( constraint.isValid( null, null ) );
assertFalse( constraint.isValid( "", null ) );
assertFalse( constraint.isValid( "bla bla", null ) );
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -1,6 +1,7 @@
package org.hibernate.validation.engine.xml;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
import javax.validation.groups.Default;
/**
@@ -14,7 +15,7 @@
private String lastname;
- //@Pattern(regexp = "[0-9 -]?", groups = Optional.class)
+ @Pattern(regexp = "[0-9 -]+", message = "A phone nmber can only contain
numbers, whitespaces and dashes.")
private String phoneNumber;
@NotNull(groups = Default.class)
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08
12:48:10 UTC (rev 16279)
@@ -82,4 +82,24 @@
constraintViolations = validator.validate( user );
assertNumberOfViolations( constraintViolations, 0 );
}
+
+ @Test
+ public void testAnnotationDefinedConstraintApplies() {
+ Validator validator = getValidator();
+
+ User user = new User();
+ user.setConsistent( true );
+ user.setPhoneNumber( "police" );
+
+ Set<ConstraintViolation<User>> constraintViolations = validator.validate(
user );
+ assertNumberOfViolations( constraintViolations, 1 );
+ TestUtil.assertConstraintViolation(
+ constraintViolations.iterator().next(),
+ "A phone nmber can only contain numbers, whitespaces and dashes."
+ );
+
+ user.setPhoneNumber( "112" );
+ constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 0 );
+ }
}
Modified:
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
---
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08
11:23:35 UTC (rev 16278)
+++
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08
12:48:10 UTC (rev 16279)
@@ -25,7 +25,7 @@
<field name="lastname">
<constraint
annotation="javax.validation.constraints.Pattern">
<message>Last name has to start with with a capital
letter.</message>
- <element name="regexp">^[A-Z].*</element>
+ <element name="regexp">^[A-Z][a-z]+</element>
<!--element name="patterns">
<annotation>
<element name="value">myRegExp</element>