Handle Validation of Cascaded Generic properties.
Make GwtValidators Singletons.
[JSR 303 TCK Result] 88 of 257 (34.24%) Pass with 38 Failures and 14 Errors.
Review at http://gwt-code-reviews.appspot.com/1343801
Review by: rchandia@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9678 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.java b/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.java
index 17da692..1f0ad4f 100644
--- a/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.java
+++ b/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.java
@@ -20,6 +20,7 @@
import java.util.Set;
import javax.validation.ConstraintValidatorFactory;
+import javax.validation.ConstraintViolation;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.ValidationException;
@@ -58,6 +59,10 @@
throw new ValidationException();
}
+ public abstract <T> Set<ConstraintViolation<T>> validate(
+ GwtValidationContext<T> context, Object object, Class<?>... groups)
+ throws ValidationException;
+
protected void checkGroups(Class<?>... groups) {
// an empty list of valid groups means all groups are valid.
if (!validGroups.isEmpty()
diff --git a/user/src/com/google/gwt/validation/client/impl/GwtValidationContext.java b/user/src/com/google/gwt/validation/client/impl/GwtValidationContext.java
index 0ff46f5..612813f 100644
--- a/user/src/com/google/gwt/validation/client/impl/GwtValidationContext.java
+++ b/user/src/com/google/gwt/validation/client/impl/GwtValidationContext.java
@@ -32,15 +32,17 @@
private PathImpl path = new PathImpl();
private final T rootBean;
private final MessageInterpolator messageInterpolator;
+ private final AbstractGwtValidator validator;
/**
*
*/
public GwtValidationContext(T rootBean, BeanDescriptor beanDescriptor,
- MessageInterpolator messageInterpolator) {
+ MessageInterpolator messageInterpolator, AbstractGwtValidator validator) {
this.rootBean = rootBean;
this.beanDescriptor = beanDescriptor;
this.messageInterpolator = messageInterpolator;
+ this.validator = validator;
}
/**
@@ -51,7 +53,7 @@
*/
public GwtValidationContext<T> append(String name) {
GwtValidationContext<T> temp = new GwtValidationContext<T>(rootBean,
- beanDescriptor, messageInterpolator);
+ beanDescriptor, messageInterpolator, validator);
temp.path = path.append(name);
return temp;
}
@@ -64,7 +66,7 @@
*/
public GwtValidationContext<T> appendIndex(String name, int index) {
GwtValidationContext<T> temp = new GwtValidationContext<T>(rootBean,
- beanDescriptor, messageInterpolator);
+ beanDescriptor, messageInterpolator, validator);
temp.path = path.appendIndex(name, index);
return temp;
}
@@ -77,7 +79,7 @@
*/
public GwtValidationContext<T> appendKey(String name, String key) {
GwtValidationContext<T> temp = new GwtValidationContext<T>(rootBean,
- beanDescriptor, messageInterpolator);
+ beanDescriptor, messageInterpolator, validator);
temp.path = path.appendKey(name, key);
return temp;
}
@@ -99,4 +101,8 @@
public Class<T> getRootBeanClass() {
return (Class<T>) rootBean.getClass();
}
+
+ public AbstractGwtValidator getValidator() {
+ return validator;
+ }
}
diff --git a/user/src/com/google/gwt/validation/rebind/AbstractCreator.java b/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
index 3e02b60..4e79099 100644
--- a/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
@@ -20,7 +20,6 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JPackage;
-import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.user.rebind.AbstractSourceCreator;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -65,11 +64,12 @@
protected abstract void compose(ClassSourceFileComposerFactory composerFactory);
- protected BeanHelper createBeanHelper(Class<?> clazz) {
+ protected BeanHelper createBeanHelper(Class<?> clazz)
+ throws UnableToCompleteException {
return BeanHelper.createBeanHelper(clazz, logger, context);
}
- protected BeanHelper createBeanHelper(JType jType)
+ protected BeanHelper createBeanHelper(JClassType jType)
throws UnableToCompleteException {
return BeanHelper.createBeanHelper(jType, logger, context);
}
@@ -92,9 +92,9 @@
sw.indent();
sw.indent();
- // GWT.create(MyBeanValidator.class);
- sw.println("GWT.create(" + bean.getFullyQualifiedValidatorName()
- + ".class);");
+ // MyBeanValidator.INSTANCE;
+ sw.print(bean.getFullyQualifiedValidatorName());
+ sw.println(".INSTANCE;");
sw.outdent();
sw.outdent();
}
diff --git a/user/src/com/google/gwt/validation/rebind/BeanHelper.java b/user/src/com/google/gwt/validation/rebind/BeanHelper.java
index f87a6e9..aaee68e 100644
--- a/user/src/com/google/gwt/validation/rebind/BeanHelper.java
+++ b/user/src/com/google/gwt/validation/rebind/BeanHelper.java
@@ -15,11 +15,18 @@
*/
package com.google.gwt.validation.rebind;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JField;
+import com.google.gwt.core.ext.typeinfo.JParameterizedType;
+import com.google.gwt.core.ext.typeinfo.JRawType;
import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.core.ext.typeinfo.NotFoundException;
+import com.google.gwt.thirdparty.guava.common.base.Function;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.validation.client.impl.GwtSpecificValidator;
@@ -32,6 +39,7 @@
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.metadata.BeanDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
/**
* A simple struct for the various values associated with a Bean that can be
@@ -39,6 +47,13 @@
*/
final class BeanHelper {
+ public static final Function<BeanHelper, Class<?>> TO_CLAZZ =
+ new Function<BeanHelper, Class<?>>() {
+ public Class<?> apply(BeanHelper helper) {
+ return helper.getClazz();
+ }
+ };
+
private static final Validator serverSideValidor = Validation.buildDefaultValidatorFactory().getValidator();
// stash the map in a ThreadLocal, since each GWT module lives in its own
@@ -51,28 +66,27 @@
}
};
- protected static BeanHelper createBeanHelper(Class<?> clazz,
- TreeLogger logger, GeneratorContext context) {
- JClassType beanType = context.getTypeOracle().findType(
- clazz.getCanonicalName());
- BeanHelper helper = getBeanHelper(beanType);
- if (helper == null) {
- helper = new BeanHelper(beanType, clazz,
- serverSideValidor.getConstraintsForClass(clazz));
- addBeanHelper(helper);
- writeInterface(context, logger, helper);
- }
- return helper;
+ public static Map<JClassType, BeanHelper> getBeanHelpers() {
+ return Collections.unmodifiableMap(threadLocalHelperMap.get());
}
- protected static BeanHelper createBeanHelper(JType jType, TreeLogger logger,
+ protected static BeanHelper createBeanHelper(Class<?> clazz,
+ TreeLogger logger, GeneratorContext context)
+ throws UnableToCompleteException {
+ JClassType beanType = context.getTypeOracle().findType(
+ clazz.getCanonicalName());
+ return createBeanHelper(clazz, beanType, logger, context);
+ }
+
+ protected static BeanHelper createBeanHelper(JClassType jType, TreeLogger logger,
GeneratorContext context) throws UnableToCompleteException {
+ JClassType erasedType = jType.getErasedType();
try {
- Class<?> clazz = Class.forName(jType.getQualifiedSourceName());
- return createBeanHelper(clazz, logger, context);
+ Class<?> clazz = Class.forName(erasedType.getQualifiedBinaryName());
+ return createBeanHelper(clazz, erasedType, logger, context);
} catch (ClassNotFoundException e) {
- logger.log(TreeLogger.ERROR, "Unable to create BeanHelper for " + jType,
- e);
+ logger.log(TreeLogger.ERROR, "Unable to create BeanHelper for "
+ + erasedType, e);
throw new UnableToCompleteException();
}
}
@@ -82,7 +96,7 @@
}
static BeanHelper getBeanHelper(JClassType beanType) {
- return getBeanHelpers().get(beanType);
+ return getBeanHelpers().get(beanType.getErasedType());
}
/**
@@ -101,8 +115,17 @@
bean.getPackage(), bean.getValidatorName());
factory.addImplementedInterface(GwtSpecificValidator.class.getCanonicalName()
+ " <" + bean.getTypeCanonicalName() + ">");
+ factory.addImport(GWT.class.getCanonicalName());
factory.makeInterface();
SourceWriter sw = factory.createSourceWriter(context, pw);
+
+ // static MyValidator INSTANCE = GWT.create(MyValidator.class);
+ sw.print("static ");
+ sw.print(bean.getValidatorName());
+ sw.print(" INSTANCE = GWT.create(");
+ sw.print(bean.getValidatorName());
+ sw.println(".class);");
+
sw.commit(interfaceLogger);
pw.close();
}
@@ -112,8 +135,45 @@
threadLocalHelperMap.get().put(helper.getJClass(), helper);
}
- private static Map<JClassType, BeanHelper> getBeanHelpers() {
- return Collections.unmodifiableMap(threadLocalHelperMap.get());
+ private static BeanHelper createBeanHelper(Class<?> clazz,
+ JClassType beanType, TreeLogger logger, GeneratorContext context)
+ throws UnableToCompleteException {
+ BeanHelper helper = getBeanHelper(beanType);
+ if (helper == null) {
+ helper = new BeanHelper(beanType, clazz,
+ serverSideValidor.getConstraintsForClass(clazz));
+ addBeanHelper(helper);
+ writeInterface(context, logger, helper);
+ // now recurse on all Cascaded elements
+ for (PropertyDescriptor p : helper.getBeanDescriptor().getConstrainedProperties()) {
+ if (p.isCascaded()) {
+ createBeanHelper(p, helper, logger, context);
+ }
+ }
+ }
+ return helper;
+ }
+
+ private static void createBeanHelper(PropertyDescriptor p, BeanHelper parent,
+ TreeLogger logger, GeneratorContext context)
+ throws UnableToCompleteException {
+ Class<?> elementClass = p.getElementClass();
+ if (GwtSpecificValidatorCreator.isIterableOrMap(elementClass)) {
+ if (parent.hasField(p)) {
+ JClassType type = parent.getAssociationType(p, true);
+
+ createBeanHelper(type.getErasedType(), logger, context);
+ }
+ if (parent.hasGetter(p)) {
+ JClassType type = parent.getAssociationType(p, false);
+
+ createBeanHelper(type.getErasedType(), logger, context);
+ }
+ } else {
+ if (serverSideValidor.getConstraintsForClass(elementClass).isBeanConstrained()) {
+ createBeanHelper(elementClass, logger, context);
+ }
+ }
}
private final BeanDescriptor beanDescriptor;
@@ -130,6 +190,25 @@
this.clazz = clazz;
}
+ public JClassType getAssociationType(PropertyDescriptor p,
+ boolean useField) {
+ JType type = this.getElementType(p, useField);
+ JArrayType jArray = type.isArray();
+ if (jArray != null) {
+ return jArray.getComponentType().isClassOrInterface();
+ }
+ JParameterizedType pType = type.isParameterized();
+ JClassType[] typeArgs;
+ if (pType == null) {
+ JRawType rType = type.isRawType();
+ typeArgs = rType.getGenericType().getTypeParameters();
+ } else {
+ typeArgs = pType.getTypeArgs();
+ }
+ // it is either a Iterable or a Map use the last type arg.
+ return typeArgs[typeArgs.length - 1].isClassOrInterface();
+ }
+
public BeanDescriptor getBeanDescriptor() {
return beanDescriptor;
}
@@ -175,6 +254,30 @@
return getTypeCanonicalName();
}
+ JType getElementType(PropertyDescriptor p, boolean useField) {
+ if (useField) {
+ return jClass.findField(p.getPropertyName()).getType();
+ } else {
+ return jClass.findMethod(GwtSpecificValidatorCreator.asGetter(p),
+ GwtSpecificValidatorCreator.NO_ARGS).getReturnType();
+ }
+ }
+
+ boolean hasField(PropertyDescriptor p) {
+ JField field = jClass.findField(p.getPropertyName());
+ return field != null;
+ }
+
+ boolean hasGetter(PropertyDescriptor p) {
+ JType[] paramTypes = new JType[]{};
+ try {
+ jClass.getMethod(GwtSpecificValidatorCreator.asGetter(p), paramTypes);
+ return true;
+ } catch (NotFoundException e) {
+ return false;
+ }
+ }
+
private String makeJavaSafe(String in) {
return in.replaceAll("\\.", "_");
}
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
index c839b5e..d16aa69 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -22,14 +22,11 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
-import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.thirdparty.guava.common.base.Function;
@@ -86,10 +83,10 @@
private static final Annotation[] NO_ANNOTATIONS = new Annotation[]{};
- private static final JType[] NO_ARGS = new JType[]{};
+ static final JType[] NO_ARGS = new JType[]{};
- private static Function<java.beans.PropertyDescriptor, String>
- PROPERTY_DESCRIPTOR_TO_NAME =
+ private static Function<java.beans.PropertyDescriptor, String>
+ PROPERTY_DESCRIPTOR_TO_NAME =
new Function<java.beans.PropertyDescriptor, String>() {
public String apply(java.beans.PropertyDescriptor pd) {
return pd.getName();
@@ -103,6 +100,10 @@
}
};
+ public static String asGetter(PropertyDescriptor p) {
+ return "get" + capitalizeFirstLetter(p.getPropertyName());
+ }
+
/**
* Returns the literal value of an object that is suitable for inclusion in
* Java Source code.
@@ -156,6 +157,26 @@
+ " is can not be represented as a Java Literal.");
}
+ public static String capitalizeFirstLetter(String propertyName) {
+ if (propertyName == null) {
+ return null;
+ }
+ if (propertyName.length() == 0) {
+ return "";
+ }
+ String cap = propertyName.substring(0, 1).toUpperCase();
+ if (propertyName.length() > 1) {
+ cap += propertyName.substring(1);
+ }
+ return cap;
+ }
+
+ public static boolean isIterableOrMap(Class<?> elementClass) {
+ // TODO(nchalko) handle iterables everywhere this is called.
+ return elementClass.isArray()
+ || Iterable.class.isAssignableFrom(elementClass)
+ || Map.class.isAssignableFrom(elementClass);
+ }
static <T extends Annotation> Class<?> getTypeOfConstraintValidator(
Class<? extends ConstraintValidator<T, ?>> constraintClass) {
@@ -169,7 +190,6 @@
throw new IllegalStateException(
"ConstraintValidators must have a isValid method");
}
-
// Visible for testing
static <A extends Annotation> Class<? extends ConstraintValidator<A, ?>> getValidatorForType(
Class<?> type,
@@ -207,16 +227,16 @@
return getValidatorForType(clazz, constraintValidatorClasses);
}
- private BeanHelper beanHelper;
- private Set<BeanHelper> beansToValidate = Sets.newHashSet();
+ private final BeanHelper beanHelper;
+
+ private final Set<BeanHelper> beansToValidate = Sets.newHashSet();
+
private final JClassType beanType;
private final Set<JField> fieldsToWrap = Sets.newHashSet();
private Set<JMethod> gettersToWrap = Sets.newHashSet();
-
-
private final TypeOracle oracle;
public GwtSpecificValidatorCreator(JClassType validatorType,
@@ -279,24 +299,6 @@
return collection.toArray(array);
}
- private String asGetter(PropertyDescriptor p) {
- return "get" + capitalizeFirstLetter(p.getPropertyName());
- }
-
- private String capitalizeFirstLetter(String propertyName) {
- if (propertyName == null) {
- return null;
- }
- if (propertyName.length() == 0) {
- return "";
- }
- String cap = propertyName.substring(0, 1).toUpperCase();
- if (propertyName.length() > 1) {
- cap += propertyName.substring(1);
- }
- return cap;
- }
-
private String constraintDescriptorVar(String name, int count) {
String s = name + "_c" + count;
return s;
@@ -340,58 +342,12 @@
return NO_ANNOTATIONS;
}
- private JType getAssociationType(PropertyDescriptor p, boolean useField) {
- JType type = getElementType(p, useField);
- JArrayType jArray = type.isArray();
- if (jArray != null) {
- // TODO(nchalko) check stuff
- return jArray.getComponentType();
- }
- JParameterizedType pType = type.isParameterized();
- JClassType[] typeArgs = pType.getTypeArgs();
- // it is either a Iterable or a Map use the last type arg.
- return typeArgs[typeArgs.length - 1];
- }
-
-
- private JType getElementType(PropertyDescriptor p, boolean useField) {
- if (useField) {
- return beanType.findField(p.getPropertyName()).getType();
- } else {
- return beanType.findMethod(this.asGetter(p), NO_ARGS).getReturnType();
- }
- }
-
- /**
- * @param elementType
- * @return
- */
private String getQualifiedSourceNonPrimitiveType(JType elementType) {
JPrimitiveType primitive = elementType.isPrimitive();
return primitive == null ? elementType.getQualifiedSourceName()
: primitive.getQualifiedBoxedSourceName();
}
- private boolean hasField(PropertyDescriptor p) {
- JField field = beanType.findField(p.getPropertyName());
- return field != null;
- }
-
- /**
- * @param beanHelper2
- * @param p
- * @return
- */
- private boolean hasGetter(PropertyDescriptor p) {
- JType[] paramTypes = new JType[]{};
- try {
- beanType.getMethod(asGetter(p), paramTypes);
- return true;
- } catch (NotFoundException e) {
- return false;
- }
- }
-
private boolean hasMatchingAnnotation(Annotation expectedAnnotation,
Annotation[] annotations) throws UnableToCompleteException {
// See spec section 2.2. Applying multiple constraints of the same type
@@ -453,13 +409,6 @@
return getAnnotation(p, useField, Valid.class) != null;
}
- private boolean isIterableOrMap(Class<?> elementClass) {
- // TODO(nchalko) handle iterables everywhere this is called.
- return elementClass.isArray()
- || Iterable.class.isAssignableFrom(elementClass)
- || Map.class.isAssignableFrom(elementClass);
- }
-
private boolean isPropertyConstrained(BeanHelper helper, PropertyDescriptor p) {
Set<PropertyDescriptor> propertyDescriptors =
helper.getBeanDescriptor().getConstrainedProperties();
@@ -695,7 +644,7 @@
writePropertyDescriptor(sw, p);
if (p.isCascaded()) {
beansToValidate.add(isIterableOrMap(p.getElementClass())
- ? createBeanHelper(getAssociationType(p, true))
+ ? createBeanHelper(beanHelper.getAssociationType(p, true))
: createBeanHelper(p.getElementClass()));
}
}
@@ -901,11 +850,11 @@
throws UnableToCompleteException {
for (PropertyDescriptor p :
beanHelper.getBeanDescriptor().getConstrainedProperties()) {
- if (hasField(p)) {
+ if (beanHelper.hasField(p)) {
writeValidatePropertyMethod(sw, p, true);
sw.println();
}
- if (hasGetter(p)) {
+ if (beanHelper.hasGetter(p)) {
writeValidatePropertyMethod(sw, p, false);
sw.println();
}
@@ -930,69 +879,63 @@
writeNewViolations(sw);
- if (beanHelper.getBeanDescriptor().isBeanConstrained()) {
+ // /// For each group
- // /// For each group
+ // TODO(nchalko) handle the sequence in the AbstractValidator
- // TODO(nchalko) handle the sequence in the AbstractValidator
+ // See JSR 303 section 3.5
+ // all reachable fields
+ // all reachable getters (both) at once
+ // including all reachable and cascadable associations
- // See JSR 303 section 3.5
- // all reachable fields
- // all reachable getters (both) at once
+ Set<PropertyDescriptor> properties = beanHelper.getBeanDescriptor().getConstrainedProperties();
- Set<PropertyDescriptor> properties = beanHelper.getBeanDescriptor().getConstrainedProperties();
-
- for (PropertyDescriptor p : properties) {
- writeValidatePropertyCall(sw, p, false);
- }
-
- // all class level constraints
- // including super classes
- // including super interfaces
-
- 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
-
- // validate(context, violations, null, object,
- 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
-
- // 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++;
- }
-
- // validate all super classes and interfaces
- writeValidateInheritance(sw, clazz, Stage.OBJECT, null);
-
- // all reachable and cascadable associations
+ for (PropertyDescriptor p : properties) {
+ writeValidatePropertyCall(sw, p, false);
}
+
+ // all class level constraints
+
+
+ int count = 0;
+ Class<?> clazz = beanHelper.getClazz();
+ for (ConstraintDescriptor<?> constraint : beanHelper.getBeanDescriptor().getConstraintDescriptors()) {
+ if (hasMatchingAnnotation(constraint)) {
+ 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, ");
+
+ // 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++;
+ }
+
+ // validate super classes and super interfaces
+ writeValidateInheritance(sw, clazz, Stage.OBJECT, null);
+
// return violations;
sw.println("return violations;");
- writeCatchUnexpectedException(
- sw,
+ writeCatchUnexpectedException(sw,
"\"Error validating " + beanHelper.getTypeCanonicalName() + "\"");
sw.outdent();
@@ -1045,7 +988,8 @@
if (useValue) {
sw.print("null, ");
sw.print("(");
- sw.print(getQualifiedSourceNonPrimitiveType(getElementType(p, true)));
+ sw.print(getQualifiedSourceNonPrimitiveType(beanHelper.getElementType(p,
+ true)));
sw.print(") value");
} else {
sw.print("object, ");
@@ -1077,7 +1021,8 @@
if (useValue) {
sw.print("null, ");
sw.print("(");
- sw.print(getQualifiedSourceNonPrimitiveType(getElementType(p, false)));
+ sw.print(getQualifiedSourceNonPrimitiveType(beanHelper.getElementType(p,
+ false)));
sw.print(") value");
} else {
sw.print("object, ");
@@ -1098,7 +1043,8 @@
}
private void writeValidateInheritance(SourceWriter sw, Class<?> clazz,
- Stage stage, PropertyDescriptor property) {
+ Stage stage, PropertyDescriptor property)
+ throws UnableToCompleteException {
writeValidateInterfaces(sw, clazz, stage, property);
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
@@ -1107,22 +1053,19 @@
}
private void writeValidateInterfaces(SourceWriter sw, Class<?> clazz,
- Stage stage, PropertyDescriptor p) {
+ Stage stage, PropertyDescriptor p) throws UnableToCompleteException {
for (Class<?> type : clazz.getInterfaces()) {
writeValidatorCall(sw, type, stage, p);
writeValidateInterfaces(sw, type, stage, p);
}
}
- private void writeValidateIterable(SourceWriter sw, PropertyDescriptor p,
- JType associationType, BeanHelper helper) {
+ private void writeValidateIterable(SourceWriter sw, PropertyDescriptor p) {
// int i = 0;
sw.println("int i = 0;");
- // for (BeanType instance : value) {
- sw.print("for(");
- sw.print(associationType.getQualifiedSourceName());
- sw.println(" instance : value) {");
+ // for (Object instance : value) {
+ sw.print("for(Object instance : value) {");
sw.indent();
// if(instance != null ) {
@@ -1134,9 +1077,8 @@
sw.indent();
sw.indent();
- // myGwtValidator.validate(
- sw.print(helper.getValidatorInstanceName());
- sw.println(".validate(");
+ // context.getValidator().validate(
+ sw.println("context.getValidator().validate(");
sw.indent();
sw.indent();
@@ -1161,14 +1103,11 @@
sw.println("}");
}
- private void writeValidateMap(SourceWriter sw, PropertyDescriptor p,
- JType associationType, BeanHelper helper) {
+ private void writeValidateMap(SourceWriter sw, PropertyDescriptor p) {
// for (Entry<?, Type> entry : value.entrySet()) {
sw.print("for(");
sw.print(Entry.class.getCanonicalName());
- sw.print("<?, ");
- sw.print(associationType.getQualifiedSourceName());
- sw.println("> entry : value.entrySet()) {");
+ sw.print("<?, ?> entry : value.entrySet()) {");
sw.indent();
// if(entry.getValue() != null ) {
@@ -1180,9 +1119,8 @@
sw.indent();
sw.indent();
- // myGwtValidator.validate(
- sw.print(helper.getValidatorInstanceName());
- sw.println(".validate(");
+ // context.getValidator().validate(
+ sw.println("context.getValidator().validate(");
sw.indent();
sw.indent();
@@ -1207,7 +1145,8 @@
sw.println("}");
}
- private void writeValidateProperty(SourceWriter sw) {
+ private void writeValidateProperty(SourceWriter sw)
+ throws UnableToCompleteException {
// public <T> Set<ConstraintViolation<T>> validate(
sw.println("public <T> Set<ConstraintViolation<T>> validateProperty(");
@@ -1262,12 +1201,12 @@
private void writeValidatePropertyCall(SourceWriter sw,
PropertyDescriptor property, boolean useValue) {
- if (hasGetter(property)) {
+ if (beanHelper.hasGetter(property)) {
if (useValue) {
// if ( value == null || value instanceof propertyType) {
sw.print("if ( value == null || value instanceof ");
- sw.print(getQualifiedSourceNonPrimitiveType(getElementType(property,
- false)));
+ sw.print(getQualifiedSourceNonPrimitiveType(beanHelper.getElementType(
+ property, false)));
sw.println(") {");
sw.indent();
}
@@ -1280,13 +1219,12 @@
}
}
-
- if (hasField(property)) {
+ if (beanHelper.hasField(property)) {
if (useValue) {
// if ( value == null || value instanceof propertyType) {
sw.print("if ( value == null || value instanceof ");
- sw.print(getQualifiedSourceNonPrimitiveType(getElementType(property,
- true)));
+ sw.print(getQualifiedSourceNonPrimitiveType(beanHelper.getElementType(
+ property, true)));
sw.println(") {");
sw.indent();
}
@@ -1299,7 +1237,7 @@
}
}
- if (useValue & (hasGetter(property) || hasField(property))) {
+ if (useValue & (beanHelper.hasGetter(property) || beanHelper.hasField(property))) {
// {
sw.println(" {");
sw.indent();
@@ -1318,7 +1256,7 @@
private void writeValidatePropertyMethod(SourceWriter sw,
PropertyDescriptor p, boolean useField) throws UnableToCompleteException {
Class<?> elementClass = p.getElementClass();
- JType elementType = getElementType(p, useField);
+ JType elementType = beanHelper.getElementType(p, useField);
// private final <T> void validateProperty_{get}<p>(
sw.print("private final <T> void ");
@@ -1361,21 +1299,21 @@
if (isIterableOrMap(elementClass)) {
if (hasValid(p, useField)) {
- JType associationType = getAssociationType(p, useField);
- BeanHelper helper = createBeanHelper(associationType);
- // TODO(nchalko) assume iterable for now
+ JClassType associationType = beanHelper.getAssociationType(p,
+ useField);
+ createBeanHelper(associationType);
if (Map.class.isAssignableFrom(elementClass)) {
- writeValidateMap(sw, p, associationType, helper);
+ writeValidateMap(sw, p);
} else {
- writeValidateIterable(sw, p, associationType, helper);
+ writeValidateIterable(sw, p);
}
}
} else {
- BeanHelper helper = createBeanHelper(elementClass);
- // violations.addAll(myGwtValidator.validate(context, value, groups));
+ createBeanHelper(elementClass);
+ // violations.addAll(myContext.getValidator().validate(context, value,
+ // groups));
sw.print("violations.addAll(");
- sw.print(helper.getValidatorInstanceName());
- sw.println(".validate(myContext, value, groups));");
+ sw.println("myContext.getValidator().validate(myContext, value, groups));");
}
// }
@@ -1398,7 +1336,8 @@
sw.println("}");
}
- private void writeValidateValue(SourceWriter sw) {
+ private void writeValidateValue(SourceWriter sw)
+ throws UnableToCompleteException {
// public <T> Set<ConstraintViolation<T>> validate(
sw.println("public <T> Set<ConstraintViolation<T>> validateValue(");
@@ -1455,7 +1394,7 @@
}
private void writeValidatorCall(SourceWriter sw, Class<?> type, Stage stage,
- PropertyDescriptor p) {
+ PropertyDescriptor p) throws UnableToCompleteException {
if (BeanHelper.isClassConstrained(type) && !isIterableOrMap(type)) {
BeanHelper helper = createBeanHelper(type);
beansToValidate.add(helper);
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
index 11ec398..10c0448 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Google Inc.
- *
+ *
* 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
@@ -49,13 +49,12 @@
JClassType gwtSpecificInterface = getGwtSpecificValidator(logger, validator);
JClassType beanType = getBeanType(logger, validator, gwtSpecificInterface);
- BeanHelper beanHelper = BeanHelper.getBeanHelper(beanType);
+ BeanHelper beanHelper = BeanHelper.createBeanHelper(beanType,logger,context);
if (beanHelper == null) {
- logger.log(TreeLogger.ERROR, "Unable to find BeanHelper for " + beanType
+ logger.log(TreeLogger.ERROR, "Unable to create BeanHelper for " + beanType
+ " " + GwtSpecificValidator.class.getSimpleName()
- + " should only be referenced from a class created by "
- + ValidatorGenerator.class.getCanonicalName(), null);
+ + ".", null);
throw new UnableToCompleteException();
}
diff --git a/user/src/com/google/gwt/validation/rebind/Util.java b/user/src/com/google/gwt/validation/rebind/Util.java
new file mode 100644
index 0000000..b0616ab
--- /dev/null
+++ b/user/src/com/google/gwt/validation/rebind/Util.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.validation.rebind;
+
+import com.google.gwt.thirdparty.guava.common.base.Function;
+import com.google.gwt.thirdparty.guava.common.base.Functions;
+import com.google.gwt.thirdparty.guava.common.base.Predicate;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
+import com.google.gwt.thirdparty.guava.common.collect.Iterables;
+import com.google.gwt.thirdparty.guava.common.collect.Lists;
+import com.google.gwt.thirdparty.guava.common.collect.Ordering;
+import com.google.gwt.thirdparty.guava.common.collect.Sets;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Static utilities for the validation rebind package.
+ */
+class Util {
+
+ /**
+ * Creates a Predicate that returns false if source contains an associated
+ * class that is a super type of the class associated with the tested T.
+ *
+ * @param <T> the type to test
+ * @param source the Set of <T> to look for class matches.
+ * @param toClass Function from T to Class
+ * @return newly create predicate.
+ */
+ static <T> Predicate<T> createMostSpecificMatchPredicate(final Set<T> source,
+ final Function<T, Class<?>> toClass) {
+ return new Predicate<T>() {
+
+ public boolean apply(T input) {
+ Class<?> inputClass = toClass.apply(input);
+ for (Class<?> match : Iterables.transform(source, toClass)) {
+ if (!inputClass.equals(match) && inputClass.isAssignableFrom(match)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+ }
+
+ /**
+ * Selects first only the classes that are assignable from the target, and
+ * then returns the most specific matching classes.
+ *
+ * @param target the Class to match
+ * @param availableClasses classes to search
+ * @return Set of only the most specific classes that match the target.
+ */
+ static Set<Class<?>> findBestMatches(Class<?> target,
+ Set<Class<?>> availableClasses) {
+ Set<Class<?>> matches = new HashSet<Class<?>>();
+ if (availableClasses.contains(target)) {
+ return ImmutableSet.<Class<?>> of(target);
+ } else {
+ for (Class<?> clazz : availableClasses) {
+ if (clazz.isAssignableFrom(target)) {
+ matches.add(clazz);
+ }
+ }
+ }
+ Predicate<Class<?>> moreSpecificClassPredicate = createMostSpecificMatchPredicate(
+ matches, Functions.<Class<?>> identity());
+ return Sets.filter(matches, moreSpecificClassPredicate);
+ }
+
+ /**
+ * Returns a Immutable List sorted with the most specific associated class
+ * first. Each element is guaranteed to not be assignable to any element that
+ * appears before it in the list.
+ */
+ static <T> ImmutableList<T> sortMostSpecificFirst(Iterable<T> classes,
+ Function<T, Class<?>> toClass) {
+ Set<T> working = Sets.newHashSet(classes);
+ List<T> sorted = Lists.newArrayList();
+ Predicate<T> mostSpecific = createMostSpecificMatchPredicate(working, toClass);
+ boolean changed = false;
+ do {
+ changed = false;
+ for (T t : Ordering.usingToString().sortedCopy(working)) {
+ if (mostSpecific.apply(t)) {
+ sorted.add(t);
+ working.remove(t);
+ changed = true;
+ }
+ }
+ } while (changed);
+ if (!working.isEmpty()) {
+ throw new IllegalStateException(
+ "Unable to find a element that does not have a more specific element in the set "
+ + working);
+ }
+ return ImmutableList.copyOf(sorted);
+ }
+
+ private Util() {
+ }
+}
diff --git a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
index a2a92cf..33e75fe 100644
--- a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
@@ -40,7 +41,7 @@
public class ValidatorCreator extends AbstractCreator {
/**
- * The beans to validate in source declaratoin order.
+ * The beans to validate in source declaration order.
*/
private final List<BeanHelper> beansToValidate = Lists.newArrayList();
private final GwtValidation gwtValidation;
@@ -49,7 +50,7 @@
public ValidatorCreator(JClassType validatorType, //
GwtValidation gwtValidation, //
TreeLogger logger, //
- GeneratorContext context) {
+ GeneratorContext context) throws UnableToCompleteException {
super(context, logger, validatorType);
this.gwtValidation = gwtValidation;
@@ -76,17 +77,17 @@
@Override
protected void writeClassBody(SourceWriter sourceWriter) {
- writeTypeSupport(sourceWriter);
- sourceWriter.println();
- writeConstructor(sourceWriter);
- sourceWriter.println();
- writeValidate(sourceWriter);
- sourceWriter.println();
- writeValidateProperty(sourceWriter);
- sourceWriter.println();
- writeValidateValue(sourceWriter);
- sourceWriter.println();
- writeGetConstraintsForClass(sourceWriter);
+ writeConstructor(sourceWriter);
+ sourceWriter.println();
+ writeValidate(sourceWriter);
+ sourceWriter.println();
+ writeValidateProperty(sourceWriter);
+ sourceWriter.println();
+ writeValidateValue(sourceWriter);
+ sourceWriter.println();
+ writeGetConstraintsForClass(sourceWriter);
+ sourceWriter.println();
+ writeGwtValidate(sourceWriter);
}
private String getSimpleName() {
@@ -117,17 +118,28 @@
private void writeContext(SourceWriter sw, BeanHelper bean, String objectName) {
- // GwtValidationContext<T> context =
- // new GwtValidationContext<T>(object,myBeanValidator.getConstraints(),
- // getMessageInterpolator());
+ // GwtValidationContext<T> context = new GwtValidationContext<T>(
sw.print(GwtValidationContext.class.getSimpleName());
sw.print("<T> context =");
sw.print(" new " + GwtValidationContext.class.getSimpleName());
- sw.print("<T>(" + objectName + ", ");
- sw.print(bean.getValidatorInstanceName());
- sw.print(".getConstraints(), ");
- sw.print("getMessageInterpolator()");
- sw.println(");");
+ sw.println("<T>" + "(");
+ sw.indent();
+ sw.indent();
+
+ // object,
+ sw.println(objectName + ", ");
+
+ // MyBeanValidator.INSTANCE.getConstraints(),
+ sw.print(bean.getFullyQualifiedValidatorName());
+ sw.println(".INSTANCE.getConstraints(), ");
+
+ // getMessageInterpolator(),
+ sw.println("getMessageInterpolator(), ");
+
+ // this);
+ sw.println("this);");
+ sw.outdent();
+ sw.outdent();
}
private void writeGetConstraintsForClass(SourceWriter sw) {
@@ -155,9 +167,61 @@
sw.println("if (clazz.equals(" + bean.getTypeCanonicalName() + ".class)) {");
sw.indent();
- // return myBeanValidator.getConstraints();
+ // return MyBeanValidator.INSTANCE.getConstraints();
sw.print("return ");
- sw.print(bean.getValidatorInstanceName() + ".getConstraints();");
+ sw.print(bean.getFullyQualifiedValidatorName());
+ sw.println(".INSTANCE.getConstraints();");
+
+ // }
+ sw.outdent();
+ sw.println("}");
+ }
+
+ private void writeGwtValidate(SourceWriter sw) {
+ // public <T> Set<ConstraintViolation<T>> validate(GwtValidationContext<T>
+ // context,
+ sw.print("public <T> Set<ConstraintViolation<T>> ");
+ sw.println("validate(GwtValidationContext<T> context,");
+ sw.indent();
+ sw.indent();
+
+ // Object object, Class<?>... groups) {
+ sw.println("Object object, Class<?>... groups) {");
+ sw.outdent();
+
+ sw.println("checkNotNull(context, \"context\");");
+ sw.println("checkNotNull(object, \"object\");");
+ sw.println("checkNotNull(groups, \"groups\");");
+ sw.println("checkGroups(groups);");
+
+ for (BeanHelper bean : Util.sortMostSpecificFirst(
+ BeanHelper.getBeanHelpers().values(), BeanHelper.TO_CLAZZ)) {
+ writeGwtValidate(sw, bean);
+ }
+
+ // TODO(nchalko) log warning instead.
+ writeThrowIllegalArgumnet(sw, "object.getClass().getName()");
+
+ sw.outdent();
+ sw.println("}");
+ }
+
+ private void writeGwtValidate(SourceWriter sw, BeanHelper bean) {
+ writeIfInstanceofBeanType(sw, bean);
+ sw.indent();
+
+ // return PersonValidator.INSTANCE
+
+ sw.print("return ");
+ sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
+ sw.indent();
+ sw.indent();
+ // .validate(context, (<<MyBean>>) object, groups);
+ sw.print(".validate(context, ");
+ sw.print("(" + bean.getTypeCanonicalName() + ") object, ");
+ sw.println("groups);");
+ sw.outdent();
+ sw.outdent();
// }
sw.outdent();
@@ -192,11 +256,6 @@
sourceWriter.outdent();
}
- private void writeTypeSupport(SourceWriter sw) {
- for (BeanHelper bean : beansToValidate) {
- writeValidatorInstance(sw, bean);
- }
- }
private void writeValidate(SourceWriter sw) {
// public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>...
@@ -224,13 +283,20 @@
writeContext(sw, bean, "object");
- // return personValidator.validate(context, (<<MyBean>>) object, groups);
+ // return PersonValidator.INSTANCE
sw.print("return ");
- sw.print(bean.getValidatorInstanceName() + ".validate(");
- sw.print("context, ");
+ sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
+ sw.indent();
+ sw.indent();
+
+ // .validate(context, (<<MyBean>>) object, groups);
+ sw.print(".validate(context, ");
sw.print("(" + bean.getTypeCanonicalName() + ") object, ");
sw.println("groups);");
+ sw.outdent();
+ sw.outdent();
+ // }
sw.outdent();
sw.println("}");
}
@@ -258,11 +324,23 @@
writeIfInstanceofBeanType(sw, bean);
sw.indent();
writeContext(sw, bean, "object");
- sw.print("return " + bean.getValidatorInstanceName()
- + ".validateProperty(context, (" + bean.getTypeCanonicalName()
- + ") object, propertyName, ");
+
+ // return PersonValidator.INSTANCE
+ sw.print("return ");
+ sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
+ sw.indent();
+ sw.indent();
+
+ // .validateProperty(context, (MyBean) object, propertyName, groups);
+ sw.print(".validateProperty(context, (");
+ sw.print(bean.getTypeCanonicalName());
+ sw.print(") object, propertyName, ");
sw.println("groups);");
- sw.outdent(); // if
+ sw.outdent();
+ sw.outdent();
+
+ // }
+ sw.outdent();
sw.println("}");
}
@@ -290,10 +368,23 @@
+ ".class)) {");
sw.indent();
writeContext(sw, bean, "null");
- sw.println("return " + bean.getValidatorInstanceName()
- + ".validateValue(context, (Class<" + bean.getTypeCanonicalName()
- + ">)beanType, propertyName, value, groups);");
- sw.outdent(); // if
+
+ // return PersonValidator.INSTANCE
+ sw.print("return ");
+ sw.println(bean.getFullyQualifiedValidatorName() + ".INSTANCE");
+ sw.indent();
+ sw.indent();
+
+ // .validateValue(context, (Class<MyBean> beanType, propertyName, value,
+ // groups);
+ sw.print(".validateValue(context, (Class<");
+ sw.print(bean.getTypeCanonicalName());
+ sw.println(">)beanType, propertyName, value, groups);");
+ sw.outdent();
+ sw.outdent();
+
+ // }
+ sw.outdent();
sw.println("}");
}
}
diff --git a/user/test/com/google/gwt/validation/RebindJreSuite.java b/user/test/com/google/gwt/validation/RebindJreSuite.java
new file mode 100644
index 0000000..0929b60
--- /dev/null
+++ b/user/test/com/google/gwt/validation/RebindJreSuite.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.validation;
+
+import com.google.gwt.validation.rebind.GwtSpecificValidatorCreatorTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * All validation client non GWT tests.
+ */
+public class RebindJreSuite {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(
+ "Test suite for validation rebind code that does not require GWT.");
+ suite.addTestSuite(GwtSpecificValidatorCreatorTest.class);
+ return suite;
+ }
+}
diff --git a/user/test/com/google/gwt/validation/rebind/UtilTest.java b/user/test/com/google/gwt/validation/rebind/UtilTest.java
new file mode 100644
index 0000000..f55f07c
--- /dev/null
+++ b/user/test/com/google/gwt/validation/rebind/UtilTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.validation.rebind;
+
+import static com.google.gwt.validation.rebind.Util.findBestMatches;
+
+import com.google.gwt.thirdparty.guava.common.base.Function;
+import com.google.gwt.thirdparty.guava.common.base.Functions;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
+import com.google.gwt.thirdparty.guava.common.collect.Iterables;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Tests for {@link Util}.
+ */
+public class UtilTest extends TestCase {
+
+ private class Alice {
+ }
+
+ private class Bob {
+ }
+
+ private class Bobby extends Bob {
+ }
+ private class Bobby2 extends Bobby {
+ }
+
+ private interface C1 {
+ }
+
+ private interface C2 {
+ }
+
+ private class Chuck implements C1, C2 {
+ }
+
+ private final static Function<Class<?>, Class<?>> classIdentity = Functions.identity();
+
+ private static void assertContentsInOrder(List<Class<?>> actual,
+ Class<?>... classes) {
+ assertEquals(ImmutableList.copyOf(classes), actual);
+ }
+
+ private static ImmutableSet<Class<?>> of(Class<?>... classes) {
+ return ImmutableSet.copyOf(classes);
+ }
+
+ public void testBestMatches_Bobby2() {
+ Set<Class<?>> actual = findBestMatches(Bobby2.class,
+ of(Alice.class, Bob.class, Bobby.class));
+ assertEquals(1, actual.size());
+ assertEquals(Bobby.class, Iterables.get(actual, 0));
+ }
+
+ public void testBestMatches_none() {
+ Set<Class<?>> actual = Util.findBestMatches(Bob.class, of(Alice.class));
+ assertEquals(0, actual.size());
+ }
+
+ public void testBestMatches_one() {
+ Set<Class<?>> actual = findBestMatches(Bob.class,
+ of(Alice.class, Bob.class));
+ assertEquals(1, actual.size());
+ assertEquals(Bob.class, Iterables.get(actual, 0));
+ }
+
+ public void testBestMatches_two() {
+ Set<Class<?>> actual = findBestMatches(Chuck.class, of(C1.class, C2.class));
+ assertEquals(2, actual.size());
+ }
+
+ public void testSortMostSpecificFirst_chuck() {
+
+ List<Class<?>> actual = Util.sortMostSpecificFirst(
+ of(C2.class, C1.class, Chuck.class), classIdentity);
+ assertContentsInOrder(actual, Chuck.class, C1.class, C2.class);
+ }
+
+ public void testSortMostSpecificFirst_one() {
+ List<Class<?>> actual = Util.sortMostSpecificFirst(of(Alice.class),
+ classIdentity);
+ assertContentsInOrder(actual, Alice.class);
+ }
+}
diff --git a/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java
index 6c4b4ba..9528c98 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java
@@ -43,11 +43,13 @@
@Failing(issue = 5882)
public void testComposedConstraints() {
delegate.testComposedConstraints();
+ fail("This test only fails on IE. Forcing it to fail here to keep the counts even. See issue 5882.");
}
@Failing(issue = 5882)
public void testComposedConstraintsAreRecursive() {
delegate.testComposedConstraintsAreRecursive();
+ fail("This test only fails on IE. Forcing it to fail here to keep the counts even. See issue 5882.");
}
@Failing(issue = 5799)
diff --git a/user/test/org/hibernate/jsr303/tck/tests/constraints/customconstraint/CustomConstraintValidatorGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/constraints/customconstraint/CustomConstraintValidatorGwtTest.java
index 5cf8ba3..0ac0d6e 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/constraints/customconstraint/CustomConstraintValidatorGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/constraints/customconstraint/CustomConstraintValidatorGwtTest.java
@@ -33,6 +33,7 @@
@Failing(issue = 5882)
public void testDefaultPropertyPath() {
delegate.testDefaultPropertyPath();
+ fail("This test only fails on IE. Forcing it to fail here to keep the counts even. See issue 5882.");
}
@Failing(issue = 5800)
diff --git a/user/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java
index 9989ef2..30f85f4 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java
@@ -37,6 +37,7 @@
@Failing(issue = 5882)
public void testResolutionOfMinMaxForDifferentTypes() {
delegate.testResolutionOfMinMaxForDifferentTypes();
+ fail("This test only fails on IE. Forcing it to fail here to keep the counts even. See issue 5882.");
}
@Failing(issue = 5806)
@@ -56,7 +57,6 @@
delegate.testTargetTypeIsClass();
}
- @Failing(issue = 5806)
public void testTargetTypeIsInterface() {
delegate.testTargetTypeIsInterface();
}
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 e870ffc..4a1615c 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/PropertyPathGwtTest.java
@@ -32,8 +32,9 @@
delegate.testPropertyPathTraversedObject();
}
- @Failing(issue = 5803)
+ @Failing(issue = 5982)
public void testPropertyPathWithArray() {
+ fail("Force an early failure for Issue 5982 to prevent all following tests from failing.");
delegate.testPropertyPathWithArray();
}
@@ -41,8 +42,9 @@
delegate.testPropertyPathWithConstraintViolationForRootObject();
}
- @Failing(issue = 5803)
+ @Failing(issue = 5982)
public void testPropertyPathWithList() {
+ fail("Force an early failure for Issue 5982 to prevent all following tests from failing.");
delegate.testPropertyPathWithList();
}
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java
index e280916..613a9ad 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java
@@ -30,18 +30,19 @@
delegate.testConstraintDescriptorWithoutExplicitGroup();
}
- @Failing(issue = 5882)
public void testConstraintViolation() {
delegate.testConstraintViolation();
}
- @Failing(issue = 5930)
+ @Failing(issue = 5982)
public void testGraphValidationWithArray() {
+ fail("Force an early failure for Issue 5982 to prevent all following tests from failing.");
delegate.testGraphValidationWithArray();
}
- @Failing(issue = 5930)
+ @Failing(issue = 5982)
public void testGraphValidationWithList() {
+ fail("Force an early failure for Issue 5982 to prevent all following tests from failing.");
delegate.testGraphValidationWithList();
}
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidatePropertyGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidatePropertyGwtTest.java
index 93bb063..74505c9 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidatePropertyGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidatePropertyGwtTest.java
@@ -49,6 +49,7 @@
@Failing(issue = 5882)
public void testValidateProperty() {
delegate.testValidateProperty();
+ fail("This test only fails on IE. Forcing it to fail here to keep the counts even. See issue 5882.");
}
public void testValidatePropertyWithEmptyProperty() {
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/GraphNavigationGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/GraphNavigationGwtTest.java
index 7ff07fe..032d939 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/GraphNavigationGwtTest.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/GraphNavigationGwtTest.java
@@ -20,7 +20,7 @@
import org.hibernate.jsr303.tck.util.client.Failing;
/**
- * Test wrapper for {@link ValidationTest}.
+ * Test wrapper for {@link GraphNavigationTest}.
*/
public class GraphNavigationGwtTest extends GWTTestCase {
@@ -31,7 +31,6 @@
return "org.hibernate.jsr303.tck.tests.validation.graphnavigation.TckTest";
}
- @Failing(issue = 5946)
public void testContainedIterable() {
delegate.testContainedIterable();
}
@@ -41,7 +40,6 @@
delegate.testContainedMap();
}
- @Failing(issue = 5946)
public void testContainedSet() {
delegate.testContainedSet();
}
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/TckTestValidatorFactory.java b/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/TckTestValidatorFactory.java
index 0bdf158..1f6e2ca 100644
--- a/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/TckTestValidatorFactory.java
+++ b/user/test/org/hibernate/jsr303/tck/tests/validation/graphnavigation/TckTestValidatorFactory.java
@@ -31,8 +31,10 @@
* Marker Interface for {@link GWT#create(Class)}.
*/
@GwtValidation(value = {
- AnimalCaretaker.class, Elephant.class, Parent.class,
- SingleCage.class, Zoo.class})
+ AnimalCaretaker.class, Elephant.class, Condor.class, GameReserve.class,
+ Parent.class,
+ MultiCage.class, MultiCage.class, SingleCage.class, Zebra.class,
+ Zoo.class})
public static interface GwtValidator extends Validator {
}