Author: hardy.ferentschik
Date: 2009-03-07 12:57:46 -0500 (Sat, 07 Mar 2009)
New Revision: 16106
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Auditable.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Order.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/ConstraintDescriptorImpl.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/groups/GroupTest.java
Log:
HV-115 Implicit grouping
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-03-07
08:33:16 UTC (rev 16105)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -176,7 +176,7 @@
private <A extends Annotation> void initFieldConstraints(Class clazz) {
for ( Field field : clazz.getDeclaredFields() ) {
- List<ConstraintDescriptorImpl> fieldMetadata = findFieldLevelConstraints( field
);
+ List<ConstraintDescriptorImpl> fieldMetadata = findConstraints( field );
for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
ReflectionHelper.setAccessibility( field );
MetaConstraint<T, A> metaConstraint = new MetaConstraint<T, A>(
@@ -186,7 +186,6 @@
}
if ( field.isAnnotationPresent( Valid.class ) ) {
ReflectionHelper.setAccessibility( field );
- String name = field.getName();
cascadedFields.add( field );
addPropertyDescriptorForMember( field );
}
@@ -195,7 +194,7 @@
private <A extends Annotation> void initMethodConstraints(Class clazz) {
for ( Method method : clazz.getDeclaredMethods() ) {
- List<ConstraintDescriptorImpl> methodMetadata = findMethodLevelConstraints(
method );
+ List<ConstraintDescriptorImpl> methodMetadata = findConstraints( method );
for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
ReflectionHelper.setAccessibility( method );
MetaConstraint<T, A> metaConstraint = new MetaConstraint<T, A>(
@@ -238,12 +237,13 @@
/**
* 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(A annotation) {
+ private <A extends Annotation> List<ConstraintDescriptorImpl>
findConstraintAnnotations(Class<?> clazz, A annotation) {
List<ConstraintDescriptorImpl> constraintDescriptors = new
ArrayList<ConstraintDescriptorImpl>();
List<Annotation> constraints = new ArrayList<Annotation>();
@@ -256,16 +256,23 @@
constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) );
for ( Annotation constraint : constraints ) {
- final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
constraint );
+ final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
clazz, constraint );
constraintDescriptors.add( constraintDescriptor );
}
return constraintDescriptors;
}
@SuppressWarnings("unchecked")
- private <A extends Annotation> ConstraintDescriptorImpl
buildConstraintDescriptor(A annotation) {
+ private <A extends Annotation> ConstraintDescriptorImpl
buildConstraintDescriptor(Class<?> clazz, A annotation) {
Class<?>[] groups = ReflectionHelper.getAnnotationParameter( annotation,
"groups", Class[].class );
- return new ConstraintDescriptorImpl( annotation, groups, constraintHelper );
+ ConstraintDescriptorImpl constraintDescriptor;
+ if ( clazz.isInterface() ) {
+ constraintDescriptor = new ConstraintDescriptorImpl( annotation, groups,
constraintHelper, clazz );
+ }
+ else {
+ constraintDescriptor = new ConstraintDescriptorImpl( annotation, groups,
constraintHelper );
+ }
+ return constraintDescriptor;
}
/**
@@ -276,10 +283,10 @@
*
* @return A list of constraint descriptors for all constraint specified on the given
class.
*/
- private List<ConstraintDescriptorImpl> findClassLevelConstraints(Class beanClass)
{
+ private List<ConstraintDescriptorImpl> findClassLevelConstraints(Class<?>
beanClass) {
List<ConstraintDescriptorImpl> metadata = new
ArrayList<ConstraintDescriptorImpl>();
for ( Annotation annotation : beanClass.getAnnotations() ) {
- metadata.addAll( findConstraintAnnotations( annotation ) );
+ metadata.addAll( findConstraintAnnotations( beanClass, annotation ) );
}
for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
beanDescriptor.addConstraintDescriptor( constraintDescriptor );
@@ -287,61 +294,39 @@
return metadata;
}
+
/**
- * Finds all constraint annotations defined for the given methods and returns them in a
list of
+ * Finds all constraint annotations defined for the given field/method and returns them
in a list of
* constraint descriptors.
*
- * @param method The method to check for constraints annotations.
+ * @param member The fiels or method to check for constraints annotations.
*
- * @return A list of constraint descriptors for all constraint specified for the given
method.
+ * @return A list of constraint descriptors for all constraint specified for the given
field or method.
*/
- private List<ConstraintDescriptorImpl> findMethodLevelConstraints(Method method)
{
+ private List<ConstraintDescriptorImpl> findConstraints(Member member) {
+ assert member instanceof Field || member instanceof Method;
+
List<ConstraintDescriptorImpl> metadata = new
ArrayList<ConstraintDescriptorImpl>();
- for ( Annotation annotation : method.getAnnotations() ) {
- metadata.addAll( findConstraintAnnotations( annotation ) );
+ for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) {
+ metadata.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation )
);
}
- String methodName = ReflectionHelper.getPropertyName( method );
+ String name = ReflectionHelper.getPropertyName( member );
for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
- if ( methodName == null ) {
+ 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. " +
method.getName() + "() does not."
+ "Annotated methods must follow the JavaBeans naming convention. " +
member.getName() + "() does not."
);
}
- PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get( methodName );
+ PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get( name );
if ( propertyDescriptor == null ) {
- propertyDescriptor = addPropertyDescriptorForMember( method );
+ propertyDescriptor = addPropertyDescriptorForMember( member );
}
propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
}
return metadata;
}
- /**
- * Finds all constraint annotations defined for the given field and returns them in a
list of
- * constraint descriptors.
- *
- * @param field The field to check for constraints annotations.
- *
- * @return A list of constraint descriptors for all constraint specified on the given
field.
- */
- private List<ConstraintDescriptorImpl> findFieldLevelConstraints(Field field) {
- List<ConstraintDescriptorImpl> metadata = new
ArrayList<ConstraintDescriptorImpl>();
- for ( Annotation annotation : field.getAnnotations() ) {
- metadata.addAll( findConstraintAnnotations( annotation ) );
- }
-
- String fieldName = field.getName();
- for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
- PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl )
propertyDescriptors.get( fieldName );
- if ( propertyDescriptor == null ) {
- propertyDescriptor = addPropertyDescriptorForMember( field );
- }
- propertyDescriptor.addConstraintDescriptor( constraintDescriptor );
- }
- return metadata;
- }
-
public Class<T> getBeanClass() {
return beanClass;
}
Modified:
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-03-07
08:33:16 UTC (rev 16105)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintDescriptorImpl.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -96,6 +96,11 @@
*/
private final ConstraintHelper constraintHelper;
+ public ConstraintDescriptorImpl(T annotation, Class<?>[] groups, ConstraintHelper
constraintHelper, Class<?> implicitGroup) {
+ this( annotation, groups, constraintHelper );
+ this.groups.add( implicitGroup );
+ }
+
public ConstraintDescriptorImpl(T annotation, Class<?>[] groups, ConstraintHelper
constraintHelper) {
this( annotation, new HashSet<Class<?>>(), constraintHelper );
if ( groups.length == 0 ) {
@@ -127,14 +132,14 @@
else {
//TODO are we sure a @Constraint is there?
final Class<? extends Annotation> annotationType = annotation.annotationType();
- Class<? extends ConstraintValidator<?,?>>[] validatedBy = annotationType
+ Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
.getAnnotation( Constraint.class )
.validatedBy();
- for (Class<? extends ConstraintValidator<?,?>> validator : 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<T,?>> safeValidator = (Class<?
extends ConstraintValidator<T,?>>) validator;
+ Class<? extends ConstraintValidator<T, ?>> safeValidator = ( Class<?
extends ConstraintValidator<T, ?>> ) validator;
constraintClasses.add( safeValidator );
}
}
@@ -165,14 +170,14 @@
* {@inheritDoc}
*/
public Map<String, Object> getParameters() {
- return Collections.unmodifiableMap(parameters);
+ return Collections.unmodifiableMap( parameters );
}
/**
* {@inheritDoc}
*/
public Set<ConstraintDescriptor<?>> getComposingConstraints() {
- return Collections.unmodifiableSet(composingConstraints);
+ return Collections.unmodifiableSet( composingConstraints );
}
/**
@@ -259,7 +264,9 @@
for ( Annotation declaredAnnotation :
annotation.annotationType().getDeclaredAnnotations() ) {
if ( constraintHelper.isConstraintAnnotation( declaredAnnotation )
|| constraintHelper.isBuiltinConstraint( declaredAnnotation ) ) {
- ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
declaredAnnotation, OVERRIDES_PARAMETER_DEFAULT_INDEX );
+ ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
+ declaredAnnotation, OVERRIDES_PARAMETER_DEFAULT_INDEX
+ );
composingConstraints.add( descriptor );
log.debug( "Adding composing constraint: " + descriptor );
}
@@ -268,7 +275,7 @@
int index = 1;
for ( Annotation constraintAnnotation : multiValueConstraints ) {
ConstraintDescriptorImpl<?> descriptor = createComposingConstraintDescriptor(
- constraintAnnotation, index
+ constraintAnnotation, index
);
composingConstraints.add( descriptor );
log.debug( "Adding composing constraint: " + descriptor );
@@ -282,12 +289,12 @@
//TODO don't quite understand this warning
//TODO assuming U.getClass() returns Class<U>
@SuppressWarnings("unchecked")
- final Class<U> annotationType = (Class<U>)
declaredAnnotation.annotationType();
+ final Class<U> annotationType = ( Class<U> )
declaredAnnotation.annotationType();
return createComposingConstraintDescriptor(
- index,
- declaredAnnotation,
- annotationType
- );
+ index,
+ declaredAnnotation,
+ annotationType
+ );
}
private <U extends Annotation> ConstraintDescriptorImpl<U>
createComposingConstraintDescriptor(int index, U constraintAnnotation, Class<U>
annotationType) {
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-03-07
08:33:16 UTC (rev 16105)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -142,6 +142,26 @@
}
/**
+ * Returns the type of the field of return type of a method.
+ *
+ * @param member the member for which to get the type.
+ *
+ * @return Returns the type of the field of return type of a method.
+ */
+ public static Class<?> getAnnotations(Member member) {
+
+ Class<?> type = null;
+ if ( member instanceof Field ) {
+ type = ( ( Field ) member ).getType();
+ }
+
+ if ( member instanceof Method ) {
+ type = ( ( Method ) member ).getReturnType();
+ }
+ return type;
+ }
+
+ /**
* @param member The <code>Member</code> instance for which to retrieve the
type.
*
* @return Retrurns the <code>Type</code> of the given
<code>Field</code> or <code>Method</code>.
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Auditable.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Auditable.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Auditable.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -0,0 +1,37 @@
+// $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.groups;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public interface Auditable {
+ @NotNull
+ String getCreationDate();
+
+ @NotNull
+ String getLastUpdate();
+
+ @NotNull
+ String getLastModifier();
+
+ @NotNull
+ String getLastReader();
+}
Property changes on:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Auditable.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java 2009-03-07
08:33:16 UTC (rev 16105)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupTest.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -18,11 +18,13 @@
package org.hibernate.validation.engine.groups;
import java.util.Set;
+import javax.validation.BeanDescriptor;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.groups.Default;
+import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
@@ -344,7 +346,11 @@
1,
constraintViolations.size()
);
- assertEquals( "Wrong constraint", "length must be between 2 and
20", constraintViolations.iterator().next().getMessage() );
+ assertEquals(
+ "Wrong constraint",
+ "length must be between 2 and 20",
+ constraintViolations.iterator().next().getMessage()
+ );
constraintViolations = validator.validateProperty( car, "type" );
assertEquals(
@@ -352,7 +358,11 @@
1,
constraintViolations.size()
);
- assertEquals( "Wrong constraint", "length must be between 2 and
20", constraintViolations.iterator().next().getMessage() );
+ assertEquals(
+ "Wrong constraint",
+ "length must be between 2 and 20",
+ constraintViolations.iterator().next().getMessage()
+ );
constraintViolations = validator.validateValue( Car.class, "type",
"A" );
assertEquals(
@@ -360,7 +370,11 @@
1,
constraintViolations.size()
);
- assertEquals( "Wrong constraint", "length must be between 2 and
20", constraintViolations.iterator().next().getMessage() );
+ assertEquals(
+ "Wrong constraint",
+ "length must be between 2 and 20",
+ constraintViolations.iterator().next().getMessage()
+ );
}
/**
@@ -380,4 +394,25 @@
);
}
}
+
+ /**
+ * HV-115
+ */
+ @Test
+ public void testImplicitGroup() {
+ Validator validator = TestUtil.getValidator();
+ BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Order.class );
+ assertTrue( beanDescriptor.isBeanConstrained() );
+
+ Set<String> constraintProperties = beanDescriptor.getConstrainedProperties();
+ assertTrue( "Each of the properties should have at least one constraint.",
constraintProperties.size() == 5 );
+
+ Order order = new Order();
+ Set<ConstraintViolation<Order>> violations = validator.validate( order );
+ assertTrue( "All 5 NotNull constraints should fail.", violations.size() == 5
);
+
+ // use implicit group Auditable
+ violations = validator.validate( order, Auditable.class );
+ assertTrue( "All 4 NotNull constraints on Auditable should fail.",
violations.size() == 4 );
+ }
}
\ No newline at end of file
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Order.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Order.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Order.java 2009-03-07
17:57:46 UTC (rev 16106)
@@ -0,0 +1,54 @@
+// $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.groups;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Order implements Auditable {
+ private String creationDate;
+ private String lastUpdate;
+ private String lastModifier;
+ private String lastReader;
+ private String orderNumber;
+
+ public String getCreationDate() {
+ return this.creationDate;
+ }
+
+ public String getLastUpdate() {
+ return this.lastUpdate;
+ }
+
+ public String getLastModifier() {
+ return this.lastModifier;
+ }
+
+ public String getLastReader() {
+ return this.lastReader;
+ }
+
+ @NotNull
+ @Size(min = 10, max = 10)
+ public String getOrderNumber() {
+ return this.orderNumber;
+ }
+}
Property changes on:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/Order.java
___________________________________________________________________
Name: svn:keywords
+ Id