You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by ro...@apache.org on 2010/05/03 10:35:47 UTC

svn commit: r940395 - in /incubator/bval/trunk/bval-jsr303/src: main/java/org/apache/bval/jsr303/ main/java/org/apache/bval/jsr303/xml/ test/java/org/apache/bval/jsr303/

Author: romanstumm
Date: Mon May  3 08:35:46 2010
New Revision: 940395

URL: http://svn.apache.org/viewvc?rev=940395&view=rev
Log:
BVAL-32 Annotations associated with composited contraints must reflect inherited groups- fixes from Carlos Varla

Modified:
    incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToBuilder.java
    incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintValidation.java
    incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java
    incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java
    incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java

Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToBuilder.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToBuilder.java?rev=940395&r1=940394&r2=940395&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToBuilder.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToBuilder.java Mon May  3 08:35:46 2010
@@ -16,6 +16,8 @@
  */
 package org.apache.bval.jsr303;
 
+import org.apache.bval.jsr303.xml.AnnotationProxyBuilder;
+
 import java.lang.annotation.Annotation;
 import java.util.Set;
 
@@ -33,7 +35,18 @@ public class AppendValidationToBuilder i
         // JSR-303 2.3:
         // Groups from the main constraint annotation are inherited by the composing annotations.
         // Any groups definition on a composing annotation is ignored.
