Public:  First take at GWT validation that actually validates on the client side.

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

Review by: robertvawter@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8952 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/build.xml b/build.xml
index f1403d4..8ca3bdf 100755
--- a/build.xml
+++ b/build.xml
@@ -174,6 +174,7 @@
       <classpath>
         <pathelement location="${gwt.build.out}/tools/api-checker/bin"/>
         <fileset dir="${gwt.build.lib}" includes="gwt-user.jar,gwt-dev.jar" />
+        <pathelement location="${gwt.tools.lib}//hibernate/validator/hibernate-validator-4.1.0.Final.jar" />
         <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar" />
         <pathelement path="${java.class.path}"/>
         <pathelement location="${gwt.tools.lib}/apache/ant-1.6.5.jar" />
diff --git a/eclipse/samples/Validation/.classpath b/eclipse/samples/Validation/.classpath
index b67ec19..f36f38b 100644
--- a/eclipse/samples/Validation/.classpath
+++ b/eclipse/samples/Validation/.classpath
@@ -2,9 +2,13 @@
 <classpath>
 	<classpathentry kind="src" path="core/src"/>
 	<classpathentry kind="src" output="war" path="core/war"/>
+	<classpathentry kind="src" path="gwt-gen"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/gwt-user"/>
-	<classpathentry kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
-	<classpathentry kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA.jar" sourcepath="/GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/apache/log4j/log4j-1.2.16.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final.jar" sourcepath="/GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/slf4j/slf4j-api/slf4j-api-1.6.1.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar"/>
 	<classpathentry kind="output" path="war/WEB-INF/classes"/>
 </classpath>
diff --git a/eclipse/user/.classpath b/eclipse/user/.classpath
index 605bfdf..5075ee1 100644
--- a/eclipse/user/.classpath
+++ b/eclipse/user/.classpath
@@ -39,6 +39,11 @@
 	<classpathentry exported="true" kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA.jar" sourcepath="/GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
 	<classpathentry exported="true" kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
 	<classpathentry kind="var" path="GWT_TOOLS/lib/jetty/jetty-6.1.11.jar" sourcepath="/GWT_TOOLS/lib/jetty/jetty-6.1.11-src.zip"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final.jar" sourcepath="/GWT_TOOLS/lib/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/apache/log4j/log4j-1.2.16.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/slf4j/slf4j-api/slf4j-api-1.6.1.jar"/>
+	<classpathentry kind="var" path="GWT_TOOLS/lib/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar"/>
 	<classpathentry kind="var" path="GWT_TOOLS/lib/guava/guava-r06/guava-r06-rebased.jar"/>
 	<classpathentry kind="var" path="GWT_TOOLS/lib/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/samples/common.ant.xml b/samples/common.ant.xml
index 0152144..829e22b 100755
--- a/samples/common.ant.xml
+++ b/samples/common.ant.xml
@@ -65,6 +65,7 @@
         <pathelement location="${gwt.dev.jar}" />
         <pathelement location="${gwt.tools.lib}/jsr107cache/jsr107cache-1.1.jar"/>
         <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar"/>
+        <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final.jar" />
         <path refid="gae.extraclasspath" />
       </classpath>
     </gwt.javac>
@@ -83,9 +84,26 @@
         <mkdir dir="${sample.build}/war" />
         <gwt.timer name="${sample.upper} with ${gwt.samples.localworkers} localWorkers">
           <java dir="${sample.build}" classname="com.google.gwt.dev.Compiler"
-                classpath="${sample.path}:${sample.build}/war/WEB-INF/classes:${gwt.user.jar}:${gwt.dev.jar}:${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar:${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA-sources.jar"
-		fork="yes" failonerror="true">
-            <jvmarg value="-Xmx256M"/>
+                		fork="yes" failonerror="true">
+            <classpath>
+              <pathelement path="${sample.path}" />
+              <pathelement location="${sample.build}/war/WEB-INF/classes" />
+              <pathelement location="${gwt.user.jar}" />
+              <pathelement location="${gwt.dev.jar}" />
+              <pathelement location="${gwt.tools.lib}/apache/log4j/log4j-1.2.16.jar" />
+              <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar" />
+              <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA-sources.jar" />
+              <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final.jar" />
+              <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar" />
+              <pathelement location="${gwt.tools.lib}/slf4j/slf4j-api/slf4j-api-1.6.1.jar" />
+              <pathelement location="${gwt.tools.lib}/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar" />
+              <!-- Needed for JDK 1.5-->
+              <pathelement location="${gwt.tools.lib}/javax/activation/activation-1.1.jar" />
+              <pathelement location="${gwt.tools.lib}/javax/xml/bind/jaxb-api-2.1.jar" />
+              <pathelement location="${gwt.tools.lib}/sun/jaxb/jaxb-impl.2.1.3.jar" />
+              <pathelement location="${gwt.tools.lib}/javax/xml/stream/staxb-api-1.0-2.jar" />
+            </classpath>
+            <jvmarg value="-Xmx256M" />
             <arg value="-localWorkers" />
             <arg value="${gwt.samples.localworkers}" />
             <arg value="-war" />
diff --git a/samples/validation/src/com/google/gwt/sample/validation/Validation.gwt.xml b/samples/validation/src/com/google/gwt/sample/validation/Validation.gwt.xml
index 8b74b57..55dc76a 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/Validation.gwt.xml
+++ b/samples/validation/src/com/google/gwt/sample/validation/Validation.gwt.xml
@@ -16,7 +16,7 @@
   <inherits name='com.google.gwt.rpc.RPC'/>
   <inherits name='com.google.gwt.user.User'/>
   <inherits name='com.google.gwt.user.theme.standard.Standard'/>
-  <inherits name='com.google.gwt.validation.Validation'/>
+  <inherits name='org.hibernate.validator.HibernateValidator'/>
 
   <entry-point class='com.google.gwt.sample.validation.client.Validation'/>
 
diff --git a/samples/validation/src/com/google/gwt/sample/validation/client/GreetingService.java b/samples/validation/src/com/google/gwt/sample/validation/client/GreetingService.java
index 41f61f4..c54f455 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/client/GreetingService.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/client/GreetingService.java
@@ -4,9 +4,9 @@
  * 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
diff --git a/samples/validation/src/com/google/gwt/sample/validation/client/GreetingServiceAsync.java b/samples/validation/src/com/google/gwt/sample/validation/client/GreetingServiceAsync.java
index cbc3b97..dda64fb 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/client/GreetingServiceAsync.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/client/GreetingServiceAsync.java
@@ -4,7 +4,7 @@
  * 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
diff --git a/samples/validation/src/com/google/gwt/sample/validation/client/SampleValidator.java b/samples/validation/src/com/google/gwt/sample/validation/client/SampleValidator.java
index 14f8bb5..5f8c74c 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/client/SampleValidator.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/client/SampleValidator.java
@@ -19,11 +19,25 @@
 import com.google.gwt.validation.client.GwtValidation;
 
 import javax.validation.Validator;
+import javax.validation.groups.Default;
 
 /**
  * Validator marker for the Valiation Sample project. Only the classes listed in
  * the {@link GwtValidation} annotation can be validated.
  */
-@GwtValidation(Person.class)
+@GwtValidation(value = Person.class,
+ groups = {
+    Default.class, SampleValidator.ClientGroup.class})
 public interface SampleValidator extends Validator {
+  /**
+   * Client Validation Group
+   */
+  public interface ClientGroup {
+  }
+
+  /**
+   * Server Validation Group
+   */
+  public interface ServerGroup {
+  }
 }
diff --git a/samples/validation/src/com/google/gwt/sample/validation/client/Validation.java b/samples/validation/src/com/google/gwt/sample/validation/client/Validation.java
index 6a33243..86bb36e 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/client/Validation.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/client/Validation.java
@@ -4,7 +4,7 @@
  * 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
@@ -30,12 +30,10 @@
    */
   private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
 
-
   /**
    * This is the entry point method.
    */
   public void onModuleLoad() {
-
     Person person = new Person();
     ValidationView view = new ValidationView(person, greetingService);
     RootPanel.get("view").add(view);
diff --git a/samples/validation/src/com/google/gwt/sample/validation/server/GreetingServiceImpl.java b/samples/validation/src/com/google/gwt/sample/validation/server/GreetingServiceImpl.java
index 00a2bd8..3ee9de7 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/server/GreetingServiceImpl.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/server/GreetingServiceImpl.java
@@ -4,7 +4,7 @@
  * 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
diff --git a/samples/validation/src/com/google/gwt/sample/validation/shared/NoOp.java b/samples/validation/src/com/google/gwt/sample/validation/shared/NoOp.java
new file mode 100644
index 0000000..197a655
--- /dev/null
+++ b/samples/validation/src/com/google/gwt/sample/validation/shared/NoOp.java
@@ -0,0 +1,46 @@
+/*
+ * 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.validation.shared;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+/**
+ * Test constaint that is always valid
+ */
+@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE})
+@Retention(RUNTIME)
+@Documented
+@Constraint(validatedBy = {NoOpValidator.class})
+public @interface NoOp {
+  String message() default "Hey, this can't fail!";
+
+  Class<?>[] groups() default {};
+
+  Class<? extends Payload>[] payload() default {};
+}
\ No newline at end of file
diff --git a/samples/validation/src/com/google/gwt/sample/validation/shared/NoOpValidator.java b/samples/validation/src/com/google/gwt/sample/validation/shared/NoOpValidator.java
new file mode 100644
index 0000000..348befe
--- /dev/null
+++ b/samples/validation/src/com/google/gwt/sample/validation/shared/NoOpValidator.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.validation.shared;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * This is always valid.
+ */
+public class NoOpValidator implements ConstraintValidator<NoOp, Object> {
+
+  public void initialize(NoOp constraintAnnotation) {
+  }
+
+  public boolean isValid(Object value, ConstraintValidatorContext context) {
+    return true;
+  }
+}
diff --git a/samples/validation/src/com/google/gwt/sample/validation/shared/Person.java b/samples/validation/src/com/google/gwt/sample/validation/shared/Person.java
index 27d196b..82a68eb 100644
--- a/samples/validation/src/com/google/gwt/sample/validation/shared/Person.java
+++ b/samples/validation/src/com/google/gwt/sample/validation/shared/Person.java
@@ -23,6 +23,7 @@
 /**
  * A sample bean to show validation on.
  */
