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/04 17:35:16 UTC
svn commit: r940911 - in /incubator/bval/trunk/bval-jsr303/src:
main/java/org/apache/bval/jsr303/
main/java/org/apache/bval/jsr303/extensions/
test/java/org/apache/bval/jsr303/ test/java/org/apache/bval/jsr303/xml/
Author: romanstumm
Date: Tue May 4 15:35:16 2010
New Revision: 940911
URL: http://svn.apache.org/viewvc?rev=940911&view=rev
Log:
BVAL-35 Improved support of @OverridesAttribute - from Carlos Varla
Added:
incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/BaseAppendValidation.java
Modified:
incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AnnotationConstraintBuilder.java
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/AppendValidationToMeta.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/Jsr303MetaBeanFactory.java
incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/extensions/AppendValidationToList.java
incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ComposedConstraintsTest.java
incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ConstraintCompositionTest.java
incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/xml/ValidationParserTest.java
Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AnnotationConstraintBuilder.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AnnotationConstraintBuilder.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AnnotationConstraintBuilder.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AnnotationConstraintBuilder.java Tue May 4 15:35:16 2010
@@ -21,6 +21,7 @@ package org.apache.bval.jsr303;
import org.apache.bval.jsr303.groups.GroupsComputer;
import org.apache.bval.jsr303.util.SecureActions;
+import org.apache.bval.jsr303.xml.AnnotationProxyBuilder;
import org.apache.bval.util.AccessStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -156,30 +157,44 @@ final class AnnotationConstraintBuilder
constraintValidation.addComposed(composite); // add AFTER apply()
}
- private void applyOverridesAttributes(ConstraintValidation composite) {
- if (null == overrides) buildOverridesAttributes();
+ private void applyOverridesAttributes(ConstraintValidation<?> composite) {
+ if (null == overrides) {
+ buildOverridesAttributes();
+ }
if (!overrides.isEmpty()) {
- int index = computeIndex(composite); // assume composite not yet added! (+1)
- if (index < 0) {
- ConstraintOverrides override = // search for constraintIndex = -1
- findOverride(composite.getAnnotation().annotationType(), -1);
- if (override != null) override.applyOn(composite);
- else override = // search for constraintIndex == 0
- findOverride(composite.getAnnotation().annotationType(), 0);
- if (override != null) override.applyOn(composite);
- } else { // search for constraintIndex > 0
- ConstraintOverrides override =
- findOverride(composite.getAnnotation().annotationType(), index + 1);
- if (override != null) override.applyOn(composite);
+ int index = computeIndex(composite);
+
+ // Search for the overrides to apply
+ ConstraintOverrides generalOverride = findOverride(composite.getAnnotation().annotationType(), -1);
+ if ( generalOverride != null ) {
+ if ( index > 0 ) {
+ throw new ConstraintDeclarationException("Wrong OverridesAttribute declaration for " + generalOverride.constraintType + ", it needs a defined index when there is a list of constraints");
+ }
+ generalOverride.applyOn(composite);
+ }
+
+ ConstraintOverrides override = findOverride(composite.getAnnotation().annotationType(), index);
+ if ( override != null ) {
+ override.applyOn(composite);
}
+
}
}
- private int computeIndex(ConstraintValidation composite) {
- int idx = -1;
+
+ /**
+ * Calculates the index of the composite constraint. The index represents
+ * the order in which it is added in reference to other constraints of the
+ * same type.
+ *
+ * @param composite
+ * The composite constraint (not yet added).
+ * @return An integer index always >= 0
+ */
+ private int computeIndex(ConstraintValidation<?> composite) {
+ int idx = 0;
for (ConstraintValidation<?> each : constraintValidation.getComposingValidations()) {
- if (each.getAnnotation().annotationType() ==
- composite.getAnnotation().annotationType()) {
+ if (each.getAnnotation().annotationType() == composite.getAnnotation().annotationType()) {
idx++;
}
}
@@ -188,7 +203,7 @@ final class AnnotationConstraintBuilder
/** read overridesAttributes from constraintValidation.annotation */
private void buildOverridesAttributes() {
- overrides = new LinkedList();
+ overrides = new LinkedList<ConstraintOverrides>();
for (Method method : constraintValidation.getAnnotation()
.annotationType()
.getDeclaredMethods()) {
@@ -246,7 +261,17 @@ final class AnnotationConstraintBuilder
}
public void applyOn(ConstraintValidation composite) {
+ // Update the attributes
composite.getAttributes().putAll(values);
+
+ // And the annotation
+ Annotation originalAnnot = composite.getAnnotation();
+ AnnotationProxyBuilder<Annotation> apb = new AnnotationProxyBuilder<Annotation>(originalAnnot);
+ for ( String key : values.keySet() ) {
+ apb.putValue(key, values.get(key));
+ }
+ Annotation newAnnot = apb.createAnnotation();
+ composite.setAnnotation(newAnnot);
}
}
}
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=940911&r1=940910&r2=940911&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 Tue May 4 15:35:16 2010
@@ -25,14 +25,14 @@ import java.util.Set;
/**
* Description: <br/>
*/
-public class AppendValidationToBuilder implements AppendValidation {
+public class AppendValidationToBuilder extends BaseAppendValidation {
private final AnnotationConstraintBuilder builder;
public AppendValidationToBuilder(AnnotationConstraintBuilder builder) {
this.builder = builder;
}
- public <T extends Annotation> void append(ConstraintValidation<T> validation) {
+ public <T extends Annotation> void preProcessValidation(ConstraintValidation<T> validation) {
// 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.
@@ -52,8 +52,9 @@ public class AppendValidationToBuilder i
apb.putValue("payload", inheritedPayload.toArray(new Class[inheritedPayload.size()]));
T newAnnot = apb.createAnnotation();
validation.setAnnotation(newAnnot);
-
- // And finally, add the composed validation
+ }
+
+ public <T extends Annotation> void performAppend(ConstraintValidation<T> validation) {
builder.addComposed(validation);
}
Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToMeta.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToMeta.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToMeta.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/AppendValidationToMeta.java Tue May 4 15:35:16 2010
@@ -16,21 +16,21 @@
*/
package org.apache.bval.jsr303;
-import java.lang.annotation.Annotation;
-
import org.apache.bval.model.FeaturesCapable;
+import java.lang.annotation.Annotation;
+
/**
* Description: <br/>
*/
-public class AppendValidationToMeta implements AppendValidation {
+public class AppendValidationToMeta extends BaseAppendValidation {
private final FeaturesCapable feature;
public AppendValidationToMeta(FeaturesCapable meta) {
this.feature = meta;
}
- public <T extends Annotation> void append(ConstraintValidation<T> validation) {
+ public <T extends Annotation> void performAppend(ConstraintValidation<T> validation) {
feature.addValidation(validation);
}
}
Added: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/BaseAppendValidation.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/BaseAppendValidation.java?rev=940911&view=auto
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/BaseAppendValidation.java (added)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/BaseAppendValidation.java Tue May 4 15:35:16 2010
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.bval.jsr303;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Abstract base validation appender that initializes the
+ * {@link ConstraintValidation#getValidator()} on post-processing.
+ *
+ * @author Carlos Vara
+ */
+public abstract class BaseAppendValidation implements AppendValidation {
+
+ /**
+ * Append operation divided in 3 stages: pre & post processing and the
+ * "real" append process.
+ */
+ public final <T extends Annotation> void append(ConstraintValidation<T> validation) {
+ preProcessValidation(validation);
+ performAppend(validation);
+ postProcessValidation(validation);
+ }
+
+ /**
+ * Performs the actual "appending" operation to the underlying data
+ * structure that holds the validations. Implementations shouldn't try to do
+ * more than that in this step.
+ *
+ * @param <T>
+ * The type of the validation.
+ * @param validation
+ * The validation to be appended.
+ */
+ public abstract <T extends Annotation> void performAppend(ConstraintValidation<T> validation);
+
+ /**
+ * Pre-process the validation before appending it.
+ *
+ * @param <T>
+ * The type of the validation.
+ * @param validation
+ * The validation to be appended.
+ */
+ public <T extends Annotation> void preProcessValidation(ConstraintValidation<T> validation) {
+ // No generic pre-processing
+ }
+
+ /**
+ * Post-process the validation once it has been appended.
+ *
+ * @param <T>
+ * The type of the validation.
+ * @param validation
+ * The validation to be appended.
+ */
+ public <T extends Annotation> void postProcessValidation(ConstraintValidation<T> validation) {
+ // Initialize the validator
+ validation.initialize();
+ }
+
+}
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=940911&r1=940910&r2=940911&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 Tue May 4 15:35:16 2010
@@ -27,6 +27,7 @@ import org.apache.bval.model.ValidationC
import org.apache.bval.model.ValidationListener;
import org.apache.bval.util.AccessStrategy;
+import javax.validation.ConstraintDefinitionException;
import javax.validation.ConstraintValidator;
import javax.validation.Payload;
import javax.validation.ValidationException;
@@ -150,6 +151,9 @@ public class ConstraintValidation<T exte
}
}
+ // Restore current constraint validation
+ context.setConstraintValidation(this);
+
if (validator != null) {
ConstraintValidatorContextImpl jsrContext =
new ConstraintValidatorContextImpl(context, this);
@@ -159,6 +163,23 @@ public class ConstraintValidation<T exte
}
}
+ /**
+ * Initialize the validator (if not <code>null</code>) with the stored
+ * annotation.
+ */
+ public void initialize() {
+ if (null != validator) {
+ try {
+ validator.initialize(annotation);
+ } catch (RuntimeException e) {
+ // Either a "legit" problem initializing the validator or a
+ // ClassCastException if the validator associated annotation is
+ // not a supertype of the validated annotation.
+ throw new ConstraintDefinitionException("Incorrect validator [" + validator.getClass().getCanonicalName() + "] for annotation " + annotation.annotationType().getCanonicalName(), e);
+ }
+ }
+ }
+
private boolean isCascadeEnabled(GroupValidationContext context) {
PathImpl path = context.getPropertyPath();
NodeImpl node = path.getLeafNode();
Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java Tue May 4 15:35:16 2010
@@ -437,13 +437,7 @@ public class Jsr303MetaBeanFactory imple
checkOneType(assignableTypes, type, owner, annotation, access);
validator = getConstraintValidatorFactory()
.getInstance(validatorTypes.get(assignableTypes.get(0)));
- try {
- validator.initialize(annotation);
- } catch (RuntimeException e) {
- // Either a "legit" problem initializing the validator or a ClassCastException if
- // the validator associated annotation is not a supertype of the validated annotation.
- throw new ConstraintDefinitionException("Incorrect validator ["+validator.getClass().getCanonicalName()+"] for annotation " + annotation.annotationType().getCanonicalName(), e);
- }
+ // NOTE: validator initialization deferred until append phase
} else {
validator = null;
}
Modified: incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/extensions/AppendValidationToList.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/extensions/AppendValidationToList.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/extensions/AppendValidationToList.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/main/java/org/apache/bval/jsr303/extensions/AppendValidationToList.java Tue May 4 15:35:16 2010
@@ -17,23 +17,23 @@
package org.apache.bval.jsr303.extensions;
+import org.apache.bval.jsr303.BaseAppendValidation;
+import org.apache.bval.jsr303.ConstraintValidation;
+
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
-import org.apache.bval.jsr303.AppendValidation;
-import org.apache.bval.jsr303.ConstraintValidation;
-
/**
* Description: <br/>
*/
-public class AppendValidationToList implements AppendValidation {
+public class AppendValidationToList extends BaseAppendValidation {
private final List<ConstraintValidation<? extends Annotation>> validations = new ArrayList<ConstraintValidation<? extends Annotation>>();
public AppendValidationToList() {
}
- public <T extends Annotation> void append(ConstraintValidation<T> validation) {
+ public <T extends Annotation> void performAppend(ConstraintValidation<T> validation) {
validations.add(validation);
}
Modified: incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ComposedConstraintsTest.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ComposedConstraintsTest.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ComposedConstraintsTest.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/ComposedConstraintsTest.java Tue May 4 15:35:16 2010
@@ -79,7 +79,7 @@ public class ComposedConstraintsTest ext
ConstraintViolation<FrenchAddress> finding = findings.iterator().next();
Assert.assertEquals("Wrong zipcode", finding.getMessage());
- adr.setZipCode("12345");
+ adr.setZipCode("1234567");
findings = val.validate(adr);
Assert.assertEquals(0, findings.size());
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=940911&r1=940910&r2=940911&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 Tue May 4 15:35:16 2010
@@ -24,6 +24,7 @@ import junit.framework.TestCase;
import javax.validation.*;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
import javax.validation.metadata.ConstraintDescriptor;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
@@ -134,11 +135,43 @@ public class ConstraintCompositionTest e
Assert.assertEquals("There should only be 1 payload class", 1, notNullPayload.size());
Assert.assertTrue("Payload1 should be the only payload", notNullPayload.contains(Payload1.class));
}
-
+
+ /**
+ * Checks that {@link OverridesAttribute#constraintIndex()} parsing and
+ * applying works.
+ */
+ public void testIndexedOverridesAttributes() {
+ Validator validator = getValidator();
+
+ Person p = new Person();
+ p.name = "valid";
+
+ // With a valid id, no errors expected
+ p.id = "1234";
+ Set<ConstraintViolation<Person>> constraintViolations = validator.validate(p);
+ Assert.assertTrue("No violations should be reported on valid id", constraintViolations.isEmpty());
+
+ // With a short id, only 1 error expected
+ p.id = "1";
+ constraintViolations = validator.validate(p);
+ Assert.assertEquals("Only 1 violation expected", 1, constraintViolations.size());
+ ConstraintViolation<Person> violation = constraintViolations.iterator().next();
+ Assert.assertEquals("Wrong violation", "Id is too short", violation.getMessage());
+
+ // With a long id, only 1 error expected
+ p.id = "loooooong id";
+ constraintViolations = validator.validate(p);
+ Assert.assertEquals("Only 1 violation expected", 1, constraintViolations.size());
+ violation = constraintViolations.iterator().next();
+ Assert.assertEquals("Wrong violation", "Id is too long", violation.getMessage());
+ }
public static class Person {
@PersonName
String name;
+
+ @PersonId
+ String id;
}
public static class Man {
@@ -168,6 +201,25 @@ public class ConstraintCompositionTest e
Class<? extends Payload>[] payload() default {};
}
+
+ @Size.List({ @Size(min=3, max=3, message="Id is too short"), @Size(min=5,max=5, message="Id is too long") })
+ @Constraint(validatedBy = {})
+ @Documented
+ @Target({ METHOD, FIELD, TYPE })
+ @Retention(RUNTIME)
+ public static @interface PersonId {
+ String message() default "Wrong person id";
+ Class<?>[] groups() default { };
+ Class<? extends Payload>[] payload() default {};
+
+ @OverridesAttribute(constraint=Size.class,constraintIndex=0,name="max")
+ int maxSize() default 1000;
+
+ @OverridesAttribute(constraint=Size.class,constraintIndex=1,name="min")
+ int minSize() default 0;
+
+ }
+
public static interface Group1 {
}
Modified: incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/xml/ValidationParserTest.java
URL: http://svn.apache.org/viewvc/incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/xml/ValidationParserTest.java?rev=940911&r1=940910&r2=940911&view=diff
==============================================================================
--- incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/xml/ValidationParserTest.java (original)
+++ incubator/bval/trunk/bval-jsr303/src/test/java/org/apache/bval/jsr303/xml/ValidationParserTest.java Tue May 4 15:35:16 2010
@@ -21,19 +21,16 @@ package org.apache.bval.jsr303.xml;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
-
-import javax.validation.ConstraintViolation;
-import javax.validation.Validation;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-
import org.apache.bval.jsr303.ApacheValidationProvider;
import org.apache.bval.jsr303.ApacheValidatorConfiguration;
import org.apache.bval.jsr303.ConfigurationImpl;
import org.apache.bval.jsr303.example.XmlEntitySampleBean;
import org.apache.bval.jsr303.resolver.SimpleTraversableResolver;
-import org.apache.bval.jsr303.xml.ValidationParser;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
import java.util.Set;
/**
@@ -82,7 +79,7 @@ public class ValidationParserTest extend
assertTrue(!results.isEmpty());
assertTrue(results.size() == 3);
- bean.setZipCode("valid");
+ bean.setZipCode("123");
bean.setValueCode("20");
bean.setFirstName("valid");
results = validator.validate(bean);