]> source.dussan.org Git - vaadin-framework.git/commitdiff
#680: merged to 6.0: validator base classes and standard validators for regular expre...
authorHenri Sara <henri.sara@itmill.com>
Fri, 3 Apr 2009 07:15:26 +0000 (07:15 +0000)
committerHenri Sara <henri.sara@itmill.com>
Fri, 3 Apr 2009 07:15:26 +0000 (07:15 +0000)
svn changeset:7292/svn branch:6.0

src/com/itmill/toolkit/data/validator/AbstractStringValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/AbstractValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/CompositeValidator.java
src/com/itmill/toolkit/data/validator/DoubleValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/EmailValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/IntegerValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/RegexpValidator.java [new file with mode: 0644]
src/com/itmill/toolkit/data/validator/StringLengthValidator.java
src/com/itmill/toolkit/tests/validation/TestValidators.java [new file with mode: 0644]

diff --git a/src/com/itmill/toolkit/data/validator/AbstractStringValidator.java b/src/com/itmill/toolkit/data/validator/AbstractStringValidator.java
new file mode 100644 (file)
index 0000000..7f26a87
--- /dev/null
@@ -0,0 +1,54 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+/**\r
+ * Validator base class for validating strings. See\r
+ * {@link com.itmill.toolkit.data.validator.AbstractValidator} for more\r
+ * information.\r
+ * \r
+ * <p>\r
+ * If the validation fails, the exception thrown contains the error message with\r
+ * its argument 0 replaced with the string being validated.\r
+ * </p>\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public abstract class AbstractStringValidator extends AbstractValidator {\r
+\r
+    /**\r
+     * Constructs a validator for strings.\r
+     * <p>\r
+     * Null and empty string values are always accepted. To disallow empty\r
+     * values, set the field being validated as required.\r
+     * </p>\r
+     * \r
+     * @param errorMessage\r
+     *            the message included in the exception (with its parameter {0}\r
+     *            replaced by the string to be validated) in case the validation\r
+     *            fails\r
+     */\r
+    public AbstractStringValidator(String errorMessage) {\r
+        super(errorMessage);\r
+    }\r
+\r
+    public boolean isValid(Object value) {\r
+        if (value == null) {\r
+            return true;\r
+        }\r
+        if (!(value instanceof String)) {\r
+            return false;\r
+        }\r
+        return isValidString((String) value);\r
+    }\r
+\r
+    /**\r
+     * Checks if the given string is valid.\r
+     * \r
+     * @param value\r
+     *            String to check. Can never be null.\r
+     * @return true if the string is valid, false otherwise\r
+     */\r
+    protected abstract boolean isValidString(String value);\r
+}\r
diff --git a/src/com/itmill/toolkit/data/validator/AbstractValidator.java b/src/com/itmill/toolkit/data/validator/AbstractValidator.java
new file mode 100644 (file)
index 0000000..93d6ae4
--- /dev/null
@@ -0,0 +1,67 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+import com.itmill.toolkit.data.Validator;\r
+\r
+/**\r
+ * Default Validator base class. See\r
+ * {@link com.itmill.toolkit.data.validator.Validator} for more information.\r
+ * <p>\r
+ * If the validation fails, the exception thrown contains the error message with\r
+ * its argument 0 replaced with the toString() of the object being validated.\r
+ * </p>\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public abstract class AbstractValidator implements Validator {\r
+\r
+    /**\r
+     * Error message.\r
+     */\r
+    private String errorMessage;\r
+\r
+    /**\r
+     * Constructs a validator with an error message.\r
+     * \r
+     * @param errorMessage\r
+     *            the message included in the exception (with its parameter {0}\r
+     *            replaced by toString() of the object to be validated) in case\r
+     *            the validation fails\r
+     */\r
+    public AbstractValidator(String errorMessage) {\r
+        this.errorMessage = errorMessage;\r
+    }\r
+\r
+    public void validate(Object value) throws InvalidValueException {\r
+        if (!isValid(value)) {\r
+            String message;\r
+            if (value == null) {\r
+                message = errorMessage.replace("{0}", "null");\r
+            } else {\r
+                message = errorMessage.replace("{0}", value.toString());\r
+            }\r
+            throw new InvalidValueException(message);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Gets the message to be displayed in case the value does not validate.\r
+     * \r
+     * @return the Error Message.\r
+     */\r
+    public String getErrorMessage() {\r
+        return errorMessage;\r
+    }\r
+\r
+    /**\r
+     * Sets the message to be displayed in case the value does not validate.\r
+     * \r
+     * @param errorMessage\r
+     *            the Error Message to set.\r
+     */\r
+    public void setErrorMessage(String errorMessage) {\r
+        this.errorMessage = errorMessage;\r
+    }\r
+}\r
index f8ac2fc7eb447ced3f3cb7483755a6ed5622653a..6aa9d07b992f0e423122d1b497eaac9466a609b2 100644 (file)
@@ -6,8 +6,8 @@ package com.itmill.toolkit.data.validator;
 
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 
 import com.itmill.toolkit.data.Validator;
 
@@ -23,7 +23,7 @@ import com.itmill.toolkit.data.Validator;
  * @VERSION@
  * @since 3.0
  */
-public class CompositeValidator implements Validator {
+public class CompositeValidator extends AbstractValidator {
 
     /**
      * The validators are combined with <code>AND</code> clause: validity of the
@@ -53,26 +53,22 @@ public class CompositeValidator implements Validator {
     /**
      * List of contained validators.
      */
-    private final LinkedList validators = new LinkedList();
-
-    /**
-     * Error message.
-     */
-    private String errorMessage;
+    private final List<Validator> validators = new LinkedList<Validator>();
 
     /**
      * Construct a composite validator in <code>AND</code> mode without error
      * message.
      */
     public CompositeValidator() {
+        super("");
     }
 
     /**
      * Constructs a composite validator in given mode.
      */
     public CompositeValidator(int mode, String errorMessage) {
+        super(errorMessage);
         setMode(mode);
-        setErrorMessage(errorMessage);
     }
 
     /**
@@ -94,19 +90,20 @@ public class CompositeValidator implements Validator {
      * @throws Validator.InvalidValueException
      *             if the value is not valid.
      */
+    @Override
     public void validate(Object value) throws Validator.InvalidValueException {
         switch (mode) {
         case MODE_AND:
-            for (final Iterator i = validators.iterator(); i.hasNext();) {
-                ((Validator) i.next()).validate(value);
+            for (Validator validator : validators) {
+                validator.validate(value);
             }
             return;
 
         case MODE_OR:
             Validator.InvalidValueException first = null;
-            for (final Iterator i = validators.iterator(); i.hasNext();) {
+            for (Validator v : validators) {
                 try {
-                    ((Validator) i.next()).validate(value);
+                    v.validate(value);
                     return;
                 } catch (final Validator.InvalidValueException e) {
                     if (first == null) {
@@ -141,8 +138,7 @@ public class CompositeValidator implements Validator {
     public boolean isValid(Object value) {
         switch (mode) {
         case MODE_AND:
-            for (final Iterator i = validators.iterator(); i.hasNext();) {
-                final Validator v = (Validator) i.next();
+            for (Validator v : validators) {
                 if (!v.isValid(value)) {
                     return false;
                 }
@@ -150,8 +146,7 @@ public class CompositeValidator implements Validator {
             return true;
 
         case MODE_OR:
-            for (final Iterator i = validators.iterator(); i.hasNext();) {
-                final Validator v = (Validator) i.next();
+            for (Validator v : validators) {
                 if (v.isValid(value)) {
                     return true;
                 }
@@ -193,9 +188,10 @@ public class CompositeValidator implements Validator {
      * Gets the error message for the composite validator. If the error message
      * is null, original error messages of the sub-validators are used instead.
      */
+    @Override
     public String getErrorMessage() {
-        if (errorMessage != null) {
-            return errorMessage;
+        if (getErrorMessage() != null) {
+            return getErrorMessage();
         }
 
         // TODO Return composite error message
@@ -203,17 +199,6 @@ public class CompositeValidator implements Validator {
         return null;
     }
 
-    /**
-     * Sets the error message for the composite validator. If the error message
-     * is null, original error messages of the sub-validators are used instead.
-     * 
-     * @param errorMessage
-     *            the Error Message to set.
-     */
-    public void setErrorMessage(String errorMessage) {
-        this.errorMessage = errorMessage;
-    }
-
     /**
      * Adds validator to the interface.
      * 
@@ -254,23 +239,22 @@ public class CompositeValidator implements Validator {
      * validators of given type null is returned.
      * </p>
      * 
-     * @return Collection of validators compatible with given type that must
-     *         apply or null if none fould.
+     * @return Collection<Validator> of validators compatible with given type
+     *         that must apply or null if none fould.
      */
-    public Collection getSubValidators(Class validatorType) {
+    public Collection<Validator> getSubValidators(Class validatorType) {
         if (mode != MODE_AND) {
             return null;
         }
 
-        final HashSet found = new HashSet();
-        for (final Iterator i = validators.iterator(); i.hasNext();) {
-            final Validator v = (Validator) i.next();
+        final HashSet<Validator> found = new HashSet<Validator>();
+        for (Validator v : validators) {
             if (validatorType.isAssignableFrom(v.getClass())) {
                 found.add(v);
             }
             if (v instanceof CompositeValidator
                     && ((CompositeValidator) v).getMode() == MODE_AND) {
-                final Collection c = ((CompositeValidator) v)
+                final Collection<Validator> c = ((CompositeValidator) v)
                         .getSubValidators(validatorType);
                 if (c != null) {
                     found.addAll(c);
diff --git a/src/com/itmill/toolkit/data/validator/DoubleValidator.java b/src/com/itmill/toolkit/data/validator/DoubleValidator.java
new file mode 100644 (file)
index 0000000..56f537f
--- /dev/null
@@ -0,0 +1,36 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+/**\r
+ * String validator for a double precision floating point number. See\r
+ * {@link com.itmill.toolkit.data.validator.AbstractStringValidator} for more\r
+ * information.\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public class DoubleValidator extends AbstractStringValidator {\r
+\r
+    /**\r
+     * Creates a validator for checking that a string can be parsed as an\r
+     * double.\r
+     * \r
+     * @param errorMessage\r
+     *            the message to display in case the value does not validate.\r
+     */\r
+    public DoubleValidator(String errorMessage) {\r
+        super(errorMessage);\r
+    }\r
+\r
+    @Override\r
+    protected boolean isValidString(String value) {\r
+        try {\r
+            Double.parseDouble(value);\r
+            return true;\r
+        } catch (Exception e) {\r
+            return false;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/src/com/itmill/toolkit/data/validator/EmailValidator.java b/src/com/itmill/toolkit/data/validator/EmailValidator.java
new file mode 100644 (file)
index 0000000..b5abb4d
--- /dev/null
@@ -0,0 +1,31 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+/**\r
+ * String validator for e-mail addresses. The e-mail address syntax is not\r
+ * complete according to RFC 822 but handles the vast majority of valid e-mail\r
+ * addresses correctly.\r
+ * \r
+ * See {@link com.itmill.toolkit.data.validator.AbstractStringValidator} for\r
+ * more information.\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public class EmailValidator extends RegexpValidator {\r
+\r
+    /**\r
+     * Creates a validator for checking that a string is a syntactically valid\r
+     * e-mail address.\r
+     * \r
+     * @param errorMessage\r
+     *            the message to display in case the value does not validate.\r
+     */\r
+    public EmailValidator(String errorMessage) {\r
+        super(\r
+                "^([a-zA-Z0-9_\\.\\-+])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9]{2,4})+$",\r
+                true, errorMessage);\r
+    }\r
+\r
+}\r
diff --git a/src/com/itmill/toolkit/data/validator/IntegerValidator.java b/src/com/itmill/toolkit/data/validator/IntegerValidator.java
new file mode 100644 (file)
index 0000000..f48e859
--- /dev/null
@@ -0,0 +1,37 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+/**\r
+ * String validator for integers. See\r
+ * {@link com.itmill.toolkit.data.validator.AbstractStringValidator} for more\r
+ * information.\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public class IntegerValidator extends AbstractStringValidator {\r
+\r
+    /**\r
+     * Creates a validator for checking that a string can be parsed as an\r
+     * integer.\r
+     * \r
+     * @param errorMessage\r
+     *            the message to display in case the value does not validate.\r
+     */\r
+    public IntegerValidator(String errorMessage) {\r
+        super(errorMessage);\r
+\r
+    }\r
+\r
+    @Override\r
+    protected boolean isValidString(String value) {\r
+        try {\r
+            Integer.parseInt(value);\r
+            return true;\r
+        } catch (Exception e) {\r
+            return false;\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/src/com/itmill/toolkit/data/validator/RegexpValidator.java b/src/com/itmill/toolkit/data/validator/RegexpValidator.java
new file mode 100644 (file)
index 0000000..56316be
--- /dev/null
@@ -0,0 +1,86 @@
+package com.itmill.toolkit.data.validator;\r
+\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+/**\r
+ * String validator comparing the string against a Java regular expression. Both\r
+ * complete matches and substring matches are supported.\r
+ * \r
+ * <p>\r
+ * For the Java regular expression syntax, see\r
+ * {@link java.util.regex.Pattern#sum}\r
+ * </p>\r
+ * <p>\r
+ * See {@link com.itmill.toolkit.data.validator.AbstractStringValidator} for\r
+ * more information.\r
+ * </p>\r
+ * \r
+ * @author IT Mill Ltd.\r
+ * @version\r
+ * @VERSION@\r
+ * @since 5.4\r
+ */\r
+public class RegexpValidator extends AbstractStringValidator {\r
+\r
+    private Pattern pattern;\r
+    private boolean complete;\r
+    private Matcher matcher = null;\r
+\r
+    /**\r
+     * Creates a validator for checking that the regular expression matches the\r
+     * complete string to validate.\r
+     * \r
+     * @param regexp\r
+     *            a Java regular expression\r
+     * @param errorMessage\r
+     *            the message to display in case the value does not validate.\r
+     */\r
+    public RegexpValidator(String regexp, String errorMessage) {\r
+        this(regexp, true, errorMessage);\r
+    }\r
+\r
+    /**\r
+     * Creates a validator for checking that the regular expression matches the\r
+     * string to validate.\r
+     * \r
+     * @param regexp\r
+     *            a Java regular expression\r
+     * @param complete\r
+     *            true to use check for a complete match, false to look for a\r
+     *            matching substring\r
+     * @param errorMessage\r
+     *            the message to display in case the value does not validate.\r
+     */\r
+    public RegexpValidator(String regexp, boolean complete, String errorMessage) {\r
+        super(errorMessage);\r
+        pattern = Pattern.compile(regexp);\r
+        this.complete = complete;\r
+    }\r
+\r
+    @Override\r
+    protected boolean isValidString(String value) {\r
+        if (complete) {\r
+            return getMatcher(value).matches();\r
+        } else {\r
+            return getMatcher(value).find();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Get a new or reused matcher for the pattern\r
+     * \r
+     * @param value\r
+     *            the string to find matches in\r
+     * @return Matcher for the string\r
+     */\r
+    private Matcher getMatcher(String value) {\r
+        if (matcher == null) {\r
+            matcher = pattern.matcher(value);\r
+        } else {\r
+            matcher.reset(value);\r
+        }\r
+        return matcher;\r
+    }\r
+\r
+}\r
index df702cfea4ee290c8a2470276bbdb04456b8cc86..e4c28041a73576a02fa80ef14911dcd4bf57aba6 100644 (file)
@@ -4,8 +4,6 @@
 
 package com.itmill.toolkit.data.validator;
 
-import com.itmill.toolkit.data.Validator;
-
 /**
  * This <code>StringLengthValidator</code> is used to validate the length of
  * strings.
@@ -15,7 +13,7 @@ import com.itmill.toolkit.data.Validator;
  * @VERSION@
  * @since 3.0
  */
-public class StringLengthValidator implements Validator {
+public class StringLengthValidator extends AbstractValidator {
 
     private int minLength = -1;
 
@@ -23,8 +21,6 @@ public class StringLengthValidator implements Validator {
 
     private boolean allowNull = true;
 
-    private String errorMessage;
-
     /**
      * Creates a new StringLengthValidator with a given error message.
      * 
@@ -32,7 +28,7 @@ public class StringLengthValidator implements Validator {
      *            the message to display in case the value does not validate.
      */
     public StringLengthValidator(String errorMessage) {
-        setErrorMessage(errorMessage);
+        super(errorMessage);
     }
 
     /**
@@ -42,11 +38,12 @@ public class StringLengthValidator implements Validator {
      * @param errorMessage
      *            the message to display in case the value does not validate.
      * @param minLength
-     *            the minimum permissable length of the string.
+     *            the minimum permissible length of the string.
      * @param maxLength
-     *            the maximum permissable length of the string.
+     *            the maximum permissible length of the string.
      * @param allowNull
-     *            Are null strings permissable?
+     *            Are null strings permissible? This can be handled better by
+     *            setting a field as required or not.
      */
     public StringLengthValidator(String errorMessage, int minLength,
             int maxLength, boolean allowNull) {
@@ -56,37 +53,6 @@ public class StringLengthValidator implements Validator {
         setNullAllowed(allowNull);
     }
 
-    /**
-     * Validates the value.
-     * 
-     * @param value
-     *            the value to validate.
-     * @throws Validator.InvalidValueException
-     *             if the value was invalid.
-     */
-    public void validate(Object value) throws Validator.InvalidValueException {
-        if (value == null) {
-            if (allowNull) {
-                return;
-            } else {
-                throw new Validator.InvalidValueException(errorMessage);
-            }
-        }
-        final String s = value.toString();
-        if (s == null) {
-            if (allowNull) {
-                return;
-            } else {
-                throw new Validator.InvalidValueException(errorMessage);
-            }
-        }
-        final int len = s.length();
-        if ((minLength >= 0 && len < minLength)
-                || (maxLength >= 0 && len > maxLength)) {
-            throw new Validator.InvalidValueException(errorMessage);
-        }
-    }
-
     /**
      * Checks if the given value is valid.
      * 
@@ -116,12 +82,13 @@ public class StringLengthValidator implements Validator {
      * @return <code>true</code> if allows null string, otherwise
      *         <code>false</code>.
      */
+    @Deprecated
     public final boolean isNullAllowed() {
         return allowNull;
     }
 
     /**
-     * Gets the maximum permissable length of the string.
+     * Gets the maximum permissible length of the string.
      * 
      * @return the maximum length of the string.
      */
@@ -130,7 +97,7 @@ public class StringLengthValidator implements Validator {
     }
 
     /**
-     * Gets the minimum permissable length of the string.
+     * Gets the minimum permissible length of the string.
      * 
      * @return the minimum length of the string.
      */
@@ -139,14 +106,16 @@ public class StringLengthValidator implements Validator {
     }
 
     /**
-     * Sets whether null-strings are to be allowed.
+     * Sets whether null-strings are to be allowed. This can be better handled
+     * by setting a field as required or not.
      */
+    @Deprecated
     public void setNullAllowed(boolean allowNull) {
         this.allowNull = allowNull;
     }
 
     /**
-     * Sets the maximum permissable length of the string.
+     * Sets the maximum permissible length of the string.
      * 
      * @param maxLength
      *            the length to set.
@@ -159,7 +128,7 @@ public class StringLengthValidator implements Validator {
     }
 
     /**
-     * Sets the minimum permissable length.
+     * Sets the minimum permissible length.
      * 
      * @param minLength
      *            the length to set.
@@ -171,23 +140,4 @@ public class StringLengthValidator implements Validator {
         this.minLength = minLength;
     }
 
-    /**
-     * Gets the message to be displayed in case the value does not validate.
-     * 
-     * @return the Error Message.
-     */
-    public String getErrorMessage() {
-        return errorMessage;
-    }
-
-    /**
-     * Sets the message to be displayer in case the value does not validate.
-     * 
-     * @param errorMessage
-     *            the Error Message to set.
-     */
-    public void setErrorMessage(String errorMessage) {
-        this.errorMessage = errorMessage;
-    }
-
 }
diff --git a/src/com/itmill/toolkit/tests/validation/TestValidators.java b/src/com/itmill/toolkit/tests/validation/TestValidators.java
new file mode 100644 (file)
index 0000000..2a75bdd
--- /dev/null
@@ -0,0 +1,163 @@
+package com.itmill.toolkit.tests.validation;\r
+\r
+import com.itmill.toolkit.data.Validator;\r
+import com.itmill.toolkit.data.validator.AbstractStringValidator;\r
+import com.itmill.toolkit.data.validator.CompositeValidator;\r
+import com.itmill.toolkit.data.validator.DoubleValidator;\r
+import com.itmill.toolkit.data.validator.EmailValidator;\r
+import com.itmill.toolkit.data.validator.IntegerValidator;\r
+import com.itmill.toolkit.data.validator.RegexpValidator;\r
+import com.itmill.toolkit.data.validator.StringLengthValidator;\r
+import com.itmill.toolkit.tests.components.TestBase;\r
+import com.itmill.toolkit.ui.Button;\r
+import com.itmill.toolkit.ui.Form;\r
+import com.itmill.toolkit.ui.TextField;\r
+import com.itmill.toolkit.ui.VerticalLayout;\r
+import com.itmill.toolkit.ui.Button.ClickEvent;\r
+import com.itmill.toolkit.ui.Button.ClickListener;\r
+import com.itmill.toolkit.ui.Window.Notification;\r
+\r
+public class TestValidators extends TestBase {\r
+\r
+    @Override\r
+    protected Integer getTicketNumber() {\r
+        return 680;\r
+    }\r
+\r
+    @Override\r
+    protected String getDescription() {\r
+        return "This test verifies that various validators work correctly";\r
+    }\r
+\r
+    @Override\r
+    public void setup() {\r
+        final Form form = new Form(new VerticalLayout());\r
+\r
+        // simple validators\r
+\r
+        TextField tf = new TextField("A field, must contain 1-2 chars");\r
+        tf\r
+                .addValidator(new StringLengthValidator("Invalid length", 1, 2,\r
+                        false));\r
+        tf.setRequired(true);\r
+        tf.setValue("ab");\r
+        form.addField("a", tf);\r
+\r
+        tf = new TextField("A field, must contain an integer");\r
+        tf.addValidator(new IntegerValidator("Invalid integer {0}"));\r
+        tf.setRequired(true);\r
+        tf.setValue("123");\r
+        form.addField("b", tf);\r
+\r
+        tf = new TextField("A field, must contain an integer or be empty");\r
+        tf.addValidator(new IntegerValidator("Invalid integer {0}"));\r
+        tf.setValue("-321");\r
+        form.addField("c", tf);\r
+\r
+        tf = new TextField(\r
+                "A field, must contain a floating point number or be empty");\r
+        tf.addValidator(new DoubleValidator("Invalid double {0}"));\r
+        tf.setValue("-123.45e6");\r
+        form.addField("d", tf);\r
+\r
+        tf = new TextField(\r
+                "A field, must contain an e-mail address or be empty");\r
+        tf.addValidator(new EmailValidator("Invalid e-mail address {0}"));\r
+        tf.setValue("a.b@example.com");\r
+        form.addField("e", tf);\r
+\r
+        // regular expressions\r
+\r
+        tf = new TextField("A field, must match the regular expression a.*b.*c");\r
+        tf.addValidator(new RegexpValidator("a.*b.*c",\r
+                "{0} does not match the regular expression"));\r
+        tf.setValue("aagsabeqgc");\r
+        form.addField("f", tf);\r
+\r
+        tf = new TextField(\r
+                "A field, must contain the regular expression a.*b.*c");\r
+        tf.addValidator(new RegexpValidator("a.*b.*c", false,\r
+                "{0} does not contain the regular expression"));\r
+        tf.setValue("aagsabeqgc");\r
+        form.addField("g", tf);\r
+\r
+        tf = new TextField(\r
+                "A field, must match the regular expression ^a.*b.*c$");\r
+        tf.addValidator(new RegexpValidator("^a.*b.*c$", false,\r
+                "{0} does not match the regular expression with ^ and $"));\r
+        tf.setValue("aagsabeqgc");\r
+        form.addField("h", tf);\r
+\r
+        tf = new TextField(\r
+                "A field, must contain the regular expression ^a.*b.*c$");\r
+        tf.addValidator(new RegexpValidator("^a.*b.*c$", false,\r
+                "{0} does not contain the regular expression with ^ and $"));\r
+        tf.setValue("aagsabeqgc");\r
+        form.addField("i", tf);\r
+\r
+        // TODO CompositeValidator\r
+        tf = new TextField(\r
+                "A field, must be a floating point number with 4-5 chars");\r
+        CompositeValidator cv = new CompositeValidator(\r
+                CompositeValidator.MODE_AND,\r
+                "The field must contain a floating point number with 4-5 characters");\r
+        cv\r
+                .addValidator(new StringLengthValidator(\r
+                        "String length of '{0}' should be 4-5 characters", 4,\r
+                        5, false));\r
+        cv.addValidator(new DoubleValidator(\r
+                "{0} must be a floating point number"));\r
+        tf.addValidator(cv);\r
+        tf.setValue("12.34");\r
+        form.addField("j", tf);\r
+\r
+        // Postal code that must be 5 digits (10000-99999).\r
+        tf = new TextField("Postal Code");\r
+        tf.setColumns(5);\r
+\r
+        // Create the validator - this would be even easier with RegexpValidator\r
+        Validator postalCodeValidator = new AbstractStringValidator(\r
+                "Postal code must be a number 10000-99999.") {\r
+            @Override\r
+            protected boolean isValidString(String value) {\r
+                return value.matches("[1-9][0-9]{4}");\r
+            }\r
+        };\r
+        tf.addValidator(postalCodeValidator);\r
+        tf.setValue("12345");\r
+        form.addField("k", tf);\r
+\r
+        Button b = new Button("Commit", new ClickListener() {\r
+\r
+            public void buttonClick(ClickEvent event) {\r
+                try {\r
+                    form.commit();\r
+                    if (form.isValid()) {\r
+                        getMainWindow().showNotification(\r
+                                "OK! Form validated and no error was thrown",\r
+                                Notification.TYPE_HUMANIZED_MESSAGE);\r
+                    } else {\r
+                        getMainWindow().showNotification(\r
+                                "Form is invalid but no exception was thrown",\r
+                                Notification.TYPE_ERROR_MESSAGE);\r
+                    }\r
+                } catch (Exception e) {\r
+                    if (form.isValid()) {\r
+                        getMainWindow().showNotification(\r
+                                "Form is valid but an exception was thrown",\r
+                                Notification.TYPE_ERROR_MESSAGE);\r
+                    } else {\r
+                        getMainWindow().showNotification(\r
+                                "OK! Error was thrown for an invalid input",\r
+                                Notification.TYPE_HUMANIZED_MESSAGE);\r
+\r
+                    }\r
+                }\r
+            }\r
+\r
+        });\r
+\r
+        addComponent(form);\r
+        addComponent(b);\r
+    }\r
+}\r