-        validation.setGroups(builder.getConstraintValidation().getGroups());
+        Set<Class<?>> inheritedGroups = builder.getConstraintValidation().getGroups();
+        validation.setGroups(inheritedGroups);
+
+        // Inherited groups value must also be replicated in the annotation, so
+        // it has to be substituted with a new proxy.
+        T originalAnnot = validation.getAnnotation();
+        AnnotationProxyBuilder<T> apb = new AnnotationProxyBuilder<T>(originalAnnot);
+        apb.putValue("groups", inheritedGroups.toArray(new Class[inheritedGroups.size()]));
+        T newAnnot = apb.createAnnotation();
+        validation.setAnnotation(newAnnot);
+        
+        // And finally, add the composed validation
         builder.addComposed(validation);
     }
     

Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintValidation.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintValidation.java?rev=940395&r1=940394&r2=940395&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintValidation.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintValidation.java Mon May  3 08:35:46 2010
@@ -42,7 +42,7 @@ public class ConstraintValidation<T exte
       implements Validation, ConstraintDescriptor<T> {
     private static final String ANNOTATION_MESSAGE = "message";
     private final ConstraintValidator validator;
-    private final T annotation; // for metadata request API
+    private T annotation; // for metadata request API
     private final AccessStrategy access;
     private final boolean reportFromComposite;
     private final Map<String, Object> attributes;
@@ -227,6 +227,10 @@ public class ConstraintValidation<T exte
     public AccessStrategy getAccess() {
         return access;
     }
+    
+    public void setAnnotation(T annotation) {
+        this.annotation = annotation;
+    }
 
     /////////////////////////// ConstraintDescriptor implementation
 

Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java?rev=940395&r1=940394&r2=940395&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java Mon May  3 08:35:46 2010
@@ -17,6 +17,9 @@
 package org.apache.bval.jsr303.xml;
 
 
+import org.apache.bval.jsr303.util.SecureActions;
+
+import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -25,8 +28,6 @@ import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import org.apache.bval.jsr303.util.SecureActions;
-
 
 /**
  * Description: <br/>
@@ -34,7 +35,7 @@ import org.apache.bval.jsr303.util.Secur
  * "real" source code annotation.
  * <p/>
  */
-public class AnnotationProxy implements Annotation, InvocationHandler {
+public class AnnotationProxy implements Annotation, InvocationHandler, Serializable {
 
     private final Class<? extends Annotation> annotationType;
     private final Map<String, Object> values;

Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java?rev=940395&r1=940394&r2=940395&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java Mon May  3 08:35:46 2010
@@ -17,13 +17,14 @@
 package org.apache.bval.jsr303.xml;
 
 
-import javax.validation.Payload;
-import javax.validation.ValidationException;
-
 import org.apache.bval.jsr303.util.SecureActions;
 
+import javax.validation.Payload;
+import javax.validation.ValidationException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.HashMap;
 import java.util.Map;
@@ -32,7 +33,7 @@ import java.util.Map;
  * Description: Holds the information and creates an annotation proxy
  * during xml parsing of validation mapping constraints. <br/>
  */
-final class AnnotationProxyBuilder<A extends Annotation> {
+final public class AnnotationProxyBuilder<A extends Annotation> {
     private static final String ANNOTATION_PAYLOAD = "payload";
     private static final String ANNOTATION_GROUPS = "groups";
     private static final String ANNOTATION_MESSAGE = "message";
@@ -52,6 +53,34 @@ final class AnnotationProxyBuilder<A ext
         }
     }
 
+    /**
+     * Replicates an existing {@link Annotation} instance.
+     * 
+     * @param annot
+     *            Annotation to be replicated.
+     */
+    public AnnotationProxyBuilder(A annot) {
+        this.type = (Class<A>) annot.annotationType();
+        // Obtain the "elements" of the annotation
+        Method[] methods = SecureActions.getDeclaredMethods(annot.annotationType());
+        for ( Method m : methods ) {
+            if ( !m.isAccessible() ) {
+                m.setAccessible(true);
+            }
+            try {
+                Object value = m.invoke(annot);
+                this.elements.put(m.getName(), value);
+            } catch (IllegalArgumentException e) {
+                // No args, so should not happen
+                throw new ValidationException("Cannot access annotation " + annot + " element: " + m.getName());
+            } catch (IllegalAccessException e) {
+                throw new ValidationException("Cannot access annotation " + annot + " element: " + m.getName());
+            } catch (InvocationTargetException e) {
+                throw new ValidationException("Cannot access annotation " + annot + " element: " + m.getName());
+            }
+        }
+    }
+
     public void putValue(String elementName, Object value) {
         elements.put(elementName, value);
     }

Modified: incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java?rev=940395&r1=940394&r2=940395&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java Mon May  3 08:35:46 2010
@@ -19,27 +19,20 @@
 
 package org.apache.bval.jsr303;
 
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import junit.framework.Assert;
+import junit.framework.TestCase;
 
+import javax.validation.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.metadata.ConstraintDescriptor;
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 import java.util.Locale;
 import java.util.Set;
 
-import javax.validation.Constraint;
-import javax.validation.ConstraintViolation;
-import javax.validation.Payload;
-import javax.validation.Validation;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-import javax.validation.constraints.NotNull;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * Checks that groups are correctly inherited from the root constraint to its
@@ -91,6 +84,31 @@ public class ConstraintCompositionTest e
         String msg = violations.iterator().next().getMessage();
         Assert.assertEquals("Incorrect violation message", "A person needs a non null name", msg);
     }
+
+    /**
+     * Checks that the groups() value of the constraint annotations are
+     * correctly set to the inherited ones.
+     */
+    public void testAnnotationGroupsAreInherited() {
+        Validator validator = getValidator();
+        
+        // Check that the groups() value is right when querying the metadata
+        ConstraintDescriptor<?> manNameDesc = getValidator().getConstraintsForClass(Man.class).getConstraintsForProperty("name").getConstraintDescriptors().iterator().next();
+        ConstraintDescriptor<?> personNameDesc = manNameDesc.getComposingConstraints().iterator().next();
+        ConstraintDescriptor<?> notNullDesc = personNameDesc.getComposingConstraints().iterator().next();
+        Assert.assertEquals("There should only be 1 group", 1, manNameDesc.getGroups().size());
+        Assert.assertTrue("Group1 should be present", manNameDesc.getGroups().contains(Group1.class));
+        Assert.assertEquals("There should only be 1 group", 1, personNameDesc.getGroups().size());
+        Assert.assertTrue("Group1 should be present", personNameDesc.getGroups().contains(Group1.class));
+        Assert.assertEquals("There should only be 1 group", 1, personNameDesc.getGroups().size());
+        Assert.assertTrue("Group1 should be present", notNullDesc.getGroups().contains(Group1.class));
+        
+        // Check that the groups() value is right when accesing it from an error
+        Set<ConstraintViolation<Man>> violations = validator.validate(new Man(), Group1.class);
+        Set<Class<?>> notNullGroups = violations.iterator().next().getConstraintDescriptor().getGroups();
+        Assert.assertEquals("There should only be 1 group", 1, notNullGroups.size());
+        Assert.assertTrue("Group1 should be the only group", notNullGroups.contains(Group1.class));
+    }