Select the correct ConstraintValidator for the bean type.
This does not implement the full spec, but will always return
a compatible ConstraintValidator if available.
[JSR 303 TCK Result] 53 of 258 (20.54%) Pass with 28 Failures and 13 Errors.

Review at http://gwt-code-reviews.appspot.com/1238801

Review by: rchandia@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9475 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintGwtSuite.java b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintGwtSuite.java
new file mode 100644
index 0000000..aca3b7e
--- /dev/null
+++ b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintGwtSuite.java
@@ -0,0 +1,32 @@
+/*
+ * 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.sample.validationtck.constraints.customconstraint;
+
+import com.google.gwt.junit.tools.GWTTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Tck Tests for the {@code constraints customconstraint} package.
+ */
+public class CustomConstraintGwtSuite {
+  public static Test suite() {
+    GWTTestSuite suite = new GWTTestSuite(
+        "TCK for GWT Validation, constraints customconstraint package");
+    suite.addTestSuite(CustomConstraintValidatorGwtTest.class);
+    return suite;
+  }
+}
diff --git a/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintValidatorGwtTest.java b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintValidatorGwtTest.java
new file mode 100644
index 0000000..a20570a
--- /dev/null
+++ b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/CustomConstraintValidatorGwtTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.sample.validationtck.constraints.customconstraint;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import org.hibernate.jsr303.tck.tests.constraints.customconstraint.CustomConstraintValidatorTest;
+
+/**
+ * Test wrapper for {@link CustomConstraintValidatorTest}.
+ */
+public class CustomConstraintValidatorGwtTest extends GWTTestCase {
+  private final CustomConstraintValidatorTest delegate = new CustomConstraintValidatorTest();
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.sample.validationtck.constraints.customconstraint.TckTest";
+  }
+
+  public void testDefaultPropertyPath() {
+    delegate.testDefaultPropertyPath();
+  }
+
+  public void testIsValidIsCalledForEachValidation() {
+    delegate.testIsValidIsCalledForEachValidation();
+  }
+
+  public void testNonInterpolatedMessageParameterIsUsed() {
+    delegate.testNonInterpolatedMessageParameterIsUsed();
+  }
+
+  public void testOneConstraintViolationPerFailingConstraint() {
+    delegate.testOneConstraintViolationPerFailingConstraint();
+  }
+
+  public void testRightValidatorIsSelectedAndInitializedCalled() {
+    delegate.testRightValidatorIsSelectedAndInitializedCalled();
+  }
+
+  public void testRuntimeExceptionFromInitializeIsWrapped() {
+    delegate.testRuntimeExceptionFromInitializeIsWrapped();
+  }
+
+  public void testRuntimeExceptionFromIsValidIsWrapped() {
+    delegate.testRuntimeExceptionFromIsValidIsWrapped();
+  }
+
+  public void testUnexpectedTypeExceptionIsRaisedForInvalidType() {
+    delegate.testUnexpectedTypeExceptionIsRaisedForInvalidType();
+  }
+}
diff --git a/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTest.gwt.xml b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTest.gwt.xml
new file mode 100644
index 0000000..3a619ba
--- /dev/null
+++ b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTest.gwt.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.1/distro-source/core/src/gwt-module.dtd">
+<!--
+  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.
+-->
+<module>
+  <inherits name="com.google.gwt.sample.validationtck.ValidationTck" />
+  <source path="">
+    <include name="*.java" />
+    <exclude name="super" />
+  </source>
+  <replace-with class="com.google.gwt.sample.validationtck.constraints.customconstraint.TckTestValidatorFactory">
+    <when-type-is class="javax.validation.ValidatorFactory"/>
+  </replace-with>
+</module>
\ No newline at end of file
diff --git a/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTestValidatorFactory.java b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTestValidatorFactory.java
new file mode 100644
index 0000000..86f96b3
--- /dev/null
+++ b/samples/validationtck/test/com/google/gwt/sample/validationtck/constraints/customconstraint/TckTestValidatorFactory.java
@@ -0,0 +1,47 @@
+/*
+ * 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.sample.validationtck.constraints.customconstraint;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.validation.client.AbstractGwtValidatorFactory;
+import com.google.gwt.validation.client.GwtValidation;
+import com.google.gwt.validation.client.impl.AbstractGwtValidator;
+
+import org.hibernate.jsr303.tck.tests.constraints.customconstraint.Author;
+import org.hibernate.jsr303.tck.tests.constraints.customconstraint.CustomConstraintValidatorTest.Freezer;
+import org.hibernate.jsr303.tck.tests.constraints.customconstraint.CustomConstraintValidatorTest.OddShoe;
+import org.hibernate.jsr303.tck.tests.constraints.customconstraint.CustomConstraintValidatorTest.Shoe;
+
+import javax.validation.Validator;
+
+/**
+ * {@link AbstractGwtValidatorFactory} implementation that uses
+ * {@link com.google.gwt.validation.client.GwtValidation GwtValidation}.
+ */
+public final class TckTestValidatorFactory extends AbstractGwtValidatorFactory {
+  /**
+   * Marker Interface to {@link GWT#create(Class)}.
+   */
+  @GwtValidation(value = {
+      Author.class, Freezer.class, OddShoe.class, Shoe.class})
+  public static interface GwtValidator extends Validator {
+  }
+
+  @Override
+  public AbstractGwtValidator createValidator() {
+    return GWT.create(GwtValidator.class);
+  }
+}
diff --git a/samples/validationtck/test/com/google/gwt/sample/validationtck/validation/TckTestValidatorFactory.java b/samples/validationtck/test/com/google/gwt/sample/validationtck/validation/TckTestValidatorFactory.java
index a5fb694..79bec12 100644
--- a/samples/validationtck/test/com/google/gwt/sample/validationtck/validation/TckTestValidatorFactory.java
+++ b/samples/validationtck/test/com/google/gwt/sample/validationtck/validation/TckTestValidatorFactory.java
@@ -21,10 +21,13 @@
 import com.google.gwt.validation.client.impl.AbstractGwtValidator;
 
 import org.hibernate.jsr303.tck.tests.validation.Actor;
