Author: hardy.ferentschik
Date: 2008-10-28 11:39:45 -0400 (Tue, 28 Oct 2008)
New Revision: 15412
Removed:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.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/ValidatorImplTest.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java
Log:
Some more refactorings towards implementing composite constraints
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -239,29 +239,30 @@
private <A extends Annotation> List<ConstraintDescriptorImpl>
findConstraintAnnotations(A annotation) {
List<ConstraintDescriptorImpl> constraintDescriptors = new
ArrayList<ConstraintDescriptorImpl>();
- List<Annotation> constraintCandidates = new ArrayList<Annotation>();
- constraintCandidates.add( annotation );
+ List<Annotation> constraints = new ArrayList<Annotation>();
+ if ( ReflectionHelper.isConstraintAnnotation( annotation ) ||
+ ReflectionHelper.isBuiltInConstraintAnnotation( annotation) ) {
+ constraints.add( annotation );
+ }
// check if we have a multi value constraint
- Annotation[] annotations = getMultiValueConstraintsCandidates( annotation );
- constraintCandidates.addAll( Arrays.asList( annotations ) );
+ constraints.addAll( ReflectionHelper.getMultiValueConstraints( annotation ) );
- for ( Annotation constraintCandiate : constraintCandidates ) {
-
- if ( ReflectionHelper.isBuiltInConstraintAnnotation( constraintCandiate ) ) {
- Class constraintClass = ReflectionHelper.getBuiltInConstraint( constraintCandiate );
+ for ( Annotation constraint : constraints ) {
+ if ( ReflectionHelper.isBuiltInConstraintAnnotation( constraint ) ) {
+ Class constraintClass = ReflectionHelper.getBuiltInConstraint( constraint );
final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
- constraintCandiate, constraintClass
+ constraint, constraintClass
);
constraintDescriptors.add( constraintDescriptor );
continue;
}
- if ( ReflectionHelper.isConstraintAnnotation( constraintCandiate ) ) {
- ConstraintValidator constraintValidator = constraintCandiate.annotationType()
+ if ( ReflectionHelper.isConstraintAnnotation( constraint ) ) {
+ ConstraintValidator constraintValidator = constraint.annotationType()
.getAnnotation( ConstraintValidator.class );
final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor(
- constraintCandiate, constraintValidator.value()
+ constraint, constraintValidator.value()
);
constraintDescriptors.add( constraintDescriptor );
}
@@ -298,31 +299,6 @@
}
/**
- * Checks whether the given annotation has a value parameter which returns an array of
annotations.
- *
- * @param annotation the annotation to check.
- *
- * @return The list of potential constraint annotations or the empty array.
- *
- * @todo Not only check that the return type of value is an array, but an array of
annotaitons. Need to check syntax.
- */
- private <A extends Annotation> Annotation[] getMultiValueConstraintsCandidates(A
annotation) {
- try {
- Method m = annotation.getClass().getMethod( "value" );
- Class returnType = m.getReturnType();
- if ( returnType.isArray() ) {
- return ( Annotation[] ) m.invoke( annotation );
- }
- else {
- return new Annotation[0];
- }
- }
- catch ( Exception e ) {
- return new Annotation[0];
- }
- }
-
- /**
* Finds all constraint annotations defined for the given class and returns them in a
list of
* constraint descriptors.
*
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 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -34,10 +34,13 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.ArrayList;
import javax.validation.ConstraintValidator;
import javax.validation.ValidationException;
import javax.validation.constraints.NotNull;
+import org.slf4j.Logger;
+
import org.hibernate.validation.constraints.NotNullConstraint;
/**
@@ -47,6 +50,8 @@
*/
public class ReflectionHelper {
+ private static final Logger log = LoggerFactory.make();
+
/**
* Private constructor in order to avoid instantiation.
*/
@@ -67,6 +72,13 @@
}
}
+ /**
+ * 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;
@@ -77,33 +89,80 @@
return isBuiltInConstraintAnnotation;
}
+ /**
+ * Checks whehter 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 static boolean isConstraintAnnotation(Annotation annotation) {
- boolean isConstraintAnnotation = true;
ConstraintValidator constraintValidator = annotation.annotationType()
.getAnnotation( ConstraintValidator.class );
if ( constraintValidator == null ) {
- isConstraintAnnotation = false;
- return isConstraintAnnotation;
+ return false;
}
try {
getAnnotationParameter( annotation, "message", String.class );
- } catch ( Exception e ) {
- throw new ValidationException( "Constraint annotation has to define message
element." );
}
+ catch ( Exception e ) {
+ String msg = annotation.annotationType().getName() + " contains
ConstraintValidator annotation, but does " +
+ "not contain a message parameter. Annotation is getting ignored.";
+ log.warn( msg );
+ return false;
+ }
try {
getAnnotationParameter( annotation, "groups", String[].class );
}
catch ( Exception e ) {
- throw new ValidationException( "Constraint annotation has to define groups
element." );
+ String msg = annotation.annotationType().getName() + " contains
ConstraintValidator annotation, but does " +
+ "not contain a groups parameter. Annotation is getting ignored.";
+ log.warn( msg );
+ return false;
}
- return isConstraintAnnotation;
+ return true;
}
+ /**
+ * 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 static <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 ) || isBuiltInConstraintAnnotation( a )) {
+ annotationList.add( a );
+ }
+ }
+ }
+ }
+ catch ( Exception e ) {
+ // ignore
+ }
+ return annotationList;
+ }
+
@SuppressWarnings("unchecked")
public static <T> T getAnnotationParameter(Annotation annotation, String
parameterName, Class<T> type) {
try {
Deleted:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -1,51 +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.eg;
-
-import org.hibernate.validation.eg.constraint.NoGroups;
-
-/**
- * @author Hardy Ferentschik
- */
-public class Female implements Person {
-
- // @NoGroups is an invalid annotation (missing group paramter)
- @NoGroups
- private String firstName;
- private String lastName;
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
- public String getMiddleName() {
- return null;
- }
-}
\ No newline at end of file
Deleted:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -1,50 +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.eg;
-
-import org.hibernate.validation.eg.constraint.NoMessage;
-
-/**
- * @author Hardy Ferentschik
- */
-public class Male implements Person {
- // @NoMessage is an invalid annotation (no message paramter)
- @NoMessage
- private String firstName;
- private String lastName;
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
- public String getMiddleName() {
- return null;
- }
-}
\ No newline at end of file
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -38,8 +38,6 @@
import org.hibernate.validation.eg.Dictonary;
import org.hibernate.validation.eg.Engine;
import org.hibernate.validation.eg.EnglishDictonary;
-import org.hibernate.validation.eg.Female;
-import org.hibernate.validation.eg.Male;
import org.hibernate.validation.eg.Order;
import org.hibernate.validation.eg.Unconstraint;
@@ -50,39 +48,8 @@
*/
public class ValidatorImplTest {
- /**
- * JSR 303: Constraint definition properties - message (2.1.1.1)
- */
- @Test
- public void testConstraintWithNoMessage() {
- try {
- new ValidatorImpl<Male>( Male.class );
- fail();
- }
- catch ( ValidationException e ) {
- assertEquals(
- "Wrong error message", "Constraint annotation has to define message
element.", e.getMessage()
- );
- }
- }
/**
- * JSR 303: Constraint definition properties - groups (2.1.1.2)
- */
- @Test
- public void testConstraintWithNoGroups() {
- try {
- new ValidatorImpl<Female>( Female.class );
- fail();
- }
- catch ( ValidationException e ) {
- assertEquals(
- "Wrong error message", "Constraint annotation has to define groups
element.", e.getMessage()
- );
- }
- }
-
- /**
* JSR 303: Requirements on classes to be validates (3.1)
*/
@Test
@@ -101,12 +68,12 @@
}
- @Test( expected = IllegalArgumentException.class)
+ @Test(expected = IllegalArgumentException.class)
public void testNullParamterToValidatorImplConstructor() {
- new ValidatorImpl<Unconstraint>( null);
+ new ValidatorImpl<Unconstraint>( null );
}
- @Test
+ @Test
public void testUnconstraintClass() {
Validator<Unconstraint> validator = new ValidatorImpl<Unconstraint>(
Unconstraint.class );
assertTrue( "There should be no constraints", !validator.hasConstraints() );
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java 2008-10-28
15:02:46 UTC (rev 15411)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java 2008-10-28
15:39:45 UTC (rev 15412)
@@ -18,7 +18,7 @@
package org.hibernate.validation.util;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -27,11 +27,20 @@
import javax.validation.constraints.NotNull;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
+import org.hibernate.validation.constraints.Pattern;
+import org.hibernate.validation.constraints.Patterns;
+import org.hibernate.validation.eg.Engine;
+import org.hibernate.validation.eg.Order;
+import org.hibernate.validation.eg.constraint.NoGroups;
+import org.hibernate.validation.eg.constraint.NoMessage;
+
/**
* Tests for the <code>ReflectionHelper</code>.
*
@@ -112,7 +121,76 @@
fail();
}
catch ( ValidationException e ) {
- assertTrue( "Wrong exception message", e.getMessage().startsWith( "The
specified annotation defines no parameter" ) );
+ assertTrue(
+ "Wrong exception message",
+ e.getMessage().startsWith( "The specified annotation defines no parameter"
)
+ );
}
}
+
+ /**
+ * JSR 303: Constraint definition properties - message (2.1.1.1)
+ */
+ @Test
+ public void testConstraintWithNoMessage() {
+ Annotation annotation = new NoGroups() {
+ public String message() {
+ return "";
+ }
+
+ public Class<? extends Annotation> annotationType() {
+ return this.getClass();
+ }
+ };
+ assertFalse(
+ "The constraint annotation should not be valid",
ReflectionHelper.isConstraintAnnotation( annotation )
+ );
+ }
+
+ /**
+ * JSR 303: Constraint definition properties - groups (2.1.1.2)
+ */
+ @Test
+ public void testConstraintWithNoGroups() {
+ Annotation annotation = new NoMessage() {
+ public String[] groups() {
+ return null;
+ }
+
+ public Class<? extends Annotation> annotationType() {
+ return this.getClass();
+ }
+ };
+ assertFalse(
+ "The constraint annotation should not be valid",
ReflectionHelper.isConstraintAnnotation( annotation )
+ );
+ }
+
+ @Test
+ public void testGetMultiValueConstraints() throws Exception {
+ Engine engine = new Engine();
+ Field[] fields = engine.getClass().getDeclaredFields();
+ assertNotNull( fields );
+ assertTrue( fields.length == 1 );
+ ReflectionHelper.setAccessibility( fields[0] );
+
+ Annotation annotation = fields[0].getAnnotation( Patterns.class );
+ assertNotNull( annotation );
+ List<Annotation> multiValueConstraintAnnotations =
ReflectionHelper.getMultiValueConstraints( annotation );
+ assertTrue( "There should be two constraint annotations",
multiValueConstraintAnnotations.size() == 2 );
+ assertTrue( "Wrong constraint annotation",
multiValueConstraintAnnotations.get( 0 ) instanceof Pattern );
+ assertTrue( "Wrong constraint annotation",
multiValueConstraintAnnotations.get( 1 ) instanceof Pattern );
+
+
+ Order order = new Order();
+ fields = order.getClass().getDeclaredFields();
+ assertNotNull( fields );
+ assertTrue( fields.length == 1 );
+ ReflectionHelper.setAccessibility( fields[0] );
+
+ annotation = fields[0].getAnnotation( NotNull.class );
+ assertNotNull( annotation );
+ multiValueConstraintAnnotations = ReflectionHelper.getMultiValueConstraints( annotation
);
+ assertTrue( "There should be two constraint annotations",
multiValueConstraintAnnotations.size() == 0 );
+ }
}