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));
+ }