+import org.hibernate.jsr303.tck.tests.validation.ActorArrayBased;
+import org.hibernate.jsr303.tck.tests.validation.ActorListBased;
 import org.hibernate.jsr303.tck.tests.validation.Address;
 import org.hibernate.jsr303.tck.tests.validation.BadlyBehavedEntity;
 import org.hibernate.jsr303.tck.tests.validation.Customer;
 import org.hibernate.jsr303.tck.tests.validation.Engine;
+import org.hibernate.jsr303.tck.tests.validation.Order;
 
 import javax.validation.Validator;
 
@@ -37,8 +40,8 @@
    * Marker Interface for {@link GWT#create(Class)}.
    */
   @GwtValidation(value = {
-      Address.class, Actor.class, BadlyBehavedEntity.class, Engine.class,
-      Customer.class})
+      Actor.class, ActorArrayBased.class, ActorListBased.class, Address.class,
+      BadlyBehavedEntity.class, Customer.class, Engine.class, Order.class})
   public static interface GwtValidator extends Validator {
   }
 
diff --git a/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTest.gwt.xml b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTest.gwt.xml
new file mode 100644
index 0000000..3a147bf
--- /dev/null
+++ b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTest.gwt.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.1/distro-source/core/src/gwt-module.dtd">
+<!--
+  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.
+-->
+<module>
+  <inherits name="com.google.gwt.sample.validationtck.ValidationTck" />
+  <source path="">
+    <include name="*.java" />
+    <exclude name="super" />
+  </source>
+  <replace-with class="org.hibernate.jsr303.tck.tests.constraints.validatorresolution.TckTestValidatorFactory">
+    <when-type-is class="javax.validation.ValidatorFactory"/>
+  </replace-with>
+</module>
\ No newline at end of file
diff --git a/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTestValidatorFactory.java b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTestValidatorFactory.java
new file mode 100644
index 0000000..2475214
--- /dev/null
+++ b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/TckTestValidatorFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.hibernate.jsr303.tck.tests.constraints.validatorresolution;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.validation.client.AbstractGwtValidatorFactory;
+import com.google.gwt.validation.client.GwtValidation;
+import com.google.gwt.validation.client.impl.AbstractGwtValidator;
+
+import org.hibernate.jsr303.tck.tests.constraints.validatorresolution.ValidatorResolutionTest.CustomClass;
+import org.hibernate.jsr303.tck.tests.constraints.validatorresolution.ValidatorResolutionTest.CustomInterfaceImpl;
+import org.hibernate.jsr303.tck.tests.constraints.validatorresolution.ValidatorResolutionTest.SubClassAHolder;
+import org.hibernate.jsr303.tck.tests.constraints.validatorresolution.ValidatorResolutionTest.SubClassBHolder;
+
+import javax.validation.Validator;
+
+/**
+ * {@link AbstractGwtValidatorFactory} implementation that uses
+ * {@link com.google.gwt.validation.client.GwtValidation GwtValidation}.
+ */
+public final class TckTestValidatorFactory extends AbstractGwtValidatorFactory {
+  /**
+   * Marker Interface for {@link GWT#create(Class)}.
+   */
+  @GwtValidation(value = {
+      Bar.class, CustomInterfaceImpl.class, CustomClass.class, Foo.class,
+      MinMax.class, SubClassAHolder.class, SubClassBHolder.class, Suburb.class})
+  public static interface GwtValidator extends Validator {
+  }
+
+  @Override
+  public AbstractGwtValidator createValidator() {
+    return GWT.create(GwtValidator.class);
+  }
+}
diff --git a/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtSuite.java b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtSuite.java
new file mode 100644
index 0000000..4d9eb22
--- /dev/null
+++ b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtSuite.java
@@ -0,0 +1,32 @@
+/*
+ * 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 org.hibernate.jsr303.tck.tests.constraints.validatorresolution;
+
+import com.google.gwt.junit.tools.GWTTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Tck Tests for the {@code validator resolution} package.
+ */
+public class ValidatorResolutionGwtSuite {
+  public static Test suite() {
+    GWTTestSuite suite = new GWTTestSuite(
+        "TCK for GWT Validation, validator resolution package");
+    suite.addTestSuite(ValidatorResolutionGwtTest.class);
+    return suite;
+  }
+}
diff --git a/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java
new file mode 100644
index 0000000..229ca07
--- /dev/null
+++ b/samples/validationtck/test/org/hibernate/jsr303/tck/tests/constraints/validatorresolution/ValidatorResolutionGwtTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.hibernate.jsr303.tck.tests.constraints.validatorresolution;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Wraps {@link ValidatorResolutionTest} .
+ */
+public class ValidatorResolutionGwtTest extends GWTTestCase {
+  ValidatorResolutionTest delegate = new ValidatorResolutionTest();
+  @Override
+  public String getModuleName() {
+    return "org.hibernate.jsr303.tck.tests.constraints.validatorresolution.TckTest";
+  }
+
+  public void testAmbiguousValidatorResolution() {
+    delegate.testAmbiguousValidatorResolution();
+  }
+
+  public void testResolutionOfMinMaxForDifferentTypes() {
+    delegate.testResolutionOfMinMaxForDifferentTypes();
+  }
+
+  public void testResolutionOfMultipleSizeValidators() {
+    delegate.testResolutionOfMultipleSizeValidators();
+  }
+
+  public void testTargetedTypeIsField() {
+    delegate.testTargetedTypeIsField();
+  }
+
+  public void testTargetedTypeIsGetter() {
+    delegate.testTargetedTypeIsGetter();
+  }
+
+  public void testTargetTypeIsClass() {
+    delegate.testTargetTypeIsClass();
+  }
+
+  public void testTargetTypeIsInterface() {
+    delegate.testTargetTypeIsInterface();
+  }
+
+  public void testUnexpectedTypeInValidatorResolution() {
+    delegate.testUnexpectedTypeInValidatorResolution();
+  }
+
+
+}
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
index f930100..bfecf27 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -32,6 +32,7 @@
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.thirdparty.guava.common.base.Predicate;
 import com.google.gwt.thirdparty.guava.common.collect.Iterables;
