tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject svn commit: r711370 - in /tapestry/tapestry5/trunk: src/site/apt/guide/ tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/ tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/...
Date Tue, 04 Nov 2008 20:03:37 GMT
Author: hlship
Date: Tue Nov  4 12:03:35 2008
New Revision: 711370

URL: http://svn.apache.org/viewvc?rev=711370&view=rev
Log:
TAP5-228: When you have multiple forms on the same page that share (some of) the same properties, it is not possible to differentiate validation constraints and messages in the message catalog

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/VariantBinding.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PerFormValidationMessageDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.properties
Modified:
    tapestry/tapestry5/trunk/src/site/apt/guide/beaneditform.apt
    tapestry/tapestry5/trunk/src/site/apt/guide/validation.apt
    tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractTextField.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportAdapter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/TranslateBindingFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ValidateBindingFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDefaultProviderImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentDefaultProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FormSupport.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/internal/FormSupportImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/Locatable.java
    tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java

Modified: tapestry/tapestry5/trunk/src/site/apt/guide/beaneditform.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/beaneditform.apt?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/guide/beaneditform.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/guide/beaneditform.apt Tue Nov  4 12:03:35 2008
@@ -78,7 +78,8 @@
 * Property ordering
 
   By default, the order in which properties are presented is as defined above (order of the getter method).
-  The {{{../apidocs/org/apache/tapestry5/beaneditor/Order.html}Order}} annotation may be used to modify the normal ordering.
+  This can be overridden using the {{{../apidocs/org/apache/tapestry5/beaneditor/ReorderProperties.html}ReorderProperties}}
+  class annotation.
   
 * Default Label
 
@@ -113,9 +114,11 @@
   You may want to customize the BeanModel further, to remove from the form properties that should not be editable by the user,
   and to change the order in which properties are presented within the form.
   
-  The BeanEditForm component has two parameters for this purpose:
-  
-  * remove: A comma separated list of property names to remove from the model.
+  The BeanEditForm component has several parameters for this purpose:
+
+  * add: A command seperated list of property names to add to the model.
+
+  * exclude: A comma separated list of property names to exclude from the model.
   
   * reorder: A comma separated list of property names indicating the desired order.
   
@@ -124,6 +127,10 @@
   If a model has more properties that are listed in the reorder parameter, then the additional properties will be ordered at the end of the form.
   
   Note that these parameters <modify> the BeanModel.
+
+  Added properties must not conflict with normal properties. Cells for added properties will render blank unless an override is provided.
+
+
     
 Providing the BeanModel
 

Modified: tapestry/tapestry5/trunk/src/site/apt/guide/validation.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/validation.apt?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/guide/validation.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/guide/validation.apt Tue Nov  4 12:03:35 2008
@@ -239,10 +239,74 @@
   This is nice and seamless; the same look and feel and behavior for both the built-in validators, and for errors generated based on
   application logic.
 
+Centralizing Validation with @Validate
+
+  The {{{../apidocs/org/apache/tapestry5/beaneditor/Validate.html}Validate}} annotation can take the place of the
+  validate parameter of TextField, PasswordField, TextArea and other components.  When the validate parameter
+  is not bound, the component will check for the @Validate annotation and use its value as the validation definition.
+
+  The annotation may be placed on the getter or setter method, or on the field itself.
+
+Customizing Validation Messages
+
+  Each validator (such as "required" or "minlength") has a default message used (on the client side and the server side)
+  when the constraint is violated; that is, when the user input is not valid.
+
+  The message can be customized by adding an entry to the page's {{{localization.html}message catalog}} (or the containing
+  component's message catalog).  As with any localized property, this can also go into the application's message catalog.
+
+  The first key checked is <formId>-<fieldId>-<validatorName>-message.
+
+  * formId: the local component id of the Form component
+
+  * fieldId: the local component id of the field (TextField, etc.)
+
+  * validatorName: the name of the validator, i.e., "required" or "minlength"
+
+  []
+
+  If there is not message for that key, a second check is made, for  <fieldId>-<validatorName>-message.
+
+  If that does not match a message, then the built-in default validation message is used.
+
+Customizing Validation Messages / BeanEditForm
+
+  The {{{beaneditform.html}BeanEditForm}} component also supports validation message customizing.  The search is the similar;
+  the <formId> is the component id of the BeanEditForm component (not the Form component it contains).
+  The <fieldId> is the property name.
+
+Configuring Validator Contraints in the Message Catalog
+
+  It is possible to omit the validation constraint from the validator parameter (or @Validator annotation), in which
+  case it is expected to be stored in the message catalog.
+
+  This is useful when the validation constraint is awkward to enter inline, such as a regular expression for use
+  with the regexp validator.
+
+  The key here is similar to customizing the validation message:  <formId>-<fieldId>-<validatorName> or
+  just <fieldId>-<validatorName>.
+
+  For example, your template may have the following:
+
+---
+  <t:textfield t:id="ssn" validate="required,regexp"/>
+---
+
+  And your message catalog can contain:
+
+---
+ssn-regexp=\d{3}-\d{2}-\d{4}
+ssn-regexp-message=Social security numbers are in the format 12-34-5678.
+---
+
+  This technique also works with the BeanEditForm; as with validation messages, the
+  formId is the BeanEditForm component's id, and the
+  fieldId is the name of the property being editted.
+
 Overriding the Translator with Events
 
   The TextField, PasswordField and TextArea components all have a translate parameter, a
-  {{{../apidocs/org/apache/tapestry5/Translator.html}Translator}} object that is used to convert values on the server
+  {{{../apidocs/org/apache/tapestry5/FieldTranslator.html}FieldTranslator}} object that is used to convert values on the server
   side to strings on the client side.
 
   In most cases, the translate parameter is not set explicitly; Tapestry derives an appropriate value
@@ -287,7 +351,7 @@
   }
 +---+
 
-  The event handler metohd has precendence over the translator.  Here it checks for the empty string
+  The event handler method has precendence over the translator.  Here it checks for the empty string
   (and note that the input may be null!) and evaluates that as zero.
 
   Again, returning null lets the normal translator do its work.
@@ -296,7 +360,7 @@
   {{{../apidocs/org/apache/tapestry5/ValidationException.html}ValidationException}} to indicate a value
   that can't be parsed.
 
