[hibernate-commits] Hibernate SVN: r16271 - in validator/trunk/hibernate-validator/src: main/java/org/hibernate/validation/util and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Apr 7 16:20:12 EDT 2009


Author: hardy.ferentschik
Date: 2009-04-07 16:20:12 -0400 (Tue, 07 Apr 2009)
New Revision: 16271

Added:
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/TestGroup.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.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/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.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 
Parsing and applying class, field and property level constraints.

Modified: 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-04-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -33,12 +33,6 @@
 public interface BeanMetaData<T> {
 
 	/**
-	 * Initalises the given meta data bean taken its current state into account. An instance of <code>BeanMetaData</code>
-	 * won't have any useful state information prior to calling this method.
-	 */
-	void init();
-
-	/**
 	 * @return the class of the bean.
 	 */
 	Class<T> getBeanClass();

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-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -93,9 +93,6 @@
 	public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
 		this.beanClass = beanClass;
 		this.constraintHelper = constraintHelper;
-	}
-
-	public void init() {
 		createMetaData();
 	}
 

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-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -24,6 +24,7 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
+import java.lang.reflect.Field;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -113,8 +114,7 @@
 	 */
 	public ValidatorContext usingContext() {
 		return new ValidatorContextImpl(
-				constraintValidatorFactory, messageInterpolator, traversableResolver,
-				constraintHelper
+				constraintValidatorFactory, messageInterpolator, traversableResolver, constraintHelper
 		);
 	}
 
@@ -143,8 +143,8 @@
 					Boolean ignoreAnnotations = bean.isIgnoreAnnotations() == null ? false : bean.isIgnoreAnnotations();
 					ignoreAnnotationDefaults.put( beanClass, ignoreAnnotations );
 					parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
-					parseFieldLevelOverrides( bean.getField() );
-					parsePropertyLevelOverrides( bean.getGetter() );
+					parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage );
+					parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage );
 					processedClasses.add( beanClass );
 				}
 			}
@@ -165,15 +165,39 @@
 		}
 	}
 
-	private void parseFieldLevelOverrides(List<FieldType> fields) {
-		for ( FieldType field : fields ) {
-			boolean ignoreFieldAnnotation = field.isIgnoreAnnotations() == null ? false : field.isIgnoreAnnotations();
+	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 );
+			boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations();
+			if ( ignoreFieldAnnotation ) {
+				ignoreAnnotationOnMember.put( beanClass, null );
+			}
+			for ( ConstraintType constraint : fieldType.getConstraint() ) {
+				MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, field, defaultPackage );
+				addMetaConstraint( beanClass, metaConstraint );
+			}
 		}
 	}
 
-	private void parsePropertyLevelOverrides(List<GetterType> getters) {
+	private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?> beanClass, String defaultPackage) {
 		for ( GetterType getter : getters ) {
+			String getterName = getter.getName();
+			if ( !ReflectionHelper.containsMethod( beanClass, getterName ) ) {
+				throw new ValidationException( beanClass.getName() + " does not contain the property  " + getterName );
+			}
+			Method method = ReflectionHelper.getMethod( beanClass, getterName );
 			boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false : getter.isIgnoreAnnotations();
+			if ( ignoreGetterAnnotation ) {
+				ignoreAnnotationOnMember.put( beanClass, null );
+			}
+			for ( ConstraintType constraint : getter.getConstraint() ) {
+				MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, method, defaultPackage );
+				addMetaConstraint( beanClass, metaConstraint );
+			}
 		}
 	}
 
@@ -186,7 +210,7 @@
 			ignoreAnnotationOnClass.add( beanClass );
 		}
 		for ( ConstraintType constraint : classType.getConstraint() ) {
-			MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, defaultPackage );
+			MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage );
 			addMetaConstraint( beanClass, metaConstraint );
 		}
 	}
@@ -202,7 +226,7 @@
 		}
 	}
 
-	private <A extends Annotation, T> MetaConstraint<?, ?> createMetaConstraint(ConstraintType constraint, Class<T> beanClass, String defaultPackage) {
+	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 );
@@ -224,7 +248,15 @@
 		ConstraintDescriptorImpl<A> constraintDescriptor = new ConstraintDescriptorImpl<A>(
 				annotation, new Class[] { }, constraintHelper
 		);
-		return new MetaConstraint<T, A>( beanClass, constraintDescriptor );
+
+		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 void checkNameIsValid(String name) {
@@ -423,7 +455,6 @@
 			for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
 				metaData.addMetaConstraint( metaConstraint );
 			}
