Implement spec section 2.2. Applying multiple constraints of the same type.
[JSR 303 TCK Result] 64 of 257 (24.90%) Pass with 26 Failures and 4 Errors.
Review at http://gwt-code-reviews.appspot.com/1288802
Review by: rchandia@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9570 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
index 409e546..111dfb3 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -46,6 +46,7 @@
import com.google.gwt.validation.client.impl.PropertyDescriptorImpl;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
@@ -55,6 +56,7 @@
import java.util.Map.Entry;
import java.util.Set;
+import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintViolation;
import javax.validation.Payload;
@@ -75,6 +77,8 @@
OBJECT, PROPERTY, VALUE
}
+ private static final Annotation[] NO_ANNOTATIONS = new Annotation[]{};
+
private static final JType[] NO_ARGS = new JType[]{};
/**
@@ -292,14 +296,27 @@
return annotation;
}
- private Annotation getAnnotation(PropertyDescriptor p, boolean useField,
- ConstraintDescriptor<?> constraint) {
- Class<? extends Annotation> expectedAnnotationClass =
- ((Annotation) constraint.getAnnotation()).annotationType();
- return getAnnotation(p, useField, expectedAnnotationClass);
+ private Annotation[] getAnnotations(PropertyDescriptor p,
+ boolean useField) {
+ Class<?> clazz = beanHelper.getClazz();
+ if (useField) {
+ try {
+ Field field = clazz.getDeclaredField(p.getPropertyName());
+ return field.getAnnotations();
+ } catch (NoSuchFieldException ignore) {
+ // Expected Case
+ }
+ } else {
+ try {
+ Method method = clazz.getMethod(asGetter(p));
+ return method.getAnnotations();
+ } catch (NoSuchMethodException ignore) {
+ // Expected Case
+ }
+ }
+ return NO_ANNOTATIONS;
}
-
private JType getAssociationType(PropertyDescriptor p, boolean useField) {
JType type = getElementType(p, useField);
JArrayType jArray = type.isArray();
@@ -313,6 +330,7 @@
return typeArgs[typeArgs.length - 1];
}
+
private JType getElementType(PropertyDescriptor p, boolean useField) {
if (useField) {
return beanType.findField(p.getPropertyName()).getType();
@@ -351,6 +369,63 @@
}
}
+ private boolean hasMatchingAnnotation(Annotation expectedAnnotation,
+ Annotation[] annotations) throws UnableToCompleteException {
+ // See spec section 2.2. Applying multiple constraints of the same type
+ for (Annotation annotation : annotations) {
+ // annotations not annotated by @Constraint
+ if (annotation.annotationType().getAnnotation(Constraint.class) == null) {
+ try {
+ // value element has a return type of an array of constraint
+ // annotations
+ Method valueMethod = annotation.annotationType().getMethod("value");
+ Class<?> valueType = valueMethod.getReturnType();
+ if (valueType.isArray()
+ && Annotation.class.isAssignableFrom(valueType.getComponentType())) {
+ Annotation[] valueAnnotions = (Annotation[]) valueMethod.invoke(annotation);
+ for (Annotation annotation2 : valueAnnotions) {
+ if (expectedAnnotation.equals(annotation2)) {
+ return true;
+ }
+ }
+ }
+ } catch (NoSuchMethodException ignore) {
+ // Expected Case.
+ } catch (Exception e) {
+ throw error(logger, e);
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean hasMatchingAnnotation(ConstraintDescriptor<?> constraint)
+ throws UnableToCompleteException {
+ Annotation expectedAnnotation = constraint.getAnnotation();
+ Class<? extends Annotation> expectedAnnotationClass = expectedAnnotation.annotationType();
+ if (expectedAnnotation.equals(beanHelper.getClazz().getAnnotation(
+ expectedAnnotationClass))) {
+ return true;
+ }
+
+ // See spec section 2.2. Applying multiple constraints of the same type
+ Annotation[] annotations = beanHelper.getClazz().getAnnotations();
+ return hasMatchingAnnotation(expectedAnnotation, annotations);
+ }
+
+ private boolean hasMatchingAnnotation(PropertyDescriptor p, boolean useField,
+ ConstraintDescriptor<?> constraint) throws UnableToCompleteException {
+ Annotation expectedAnnotation = constraint.getAnnotation();
+ Class<? extends Annotation> expectedAnnotationClass =
+ expectedAnnotation.annotationType();
+ if (expectedAnnotation.equals(getAnnotation(p, useField,
+ expectedAnnotationClass))) {
+ return true;
+ }
+ return hasMatchingAnnotation(expectedAnnotation,
+ getAnnotations(p, useField));
+ }
+
private boolean hasValid(PropertyDescriptor p, boolean useField) {
return getAnnotation(p, useField, Valid.class) != null;
}
@@ -743,7 +818,7 @@
}
}
- private void writeValidate(SourceWriter sw) {
+ private void writeValidate(SourceWriter sw) throws UnableToCompleteException {
// public <T> Set<ConstraintViolation<T>> validate(
sw.println("public <T> Set<ConstraintViolation<T>> validate(");
@@ -780,27 +855,32 @@
int count = 0;
Class<?> clazz = beanHelper.getClazz();
for (ConstraintDescriptor<?> constraint : beanHelper.getBeanDescriptor().findConstraints().getConstraintDescriptors()) {
+ Annotation annotation = constraint.getAnnotation();
+ if (hasMatchingAnnotation(constraint)) {
+ Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass = getValidatorForType(
+ constraint, clazz);
+ if (validatorClass != null) {
+ // TODO(nchalko) handle constraint.isReportAsSingleViolation() and
+ // hasComposingConstraints
- Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass = getValidatorForType(
- constraint, clazz);
- if (validatorClass != null) {
- // TODO(nchalko) handle constraint.isReportAsSingleViolation() and
- // hasComposingConstraints
+ // validate(context, violations, null, object,
+ sw.print("validate(context, violations, null, object, ");
- // validate(context, violations, object, value, validator,
- // constraintDescriptor, groups);
- sw.print("validate(context, violations, null, object, ");
- // new MyValidtor();
- sw.print("new ");
- sw.print(validatorClass.getCanonicalName());
- sw.print("(), "); // new one each time because validators are not thread
- // safe
- sw.print(constraintDescriptorVar("this", count));
- sw.println(", groups);");
- } else {
- // TODO(nchalko) What does the spec say to do here.
- logger.log(Type.WARN, "No ConstraintValidator of " + constraint
- + " for type " + clazz);
+ // new MyValidtor();
+ sw.print("new ");
+ sw.print(validatorClass.getCanonicalName());
+ sw.print("(), "); // new one each time because validators are not
+ // thread
+ // safe
+
+ // this.aConstraintDescriptor, groups);;
+ sw.print(constraintDescriptorVar("this", count));
+ sw.println(", groups);");
+ } else {
+ // TODO(nchalko) What does the spec say to do here.
+ logger.log(Type.WARN, "No ConstraintValidator of " + constraint
+ + " for type " + clazz);
+ }
}
count++; // index starts at 0
}
@@ -1213,10 +1293,7 @@
int count = 0;
for (ConstraintDescriptor<?> constraint : p.getConstraintDescriptors()) {
- Annotation annotation = getAnnotation(p, useField, constraint);
- if (annotation != null) {
- // TODO(nchalko) check for annotation equality
-
+ if (hasMatchingAnnotation(p, useField, constraint)) {
String constraintDescriptorVar = constraintDescriptorVar(
p.getPropertyName(), count);
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java
index 25bfde8..e870ffc 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java
@@ -28,7 +28,6 @@
delegate.testPropertyPathSet();
}
- @Failing(issue = 5803)
public void testPropertyPathTraversedObject() {
delegate.testPropertyPathTraversedObject();
}
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/TckTestValidatorFactory.java b/user/test/org/hibernate/jsr303/tck/tests/validation/TckTestValidatorFactory.java
index df5b82c..6be0de3 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/TckTestValidatorFactory.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/TckTestValidatorFactory.java
@@ -34,7 +34,8 @@
* Marker Interface for {@link GWT#create(Class)}.
*/
@GwtValidation(value = {
- Actor.class, ActorDB.class, ActorArrayBased.class, ActorListBased.class,
+ // Actor must be after its subclasses
+ ActorDB.class, ActorArrayBased.class, ActorListBased.class, Actor.class,
Address.class, BadlyBehavedEntity.class, Customer.class, Engine.class,
Order.class, VerySpecialClass.class})
public static interface GwtValidator extends Validator {