-  Now, what if you want to perform your own custom validation?  That's another event: "validateInput":
+  Now, what if you want to perform your own custom validation?  That's another event: "validate":
 
 +---+
   void onValidateFromCount(Integer value) throws ValidationException
@@ -313,5 +377,6 @@
 
   <<Caution:>> These events are exclusively on the <server side>.
   This means that, in certain circumstances,
-  an input value will be rejected on the client side even though it is valid on the server side.
+  an input value will be rejected on the client side even though it is valid on the server side.   You may
+  need to disable client-side validation in order to use this feature.
 

Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/beaneditor/Validate.java Tue Nov  4 12:03:35 2008
@@ -26,9 +26,9 @@
  * "required", "minlength") and optionally, a constraint value. Most validators need a constraint value, which is
  * separated from the type by an equals size (i.e., "maxlength=30").
  * <p/>
- * May be placed on an getter or setter method, or on the matching field.
+ * May be placed on any getter or setter method, or on the matching field.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ElementType.FIELD, ElementType.METHOD})
 @Retention(RUNTIME)
 @Documented
 public @interface Validate

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/ComponentResourcesCommon.java Tue Nov  4 12:03:35 2008
@@ -23,11 +23,14 @@
  * Operations shared by the public {@link org.apache.tapestry5.ComponentResources} interface and {@link
  * org.apache.tapestry5.internal.structure.ComponentPageElement} interface (on the internal side).
  */