-			metaData.init();
 			BeanMetaDataCache.addBeanMetaData( entry.getKey(), metaData );
 		}
 	}

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-04-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -554,7 +554,6 @@
 		BeanMetaDataImpl<T> metadata = BeanMetaDataCache.getBeanMetaData( beanClass );
 		if ( metadata == null ) {
 			metadata = new BeanMetaDataImpl<T>( beanClass, constraintHelper );
-			metadata.init();
 			BeanMetaDataCache.addBeanMetaData( beanClass, metadata );
 		}
 		return metadata;

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-04-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -50,24 +50,6 @@
 	private ReflectionHelper() {
 	}
 
-
-	/**
-	 * Checks whether the given annotation is a builtin constraint annotation defined as defined by the specs.
-	 *
-	 * @param annotation the annotation to check
-	 *
-	 * @return <code>true</code> if the annotation is a builtin constraint, <code>false</code> otherwise.
-	 */
-	public static boolean isBuiltInConstraintAnnotation(Annotation annotation) {
-		boolean isBuiltInConstraintAnnotation = false;
-
-		String packageName = annotation.annotationType().getPackage().getName();
-		if ( "javax.validation.constraints".equals( packageName ) ) {
-			isBuiltInConstraintAnnotation = true;
-		}
-		return isBuiltInConstraintAnnotation;
-	}
-
 	@SuppressWarnings("unchecked")
 	public static <T> T getAnnotationParameter(Annotation annotation, String parameterName, Class<T> type) {
 		try {
@@ -269,10 +251,7 @@
 		}
 		if ( type instanceof WildcardType ) {
 			Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds();
-			if ( upperBounds.length == 0 ) {
-				return false;
-			}
-			return isIterable( upperBounds[0] );
+			return upperBounds.length != 0 && isIterable( upperBounds[0] );
 		}
 		return false;
 	}
@@ -291,10 +270,7 @@
 		}
 		if ( type instanceof WildcardType ) {
 			Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds();
-			if ( upperBounds.length == 0 ) {
-				return false;
-			}
-			return isMap( upperBounds[0] );
+			return upperBounds.length != 0 && isMap( upperBounds[0] );
 		}
 		return false;
 	}
@@ -357,7 +333,7 @@
 	}
 
 	/**
-	 * Checks whether the specified class contains a field or member which matches a given property.
+	 * Checks whether the specified class contains a field or property matching the given name.
 	 *
 	 * @param clazz The class to check.
 	 * @param property The property name.
@@ -366,24 +342,83 @@
 	 *         false</code> otherwise.
 	 */
 	public static boolean containsMember(Class<?> clazz, String property) {
+		return containsField( clazz, property ) || containsMethod( clazz, property );
+	}
+
+	/**
+	 * Checks whether the specified class contains a field matching the specified name.
+	 *
+	 * @param clazz The class to check.
+	 * @param fieldName The field name.
+	 *
+	 * @return Returns <code>true</code> if the cass contains a field for the specified name, <code>
+	 *         false</code> otherwise.
+	 */
+	public static boolean containsField(Class<?> clazz, String fieldName) {
 		try {
-			clazz.getField( property );
+			clazz.getDeclaredField( fieldName );
 			return true;
 		}
 		catch ( NoSuchFieldException e ) {
-			// ignore
+			return false;
 		}
+	}
 
+	/**
+	 * Returns the field with the specified name or <code>null</code> if it does not exist.
+	 *
+	 * @param clazz The class to check.
+	 * @param fieldName The field name.
+	 *
+	 * @return Returns the field with the specified name or <code>null</code> if it does not exist.
+	 */
+	public static Field getField(Class<?> clazz, String fieldName) {
 		try {
-			clazz.getMethod( "get" + property.substring( 0, 1 ).toUpperCase() + property.substring( 1 ) );
+			Field field = clazz.getDeclaredField( fieldName );
+			setAccessibility( field );
+			return field;
+		}
+		catch ( NoSuchFieldException e ) {
+			return null;
+		}
+	}
+
+	/**
+	 * Checks whether the specified class contains a method matching the specified name.
+	 *
+	 * @param clazz The class to check.
+	 * @param methodName The method name.
+	 *
+	 * @return Returns <code>true</code> if the cass contains a property for the specified name, <code>
+	 *         false</code> otherwise.
+	 */
+	public static boolean containsMethod(Class<?> clazz, String methodName) {
+		try {
+			clazz.getMethod( "get" + methodName.substring( 0, 1 ).toUpperCase() + methodName.substring( 1 ) );
 			return true;
 		}
 		catch ( NoSuchMethodException e ) {
-			// ignore
+			return false;
 		}
-		return false;
 	}
 