+import com.google.gwt.thirdparty.guava.common.collect.Maps;
 import com.google.gwt.thirdparty.guava.common.collect.Sets;
 import com.google.gwt.thirdparty.guava.common.primitives.Primitives;
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
@@ -125,12 +126,67 @@
         + " is can not be represented as a Java Literal.");
   }
 
+  static <T extends Annotation> Class<?> getTypeOfConstraintValidator(
+      Class<? extends ConstraintValidator<T, ?>> constraintClass) {
+
+    for (Method method :  constraintClass.getMethods()) {
+      if (method.getName().equals("isValid")
+          && method.getParameterTypes().length == 2
+          && method.getReturnType().isAssignableFrom(Boolean.TYPE)) {
+        return method.getParameterTypes()[0];
+      }
+    }
+    throw new IllegalStateException(
+        "ConstraintValidators must have a isValid method");
+  }
+
+  // Visible for testing
+  static <A extends Annotation> Class<? extends ConstraintValidator<A, ?>> getValidatorForType(
+      Class<?> type,
+      List<Class<? extends ConstraintValidator<A, ?>>> constraintValidatorClasses) {
+    Map<Class<?>, Class<? extends ConstraintValidator<A, ?>>> map = Maps.newHashMap();
+    for (Class<? extends ConstraintValidator<A, ?>> constraintClass : constraintValidatorClasses) {
+      Class<?> aType = getTypeOfConstraintValidator(constraintClass);
+      if (aType.isAssignableFrom(type)) {
+        map.put(aType, constraintClass);
+      }
+    }
+    Class<?> best = null;
+    for (Class<?> c : map.keySet()) {
+      if (best == null) {
+        best = c;
+      } else {
+        if (c.equals(type)) {
+          best = c;
+          break; // Exact match we can stop
+        }
+        // TODO(nchalko) implement per spec
+        // is the new one better than the last.
+      }
+    }
+    return map.get(best);
+  }
+
+  private static <A extends Annotation> Class<? extends ConstraintValidator<A, ?>> getValidatorForType(
+      ConstraintDescriptor<A> constraint, Class<?> clazz) {
+    List<Class<? extends ConstraintValidator<A, ?>>> constraintValidatorClasses
+        = constraint.getConstraintValidatorClasses();
+    if (constraintValidatorClasses.isEmpty()) {
+      return null;
+    }
+    return getValidatorForType(clazz, constraintValidatorClasses);
+  }
+
   private BeanHelper beanHelper;
   private 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,