+@NoOp
 public class Person implements IsSerializable {
 
   @NotNull
diff --git a/samples/validation/war/WEB-INF/lib/gwt-servlet.jar b/samples/validation/war/WEB-INF/lib/gwt-servlet.jar
new file mode 100644
index 0000000..bc41164
--- /dev/null
+++ b/samples/validation/war/WEB-INF/lib/gwt-servlet.jar
Binary files differ
diff --git a/samples/validation/war/favicon.ico b/samples/validation/war/favicon.ico
index 25c8d88..d7ccc73 100644
--- a/samples/validation/war/favicon.ico
+++ b/samples/validation/war/favicon.ico
Binary files differ
diff --git a/user/build.xml b/user/build.xml
index 88b61c6..60319ea 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -56,14 +56,15 @@
     <pathelement location="${gwt.build}/out/dev/bin-test" />
     <pathelement location="test-super" />
     <pathelement location="test_i18n_${gwt.i18n.test.InnerClassChar}" />
+    <pathelement location="${gwt.tools.lib}/apache/log4j/log4j-1.2.16.jar" />
     <pathelement location="${gwt.tools.lib}/cglib/cglib-2.2.jar"/>
     <pathelement location="${gwt.tools.lib}/easymock/easymock.jar"/>
     <pathelement location="${gwt.tools.lib}/easymock/easymockclassextension.jar"/>
     <pathelement location="${gwt.tools.lib}/objectweb/asm-3.1.jar"/>
     <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar" />
     <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA-sources.jar" />
-    <pathelement location="${gwt.tools.lib}/apache/log4j/log4j-1.2.16.jar" />
     <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final.jar" />
+    <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar" />
     <pathelement location="${gwt.tools.lib}/slf4j/slf4j-api/slf4j-api-1.6.1.jar" />
     <pathelement location="${gwt.tools.lib}/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar" />
     <pathelement location="${gwt.tools}/redist/json/r2_20080312/json-1.5.jar" />
@@ -85,6 +86,9 @@
         <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar" />
         <!-- The source is included so validation is available from client code -->
         <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA-sources.jar" />
+      	<!-- Hibernate is included until we can provide the super source as an third party jar" -->
+      	<pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final.jar" />
+        <pathelement location="${gwt.tools.lib}/hibernate/validator/hibernate-validator-4.1.0.Final-sources.jar" />
         <pathelement location="${gwt.dev.jar}" />
       </classpath>
     </gwt.javac>
@@ -142,6 +146,7 @@
         <exclude name="javax/validation/super/javax/validation/MessageInterpolator.java"/>
         <exclude name="javax/validation/super/javax/validation/Configuration.java"/>
         <exclude name="javax/validation/super/javax/validation/Validation.java"/>
+        <exclude name="org/hibernate/validator/super/org/hibernate/validator/constraints/ScriptAssert.java"/>
       </fileset>
       <fileset dir="super/com/google/gwt/emul" />
       <fileset dir="super/com/google/gwt/junit/translatable" />
diff --git a/user/src/com/google/gwt/validation/client/constraints/NotGwtCompatibleValidator.java b/user/src/com/google/gwt/validation/client/constraints/NotGwtCompatibleValidator.java
new file mode 100644
index 0000000..d963323
--- /dev/null
+++ b/user/src/com/google/gwt/validation/client/constraints/NotGwtCompatibleValidator.java
@@ -0,0 +1,58 @@
+/*
+ * 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.client.constraints;
+
+import java.lang.annotation.Annotation;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * Masks a {@link ConstraintValidator} that is not GWT compatible. This
+ * validator always fails.
+ * <p>
+ * Extend this class and implement it as GWT super class. Use validation groups
+ * to keep this constraint from being validated on the client.
+ * 
+ * <p>
+ * In a super source directory override your validator like this:
+ * 
+ * <pre>
+ * public class MyValidator extends 
+ *     NotGwtCompatibleValidator &lt;MyConstraint, MyType&gt;{
+ * }
+ * </pre>
+ * 
+ * @param <A> the constraint to validate
+ * @param <T> the type to validate
+ */
+public abstract class NotGwtCompatibleValidator<A extends Annotation, T>
+    implements
+    ConstraintValidator<A, T> {
+
+
+  public final void initialize(A constraintAnnotation) {
+  }
+
+  /**
+   * Always fails.
+   */
+  public final boolean isValid(T value, ConstraintValidatorContext context) {
+    // TODO (nchalko) add a custom message
+    return false;
+  }
+
+}
diff --git a/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java b/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java
index 3894f33..34a1a5e 100644
--- a/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java
+++ b/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java
@@ -16,6 +16,9 @@
 package com.google.gwt.validation.client.impl;
 
 import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 
 import javax.validation.ConstraintValidator;
@@ -32,6 +35,31 @@
     GwtSpecificValidator<G> {
 
   /**
+   * Builds attributes one at a time.
+   * <p>
+   * Used to create a attribute map for annotations.
+   */
+  public static final class AttributeBuilder {
+   private final HashMap<String, Object> tempMap = new HashMap<String, Object>();
+
+    private AttributeBuilder() {
+    }
+
+    public Map<String, Object> build() {
+      return Collections.unmodifiableMap(tempMap);
+    }
+
+    public AttributeBuilder put(String key, Object value) {
+      tempMap.put(key, value);
+      return this;
+    }
+  }
+
+  public static AttributeBuilder attributeBuilder() {
+    return new AttributeBuilder();
+  }
+
+  /**
    * @param <A>
    * @param <T>
    * @param <V>
@@ -45,7 +73,7 @@
    */
   protected <A extends Annotation, T, V> void validate(
       GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations,
-      G object, V value, ConstraintValidator<A, V> validator,
+      G object, V value, ConstraintValidator<A, ? super V> validator,
       ConstraintDescriptorImpl<A> constraintDescriptor, Class<?>[] groups) {
     validator.initialize(constraintDescriptor.getAnnotation());
     ConstraintValidatorContextImpl<A, V> constraintValidatorContext =
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 e5b7487..5e5a552 100644
--- a/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.java
+++ b/user/src/com/google/gwt/validation/client/impl/AbstractGwtValidator.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
@@ -15,6 +15,10 @@
  */
 package com.google.gwt.validation.client.impl;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 import javax.validation.ValidationException;
 import javax.validation.Validator;
 
@@ -25,7 +29,34 @@
  */
 public abstract class AbstractGwtValidator implements Validator {
 
+  private final Set<Class<?>> validGroups;
+
+  /**
+   * 
+   * @param groups list of valid groups. An empty list defaults to just the
+   *          {@link javax.validation.groups.Default} group.
+   */
+  public AbstractGwtValidator(Class<?>... groups) {
+    validGroups = new HashSet<Class<?>>(Arrays.asList(groups));
+  }
+
   public <T> T unwrap(Class<T> type) {
     throw new ValidationException();
   }
+
+  protected void checkGroups(Class<?>... groups) {
+    // an empty list of valid groups means all groups are valid.
+    if (!validGroups.isEmpty()
+        && !validGroups.containsAll(Arrays.asList(groups))) {
+      throw new IllegalArgumentException(this.getClass()
+          + " only processes the following groups " + validGroups);
+    }
+  }
+
+  protected void checkNotNull(Object object, String name)
+      throws IllegalArgumentException {
+    if (object == null) {
+      throw new IllegalArgumentException(name + " can not be null.");
+    }
+  }
 }
diff --git a/user/src/com/google/gwt/validation/client/impl/ConstraintDescriptorImpl.java b/user/src/com/google/gwt/validation/client/impl/ConstraintDescriptorImpl.java
index 5ef4804..2485a3d 100644
--- a/user/src/com/google/gwt/validation/client/impl/ConstraintDescriptorImpl.java
+++ b/user/src/com/google/gwt/validation/client/impl/ConstraintDescriptorImpl.java
@@ -15,7 +15,10 @@
  */
 package com.google.gwt.validation.client.impl;
 
+
 import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -47,7 +50,7 @@
     private boolean reportAsSingleViolation;
 
     public ConstraintDescriptorImpl<T> build() {
-      return new ConstraintDescriptorImpl<T>(
+      return new ConstraintDescriptorImpl<T>(//
           annotation, //
           groups, //
           payload, //
@@ -79,16 +82,37 @@
       return this;
     }
 
+    /**
+     * @param classes
+     * @return
+     */
+    public Builder<T> setConstraintValidatorClasses(
+        Class<? extends ConstraintValidator<T, ?>>[] constraintValidatorClasses) {
+      List<Class<? extends ConstraintValidator<T, ?>>> list = Arrays.asList(constraintValidatorClasses);
+      setConstraintValidatorClasses(list);
+      return this;
+    }
+
     public Builder<T> setGroups(Set<Class<?>> groups) {
       this.groups = groups;
       return this;
     }
 
+    public Builder<T> setGroups(Class<?>[] classes) {
+      setGroups(new HashSet<Class<?>>(Arrays.asList(classes)));
+      return this;
+    }
+
     public Builder<T> setPayload(Set<Class<? extends Payload>> payload) {
       this.payload = payload;
       return this;
     }
 
+    public Builder<T> setPayload(Class<? extends Payload>[] classes) {
+      setPayload(new HashSet<Class<? extends Payload>>(Arrays.asList(classes)));
+      return this;
+    }
+
     public Builder<T> setReportAsSingleViolation(boolean reportAsSingleViolation) {
       this.reportAsSingleViolation = reportAsSingleViolation;
       return this;
diff --git a/user/src/com/google/gwt/validation/rebind/AbstractCreator.java b/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
index 24c1111..c40ebc6 100644
--- a/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/AbstractCreator.java
@@ -17,6 +17,7 @@
 
 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.core.ext.typeinfo.JPackage;
 import com.google.gwt.user.rebind.AbstractSourceCreator;
@@ -46,7 +47,7 @@
     this.validatorType = validatorType;
   }
 
-  public final String create() {
+  public final String create() throws UnableToCompleteException {
     SourceWriter sourceWriter = getSourceWriter(logger, context);
     if (sourceWriter != null) {
       writeClassBody(sourceWriter);
@@ -55,6 +56,12 @@
     return getQualifiedName();
   }
 
+  protected void addImports(ClassSourceFileComposerFactory composerFactory, Class<?>... imports) {
+    for (Class<?> imp : imports) {
+      composerFactory.addImport(imp.getCanonicalName());
+    }
+  }
+
   protected abstract void compose(ClassSourceFileComposerFactory composerFactory);
 
   protected final String getPackage() {
@@ -63,7 +70,8 @@
     return packageName;
   }
 
-  protected abstract void writeClassBody(SourceWriter sourceWriter);
+  protected abstract void writeClassBody(SourceWriter sourceWriter)
+      throws UnableToCompleteException;
 
   private String getQualifiedName() {
     String packageName = getPackage();
diff --git a/user/src/com/google/gwt/validation/rebind/BeanHelper.java b/user/src/com/google/gwt/validation/rebind/BeanHelper.java
index 97e52ea..021c7c3 100644
--- a/user/src/com/google/gwt/validation/rebind/BeanHelper.java
+++ b/user/src/com/google/gwt/validation/rebind/BeanHelper.java
@@ -17,19 +17,35 @@
 
 import com.google.gwt.core.ext.typeinfo.JClassType;
 
+import javax.validation.metadata.BeanDescriptor;
+
 /**
  * A simple struct for the various values associated with a Bean that can be
  * validated.
  */
 final class BeanHelper {
 
+  private final BeanDescriptor beanDescriptor;
   private final JClassType jClass;
 
-  public BeanHelper(JClassType jClass) {
+  public BeanHelper(JClassType jClass,
+      BeanDescriptor beanDescriptor) {
     super();
+    this.beanDescriptor = beanDescriptor;
     this.jClass = jClass;
   }
 
+  public BeanDescriptor getBeanDescriptor() {
+    return beanDescriptor;
+  }
+
+  /*
+   * The server side validator needs an actual class.
+   */
+  public Class<?> getClazz() throws ClassNotFoundException {
+    return Class.forName(jClass.getQualifiedSourceName());
+  }
+
   public String getDescriptorName() {
 
     return jClass.getName() + "Descriptor";
@@ -51,4 +67,4 @@
   public String toString() {
     return getTypeCanonicalName();
   }
-}
\ No newline at end of file
+}
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
index be6098a..f6a7500 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -18,19 +18,33 @@
 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.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.user.rebind.ClassSourceFileComposerFactory;
 import com.google.gwt.user.rebind.SourceWriter;
 import com.google.gwt.validation.client.impl.AbstractGwtSpecificValidator;
+import com.google.gwt.validation.client.impl.ConstraintDescriptorImpl;
 import com.google.gwt.validation.client.impl.GwtBeanDescriptor;
 import com.google.gwt.validation.client.impl.GwtValidationContext;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
+import javax.validation.ConstraintValidator;
 import javax.validation.ConstraintViolation;
-import javax.validation.metadata.BeanDescriptor;
+import javax.validation.Payload;
+import javax.validation.Validator;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
 
 /**
  * Creates a {@link com.google.gwt.validation.client.GwtSpecificValidator}.
@@ -40,42 +54,122 @@
 
 public class GwtSpecificValidatorCreator extends AbstractCreator {
 
-  final JClassType beanType;
+  /**
+     * Returns the literal value of an object that is suitable for inclusion in
+     * Java Source code.  
+     * 
+     * <p>
+     * Supports all types that {@link Annotation) value can have.
+     * 
+     * 
+     * @throws IllegalArgumentException if the type of the object does not have a java literal form.
+     */
+    public static String asLiteral(Object value) throws IllegalArgumentException {
+      Class<?> clazz = value.getClass();
+      JProgram jProgram = new JProgram();
+  
+      if (clazz.isArray()) {
+        StringBuilder sb = new StringBuilder();
+        Object[] array = (Object[]) value;
+  
+        sb.append("new " + clazz.getComponentType().getCanonicalName() + "[] ");
+        sb.append("{");
+        boolean first = true;
+        for (Object object : array) {
+          if (first) {
+            first = false;
+          } else {
+            sb.append(",");
+          }
+          sb.append(asLiteral(object));
+        }
+        sb.append("}");
+        return sb.toString();
+      }
+
+      if (value instanceof Class) {
+        return ((Class<?>) ((Class<?>) value)).getCanonicalName() + ".class";
+      }
+      if (value instanceof Double) {
+        return jProgram.getLiteralDouble(((Double) value).doubleValue()).toSource();
+      }
+      if (value instanceof Integer) {
+        return jProgram.getLiteralInt(((Integer) value).intValue()).toSource();
+      }
+      if (value instanceof String) {
+        return '"' + ((String) value).toString().replace("\"", "\\\"") + '"';
+      }
+    // TODO(nchalko) handle the rest of the literal types
+      throw new IllegalArgumentException(value.getClass()
+          + " is can not be represented as a Java Literal.");
+    }
   private BeanHelper beanHelper;
+  private final JClassType beanType;
   private final TypeOracle oracle;
 
+  private final Validator serverSideValidator;
+
   public GwtSpecificValidatorCreator(JClassType validatorType,
       JClassType beanType, BeanHelper beanHelper, TreeLogger logger,
-      GeneratorContext context) {
+      GeneratorContext context, Validator serverSideValidator) {
     super(context, logger, validatorType);
     this.oracle = context.getTypeOracle();
     this.beanType = beanType;
     this.beanHelper = beanHelper;
+    this.serverSideValidator = serverSideValidator;
+  }
+
+  protected <T> T[] asArray(Collection<?> collection, T[] array) {
+    if (collection == null) {
+      return null;
+    }
+    return collection.toArray(array);
+  }
+
+  protected String asGetter(PropertyDescriptor p) {
+    return "get" + capitalizeFirstLetter(p.getPropertyName());
+  }
+
+  protected 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;
   }
 
   @Override
   protected void compose(ClassSourceFileComposerFactory composerFactory) {
-    Class<?>[] imports = new Class<?>[]{
-        GWT.class,
-        GwtBeanDescriptor.class,
-        GwtValidationContext.class,
-        Set.class,
-        HashSet.class,
-        ConstraintViolation.class,
-        BeanDescriptor.class,
-        };
-    for (Class<?> imp : imports) {
-      composerFactory.addImport(imp.getCanonicalName());
-    }
-
+    addImports(composerFactory, GWT.class, GwtBeanDescriptor.class,
+        GwtValidationContext.class, Set.class, HashSet.class,
+        ConstraintViolation.class, Annotation.class);
     composerFactory.setSuperclass(AbstractGwtSpecificValidator.class.getCanonicalName()
         + "<" + beanType.getQualifiedSourceName() + ">");
-
     composerFactory.addImplementedInterface(validatorType.getName());
   }
 
+  protected String constraintDescriptorVar(String name, int count) {
+    String s = name + "_c" + count;
+    return s;
+  }
+
+  protected Class<? extends ConstraintValidator<? extends Annotation, ?>> getValidatorForType(
+      ConstraintDescriptor<? extends Annotation> constraint, Class<?> clazz) {
+    // TODO(nchalko) implement per spec
+    Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass = constraint.getConstraintValidatorClasses().get(
+        0);
+    return validatorClass;
+  }
+
   @Override
-  protected void writeClassBody(SourceWriter sw) {
+  protected void writeClassBody(SourceWriter sw)
+      throws UnableToCompleteException {
     writeFields(sw);
     sw.println();
     writeValidate(sw);
@@ -85,21 +179,167 @@
     writeValidateValue(sw);
     sw.println();
     writeGetDescriptor(sw);
+    sw.println();
+    writePropertyValidtors(sw);
   }
 
-  protected void writeNewViolations(SourceWriter sw) {
-    // Set<ConstraintViolation<T>> violations = new
-    // HashSet<ConstraintViolation<T>>();
-    sw.println("Set<ConstraintViolation<T>> violations = new HashSet<ConstraintViolation<T>>();");
+  protected void writeConstraintDescriptor(SourceWriter sw,
+      ConstraintDescriptor<? extends Annotation> constraint,
+      String constraintDescripotorVar) throws UnableToCompleteException {
+    Class<? extends Annotation> annotationType = constraint.getAnnotation().annotationType();
+
+    // First list all composing constraints
+    int count = 0;
+    for (ConstraintDescriptor<?> composingConstraint : constraint.getComposingConstraints()) {
+      writeConstraintDescriptor(sw, composingConstraint,
+          constraintDescripotorVar + "_" + count++);
+    }
+
+    // ConstraintDescriptorImpl<MyAnnotation> constraintDescriptor = ;
+    sw.print(ConstraintDescriptorImpl.class.getCanonicalName());
+    sw.print("<");
+
+    sw.print(annotationType.getCanonicalName());
+    sw.print(">");
+
+    sw.println(" " + constraintDescripotorVar + "  = ");
+    sw.indent();
+    sw.indent();
+
+    // ConstraintDescriptorImpl.<MyConstraint> builder()
+    sw.print(ConstraintDescriptorImpl.class.getCanonicalName());
+    sw.print(".<");
+
+    sw.print(annotationType.getCanonicalName());
+    sw.println("> builder()");
+    sw.indent();
+    sw.indent();
+
+    // .setAnnotation(new MyAnnotation )
+    sw.println(".setAnnotation( ");
+    sw.indent();
+    sw.indent();
+    writeNewAnnotation(sw, constraint);
+    sw.println(")");
+    sw.outdent();
+    sw.outdent();
+
+    // .setAttributes(builder()
+    sw.println(".setAttributes(attributeBuilder()");
+    sw.indent();
+
+    for (Map.Entry<String, Object> entry : constraint.getAttributes().entrySet()) {
+      // .put(key, value)
+      sw.print(".put(");
+      sw.print(asLiteral(entry.getKey()));
+      sw.print(", ");
+      sw.print(asLiteral(entry.getValue()));
+      sw.println(")");
+    }
+
+    // .build())
+    sw.println(".build())");
+    sw.outdent();
+
+    // .setConstraintValidatorClasses(classes )
+    sw.print(".setConstraintValidatorClasses(");
+    sw.print(asLiteral(asArray(constraint.getConstraintValidatorClasses(), 
+        new Class[0])));
+    sw.println(")");
+    
+    // .getGroups(groups)
+    sw.print(".setGroups(");
+    Set<Class<?>> groups = constraint.getGroups();
+    sw.print(asLiteral(asArray(groups, new Class<?>[0])));
+    sw.println(")");
+
+    // .setPayload(payload)
+    sw.print(".setPayload(");
+    Set<Class<? extends Payload>> payload = constraint.getPayload();
+    sw.print(asLiteral(asArray(payload, new Class[0])));
+    sw.println(")");
+
+    // .setsetReportAsSingleViolation(boolean )
+    sw.print(".setReportAsSingleViolation(");
+    sw.print(Boolean.valueOf(constraint.isReportAsSingleViolation()).toString());
+    sw.println(")");
+
+    // .build();
+    sw.println(".build();");
+    sw.outdent();
+    sw.outdent();
+
+    sw.outdent();
+    sw.outdent();
+    sw.println();
+  }
+
+  protected void writeValidateInterfaces(SourceWriter sw, Class<?> clazz) {
+    for (Class<?> type : clazz.getInterfaces()) {
+      if (serverSideValidator.getConstraintsForClass(type).isBeanConstrained()) {
+        // MyInterface_GwtSpecificValidator validator =
+        // GWT.create(MyInterface_GwtSpecificValidator);
+        // TODO (nchalko) validate interface. This Requires the
+        // MyInterface_GwtSpecficValidator
+        // interface to already be generated.
+        sw.print("//TODO(nchalko) GWT.create(");
+        sw.print(type.getCanonicalName());
+        sw.println("_GwtSpecificValidator);");
+
+        // voilations.add(validator.validate(context,this,groups));
+      }
+
+      writeValidateInterfaces(sw, type);
+    }
+  }
+
+/**
+ * @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 String validateMethodName(PropertyDescriptor p) {
+    return "validateProperty_" + p.getPropertyName();
   }
 
   /**
    * @param sourceWriter
+   * @throws UnableToCompleteException
    */
-  private void writeFields(SourceWriter sw) {
+  private void writeFields(SourceWriter sw) throws UnableToCompleteException {
     // MyBeanDescriptor beanDescriptor = GWT.create(MyBeanDescriptor);
     sw.println(GwtBeanDescriptor.class.getCanonicalName());
-    sw.println(" beanDescriptor = null; // GWT.create");
+    // TODO(nchalko) implement BeanDescriptor Generator
+    sw.println(" beanDescriptor = null; //TODO(nchalko) GWT.create");
+
+    // Create a variable for each constraint of each property
+    for (PropertyDescriptor p : beanHelper.getBeanDescriptor().getConstrainedProperties()) {
+      int count = 0;
+      for (ConstraintDescriptor<?> constraint : p.getConstraintDescriptors()) {
+        count++; // index starts at one.
+        writeConstraintDescriptor(sw, constraint,
+            constraintDescriptorVar(p.getPropertyName(), count));
+      }
+    }
+
+    // Create a variable for each constraint of this class.
+    int count = 0;
+    for (ConstraintDescriptor<?> constraint : beanHelper.getBeanDescriptor().getConstraintDescriptors()) {
+      count++; // index starts at one.
+      writeConstraintDescriptor(sw, constraint,
+          constraintDescriptorVar("this", count));
+    }
   }
 
   private void writeGetDescriptor(SourceWriter sw) {
@@ -109,13 +349,78 @@
     sw.println("getConstraints() {");
     sw.indent();
 
-    //    return beanDescriptor;
+    // return beanDescriptor;
     sw.println("return beanDescriptor;");
 
     sw.outdent();
     sw.println("}");
   }
 
+  private void writeNewAnnotation(SourceWriter sw,
+      ConstraintDescriptor<? extends Annotation> constraint)
+      throws UnableToCompleteException {
+    Annotation annotation = constraint.getAnnotation();
+    Class<? extends Annotation> annotationType = annotation.annotationType();
+
+    // new MyAnnotation () {
+    sw.print("new ");
+    sw.print(annotationType.getCanonicalName());
+    sw.println("(){");
+    sw.indent();
+    sw.indent();
+
+    // public Class<? extends Annotation> annotationType() { return
+    // MyAnnotation.class; }
+    sw.print("public Class<? extends Annotation> annotationType() {  return ");
+    sw.print(annotationType.getCanonicalName());
+    sw.println(".class; }");
+
+    for (Method method : annotationType.getMethods()) {
+      // method.isAbstract would be better
+      if (method.getDeclaringClass().equals(annotation.annotationType())) {
+        // public returnType method() { return value ;}
+        sw.print("public ");
+        sw.print(method.getReturnType().getCanonicalName()); // TODO handle
+                                                             // generics
+        sw.print(" ");
+        sw.print(method.getName());
+        sw.print("() { return ");
+
+        try {
+          Object value = method.invoke(annotation);
+          sw.print(asLiteral(value));
+        } catch (IllegalArgumentException e) {
+          throw error(logger, e);
+        } catch (IllegalAccessException e) {
+          throw error(logger, e);
+        } catch (InvocationTargetException e) {
+          throw error(logger, e);
+        }
+        sw.println(";}");
+      }
+    }
+
+    sw.outdent();
+    sw.outdent();
+    sw.println("}");
+  }
+
+  private void writeNewViolations(SourceWriter sw) {
+    // Set<ConstraintViolation<T>> violations = new
+    // HashSet<ConstraintViolation<T>>();
+    sw.println("Set<ConstraintViolation<T>> violations = new HashSet<ConstraintViolation<T>>();");
+  }
+
+  /**
+   * @param sw
+   */
+  private void writePropertyValidtors(SourceWriter sw) {
+    for (PropertyDescriptor p : beanHelper.getBeanDescriptor().getConstrainedProperties()) {
+      writeValidatePropertyMethod(sw, p);
+      sw.println();
+    }
+  }
+
   private void writeValidate(SourceWriter sw) {
     // public <T> Set<ConstraintViolation<T>> validate(
     sw.println("public <T> Set<ConstraintViolation<T>> validate(");
@@ -130,8 +435,77 @@
 
     writeNewViolations(sw);
 
-    // TODO(nchalko) loop over all constraints
+    if (beanHelper.getBeanDescriptor().isBeanConstrained()) {
 
+      // /// For each group
+
+      // TODO(nchalko) handle the sequence in the AbstractValidator
+      // Let the GwtSpecificValidators only take a single group.
+
+      // See JSR 303 section 3.5
+      // all reachable fields
+      // all reachable getters (both) at once
+
+      Set<PropertyDescriptor> properties = beanHelper.getBeanDescriptor().getConstrainedProperties();
+
+      for (PropertyDescriptor p : properties) {
+        writeValidatePropertyCall(sw, p);
+      }
+
+      // all class level constraints
+      // including super classes
+      // including super interfaces
+
+      int count = 0;
+      Class<?> clazz = null;
+      try {
+        clazz = beanHelper.getClazz();
+      } catch (ClassNotFoundException e) {
+        error(logger, e);
+      }
+      for (ConstraintDescriptor<?> constraint : beanHelper.getBeanDescriptor().findConstraints().getConstraintDescriptors()) {
+        count++; // index starts at 1
+        Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass = getValidatorForType(
+            constraint, clazz);
+        // TODO(nchalko) handle constraint.isReportAsSingleViolation() and
+        // hasComposingConstraints
+
+        // 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);");
+      }
+
+      // validate all super classes and interfaces
+
+      Class<?> superClass = clazz.getSuperclass();
+      writeValidateInterfaces(sw, clazz);
+      while (superClass != null) {
+        if (serverSideValidator.getConstraintsForClass(superClass).isBeanConstrained()) {
+          // MySuper_GwtSpecificValidator validator =
+          // GWT.create(MySuper_GwtSpecificValidator);
+          sw.print("//  GWT.create(");
+          sw.print(superClass.getCanonicalName());
+          sw.println("_GwtSpecificValidator);");
+        }
+        writeValidateInterfaces(sw, superClass);
+        superClass = superClass.getSuperclass();
+      }
+
+      // all reachable and cascadable associations
+
+      // TODO(nchalko) validationg the object graph will require top level
+      // interfaces for the classes
+      // that already generated
+
+      beanType.getFields();
+    }
     // return violations;
     sw.println("return violations;");
 
@@ -155,7 +529,38 @@
 
     writeNewViolations(sw);
 
-    // TODO(nchalko) case statement for propertyName
+    // TODO(nchalko) check if it is a valid propertyName
+
+    for (PropertyDescriptor property : beanHelper.getBeanDescriptor().getConstrainedProperties()) {
+      // if (propertyName.equals(myPropety)) {
+      sw.print("if (propertyName.equals(\"");
+      sw.print(property.getPropertyName());
+      sw.println("\")) {");
+      sw.indent();
+
+      // validate_myProperty
+      writeValidatePropertyCall(sw, property);
+
+      // }
+      sw.outdent();
+      sw.print("} else ");
+    }
+
+    // {
+    sw.println("{");
+    sw.indent();
+
+    // throw new IllegalArgumentException(propertyName
+    // +"is not a valid property of myClass");
+    sw.print("throw new ");
+    sw.print(IllegalArgumentException.class.getCanonicalName());
+    sw.print("( propertyName +\" is not a valid property of ");
+    sw.print(beanType.getQualifiedSourceName());
+    sw.println("\");");
+
+    // }
+    sw.outdent();
+    sw.println("}");
 
     // return violations;
     sw.println("return violations;");
@@ -164,6 +569,64 @@
     sw.println("}");
   }
 
+  private void writeValidatePropertyCall(SourceWriter sw, PropertyDescriptor p) {
+    String propertyName = p.getPropertyName();
+    // validateProperty_<<field>>(context, object, object.getLastName(),
+    // groups));
+    sw.print(validateMethodName(p));
+    sw.print("(context, ");
+    sw.print("violations, ");
+    sw.print("object, ");
+    sw.print("object.");
+    if (hasGetter(p)) {
+      sw.print(asGetter(p) + "()");
+    } else {
+      sw.print(propertyName);
+    }
+    sw.print(", ");
+    sw.println("groups);");
+  }
+
+  private void writeValidatePropertyMethod(SourceWriter sw, PropertyDescriptor p) {
+    // private final <T> void validateProperty_<p>(
+    sw.print("private final <T> void ");
+    sw.print(validateMethodName(p));
+    sw.println("(");
+
+    // GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations,
+    // BeanType object, <Type> value, Class<?>... groups) {
+    sw.indent();
+    sw.indent();
+    sw.println("GwtValidationContext<T> context,");
+    sw.println("Set<ConstraintViolation<T>> violations,");
+    sw.println(beanHelper.getTypeCanonicalName() + " object,");
+    sw.print(p.getElementClass().getCanonicalName());
+    sw.println(" value,");
+    sw.println("Class<?>... groups) {");
+    sw.outdent();
+    int count = 0;
+    for (ConstraintDescriptor<?> constraint : p.getConstraintDescriptors()) {
+      count++; // index starts at 1
+      Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass = getValidatorForType(
+          constraint, p.getElementClass());
+      // TODO(nchalko) handle constraint.isReportAsSingleViolation() and
+      // hasComposingConstraints
+
+      // validate(context, violations, object, value, validator,
+      // constraintDescriptor, groups);
+      sw.print("validate(context, violations, object, value, ");
+      // new MyValidtor();
+      sw.print("new ");
+      sw.print(validatorClass.getCanonicalName());
+      sw.print("(), "); // new one each time because validators are not thread
+                        // safe
+      sw.print(constraintDescriptorVar(p.getPropertyName(), count));
+      sw.println(", groups);");
+    }
+    sw.outdent();
+    sw.println("}");
+  }
+
   private void writeValidateValue(SourceWriter sw) {
     // public <T> Set<ConstraintViolation<T>> validate(
     sw.println("public <T> Set<ConstraintViolation<T>> validateValue(");
@@ -181,7 +644,47 @@
 
     writeNewViolations(sw);
 
-    // TODO(nchalko) case statement for propertyName
+    // TODO(nchalko) check if it is a valid propertyName
+
+    for (PropertyDescriptor property : beanHelper.getBeanDescriptor().getConstrainedProperties()) {
+      // if (propertyName.equals(myPropety)) {
+      sw.print("if (propertyName.equals(\"");
+      sw.print(property.getPropertyName());
+      sw.println("\")) {");
+      sw.indent();
+
+      // validateProperty_<<field>>(context, (MyType) null,
+      // object.getLastName(),
+      // groups));
+      sw.print(validateMethodName(property));
+      sw.print("(context, ");
+      sw.print("violations, ");
+      sw.print("null, ");
+      sw.print("(");
+      sw.print(property.getElementClass().getCanonicalName());
+      sw.print(") value, ");
+      sw.println("groups);");
+
+      // }
+      sw.outdent();
+      sw.print("} else ");
+    }
+
+    // {
+    sw.println("{");
+    sw.indent();
+
+    // throw new IllegalArgumentException(propertyName
+    // +"is not a valid property of myClass");
+    sw.print("throw new ");
+    sw.print(IllegalArgumentException.class.getCanonicalName());
+    sw.print("( propertyName +\" is not a valid property of ");
+    sw.print(beanType.getQualifiedSourceName());
+    sw.println("\");");
+
+    // }
+    sw.outdent();
+    sw.println("}");
 
     // return violations;
     sw.println("return violations;");
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
index 71cee0f..0f59f7c 100644
--- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
+++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorGenerator.java
@@ -24,6 +24,9 @@
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.validation.client.impl.GwtSpecificValidator;
 
+import javax.validation.Validation;
+import javax.validation.Validator;
+
 /**
  * Generates a {@link com.google.gwt.validation.client.GwtSpecificValidator}.
  * <p>
@@ -31,6 +34,8 @@
  */
 public class GwtSpecificValidatorGenerator extends Generator {
 
+  private final Validator serverSideValidor = Validation.buildDefaultValidatorFactory().getValidator();
+
   @Override
   public String generate(TreeLogger logger, GeneratorContext context,
       String typeName) throws UnableToCompleteException {
@@ -59,7 +64,7 @@
     }
 
     AbstractCreator creator = new GwtSpecificValidatorCreator(validatorType,
-        beanType, beanHelper, logger, context);
+        beanType, beanHelper, logger, context, serverSideValidor);
     return creator.create();
   }
 
diff --git a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
index e64949c..8d52981 100644
--- a/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
+++ b/user/src/com/google/gwt/validation/rebind/ValidatorCreator.java
@@ -19,7 +19,6 @@
 import com.google.gwt.core.ext.GeneratorContext;
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JPackage;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
 import com.google.gwt.user.rebind.SourceWriter;
@@ -29,19 +28,20 @@
 import com.google.gwt.validation.client.impl.GwtSpecificValidator;
 import com.google.gwt.validation.client.impl.GwtValidationContext;
 
-import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
 import javax.validation.metadata.BeanDescriptor;
 
 /**
  * Class that creates the validator for the given input class.
  */
-public class ValidatorCreator {
+public class ValidatorCreator extends AbstractCreator {
 
   // stash the map in a ThreadLocal, since each GWT module lives in its own
   // thread in DevMode
@@ -61,68 +61,53 @@
   }
 
   private final Map<JClassType, BeanHelper> beansToValidate = new HashMap<JClassType, BeanHelper>();
-  private final GeneratorContext context;
-  private final TreeLogger logger;
-  private final JClassType validatorType;
+  private final GwtValidation gwtValidation;
+  private final Validator serverSideValidor = Validation.buildDefaultValidatorFactory().getValidator();
 
-  public ValidatorCreator(JClassType validatorType,
-      GwtValidation gwtValidation, TreeLogger logger,
+  public ValidatorCreator(JClassType validatorType, //
+      GwtValidation gwtValidation, //
+      TreeLogger logger, //
       GeneratorContext context) {
-    this.validatorType = validatorType;
-    this.logger = logger;
-    this.context = context;
+    super(context, logger, validatorType);
+    this.gwtValidation = gwtValidation;
     TypeOracle oracle = context.getTypeOracle();
 
     for (Class<?> clazz : gwtValidation.value()) {
       JClassType jClass = oracle.findType(clazz.getCanonicalName());
-      BeanHelper helper = new BeanHelper(jClass);
+      BeanHelper helper = new BeanHelper(jClass,
+          serverSideValidor.getConstraintsForClass(clazz));
       beansToValidate.put(jClass, helper);
     }
     threadLocalHelperMap.get().putAll(beansToValidate);
   }
 
-  public String create() {
-    SourceWriter sourceWriter = getSourceWriter(logger, context);
-    if (sourceWriter != null) {
+  @Override
+  protected void compose(ClassSourceFileComposerFactory composerFactory) {
+   addImports(composerFactory, 
+       GWT.class,
+       GwtBeanDescriptor.class,
+       GwtSpecificValidator.class,
+       GwtValidationContext.class,
+       Set.class,
+       ConstraintViolation.class,
+       BeanDescriptor.class);
+    composerFactory.setSuperclass(AbstractGwtValidator.class.getCanonicalName());
+    composerFactory.addImplementedInterface(this.validatorType.getQualifiedSourceName());
+  }
+
+  @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);
-
-      sourceWriter.commit(logger);
-    }
-    return getQaulifiedName();
-  }
-
-  protected void writeContext(SourceWriter sourceWriter, BeanHelper bean,
-      String objectName) {
-    sourceWriter.print(GwtValidationContext.class.getCanonicalName()
-        + "<T> context = new " + GwtValidationContext.class.getCanonicalName()
-        + "<T>(" + objectName + ",");
-    sourceWriter.println(bean.getValidatorInstanceName()
-        + ".getConstraints());");
-  }
-
-  protected void writeGetConstraintsForClass(SourceWriter sourceWriter) {
-    sourceWriter.println("public BeanDescriptor getConstraintsForClass(Class<?> clazz) {");
-    sourceWriter.indent();
-    sourceWriter.println("return null;");
-    sourceWriter.outdent();
-    sourceWriter.println("}");
-    sourceWriter.println();
-  }
-
-  protected void writeIfEqulsBeanType(SourceWriter sourceWriter, BeanHelper bean) {
-    sourceWriter.println("if (object.getClass().equals("
-        + bean.getTypeCanonicalName() + ".class)) {");
-  }
-
-  protected void writeThrowIllegalArgumnet(SourceWriter sourceWriter) {
-    sourceWriter.print("throw new IllegalArgumentException(\""
-        + this.validatorType.getName() + " can only validate ");
-    sourceWriter.print(beansToValidate.toString());
-    sourceWriter.println("\");");
   }
 
   protected void writeTypeSupport(SourceWriter sw) {
@@ -142,47 +127,129 @@
 
       sw.print("private final " + bean.getValidatorName() + " ");
       sw.print(bean.getValidatorInstanceName());
-      sw.print(" = GWT.create(" + bean.getValidatorName() + ".class);");
-      sw.println();
+      sw.println(" = GWT.create(" + bean.getValidatorName() + ".class);");
     }
   }
 
-  protected void writeValidate(SourceWriter sw) {
+  private String getQaulifiedName() {
+    return validatorType.getQualifiedSourceName() + "Impl";
+  }
+
+  private String getSimpleName() {
+    return validatorType.getSimpleSourceName() + "Impl";
+  }
+
+  private void writeConstructor(SourceWriter sw) {
+    // public MyValidator() {
+    sw.println("public " + getSimpleName() + "() {");
+    sw.indent();
+
+    // super( <<groups>>);
+    sw.print("super(");
+    boolean first = true;
+    for (Class<?> group : gwtValidation.groups()) {
+      if (!first) {
+        sw.print(", ");
+      } else {
+        first = false;
+      }
+      sw.print(group.getCanonicalName() + ".class");
+    }
+    sw.println(");");
+
+    sw.outdent();
+    sw.println("}");
+  }
+
+  private void writeContext(SourceWriter sw, BeanHelper bean, String objectName) {
+    // GwtValidationContext<T> context =
+    // new GwtValidationContext<T>(object,myBeanValidator.getConstraints());
+    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.println(");");
+  }
+
+  private void writeGetConstraintsForClass(SourceWriter sourceWriter) {
+    sourceWriter.println("public BeanDescriptor getConstraintsForClass(Class<?> clazz) {");
+    sourceWriter.indent();
+    sourceWriter.println("return null;");
+    sourceWriter.outdent();
+    sourceWriter.println("}");
+  }
+
+  private void writeIfEqulsBeanType(SourceWriter sourceWriter, BeanHelper bean) {
+    sourceWriter.println("if (object.getClass().equals("
+        + bean.getTypeCanonicalName() + ".class)) {");
+  }
+
+  private void writeThrowIllegalArgumnet(SourceWriter sourceWriter) {
+    sourceWriter.print("throw new IllegalArgumentException(\""
+        + this.validatorType.getName() + " can only validate ");
+    sourceWriter.print(beansToValidate.toString());
+    sourceWriter.println("\");");
+  }
+
+  private void writeValidate(SourceWriter sw) {
+    // public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>...
+    // groups) {
     sw.println("public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {");
     sw.indent();
+
+    sw.println("checkNotNull(object, \"object\");");
+    sw.println("checkNotNull(groups, \"groups\");");
+    sw.println("checkGroups(groups);");
+
     for (BeanHelper bean : beansToValidate.values()) {
       writeValidate(sw, bean);
     }
+
     writeThrowIllegalArgumnet(sw);
-    sw.outdent(); // class
+
+    sw.outdent();
     sw.println("}");
-    sw.println();
   }
 
-  protected void writeValidate(SourceWriter sw, BeanHelper bean) {
+  private void writeValidate(SourceWriter sw, BeanHelper bean) {
     writeIfEqulsBeanType(sw, bean);
     sw.indent();
+
     writeContext(sw, bean, "object");
-    sw.print("return " + bean.getValidatorInstanceName()
-        + ".validate(context, (" + bean.getTypeCanonicalName() + ") object, ");
+
+    // return personValidator.validate(context, (<<MyBean>>) object, groups);
+    sw.print("return ");
+    sw.print(bean.getValidatorInstanceName() + ".validate(");
+    sw.print("context, ");
+    sw.print("(" + bean.getTypeCanonicalName() + ") object, ");
     sw.println("groups);");
-    sw.outdent(); // if
+
+    sw.outdent();
     sw.println("}");
   }
 
-  protected void writeValidateProperty(SourceWriter sw) {
+  private void writeValidateProperty(SourceWriter sw) {
     sw.println("public <T> Set<ConstraintViolation<T>> validateProperty(T object,String propertyName, Class<?>... groups) {");
     sw.indent();
+
+    sw.println("checkNotNull(object, \"object\");");
+    sw.println("checkNotNull(propertyName, \"propertyName\");");
+    sw.println("checkNotNull(groups, \"groups\");");
+    sw.println("checkGroups(groups);");
+
     for (BeanHelper bean : beansToValidate.values()) {
       writeValidateProperty(sw, bean);
     }
+
     writeThrowIllegalArgumnet(sw);
+
     sw.outdent();
     sw.println("}");
-    sw.println();
   }
 
-  protected void writeValidateProperty(SourceWriter sw, BeanHelper bean) {
+  private void writeValidateProperty(SourceWriter sw, BeanHelper bean) {
     writeIfEqulsBeanType(sw, bean);
     sw.indent();
     writeContext(sw, bean, "object");
@@ -194,19 +261,26 @@
     sw.println("}");
   }
 
-  protected void writeValidateValue(SourceWriter sw) {
+  private void writeValidateValue(SourceWriter sw) {
     sw.println("public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) {");
     sw.indent();
+
+    sw.println("checkNotNull(beanType, \"beanType\");");
+    sw.println("checkNotNull(propertyName, \"propertyName\");");
+    sw.println("checkNotNull(groups, \"groups\");");
+    sw.println("checkGroups(groups);");
+
     for (BeanHelper bean : beansToValidate.values()) {
       writeValidateValue(sw, bean);
     }
+
     writeThrowIllegalArgumnet(sw);
+
     sw.outdent();
     sw.println("}");
-    sw.println();
   }
 
-  protected void writeValidateValue(SourceWriter sw, BeanHelper bean) {
+  private void writeValidateValue(SourceWriter sw, BeanHelper bean) {
     sw.println("if (beanType.getClass().equals(" + bean.getTypeCanonicalName()
         + ".class)) {");
     sw.indent();
@@ -217,43 +291,4 @@
     sw.outdent(); // if
     sw.println("}");
   }
-
-  private String getQaulifiedName() {
-    return validatorType.getQualifiedSourceName() + "Impl";
-  }
-
-  private String getSimpleName() {
-    return validatorType.getSimpleSourceName() + "Impl";
-  }
-
-  private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContext ctx) {
-    JPackage serviceIntfPkg = validatorType.getPackage();
-    String packageName = serviceIntfPkg == null ? "" : serviceIntfPkg.getName();
-    String simpleName = getSimpleName();
-    PrintWriter printWriter = ctx.tryCreate(logger, packageName, simpleName);
-    if (printWriter == null) {
-      return null;
-    }
-
-    ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(
-        packageName, simpleName);
-
-    String[] imports = new String[]{
-        GWT.class.getCanonicalName(),
-        GwtBeanDescriptor.class.getCanonicalName(),
-        GwtSpecificValidator.class.getCanonicalName(),
-        GwtValidationContext.class.getCanonicalName(),
-        Set.class.getCanonicalName(),
-        ConstraintViolation.class.getCanonicalName(),
-        BeanDescriptor.class.getCanonicalName()};
-    for (String imp : imports) {
-      composerFactory.addImport(imp);
-    }
-
-    composerFactory.setSuperclass(AbstractGwtValidator.class.getCanonicalName());
-    SourceWriter sourceWriter = composerFactory.createSourceWriter(ctx,
-        printWriter);
-
-    return sourceWriter;
-  }
 }
diff --git a/user/src/org/hibernate/validator/HibernateValidator.gwt.xml b/user/src/org/hibernate/validator/HibernateValidator.gwt.xml
new file mode 100644
index 0000000..b469c70
--- /dev/null
+++ b/user/src/org/hibernate/validator/HibernateValidator.gwt.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module>
+<!-- 
+Import this module to use Hibernate Validator during the compilation of validation classes for 
+gwt clients.
+ -->
+  <inherits name='com.google.gwt.validation.Validation' />
+  <source path="constraints">
+    <exclude name="impl/scriptassert/" />
+    <exclude name="super/" />
+  </source>
+  <source path="engine">
+    <include name="NodeImpl.java"/>
+  </source>
+  <super-source path="super" />
+</module>
\ No newline at end of file
diff --git a/user/src/org/hibernate/validator/README.txt b/user/src/org/hibernate/validator/README.txt
new file mode 100644
index 0000000..26e3292
--- /dev/null
+++ b/user/src/org/hibernate/validator/README.txt
@@ -0,0 +1,13 @@
+The Hibernate Validator module is used to:
+
+1) generate client side validators.
+2) super source hibernate specific constraints
+3) super source hibernate classes needed to return ConstraintViolations from the server to the client.
+
+
+Maintenance Notes.
+Test using samples/validation.
+
+
+NOTE
+(nchalko) all of should be pushed back to hibernate.
\ No newline at end of file
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/ScriptAssert.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/ScriptAssert.java
new file mode 100644
index 0000000..260a80e
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/ScriptAssert.java
@@ -0,0 +1,136 @@
+// $Id: ScriptAssert.java 19327 2010-04-30 08:11:15Z hardy.ferentschik $
+/*
+ * JBoss, Home of Professional Open Source Copyright 2010, Red Hat, Inc. and/or
+ * its affiliates, and individual contributors by the @authors tag. See the
+ * copyright.txt in the distribution for a full listing of individual
+ * contributors.
+ * 
+ * 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.
+ */
+// MODIFIED BY GOOGLE
+package org.hibernate.validator.constraints;
+
+import org.hibernate.validator.constraints.impl.ScriptAssertValidator;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintDeclarationException;
+import javax.validation.Payload;
+
+/**
+ * <p>
+ * A class-level constraint, that evaluates a script expression against the
+ * annotated element. This constraint can be used to implement validation
+ * routines, that depend on multiple attributes of the annotated element.
+ * </p>
+ * <p>
+ * For evaluation of expressions the Java Scripting API as defined by <a
+ * href="http://jcp.org/en/jsr/detail?id=223">JSR 223</a>
+ * ("Scripting for the Java<sup>TM</sup> Platform") is used. Therefore an
+ * implementation of that API must part of the class path. This is automatically
+ * the case when running on Java 6. For older Java versions, the JSR 223 RI can
+ * be added manually to the class path.
+ * </p>
+ * The expressions to be evaluated can be written in any scripting or expression
+ * language, for which a JSR 223 compatible engine can be found in the class
+ * path. The following listing shows an example using the JavaScript engine,
+ * which comes with Java 6: </p>
+ * <p/>
+ * 
+ * <pre>
+ * &#064;ScriptAssert(lang = &quot;javascript&quot;, script = &quot;_this.startDate.before(_this.endDate)&quot;)
+ * public class CalendarEvent {
+ * <p/>
+ * 	private Date startDate;
+ * <p/>
+ * 	private Date endDate;
+ * <p/>
+ * 	//...
+ * <p/>
+ * }
+ * </pre>
+ * <p>
+ * Using a real expression language in conjunction with a shorter object alias
+ * allows for very compact expressions:
+ * </p>
+ * 
+ * <pre>
+ * &#064;ScriptAssert(lang = &quot;jexl&quot;, script = &quot;_.startDate &lt; _.endDate&quot;, alias = &quot;_&quot;)
+ * public class CalendarEvent {
+ * <p/>
+ * 	private Date startDate;
+ * <p/>
+ * 	private Date endDate;
+ * <p/>
+ * 	//...
+ * <p/>
+ * }
+ * </pre>
+ * <p>
+ * Accepts any type.
+ * </p>
+ * 
+ * @author Gunnar Morling
+ */
+@Target({TYPE})
+@Retention(RUNTIME)
+@Constraint(validatedBy = ScriptAssertValidator.class)
+@Documented
+public @interface ScriptAssert {
+
+  String message() default "{org.hibernate.validator.constraints.ScriptAssert.message}";
+
+  Class<?>[] groups() default {};
+
+  Class<? extends Payload>[] payload() default {};
+
+  /**
+   * @return The name of the script language used by this constraint as expected
+   *         by the JSR 223 {@link javax.script.ScriptEngineManager}. A
+   *         {@link ConstraintDeclarationException} will be thrown upon script
+   *         evaluation, if no engine for the given language could be found.
+   */
+  String lang();
+
+  /**
+   * @return The script to be executed. The script must return
+   *         <code>Boolean.TRUE</code>, if the annotated element could
+   *         successfully be validated, otherwise <code>Boolean.FALSE</code>.
+   *         Returning null or any type other than Boolean will cause a
+   *         {@link ConstraintDeclarationException} upon validation. Any
+   *         exception occurring during script evaluation will be wrapped into a
+   *         ConstraintDeclarationException, too. Within the script, the
+   *         validated object can be accessed from the
+   *         {@link javax.script.ScriptContext script context} using the name
+   *         specified in the <code>alias</code> attribute.
+   */
+  String script();
+
+  /**
+   * @return The name, under which the annotated element shall be registered
+   *         within the script context. Defaults to "_this".
+   */
+  String alias() default "_this";
+
+  /**
+   * Defines several {@code @ScriptAssert} annotations on the same element.
+   */
+  @Target({TYPE})
+  @Retention(RUNTIME)
+  @Documented
+  public @interface List {
+    ScriptAssert[] value();
+  }
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/EmailValidator.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/EmailValidator.java
new file mode 100644
index 0000000..46ed562
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/EmailValidator.java
@@ -0,0 +1,27 @@
+/*
+ * 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.validator.constraints.impl;
+
+import com.google.gwt.validation.client.constraints.NotGwtCompatibleValidator;
+
+import org.hibernate.validator.constraints.Email;
+
+/**
+ * This Validator is not GWT complatible.
+ */
+public class EmailValidator extends NotGwtCompatibleValidator<Email, String> {
+  // TODO(nchalko) make compatible
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/FutureValidatorForCalendar.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/FutureValidatorForCalendar.java
new file mode 100644
index 0000000..7cbf05e
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/FutureValidatorForCalendar.java
@@ -0,0 +1,27 @@
+/*
+ * 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.validator.constraints.impl;
+
+import com.google.gwt.validation.client.constraints.NotGwtCompatibleValidator;
+
+import javax.validation.constraints.Future;
+
+/**
+ * This Validator is not GWT complatible.
+ */
+public class FutureValidatorForCalendar extends
+    NotGwtCompatibleValidator<Future, Object> {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PastValidatorForCalendar.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PastValidatorForCalendar.java
new file mode 100644
index 0000000..1dba9e2
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PastValidatorForCalendar.java
@@ -0,0 +1,27 @@
+/*
+ * 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.validator.constraints.impl;
+
+import com.google.gwt.validation.client.constraints.NotGwtCompatibleValidator;
+
+import javax.validation.constraints.Past;
+
+/**
+ * This Validator is not GWT complatible.
+ */
+public class PastValidatorForCalendar extends
+    NotGwtCompatibleValidator<Past, Object> {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PatternValidator.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PatternValidator.java
new file mode 100644
index 0000000..aaf3e92
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/PatternValidator.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class PatternValidator extends
+    com.google.gwt.validation.client.constraints.PatternValidator {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/ScriptAssertValidator.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/ScriptAssertValidator.java
new file mode 100644
index 0000000..48bdc3a
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/ScriptAssertValidator.java
@@ -0,0 +1,27 @@
+/*
+ * 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.validator.constraints.impl;
+
+import com.google.gwt.validation.client.constraints.NotGwtCompatibleValidator;
+
+import org.hibernate.validator.constraints.Email;
+
+/**
+ * This Validator is not GWT complatible.
+ */
+public class ScriptAssertValidator extends
+    NotGwtCompatibleValidator<Email, String> {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArray.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArray.java
new file mode 100644
index 0000000..5ed12e4
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArray.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArray extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfObject {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfBoolean.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfBoolean.java
new file mode 100644
index 0000000..a26c805
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfBoolean.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfBoolean extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfBoolean {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfByte.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfByte.java
new file mode 100644
index 0000000..228fdd9
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfByte.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfByte extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfByte {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfChar.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfChar.java
new file mode 100644
index 0000000..8a1f3c2
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfChar.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfChar extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfChar {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfDouble.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfDouble.java
new file mode 100644
index 0000000..4e4beb8
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfDouble.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfDouble extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfDouble {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfFloat.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfFloat.java
new file mode 100644
index 0000000..8d87589
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfFloat.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfFloat extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfFloat {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfInt.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfInt.java
new file mode 100644
index 0000000..d875240
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfInt.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfInt extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfInt {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfLong.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfLong.java
new file mode 100644
index 0000000..55bf45d
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfLong.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfLong extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfLong {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfShort.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfShort.java
new file mode 100644
index 0000000..bd50c7d
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfShort.java
@@ -0,0 +1,23 @@
+/*
+ * 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.validator.constraints.impl;
+
+/**
+ * Override the Hibernate implementation with the GWT version.
+ */
+public class SizeValidatorForArraysOfShort extends
+    com.google.gwt.validation.client.constraints.SizeValidatorForArrayOfShort {
+}
diff --git a/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/URLValidator.java b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/URLValidator.java
new file mode 100644
index 0000000..bf01353
--- /dev/null
+++ b/user/src/org/hibernate/validator/super/org/hibernate/validator/constraints/impl/URLValidator.java
@@ -0,0 +1,27 @@
+/*
+ * 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.validator.constraints.impl;
+
+import com.google.gwt.validation.client.constraints.NotGwtCompatibleValidator;
+
+import org.hibernate.validator.constraints.URL;
+
+/**
+ * This Validator is not GWT complatible.
+ */
+public class URLValidator extends
+ NotGwtCompatibleValidator<URL, Object> {
+}
diff --git a/user/test/com/google/gwt/validation/example/ValidationExample.gwt.xml b/user/test/com/google/gwt/validation/example/ValidationExample.gwt.xml
index 0dddb0f..a659123 100644
--- a/user/test/com/google/gwt/validation/example/ValidationExample.gwt.xml
+++ b/user/test/com/google/gwt/validation/example/ValidationExample.gwt.xml
@@ -17,6 +17,6 @@
 -->
 <module>
   <inherits name="com.google.gwt.user.User" />
-  <inherits name="com.google.gwt.validation.Validation" />
+  <inherits name="org.hibernate.validator.HibernateValidator" />
   <source path="client" />
 </module>
\ No newline at end of file
diff --git a/user/test/com/google/gwt/validation/example/client/Author.java b/user/test/com/google/gwt/validation/example/client/Author.java
index eadf824..fc84f893f 100644
--- a/user/test/com/google/gwt/validation/example/client/Author.java
+++ b/user/test/com/google/gwt/validation/example/client/Author.java
@@ -23,8 +23,10 @@
 public class Author {
 
   private String firstName;
+
   @NotEmpty(message = "lastname must not be null")
   private String lastName;
+
   @Size(max = 30)
   private String company;
 
diff --git a/user/test/com/google/gwt/validation/example/client/AuthorTest.java b/user/test/com/google/gwt/validation/example/client/AuthorTest.java
index 2be400a..9450609 100644
--- a/user/test/com/google/gwt/validation/example/client/AuthorTest.java
+++ b/user/test/com/google/gwt/validation/example/client/AuthorTest.java
@@ -17,13 +17,17 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.validation.example.client.ExampleGwtValidator.ClientGroup;
+import com.google.gwt.validation.example.client.ExampleGwtValidator.ServerGroup;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Validator;
+import javax.validation.groups.Default;
 
 /**
  * Tests for {@link Author}.
@@ -39,6 +43,49 @@
     return "com.google.gwt.validation.example.ValidationExample";
   }
 
+  // TODO(nchalko) handle more than one validator
+
+  // @GwtValidation(value = Author.class, groups =
+  // {ExampleGwtValidator.ClientGroup.class})
+  // public interface NotDefaultValidator extends Validator {
+  // }
+
+  // public void testNotDefaultValidtor_EmptyNotDefualt() throws Exception {
+  // NotDefaultValidator other = GWT.create(NotDefaultValidator.class);
+  // Set<ConstraintViolation<Author>> violations = other.validate(author);
+  // assertContentsAnyOrder("valid author", violations);
+  // }
+
+  public void testGroup_empty() throws Exception {
+    initValidAuthor();
+    Set<ConstraintViolation<Author>> violations = validator.validate(author);
+    assertContentsAnyOrder("valid author", violations);
+  }
+
+  public void testGroup_default() throws Exception {
+    initValidAuthor();
+    Set<ConstraintViolation<Author>> violations = validator.validate(author,
+        Default.class);
+    assertContentsAnyOrder("valid author", violations);
+  }
+
+  public void testGroup_clientGroup() throws Exception {
+    initValidAuthor();
+    Set<ConstraintViolation<Author>> violations = validator.validate(author,
+        ClientGroup.class);
+    assertContentsAnyOrder("valid author", violations);
+  }
+
+  public void testGroup_serverGroup() throws Exception {
+    initValidAuthor();
+    try {
+      validator.validate(author, ServerGroup.class);
+      fail("Expected a " + IllegalArgumentException.class);
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+  }
+
   public void testValidate_string() {
     try {
       validator.validate("some string");
@@ -48,11 +95,24 @@
   }
 
   public void testValidate_valid() {
+    initValidAuthor();
+    Set<ConstraintViolation<Author>> violations = validator.validate(author);
+    assertContentsAnyOrder("valid author", violations);
+  }
+
+  public void testValidate_companySize31() {
+    initValidAuthor();
+    author.setCompany("1234567890123456789012345678901");
+    Set<ConstraintViolation<Author>> violations = validator.validate(author);
+    assertContentsAnyOrder("company size 31", toMessage(violations),
+        "{javax.validation.constraints.Size.message}"
+        );
+  }
+
+  protected void initValidAuthor() {
     author.setFirstName("John");
     author.setLastName("Smith");
     author.setCompany("Google");
-    Set<ConstraintViolation<Author>> violations = validator.validate(author);
-    assertContentsAnyOrder("valid author", violations);
   }
 
   public void testValidateProperty_object() {
@@ -67,8 +127,7 @@
     try {
       validator.validateValue(String.class, "notValid", "value");
       fail("Expected a " + IllegalArgumentException.class);
-    } catch (IllegalArgumentException e) {
-      // expected
+    } catch (IllegalArgumentException expected) {
     }
   }
 
@@ -82,11 +141,19 @@
     author = new Author();
     validator = createValidator();
   }
+  
+  private <T> List<String> toMessage(Set<ConstraintViolation<T>> violations) {
+    List<String> messages = new ArrayList<String>();
+    for (ConstraintViolation<T> violation : violations) {
+      messages.add(violation.getMessage());
+    }
+    return messages;
+  }
 
   private <T> void assertContentsAnyOrder(String message,
       Iterable<T> actual, T... expected) {
 
-    List<T> expectedList = Arrays.asList(expected);
+    List<T> expectedList = new ArrayList<T>(Arrays.asList(expected));
     message += "Expected to find " + expectedList + " but found " + actual;
     for (T a : actual) {
       if (expectedList.contains(a)) {
diff --git a/user/test/com/google/gwt/validation/example/client/ExampleGwtValidator.java b/user/test/com/google/gwt/validation/example/client/ExampleGwtValidator.java
index 46a6922..82d79d6 100644
--- a/user/test/com/google/gwt/validation/example/client/ExampleGwtValidator.java
+++ b/user/test/com/google/gwt/validation/example/client/ExampleGwtValidator.java
@@ -16,14 +16,29 @@
 package com.google.gwt.validation.example.client;
 
 import com.google.gwt.validation.client.GwtValidation;
+import com.google.gwt.validation.example.client.ExampleGwtValidator.ClientGroup;
 
 import javax.validation.Validator;
+import javax.validation.groups.Default;
 
 /**
  * Example top level class to create a {@link Validator}.
  *
  * GWT.create instances of this class
  */
-@GwtValidation(Author.class)
+@GwtValidation(
+    value = {Author.class}, 
+    groups = {Default.class, ClientGroup.class})
 public interface ExampleGwtValidator extends Validator {
+  /**
+   * The Client Validation Group
+   */
+  public interface ClientGroup {
+  }
+
+  /**
+   * The Server Validation Group
+   */
+  public interface ServerGroup {
+  }
 }
diff --git a/user/test/com/google/gwt/validation/example/client/NotEmpty.java b/user/test/com/google/gwt/validation/example/client/NotEmpty.java
index f88465c..e21489c 100644
--- a/user/test/com/google/gwt/validation/example/client/NotEmpty.java
+++ b/user/test/com/google/gwt/validation/example/client/NotEmpty.java
@@ -29,6 +29,7 @@
 import javax.validation.Constraint;
 import javax.validation.ConstraintValidator;
 import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
 import javax.validation.ReportAsSingleViolation;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
@@ -49,6 +50,8 @@
 
   Class<?>[] groups() default {};
 
+  Class<? extends Payload>[] payload() default {};
+
   /**
    * From the JSR 303 spec.
    */