+	/**
+	 * Returns the method with the specified name or <code>null</code> if it does not exist.
+	 *
+	 * @param clazz The class to check.
+	 * @param methodName The method name.
+	 *
+	 * @return Returns the method with the specified name or <code>null</code> if it does not exist.
+	 */
+	public static Method getMethod(Class<?> clazz, String methodName) {
+		try {
+			return clazz.getMethod( "get" + methodName.substring( 0, 1 ).toUpperCase() + methodName.substring( 1 ) );
+		}
+		catch ( NoSuchMethodException e ) {
+			return null;
+		}
+	}
+
 	public static Class<?> classForName(String name, Class<?> caller) throws ClassNotFoundException {
 		try {
 			ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/TestGroup.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/TestGroup.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/TestGroup.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -0,0 +1,24 @@
+// $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.xml;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public interface TestGroup {
+}

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-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java	2009-04-07 20:20:12 UTC (rev 16271)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
 /*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -23,9 +23,9 @@
 
 import org.testng.annotations.Test;
 
+import org.hibernate.validation.util.TestUtil;
 import static org.hibernate.validation.util.TestUtil.assertNumberOfViolations;
 import static org.hibernate.validation.util.TestUtil.getValidator;
-import org.hibernate.validation.util.TestUtil;
 
 /**
  * @author Hardy Ferentschik
@@ -33,7 +33,7 @@
 public class XmlConfigurationTest {
 
 	@Test
-	public void testValidatorResolutionForMinMax() {
+	public void testClassConstraintDefinedInXml() {
 		Validator validator = getValidator();
 
 		User user = new User();
@@ -45,4 +45,41 @@
 		constraintViolations = validator.validate( user );
 		assertNumberOfViolations( constraintViolations, 0 );
 	}
+
+	@Test
+	public void testPropertyConstraintDefinedInXml() {
+		Validator validator = getValidator();
+
+		User user = new User();
+		user.setConsistent( true );
+		user.setFirstname( "Wolfeschlegelsteinhausenbergerdorff" );
+
+		Set<ConstraintViolation<User>> constraintViolations = validator.validate( user );
+		assertNumberOfViolations( constraintViolations, 1 );
+		TestUtil.assertConstraintViolation( constraintViolations.iterator().next(), "Size is limited!" );
+
+		user.setFirstname( "Wolfgang" );
+		constraintViolations = validator.validate( user );
+		assertNumberOfViolations( constraintViolations, 0 );
+	}
+
+	@Test
+	public void testFieldConstraintDefinedInXml() {
+		Validator validator = getValidator();
+
+		User user = new User();
+		user.setConsistent( true );
+		user.setFirstname( "Wolfgang" );
+		user.setLastname( "doe" );
+
+		Set<ConstraintViolation<User>> constraintViolations = validator.validate( user );
+		assertNumberOfViolations( constraintViolations, 1 );
+		TestUtil.assertConstraintViolation(
+				constraintViolations.iterator().next(), "Last name has to start with with a capital letter."
+		);
+
+		user.setLastname( "Doe" );
+		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-07 17:40:07 UTC (rev 16270)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml	2009-04-07 20:20:12 UTC (rev 16271)
@@ -22,9 +22,11 @@
                 </element>
             </constraint>
         </class>
-        <field name="firstName">
-            <constraint annotation="com.acme.app.constraint.LooksLike">
-                <element name="patterns">
+        <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="patterns">
                     <annotation>
                         <element name="value">myRegExp</element>
                         <element name="flag">
@@ -34,27 +36,18 @@
                     <annotation>
                         <element name="value">my2ndRegExp</element>
                     </annotation>
-                </element>
+                </element-->
             </constraint>
         </field>
-        <field name="orders">
+        <getter name="firstname">
             <valid/>
-            <constraint annotation="com.acme.app.constraint.DiscreteSize">
-                <element name="value">
-                    <value>0</value>
-                    <value>20</value>
-                </element>
-            </constraint>
-        </field>
-        <getter name="orders">
-            <valid/>
-            <constraint annotation="javax.validation.constraint.Size">
-                <message>Size is limited</message>
+            <constraint annotation="javax.validation.constraints.Size">
+                <message>Size is limited!</message>
                 <groups>
-                    <value>com.acme.app.model.LightValidation</value>
-                    <value>javax.persistence.Default</value>
+                    <value>org.hibernate.validation.engine.xml.TestGroup</value>
+                    <value>javax.validation.groups.Default</value>
                 </groups>
-                <element name="max">30</element>
+                <element name="max">10</element>
             </constraint>
         </getter>
     </bean>




More information about the hibernate-commits mailing list