@@ -217,7 +273,7 @@
 
   private Annotation getAnnotation(PropertyDescriptor p, boolean useField,
       ConstraintDescriptor<?> constraint) {
-    Class<? extends Annotation> expectedAnnotaionClass =
+    Class<? extends Annotation> expectedAnnotaionClass = 
         ((Annotation) constraint.getAnnotation()).annotationType();
     Annotation annotation = null;
     if (useField) {
@@ -234,19 +290,6 @@
     return annotation;
   }
 
-  private <T extends Annotation> Class<? extends ConstraintValidator<T, ?>> getValidatorForType(
-      ConstraintDescriptor<T> constraint, Class<?> clazz) {
-    // TODO(nchalko) implement per spec
-
-    List<Class<? extends ConstraintValidator<T, ?>>> constraintValidatorClasses
-        = constraint.getConstraintValidatorClasses();
-    if (constraintValidatorClasses.isEmpty()) {
-      return null;
-    }
-    Class<? extends ConstraintValidator<T, ?>> validatorClass = constraintValidatorClasses.get(0);
-    return validatorClass;
-  }
-
   private boolean hasField(PropertyDescriptor p) {
     JField field = beanType.findField(p.getPropertyName());
     return field != null;
diff --git a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
index a5787e3..5bdd9f1 100644
--- a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
@@ -180,7 +180,7 @@
 
     // + "Valid values are {Foo.clas, Bar.class}
     sourceWriter.print("+ \"Valid types are ");
-    sourceWriter.print(beansToValidate.entrySet().toString());
+    sourceWriter.print(beansToValidate.values().toString());
     sourceWriter.println("\");");
     sourceWriter.outdent();
     sourceWriter.outdent();
diff --git a/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java b/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java
new file mode 100644
index 0000000..06f5b14
--- /dev/null
+++ b/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.GwtSpecificValidatorCreator.getValidatorForType;
+
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
+import com.google.gwt.validation.client.constraints.SizeValidatorForCollection;
+import com.google.gwt.validation.client.constraints.SizeValidatorForString;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.constraints.Size;
+
+/**
+ * NonGWT tests for {@link GwtSpecificValidatorCreator}.
+ */
+public class GwtSpecificValidatorCreatorTest extends TestCase {
+
+  ImmutableList<Class<? extends ConstraintValidator<Size, ?>>> sizeValidators = ImmutableList.<Class<? extends ConstraintValidator<Size, ?>>> of(
+      SizeValidatorForCollection.class, SizeValidatorForString.class);
+
+  public void testGetValidatorForType_collection() throws Exception {
+    Class<? extends ConstraintValidator<? extends Annotation, ?>> expected = SizeValidatorForCollection.class;
+    Class<? extends ConstraintValidator<Size, ?>> actual = getValidatorForType(
+        List.class, sizeValidators);
+    assertEquals(expected, actual);
+  }
+
+  public void testGetValidatorForType_string() throws Exception {
+    Class<String> target = String.class;
+    Class<? extends ConstraintValidator<Size, ?>> actual = getValidatorForType(
+        target, sizeValidators);
+    assertEquals(SizeValidatorForString.class, actual);
+  }
+}