+@SuppressWarnings({"JavaDoc"})
 public interface ComponentResourcesCommon extends Locatable
 {
     /**
-     * Returns the id of the component. The id will be unique within the component's immediate container. For a page's
-     * root component, the value null is returned.
+     * Returns the simple (or local) id of the component. The id will be unique within the component's immediate
+     * container. For a page's root component, the value null is returned.
+     * <p/>
+     * \
      */
     String getId();
 
@@ -40,26 +43,25 @@
 
     /**
      * Returns a string consisting of the logical name of the containing page, and the {@link #getNestedId() nested id}
-     * of this component, separated by a colon. I.e., "mypage:foo.bar.baz". For a page, returns just the page's logical
+     * of this component, separated by a colon. I.e., "MyPage:foo.bar.baz". For a page, returns just the page's logical
      * name.
      * <p/>
      * This value is often used to obtain an equivalent component instance in a later request.
      *
      * @see org.apache.tapestry5.services.ComponentSource#getComponent(String)
      */
-
     String getCompleteId();
 
     /**
      * A convienience for invoking {@link #triggerContextEvent(String, EventContext , ComponentEventCallback)}. Wraps
      * the context values into an {@link org.apache.tapestry5.EventContext}.
      *
-     * @param eventType event type (as determined from the request, or otherwise by design)
-     * @param context   Values that may be provided to the event handler method as method parameters, or null if no
-     *                  context values are available
-     * @param callback  the handler to be informed of the result, or null if the event is a notification that does not
-     *                  support return values from event handler methods (the value true is allowed even if the handler
-     *                  is null).
+     * @param eventType     event type (as determined from the request, or otherwise by design)
+     * @param contextValues Values that may be provided to the event handler method as method parameters, or null if no
+     *                      context values are available
+     * @param callback      the handler to be informed of the result, or null if the event is a notification that does
+     *                      not support return values from event handler methods (the value true is allowed even if the
+     *                      handler is null).
      * @return true if any event handler was invoked (even if no event handler method returns a non-null value)
      * @throws org.apache.tapestry5.runtime.ComponentEventException
      *          if an event handler method throws a checked or unchecked exception

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractTextField.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractTextField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractTextField.java Tue Nov  4 12:03:35 2008
@@ -112,9 +112,9 @@
      * Computes a default value for the "translate" parameter using {@link org.apache.tapestry5.services.ComponentDefaultProvider#defaultTranslator(String,
      * org.apache.tapestry5.ComponentResources)}.
      */
-    final FieldTranslator defaultTranslate()
+    final Binding defaultTranslate()
     {
-        return defaultProvider.defaultTranslator("value", resources);
+        return defaultProvider.defaultTranslatorBinding("value", resources);
     }
 
     final AnnotationProvider defaultAnnotationProvider()
@@ -131,9 +131,9 @@
     /**
      * Computes a default value for the "validate" parameter using {@link org.apache.tapestry5.services.FieldValidatorDefaultSource}.
      */
-    final FieldValidator defaultValidate()
+    final Binding defaultValidate()
     {
-        return defaultProvider.defaultValidator("value", resources);
+        return defaultProvider.defaultValidatorBinding("value", resources);
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java Tue Nov  4 12:03:35 2008
@@ -95,10 +95,10 @@
     private String reorder;
 
     /**
-     * If true, the default, then the embedded Form component will use client-side validation.
+     * May be bound, to override the Form's default for clientValidation.
      */
     @Parameter
-    private boolean clientValidation = true;
+    private boolean clientValidation;
 
     /**
      * Binding the zone parameter will cause the form submission to be handled as an Ajax request that updates the
@@ -107,7 +107,9 @@
     @Parameter(defaultPrefix = BindingConstants.LITERAL)
     private String zone;
 
-    @Component(parameters = {"clientValidation=inherit:clientValidation", "zone=inherit:zone"})
+    @Component(parameters = {"clientValidation=inherit:clientValidation",
+            "validationId=componentResources.id",
+            "zone=inherit:zone"})
     private Form form;
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java Tue Nov  4 12:03:35 2008
@@ -25,7 +25,6 @@
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.ComponentDefaultProvider;
-import org.apache.tapestry5.services.FieldValidatorDefaultSource;
 import org.apache.tapestry5.services.Request;
 
 import java.text.DateFormat;
@@ -139,11 +138,11 @@
     }
 
     /**
-     * Computes a default value for the "validate" parameter using {@link FieldValidatorDefaultSource}.
+     * Computes a default value for the "validate" parameter using {@link ComponentDefaultProvider}.
      */
-    final FieldValidator defaultValidate()
+    final Binding defaultValidate()
     {
-        return defaultProvider.defaultValidator("value", resources);
+        return defaultProvider.defaultValidatorBinding("value", resources);
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java Tue Nov  4 12:03:35 2008
@@ -150,6 +150,15 @@
     @Parameter(defaultPrefix = BindingConstants.LITERAL)
     private String zone;
 
+    /**
+     * Prefix value used when searching for validation messages and constraints.  The default is the Form component's
+     * id. This is overriden by {@link org.apache.tapestry5.corelib.components.BeanEditForm}.
+     *
+     * @see org.apache.tapestry5.services.FormSupport#getFormValidationId()
+     */
+    @Parameter
+    private String validationId;
+
     @Inject
     private Logger logger;
 
@@ -203,6 +212,11 @@
 
     private String name;
 
+    String defaultValidationId()
+    {
+        return resources.getId();
+    }
+
     public ValidationTracker getDefaultTracker()
     {
         if (defaultTracker == null) defaultTracker = new ValidationTrackerImpl();
@@ -298,7 +312,7 @@
     InternalFormSupport createRenderTimeFormSupport(String name, ComponentActionSink actionSink, IdAllocator allocator)
     {
         return new FormSupportImpl(resources, name, actionSink, clientBehaviorSupport,
-                                   clientValidation, allocator);
+                                   clientValidation, allocator, validationId);
     }
 
     void afterRender(MarkupWriter writer)
@@ -339,7 +353,7 @@
     {
         tracker.clear();
 
-        formSupport = new FormSupportImpl(resources);
+        formSupport = new FormSupportImpl(resources, validationId);
 
         environment.push(ValidationTracker.class, tracker);
         environment.push(FormSupport.class, formSupport);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java Tue Nov  4 12:03:35 2008
@@ -195,9 +195,9 @@
     /**
      * Computes a default value for the "validate" parameter using {@link FieldValidatorDefaultSource}.
      */
-    FieldValidator defaultValidate()
+    Binding defaultValidate()
     {
-        return defaultProvider.defaultValidator("value", resources);
+        return defaultProvider.defaultValidatorBinding("value", resources);
     }
 
     Object defaultBlankLabel()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportAdapter.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportAdapter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportAdapter.java Tue Nov  4 12:03:35 2008
@@ -75,4 +75,9 @@
     {
         return delegate.getFormComponentId();
     }
+
+    public String getFormValidationId()
+    {
+        return delegate.getFormValidationId();
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportImpl.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/internal/FormSupportImpl.java Tue Nov  4 12:03:35 2008
@@ -46,6 +46,8 @@
 
     private final ComponentActionSink actionSink;
 
+    private final String formValidationId;
+
     private List<Runnable> commands;
 
     private String encodingType;
@@ -53,9 +55,9 @@
     /**
      * Constructor used when processing a form submission.
      */
-    public FormSupportImpl(ComponentResources resources)
+    public FormSupportImpl(ComponentResources resources, String formValidationId)
     {
-        this(resources, null, null, null, false, null);
+        this(resources, null, null, null, false, null, formValidationId);
     }
 
     /**
@@ -63,7 +65,7 @@
      */
     public FormSupportImpl(ComponentResources resources, String clientId, ComponentActionSink actionSink,
                            ClientBehaviorSupport clientBehaviorSupport,
-                           boolean clientValidationEnabled, IdAllocator idAllocator)
+                           boolean clientValidationEnabled, IdAllocator idAllocator, String formValidationId)
     {
         this.resources = resources;
         this.clientId = clientId;
@@ -71,6 +73,7 @@
         this.clientBehaviorSupport = clientBehaviorSupport;
         this.clientValidationEnabled = clientValidationEnabled;
         this.idAllocator = idAllocator;
+        this.formValidationId = formValidationId;
     }
 
     public Location getLocation()
@@ -147,4 +150,9 @@
     {
         return clientValidationEnabled;
     }
+
+    public String getFormValidationId()
+    {
+        return formValidationId;
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/TranslateBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/TranslateBindingFactory.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/TranslateBindingFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/TranslateBindingFactory.java Tue Nov  4 12:03:35 2008
@@ -37,18 +37,12 @@
     public Binding newBinding(String description, ComponentResources container,
                               final ComponentResources component, final String expression, Location location)
     {
-        return new AbstractBinding(location)
+        return new VariantBinding(FieldTranslator.class, description + ": " + expression, location)
         {
             public Object get()
             {
                 return source.createTranslator(component, expression);
             }
-
-            @Override
-            public Class getBindingType()
-            {
-                return FieldTranslator.class;
-            }
         };
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ValidateBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ValidateBindingFactory.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ValidateBindingFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ValidateBindingFactory.java Tue Nov  4 12:03:35 2008
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,8 +24,9 @@
 import org.apache.tapestry5.services.FieldValidatorSource;
 
 /**
- * Factory for bindings that provide a {@link FieldValidator} based on a validator specification. This binding factory
- * is only useable with components that implement the {@link Field} interface.
+ * Factory for bindings that provide a {@link org.apache.tapestry5.FieldValidator} based on a validator specification.
+ * This binding factory is only useable with components that implement the {@link org.apache.tapestry5.Field}
+ * interface.
  */
 public class ValidateBindingFactory implements BindingFactory
 {
@@ -37,7 +38,7 @@
     }
 
     public Binding newBinding(String description, ComponentResources container,
-                              ComponentResources component, String expression, Location location)
+                              ComponentResources component, final String expression, Location location)
     {
         Object fieldAsObject = component.getComponent();
 
@@ -45,16 +46,19 @@
             throw new TapestryException(BindingsMessages.validateBindingForFieldsOnly(component),
                                         location, null);
 
-        Field field = (Field) fieldAsObject;
+        final Field field = (Field) fieldAsObject;
 
-        // The expression is a validator specification, such as "required,minLength=5".
-        // ValidatorBindingFactory is the odd man out becasuse it needs the binding component (the
-        // component whose parameter is to be bound) rather than the containing component, the way
-        // most factories work.
-
-        FieldValidator validator = fieldValidatorSource.createValidators(field, expression);
-
-        return new LiteralBinding(description, validator, location);
+        return new VariantBinding(FieldValidator.class, description + ": " + expression, location)
+        {
+            public Object get()
+            {
+                // The expression is a validator specification, such as "required,minLength=5".
+                // ValidatorBindingFactory is the odd man out becasuse it needs the binding component (the
+                // component whose parameter is to be bound) rather than the containing component, the way
+                // most factories work.
+
+                return fieldValidatorSource.createValidators(field, expression);
+            }
+        };
     }
-
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/VariantBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/VariantBinding.java?rev=711370&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/VariantBinding.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/VariantBinding.java Tue Nov  4 12:03:35 2008
@@ -0,0 +1,54 @@
+//  Copyright 2008 The Apache Software Foundation
+//
+// 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.apache.tapestry5.internal.bindings;
+
+import org.apache.tapestry5.ioc.Location;
+
+/**
+ * Extends {@link org.apache.tapestry5.internal.bindings.AbstractBinding} with a description and a binding type, with
+ * invariant forced to true.
+ */
+public abstract class VariantBinding extends AbstractBinding
+{
+    private final Class bindingType;
+
+    private final String description;
+
+    public VariantBinding(Class bindingType, String description, Location location)
+    {
+        super(location);
+
+        this.bindingType = bindingType;
+        this.description = description;
+    }
+
+    @Override
+    public boolean isInvariant()
+    {
+        return true;
+    }
+
+    @Override
+    public Class getBindingType()
+    {
+        return bindingType;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("VariantBinding[%s]", description);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDefaultProviderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDefaultProviderImpl.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDefaultProviderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDefaultProviderImpl.java Tue Nov  4 12:03:35 2008
@@ -16,6 +16,7 @@
 
 import org.apache.tapestry5.*;
 import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.bindings.VariantBinding;
 import org.apache.tapestry5.ioc.Messages;
 import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
 import static org.apache.tapestry5.ioc.internal.util.Defense.notNull;
@@ -52,6 +53,7 @@
         }
     };
 
+
     public ComponentDefaultProviderImpl(PropertyAccess propertyAccess, BindingSource bindingSource,
                                         ValueEncoderSource valueEncoderSource,
                                         FieldTranslatorSource fieldTranslatorSource,
@@ -103,6 +105,7 @@
                 componentId);
     }
 
+    @SuppressWarnings({"unchecked"})
     public ValueEncoder defaultValueEncoder(String parameterName, ComponentResources resources)
     {
         notBlank(parameterName, "parameterName");
@@ -120,10 +123,39 @@
         return fieldTranslatorSource.createDefaultTranslator(resources, parameterName);
     }
 
+    public Binding defaultTranslatorBinding(final String parameterName, final ComponentResources resources)
+    {
+        String description = String.format("default translator, parameter %s of %s",
+                                           parameterName, resources.getCompleteId());
+
+        return new VariantBinding(FieldTranslator.class, description,
+                                  resources.getLocation())
+        {
+            public Object get()
+            {
+                return defaultTranslator(parameterName, resources);
+            }
+        };
+    }
+
     public FieldValidator defaultValidator(String parameterName, ComponentResources resources)
     {
         FieldValidator result = fieldValidatorDefaultSource.createDefaultValidator(resources, parameterName);
 
         return result == null ? NOOP_VALIDATOR : result;
     }
+
+    public Binding defaultValidatorBinding(final String parameterName, final ComponentResources resources)
+    {
+        String description = String.format("default validator, parameter %s of %s", parameterName,
+                                           resources.getCompleteId());
+
+        return new VariantBinding(FieldValidator.class, description, resources.getLocation())
+        {
+            public Object get()
+            {
+                return defaultValidator(parameterName, resources);
+            }
+        };
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImpl.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImpl.java Tue Nov  4 12:03:35 2008
@@ -102,11 +102,24 @@
     private MessageFormatter findFormatter(String overrideId, Messages overrideMessages, Locale locale,
                                            Translator translator)
     {
-        String overrideKey = overrideId + "-" + translator.getName() + "-message";
+        // TAP5-228: Try to distinguish message overrides by form id and overrideId (i.e., property name) first.
+
+        String translatorName = translator.getName();
+
+        String overrideKey = formSupport.getFormValidationId() + "-" + overrideId + "-" + translatorName + "-message";
+
+        if (overrideMessages.contains(overrideKey))
+            return overrideMessages.getFormatter(overrideKey);
+
+        // Ok, look for a simpler name that omits the formId prefix.
+
+        overrideKey = overrideId + "-" + translatorName + "-message";
 
         if (overrideMessages.contains(overrideKey))
             return overrideMessages.getFormatter(overrideKey);
 
+        // Otherwise, use the built-in validation message appropriate to this validator.
+
         Messages validationMessages = validationMessagesSource.getValidationMessages(locale);
 
         return validationMessages.getFormatter(translator.getMessageKey());

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImpl.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImpl.java Tue Nov  4 12:03:35 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -77,40 +77,74 @@
 
         Validator validator = validators.get(validatorType);
 
-        if (validator == null) throw new IllegalArgumentException(
-                ServicesMessages.unknownValidatorType(validatorType, InternalUtils.sortedKeys(validators)));
+        if (validator == null)
+            throw new IllegalArgumentException(
+                    ServicesMessages.unknownValidatorType(validatorType, InternalUtils.sortedKeys(validators)));
 
         // I just have this thing about always treating parameters as finals, so
         // we introduce a second variable to treat a mutable.
 
-        String finalConstraintValue = constraintValue;
+        String formValidationid = formSupport.getFormValidationId();
+
+        Object coercedConstraintValue = computeConstraintValue(validatorType, validator, constraintValue,
+                                                               formValidationid,
+                                                               overrideId,
+                                                               overrideMessages);
+
+        MessageFormatter formatter = findMessageFormatter(formValidationid, overrideId, overrideMessages, locale,
+                                                          validatorType,
+                                                          validator);
+
+        return new FieldValidatorImpl(field, coercedConstraintValue, formatter, validator, formSupport);
+    }
+
+    private Object computeConstraintValue(String validatorType, Validator validator, String constraintValue,
+                                          String formId, String overrideId,
+                                          Messages overrideMessages)
+    {
+        Class constraintType = validator.getConstraintType();
+
+        String constraintText = findConstraintValue(validatorType, constraintType, constraintValue, formId, overrideId,
+                                                    overrideMessages);
+
+        if (constraintText == null) return null;
+
+        return typeCoercer.coerce(constraintText, constraintType);
+    }
+
+    private String findConstraintValue(String validatorType, Class constraintType, String constraintValue,
+                                       String formValidationId, String overrideId,
+                                       Messages overrideMessages)
+    {
+        if (constraintValue != null) return constraintValue;
+
+        if (constraintType == null) return null;
 
         // If no constraint was provided, check to see if it is available via a localized message
         // key. This is really handy for complex validations such as patterns.
 
-        if (finalConstraintValue == null && validator.getConstraintType() != null)
-        {
-            String key = overrideId + "-" + validatorType;
+        String perFormKey = formValidationId + "-" + overrideId + "-" + validatorType;
 
-            if (overrideMessages.contains(key)) finalConstraintValue = overrideMessages.get(key);
-            else throw new IllegalArgumentException(
-                    ServicesMessages.missingValidatorConstraint(validatorType, validator.getConstraintType()));
-        }
+        if (overrideMessages.contains(perFormKey)) return overrideMessages.get(perFormKey);
 
-        Object coercedConstraintValue = coerceConstraintValue(finalConstraintValue, validator
-                .getConstraintType());
+        String generalKey = overrideId + "-" + validatorType;
 
-        MessageFormatter formatter = findMessageFormatter(overrideId, overrideMessages, locale, validatorType,
-                                                          validator);
+        if (overrideMessages.contains(generalKey)) return overrideMessages.get(generalKey);
 
-        return new FieldValidatorImpl(field, coercedConstraintValue, formatter, validator, formSupport);
+        throw new IllegalArgumentException(
+                ServicesMessages.missingValidatorConstraint(validatorType, constraintType, perFormKey, generalKey));
     }
 
-    private MessageFormatter findMessageFormatter(String overrideId, Messages overrideMessages, Locale locale,
+    private MessageFormatter findMessageFormatter(String formId, String overrideId, Messages overrideMessages,
+                                                  Locale locale,
                                                   String validatorType, Validator validator)
     {
 
-        String overrideKey = overrideId + "-" + validatorType + "-message";
+        String overrideKey = formId + "-" + overrideId + "-" + validatorType + "-message";
+
+        if (overrideMessages.contains(overrideKey)) return overrideMessages.getFormatter(overrideKey);
+
+        overrideKey = overrideId + "-" + validatorType + "-message";
 
         if (overrideMessages.contains(overrideKey)) return overrideMessages.getFormatter(overrideKey);
 
@@ -138,14 +172,6 @@
         return new CompositeFieldValidator(fieldValidators);
     }
 
-    @SuppressWarnings("unchecked")
-    private Object coerceConstraintValue(String constraintValue, Class constraintType)
-    {
-        if (constraintType == null) return null;
-
-        return typeCoercer.coerce(constraintValue, constraintType);
-    }
-
     /**
      * A code defining what the parser is looking for.
      */
@@ -280,7 +306,6 @@
                         skipWhitespace = true;
                         state = State.TYPE_START;
                         break;
-
                     }
 
                     parseError(cursor, specification);
@@ -317,7 +342,6 @@
                 // For better or worse, ending the string with a comma is valid.
 
             default:
-
         }
 
         return result;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java Tue Nov  4 12:03:35 2008
@@ -350,9 +350,11 @@
         return MESSAGES.format("no-edit-for-data-type", datatype);
     }
 
-    static String missingValidatorConstraint(String validatorType, Class type)
+    static String missingValidatorConstraint(String validatorType, Class type, String perFormMessageKey,
+                                             String generalMessageKey)
     {
-        return MESSAGES.format("missing-validator-constraint", validatorType, type.getName());
+        return MESSAGES.format("missing-validator-constraint", validatorType, type.getName(), perFormMessageKey,
+                               generalMessageKey);
     }
 
     static String resourcesAccessForbidden(String URI)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentDefaultProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentDefaultProvider.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentDefaultProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentDefaultProvider.java Tue Nov  4 12:03:35 2008
@@ -58,16 +58,36 @@
      * @param parameterName
      * @param resources
      * @return the translator, or null
+     * @deprecated Use {@link #defaultTranslatorBinding(String, org.apache.tapestry5.ComponentResources)} instead
      */
     FieldTranslator defaultTranslator(String parameterName, ComponentResources resources);
 
     /**
+     * Provides a binding that itself provides the field translator.
+     *
+     * @param parameterName
+     * @param resources
+     * @return binding that provides the {@link org.apache.tapestry5.FieldTranslator}
+     */
+    Binding defaultTranslatorBinding(String parameterName, ComponentResources resources);
+
+    /**
      * Provides a validator based on the bound parameter type.  If the property type of the parameter is not known, then
      * a no-op validator is returned.
      *
      * @param parameterName
      * @param resources
      * @return the validator, possibly a no-op validator
+     * @deprecated Use {@link #defaultValidatorBinding(String, org.apache.tapestry5.ComponentResources)} instead
      */
     FieldValidator defaultValidator(String parameterName, ComponentResources resources);
+
+    /**
+     * Provides a binding that itself provides the field translator.
+     *
+     * @param parameterName
+     * @param resources
+     * @return binding that provides the {@link org.apache.tapestry5.FieldTranslator}
+     */
+    Binding defaultValidatorBinding(String parameterName, ComponentResources resources);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FormSupport.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FormSupport.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FormSupport.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FormSupport.java Tue Nov  4 12:03:35 2008
@@ -90,4 +90,14 @@
      * org.apache.tapestry5.corelib.components.FormInjector}.
      */
     String getFormComponentId();
+
+    /**
+     * Id used as a prefix when searching {@link org.apache.tapestry5.ioc.Messages} for validation messages and
+     * constraints. This is normally the simple id of the form.
+     *
+     * @return validation id string
+     * @see org.apache.tapestry5.services.FieldTranslatorSource
+     * @see org.apache.tapestry5.services.FieldValidatorSource
+     */
+    String getFormValidationId();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java Tue Nov  4 12:03:35 2008
@@ -1170,4 +1170,14 @@
     {
         return newMock(ComponentEventResultProcessor.class);
     }
+
+    protected final void train_getFormComponentId(FormSupport formSupport, String componentId)
+    {
+        expect(formSupport.getFormComponentId()).andReturn(componentId).atLeastOnce();
+    }
+
+    protected final void train_getFormValidationId(FormSupport formSupport, String validationId)
+    {
+        expect(formSupport.getFormValidationId()).andReturn(validationId).atLeastOnce();
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties Tue Nov  4 12:03:35 2008
@@ -77,7 +77,9 @@
 unclosed-attribute-expression=Attribute expression '%s' is missing a closing brace.
 no-display-for-data-type=There is no defined way to display data of type '%s'. Make a contribution to the BeanBlockSource service for this type.
 no-edit-for-data-type=There is no defined way to edit data of type '%s'.  Make a contribution to the BeanBlockSource service for this type.
-missing-validator-constraint=Validator '%s' requires a validation constraint (of type %s) but none was provided.
+missing-validator-constraint=Validator '%s' requires a validation constraint (of type %s) but none was provided. \
+  The constraint may be provided inside the @Validator annotaton on the property, \
+  or in the associated component message catalog as key '%s' or key '%s'. 
 resource-access-forbidden=URI %s may not be accessed remotely.
 no-markup-from-page-render=Page %s did not generate any markup when rendered. This could be because its template file could not be located, or because a \
   render phase method in the page prevented rendering.

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PerFormValidationMessageDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PerFormValidationMessageDemo.tml?rev=711370&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PerFormValidationMessageDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PerFormValidationMessageDemo.tml Tue Nov  4 12:03:35 2008
@@ -0,0 +1,12 @@
+<html t:type="border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <h1>Per-Form Validation Message Demo</h1>
+
+
+    <h1>Login</h1>
+    <t:beaneditform t:id="login" object="this" submitLabel="Login" clientValidation="false"/>
+
+    <h1>Register</h1>
+    <t:beaneditform t:id="register" object="this" submitLabel="Register" clientValidation="false"/>
+
+
+</html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/SubmitTest.java Tue Nov  4 12:03:35 2008
@@ -49,7 +49,7 @@
     {
         Request request = mockRequest();
         ComponentResources resources = mockComponentResources();
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         String elementName = "myname";
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/internal/FormSupportImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/internal/FormSupportImplTest.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/internal/FormSupportImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/internal/FormSupportImplTest.java Tue Nov  4 12:03:35 2008
@@ -24,7 +24,7 @@
     @Test
     public void execute_deferred_with_no_commands()
     {
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         support.executeDeferred();
     }
@@ -42,7 +42,7 @@
 
         replay();
 
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         support.defer(r1);
         support.defer(r2);
@@ -66,7 +66,7 @@
 
         replay();
 
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         support.defer(r1);
         support.defer(r2);
@@ -89,7 +89,7 @@
     @Test
     public void set_encoding_type()
     {
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         String encodingType = "foo/bar";
 
@@ -101,7 +101,7 @@
     @Test
     public void set_encoding_type_to_same_value_is_allowed()
     {
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         String encodingType = "foo/bar";
 
@@ -115,7 +115,7 @@
     public void set_encoding_type_conflict()
     {
 
-        FormSupportImpl support = new FormSupportImpl(null);
+        FormSupportImpl support = new FormSupportImpl(null, null);
 
         support.setEncodingType("foo");
         try
@@ -140,7 +140,8 @@
 
         replay();
 
-        FormSupportImpl support = new FormSupportImpl(null, null, null, clientBehaviorSupport, true, null);
+        FormSupportImpl support = new FormSupportImpl(null, null, null, clientBehaviorSupport, true, null,
+                                                      null);
 
         support.addValidation(barney, "required", "Who can live without Barney?", null);
 
@@ -155,7 +156,8 @@
 
         replay();
 
-        FormSupportImpl support = new FormSupportImpl(null, null, null, clientBehaviorSupport, false, null);
+        FormSupportImpl support = new FormSupportImpl(null, null, null, clientBehaviorSupport, false, null,
+                                                      null);
 
         support.addValidation(barney, "required", "Who can live without Barney?", null);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Tue Nov  4 12:03:35 2008
@@ -2446,4 +2446,33 @@
         assertText("second", "Source is null.");
         assertText("third", "Source is the empty list.");
     }
+
+    /**
+     * TAP5-228: And to think I almost blew off the integration tests!
+     */
+    public void per_form_validation_messages_and_constraints()
+    {
+        start("Per-Form Validation Messages");
+
+        clickAndWait("//input[@type='submit' and @value='Login']");
+
+        assertTextPresent("Enter the unique user id you provided when you registerred.");
+
+        type("userId", "aaa");
+
+        clickAndWait("//input[@type='submit' and @value='Login']");
+
+        assertTextPresent("You must provide at least 10 characters for User Id.");
+
+
+        clickAndWait("//input[@type='submit' and @value='Register']");
+
+        assertTextPresent("Enter a unique user id, such as your initials.");
+
+        type("userId_0", "aaa");
+
+        clickAndWait("//input[@type='submit' and @value='Register']");
+
+        assertTextPresent("You must provide at least 20 characters for User Id.");
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java?rev=711370&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java Tue Nov  4 12:03:35 2008
@@ -0,0 +1,33 @@
+//  Copyright 2008 The Apache Software Foundation
+//
+// 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.apache.tapestry5.integration.app1.pages;
+
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.beaneditor.DataType;
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+import org.apache.tapestry5.beaneditor.Validate;
+
+@ReorderProperties("userId,password")
+public class PerFormValidationMessageDemo
+{
+    @Validate("required,minlength")
+    @Property
+    private String userId;
+
+    @Validate("required")
+    @DataType("password")
+    @Property
+    private String password;
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java Tue Nov  4 12:03:35 2008
@@ -65,6 +65,9 @@
 
     private static final List<Item> ITEMS = CollectionFactory.newList(
 
+            new Item("PerFormValidationMessageDemo", "Per-Form Validation Messages",
+                     "Per-form configuration of validation messages and constraints."),
+
             new Item("EmptyLoopDemo", "Empty Loop Demo", "Use of empty parameter with the Loop component."),
 
             new Item("BlankPasswordDemo", "Blank Password Demo",

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImplTest.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldTranslatorSourceImplTest.java Tue Nov  4 12:03:35 2008
@@ -87,6 +87,10 @@
 
 
         train_findByType(ts, propertyType, translator);
+
+        train_getFormValidationId(fs, "myform");
+
+        train_contains(messages, "myform-myfield-maptrans-message", false);
         train_contains(messages, "myfield-maptrans-message", false);
         train_getValidationMessages(vms, locale, validationMessages);
 
@@ -127,6 +131,10 @@
         String message = "Formatted Message";
 
         train_findByType(ts, propertyType, translator);
+
+        train_getFormValidationId(fs, "myform");
+
+        train_contains(messages, "myform-myfield-maptrans-message", false);
         train_contains(messages, "myfield-maptrans-message", true);
         train_getMessageFormatter(messages, "myfield-maptrans-message", formatter);
 
@@ -149,6 +157,47 @@
     }
 
     @Test
+    public void create_default_translator_with_per_form_override_message()
+    {
+        Field field = mockField();
+        Messages messages = mockMessages();
+        Locale locale = Locale.ENGLISH;
+        Class propertyType = Map.class;
+        TranslatorSource ts = mockTranslatorSource();
+        ValidationMessagesSource vms = mockValidationMessagesSource();
+        FormSupport fs = mockFormSupport();
+        Translator translator = mockTranslator("maptrans", Map.class);
+        MessageFormatter formatter = mockMessageFormatter();
+        MarkupWriter writer = mockMarkupWriter();
+        String label = "My Label";
+        String message = "Formatted Message";
+
+        train_findByType(ts, propertyType, translator);
+
+        train_getFormValidationId(fs, "myform");
+
+        train_contains(messages, "myform-myfield-maptrans-message", true);
+        train_getMessageFormatter(messages, "myform-myfield-maptrans-message", formatter);
+
+        train_getLabel(field, label);
+        train_format(formatter, message, label);
+
+        translator.render(field, message, writer, fs);
+
+        replay();
+
+        FieldTranslatorSource source = new FieldTranslatorSourceImpl(ts, vms, fs);
+
+        FieldTranslator ft = source.createDefaultTranslator(field, "myfield", messages, locale, propertyType, null);
+
+        assertEquals(ft.getType(), Map.class);
+
+        ft.render(writer);
+
+        verify();
+    }
+
+    @Test
     public void create_translator_from_translator_name()
     {
         ComponentResources resources = mockComponentResources();
@@ -171,6 +220,10 @@
         train_getLocale(resources, locale);
 
         train_get(ts, "map", translator);
+
+        train_getFormValidationId(fs, "myform");
+
+        train_contains(messages, "myform-myfield-map-message", false);
         train_contains(messages, "myfield-map-message", false);
         train_getValidationMessages(vms, locale, validationMessages);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImplTest.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/FieldValidatorSourceImplTest.java Tue Nov  4 12:03:35 2008
@@ -25,6 +25,7 @@
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.runtime.Component;
 import org.apache.tapestry5.services.FieldValidatorSource;
+import org.apache.tapestry5.services.FormSupport;
 import org.apache.tapestry5.services.ValidationMessagesSource;
 import org.testng.annotations.Test;
 
@@ -90,15 +91,19 @@
         Object inputValue = new Object();
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = singletonMap("required", validator);
 
         train_getConstraintType(validator, null);
 
+        train_getFormValidationId(fs, "form");
+
         train_getComponentResources(field, resources);
 
         train_getId(resources, "fred");
         train_getContainerMessages(resources, containerMessages);
+        train_contains(containerMessages, "form-fred-required-message", false);
         train_contains(containerMessages, "fred-required-message", false);
 
         train_getLocale(resources, Locale.FRENCH);
@@ -114,7 +119,7 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidator(field, "required", null);
 
@@ -135,15 +140,20 @@
         Object inputValue = new Object();
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = singletonMap("required", validator);
 
         train_getConstraintType(validator, null);
 
+        train_getFormValidationId(fs, "form");
+
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
         train_getLocale(resources, Locale.ENGLISH);
         train_getContainerMessages(resources, containerMessages);
+
+        train_contains(containerMessages, "form-fred-required-message", false);
         train_contains(containerMessages, "fred-required-message", true);
 
         train_getMessageFormatter(containerMessages, "fred-required-message", formatter);
@@ -154,7 +164,50 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
+
+        FieldValidator fieldValidator = source.createValidator(field, "required", null);
+
+        fieldValidator.validate(inputValue);
+
+        verify();
+    }
+
+    @Test
+    public void component_messages_overrides_validator_messages_per_form() throws Exception
+    {
+        ValidationMessagesSource messagesSource = mockValidationMessagesSource();
+        Validator validator = mockValidator();
+        TypeCoercer coercer = mockTypeCoercer();
+        FieldComponent field = newFieldComponent();
+        MessageFormatter formatter = mockMessageFormatter();
+        Object inputValue = new Object();
+        ComponentResources resources = mockComponentResources();
+        Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
+
+        Map<String, Validator> map = singletonMap("required", validator);
+
+        train_getConstraintType(validator, null);
+
+        train_getFormValidationId(fs, "form");
+
+        train_getComponentResources(field, resources);
+        train_getId(resources, "fred");
+        train_getLocale(resources, Locale.ENGLISH);
+        train_getContainerMessages(resources, containerMessages);
+
+        train_contains(containerMessages, "form-fred-required-message", true);
+
+        train_getMessageFormatter(containerMessages, "form-fred-required-message", formatter);
+
+        train_isRequired(validator, false);
+        train_getValueType(validator, Object.class);
+        validator.validate(field, null, formatter, inputValue);
+
+        replay();
+
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidator(field, "required", null);
 
@@ -165,7 +218,7 @@
 
     @SuppressWarnings("unchecked")
     @Test
-    public void constraint_value_from_message_catalog() throws Exception
+    public void constraint_value_from_message_catalog_per() throws Exception
     {
         ValidationMessagesSource messagesSource = mockValidationMessagesSource();
         Validator validator = mockValidator();
@@ -176,20 +229,26 @@
         Object inputValue = new Object();
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
+
 
         Map<String, Validator> map = singletonMap("minlength", validator);
 
         train_getConstraintType(validator, Integer.class);
 
+        train_getFormValidationId(fs, "myform");
+
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
 
+        train_contains(containerMessages, "myform-fred-minlength", false);
         train_contains(containerMessages, "fred-minlength", true);
         train_get(containerMessages, "fred-minlength", "5");
 
         train_coerce(coercer, "5", Integer.class, 5);
 
         train_getContainerMessages(resources, containerMessages);
+        train_contains(containerMessages, "myform-fred-minlength-message", false);
         train_contains(containerMessages, "fred-minlength-message", false);
 
         train_getLocale(resources, Locale.FRENCH);
@@ -205,7 +264,7 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidators(field, "minlength");
 
@@ -216,6 +275,63 @@
 
     @SuppressWarnings("unchecked")
     @Test
+    public void constraint_value_from_message_catalog_per_form() throws Exception
+    {
+        ValidationMessagesSource messagesSource = mockValidationMessagesSource();
+        Validator validator = mockValidator();
+        TypeCoercer coercer = mockTypeCoercer();
+        FieldComponent field = newFieldComponent();
+        Messages messages = mockMessages();
+        MessageFormatter formatter = mockMessageFormatter();
+        Object inputValue = new Object();
+        ComponentResources resources = mockComponentResources();
+        Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
+
+
+        Map<String, Validator> map = singletonMap("minlength", validator);
+
+        train_getConstraintType(validator, Integer.class);
+
+        train_getFormValidationId(fs, "myform");
+
+        train_getComponentResources(field, resources);
+        train_getId(resources, "fred");
+
+        train_contains(containerMessages, "myform-fred-minlength", true);
+        train_get(containerMessages, "myform-fred-minlength", "5");
+
+        train_coerce(coercer, "5", Integer.class, 5);
+
+        train_getContainerMessages(resources, containerMessages);
+        train_contains(containerMessages, "myform-fred-minlength-message", false);
+        train_contains(containerMessages, "fred-minlength-message", false);
+
+        train_getLocale(resources, Locale.FRENCH);
+
+        train_getValidationMessages(messagesSource, Locale.FRENCH, messages);
+
+        train_getMessageKey(validator, "key");
+        train_getMessageFormatter(messages, "key", formatter);
+
+        train_isRequired(validator, false);
+        train_getValueType(validator, Object.class);
+        validator.validate(field, 5, formatter, inputValue);
+
+        replay();
+
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
+
+        FieldValidator fieldValidator = source.createValidators(field, "minlength");
+
+        fieldValidator.validate(inputValue);
+
+        verify();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
     public void missing_field_validator_constraint() throws Exception
     {
         ValidationMessagesSource messagesSource = mockValidationMessagesSource();
@@ -224,21 +340,25 @@
         FieldComponent field = newFieldComponent();
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = singletonMap("minlength", validator);
 
         train_getConstraintType(validator, Integer.class);
 
+        train_getFormValidationId(fs, "myform");
+
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
         train_getLocale(resources, Locale.GERMAN);
         train_getContainerMessages(resources, containerMessages);
 
+        train_contains(containerMessages, "myform-fred-minlength", false);
         train_contains(containerMessages, "fred-minlength", false);
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         try
         {
@@ -248,11 +368,10 @@
         catch (IllegalArgumentException ex)
         {
             assertEquals(ex.getMessage(),
-                         "Validator \'minlength\' requires a validation constraint (of type java.lang.Integer) but none was provided.");
+                         "Validator 'minlength' requires a validation constraint (of type java.lang.Integer) but none was provided. The constraint may be provided inside the @Validator annotaton on the property, or in the associated component message catalog as key 'myform-fred-minlength' or key 'fred-minlength'. ");
         }
 
         verify();
-
     }
 
     @SuppressWarnings("unchecked")
@@ -268,14 +387,19 @@
         Object inputValue = new Object();
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = singletonMap("required", validator);
 
+        train_getFormValidationId(fs, "myform");
+
         train_getConstraintType(validator, null);
 
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
         train_getContainerMessages(resources, containerMessages);
+
+        train_contains(containerMessages, "myform-fred-required-message", false);
         train_contains(containerMessages, "fred-required-message", false);
 
         train_getLocale(resources, Locale.FRENCH);
@@ -291,7 +415,7 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidators(field, "required");
 
@@ -316,18 +440,22 @@
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
         Integer fifteen = 15;
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = newMap();
 
         map.put("required", required);
         map.put("minLength", minLength);
 
+        train_getFormValidationId(fs, "myform");
+
         train_getConstraintType(required, null);
         train_getConstraintType(minLength, Integer.class);
 
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
         train_getContainerMessages(resources, containerMessages);
+        train_contains(containerMessages, "myform-fred-required-message", false);
         train_contains(containerMessages, "fred-required-message", false);
 
         train_getLocale(resources, Locale.FRENCH);
@@ -337,6 +465,7 @@
         train_getMessageKey(required, "required");
         train_getMessageFormatter(messages, "required", requiredFormatter);
 
+        train_contains(containerMessages, "myform-fred-minLength-message", false);
         train_contains(containerMessages, "fred-minLength-message", false);
 
         train_getMessageKey(minLength, "min-length");
@@ -354,7 +483,7 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidators(field, "required,minLength=15");
 
@@ -377,16 +506,20 @@
         ComponentResources resources = mockComponentResources();
         Messages containerMessages = mockMessages();
         Integer five = 5;
+        FormSupport fs = mockFormSupport();
 
         Map<String, Validator> map = singletonMap("minLength", validator);
 
         train_getConstraintType(validator, Integer.class);
 
+        train_getFormValidationId(fs, "myform");
+
         train_coerce(coercer, "5", Integer.class, five);
 
         train_getComponentResources(field, resources);
         train_getId(resources, "fred");
         train_getContainerMessages(resources, containerMessages);
+        train_contains(containerMessages, "myform-fred-minLength-message", false);
         train_contains(containerMessages, "fred-minLength-message", false);
 
         train_getLocale(resources, Locale.FRENCH);
@@ -402,7 +535,7 @@
 
         replay();
 
-        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, null, map);
+        FieldValidatorSource source = new FieldValidatorSourceImpl(messagesSource, coercer, fs, map);
 
         FieldValidator fieldValidator = source.createValidator(field, "minLength", "5");
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.properties?rev=711370&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.properties Tue Nov  4 12:03:35 2008
@@ -0,0 +1,7 @@
+register-userid-required-message=Enter a unique user id, such as your initials.
+login-userid-required-message=Enter the unique user id you provided when you registerred.
+
+# You'd never actually do this, but ...
+
+login-userid-minlength=10
+register-userid-minlength=20

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/Locatable.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/Locatable.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/Locatable.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/Locatable.java Tue Nov  4 12:03:35 2008
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 /**
  * Interface implemented by objects which carry a location tag. Defines a readable property, location.
  */
+@SuppressWarnings({"JavaDoc"})
 public interface Locatable
 {
     /**

Modified: tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java?rev=711370&r1=711369&r2=711370&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java (original)
+++ tapestry/tapestry5/trunk/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java Tue Nov  4 12:03:35 2008
@@ -92,9 +92,9 @@
     /**
      * Computes a default value for the "validate" parameter using {@link FieldValidatorDefaultSource}.
      */
-    final FieldValidator defaultValidate()
+    final Binding defaultValidate()
     {
-        return defaultProvider.defaultValidator("value", resources);
+        return defaultProvider.defaultValidatorBinding("value", resources);
     }
 
     public Upload()



Mime
View raw message