tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hls...@apache.org
Subject svn commit: r492704 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/ main/java/org/apache/tapestry/corelib/base/ main/java/org/apache/tapestry/corelib/components/ main/java/org/apache/tapestry/internal/bindings/ main/jav...
Date Thu, 04 Jan 2007 19:42:35 GMT
Author: hlship
Date: Thu Jan  4 11:42:33 2007
New Revision: 492704

URL: http://svn.apache.org/viewvc?view=rev&rev=492704
Log:
Determine the default Translator based on the bound property type.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/TranslateBindingFactory.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorDefaultSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorDefaultSource.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorSource.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/IntegerTranslator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/StringTranslator.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/TranslatorSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/IntegerTranslatorTest.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/TextField.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/AbstractBinding.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParser.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
    tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java Thu Jan  4 11:42:33 2007
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.Binding;
 
 /**
  * Provides a component instance with the resources provided by the framework. In many
@@ -41,6 +42,12 @@
     Component getContainer();
 
     /**
+     * Returns the {@link ComponentResources} for the container, or null if the this is the root
+     * component (that has no container).
+     */
+    ComponentResources getContainerResources();
+
+    /**
      * Returns the page that contains this component. Technically, the page itself is an internal
      * object in Tapestry and this returns the root component of the actual page, but from an
      * application developer point of view, this is the page.
@@ -69,4 +76,17 @@
 
     /** Returns the message catalog for this component. */
     Messages getMessages();
+
+    /**
+     * Returns the actual type of the bound parameter, or Object.class if the parameter is not
+     * bound. This is primarily used with property bindings, and is used to determine the actual
+     * type of the property, rather than the type of parameter (remember that type coercion
+     * automatically occurs, which can mask significant differences between the parameter type and
+     * the bound property type).
+     * 
+     * @see Binding#getBindingType()
+     * @param parameterName
+     * @return
+     */
+    Class getBoundType(String parameterName);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Translator.java Thu Jan  4 11:42:33 2007
@@ -14,6 +14,9 @@
 
 package org.apache.tapestry;
 
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.services.ValidationMessagesSource;
+
 /**
  * Translates between client-side and server-side values. Client-side values are always strings.
  * 
@@ -24,7 +27,7 @@
     /**
      * Converts a server-side value to a client-side string. This allows for formatting of the value
      * in a way appropriate to the end user. The output client value should be parsable by
-     * {@link #parseClient(String)}.
+     * {@link #parseClient(String, Messages)}.
      * 
      * @param value
      *            the server side value (which may be null)
@@ -37,9 +40,11 @@
      * 
      * @param clientValue
      *            (possibly null or the empty string)
+     * @param messages
+     *            validator messages assembled by {@link ValidationMessagesSource}
      * @return equivalent server-side value (possibly null)
      * @throws ValidationException
      *             if the value can not be parsed
      */
-    T parseClient(String clientValue) throws ValidationException;
+    T parseClient(String clientValue, Messages messages) throws ValidationException;
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java Thu Jan  4 11:42:33 2007
@@ -20,7 +20,6 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Field;
 import org.apache.tapestry.FieldValidator;
-import org.apache.tapestry.Translator;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.annotations.ComponentClass;
 import org.apache.tapestry.annotations.Environmental;
@@ -42,7 +41,7 @@
 
 /**
  * Provides initialization of the clientId and elementName properties. In addition, adds the
- * {@link RenderInformals} mixin.
+ * {@link RenderInformals}, {@link RenderDisabled} and {@link DiscardBody} mixins.
  */
 @ComponentClass
 public abstract class AbstractField implements Field
@@ -77,21 +76,6 @@
         }
     };
 
-    private static final Translator DEFAULT_TRANSLATOR = new Translator()
-    {
-
-        public Object parseClient(String clientValue) throws ValidationException
-        {
-            return clientValue;
-        }
-
-        public String toClient(Object value)
-        {
-            return value == null ? "" : value.toString();
-        }
-
-    };
-
     static class SetupAction implements ComponentAction<AbstractField>, Serializable
     {
         private static final long serialVersionUID = 2690270808212097020L;
@@ -138,7 +122,7 @@
     @Inject("service:tapestry.internal.FormParameterLookup")
     private FormParameterLookup _paramLookup;
 
-    Binding defaultLabel()
+    final Binding defaultLabel()
     {
         Messages containerMessages = _resources.getContainer().getComponentResources()
                 .getMessages();
@@ -198,7 +182,7 @@
         _elementName = elementName;
     }
 
-    private final void processSubmission()
+    private void processSubmission()
     {
         if (!_disabled)
             processSubmission(_paramLookup, _elementName);
@@ -212,7 +196,7 @@
     {
         String componentId = _resources.getId();
 
-        ComponentResources container = _resources.getContainer().getComponentResources();
+        ComponentResources container = _resources.getContainerResources();
 
         return _bindingSource.newBinding("default " + parameterName, container, componentId);
     }
@@ -239,14 +223,5 @@
     public final FieldValidator getNoopValidator()
     {
         return NOOP_VALIDATOR;
-    }
-
-    /**
-     * A translator that converts objects to strings (and converts null to the empty string), used
-     * as the default for subclasses' translate parameter.
-     */
-    public final Translator getDefaultTranslator()
-    {
-        return DEFAULT_TRANSLATOR;
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java Thu Jan  4 11:42:33 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.corelib.base;
 
+import java.util.Locale;
+
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.FieldValidator;
 import org.apache.tapestry.MarkupWriter;
@@ -24,8 +26,12 @@
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.internal.bindings.AbstractBinding;
 import org.apache.tapestry.internal.services.FormParameterLookup;
+import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.services.Binding;
+import org.apache.tapestry.services.TranslatorDefaultSource;
+import org.apache.tapestry.services.ValidationMessagesSource;
 
 /** Abstract class for a variety of components that render some variation of a text field. */
 public abstract class AbstractTextField extends AbstractField
@@ -33,7 +39,7 @@
     @Parameter(required = true)
     private Object _value;
 
-    @Parameter("defaultTranslator")
+    @Parameter
     private Translator<Object> _translate;
 
     @Parameter("noopValidator")
@@ -42,13 +48,50 @@
     @Environmental
     private ValidationTracker _tracker;
 
+    @Inject("infrastructure:ValidationMessagesSource")
+    private ValidationMessagesSource _messagesSource;
+
+    @Inject("infrastructure:TranslatorDefaultSource")
+    private TranslatorDefaultSource _translatorDefaultSource;
+
     @Inject
     private ComponentResources _resources;
 
+    @Inject
+    private Locale _locale;
+
+    final Binding defaultTranslate()
+    {
+        // Have to do this a bit the hard way: defer getting the translator until first needed,
+        // since we won't know the bound type of the value parameter until after
+        // containingPageDidLoad().
+        // This is because fields are handled in alphabetical order, and _translate is ordered
+        // before _validate.
+
+        return new AbstractBinding()
+        {
+            private Translator _translator;
+
+            public Object get()
+            {
+                if (_translator == null)
+                    _translator = _translatorDefaultSource.find(_resources.getBoundType("value"));
+
+                return _translator;
+            }
+
+            public Class getBindingType()
+            {
+                return get().getClass();
+            }
+        };
+    }
+
     /**
-     * The default value is a property of the container whose name matches the component's id.
+     * The default value is a property of the container whose name matches the component's id. May
+     * return null if the container does not have a matching property (not yet implemented).
      */
-    Binding defaultValue()
+    final Binding defaultValue()
     {
         return createDefaultParameterBinding("value");
     }
@@ -83,10 +126,11 @@
 
         _tracker.recordInput(this, rawValue);
 
+        Messages messages = _messagesSource.getValidationMessages(_locale);
+
         try
         {
-
-            Object translated = _translate.parseClient(rawValue);
+            Object translated = _translate.parseClient(rawValue, messages);
 
             _validate.check(translated);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/TextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/TextField.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/TextField.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/TextField.java Thu Jan  4 11:42:33 2007
@@ -15,7 +15,6 @@
 package org.apache.tapestry.corelib.components;
 
 import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.annotations.AfterRender;
 import org.apache.tapestry.corelib.base.AbstractTextField;
 
 /**
@@ -40,8 +39,7 @@
                 value);
     }
 
-    @AfterRender
-    final void after(MarkupWriter writer)
+    final void afterRender(MarkupWriter writer)
     {
         writer.end(); // input
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/AbstractBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/AbstractBinding.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/AbstractBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/AbstractBinding.java Thu Jan  4 11:42:33 2007
@@ -12,37 +12,41 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.bindings;
-
+package org.apache.tapestry.internal.bindings;
+
 import org.apache.tapestry.ioc.BaseLocatable;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.internal.util.TapestryException;
 import org.apache.tapestry.services.Binding;
-
-/**
- * Abstract base class for bindings.
- */
-public abstract class AbstractBinding extends BaseLocatable implements Binding
-{
-
-    public AbstractBinding(Location location)
-    {
-        super(location);
-    }
-
-    /**
-     * @throws TapestryException
-     *             always
-     */
-    public void set(Object value)
-    {
-        throw new TapestryException(BindingsMessages.bindingIsReadOnly(this), this, null);
-    }
-
-    /** Returns true. */
-    public boolean isInvariant()
-    {
-        return true;
-    }
-
-}
+
+/**
+ * Abstract base class for bindings.
+ */
+public abstract class AbstractBinding extends BaseLocatable implements Binding
+{
+    public AbstractBinding()
+    {
+        this(null);
+    }
+
+    public AbstractBinding(Location location)
+    {
+        super(location);
+    }
+
+    /**
+     * @throws TapestryException
+     *             always
+     */
+    public void set(Object value)
+    {
+        throw new TapestryException(BindingsMessages.bindingIsReadOnly(this), this, null);
+    }
+
+    /** Returns true. */
+    public boolean isInvariant()
+    {
+        return true;
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java Thu Jan  4 11:42:33 2007
@@ -18,7 +18,8 @@
 
 /**
  * Binding type for literal, immutable values. This is often used for literal string values supplied
- * in-line in the component template, but is used for many other things as well.
+ * in-line in the component template, but is used for many other things as well, any kind of fixed,
+ * read-only value.
  */
 public class LiteralBinding extends AbstractBinding
 {

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/TranslateBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/TranslateBindingFactory.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/TranslateBindingFactory.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/TranslateBindingFactory.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,31 @@
+package org.apache.tapestry.internal.bindings;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ioc.Location;
+import org.apache.tapestry.services.Binding;
+import org.apache.tapestry.services.BindingFactory;
+import org.apache.tapestry.services.TranslatorSource;
+
+/**
+ * Interprets the binding expression as the name of a {@link Translator} provided by the
+ * {@link TranslatorSource}.
+ */
+public class TranslateBindingFactory implements BindingFactory
+{
+    private final TranslatorSource _source;
+
+    public TranslateBindingFactory(TranslatorSource source)
+    {
+        _source = source;
+    }
+
+    public Binding newBinding(String description, ComponentResources container,
+            ComponentResources component, String expression, Location location)
+    {
+        Translator translator = _source.get(expression);
+
+        return new LiteralBinding(description, translator, location);
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Thu Jan  4 11:42:33 2007
@@ -279,6 +279,12 @@
                 .join(knownValidatorTypes));
     }
 
+    static String unknownTranslatorType(String translatorType, List<String> knownTranslatorTypes)
+    {
+        return MESSAGES.format("unknown-translator-type", translatorType, InternalUtils
+                .join(knownTranslatorTypes));
+    }
+
     static String validatorSpecificationParseError(int cursor, String specification)
     {
         return MESSAGES.format(

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParser.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParser.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParser.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParser.java Thu Jan  4 11:42:33 2007
@@ -12,17 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import org.apache.tapestry.internal.parser.ComponentTemplate;
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.parser.ComponentTemplate;
 import org.apache.tapestry.ioc.Resource;
-
-/**
- * Parses a resource into a {@link org.apache.tapestry.internal.parser.ComponentTemplate}.
- * 
- * 
- */
-public interface TemplateParser
-{
-    ComponentTemplate parseTemplate(Resource templateResource);
-}
+
+/**
+ * Parses a resource into a {@link org.apache.tapestry.internal.parser.ComponentTemplate}.
+ * 
+ * @see PageLoader
+ */
+public interface TemplateParser
+{
+    /**
+     * Parses the given resource into a component template.
+     * 
+     * @param templateResource
+     *            the path
+     * @return the parsed template contents
+     * @throws RuntimeException
+     *             if the resource does not exist, or if there is any kind of parse error
+     */
+    ComponentTemplate parseTemplate(Resource templateResource);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java Thu Jan  4 11:42:33 2007
@@ -533,68 +533,46 @@
 
     public void endDTD() throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void endEntity(String name) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void startDTD(String name, String publicId, String systemId) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void startEntity(String name) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void endDocument() throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void endPrefixMapping(String prefix) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void processingInstruction(String target, String data) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void skippedEntity(String name) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void startDocument() throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
     public void startPrefixMapping(String prefix, String uri) throws SAXException
     {
-        // TODO Auto-generated method stub
-
     }
 
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorDefaultSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorDefaultSourceImpl.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorDefaultSourceImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorDefaultSourceImpl.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,29 @@
+package org.apache.tapestry.internal.services;
+
+import java.util.Map;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.ioc.util.StrategyRegistry;
+import org.apache.tapestry.services.TranslatorDefaultSource;
+
+public class TranslatorDefaultSourceImpl implements TranslatorDefaultSource, InvalidationListener
+{
+    private final StrategyRegistry<Translator> _registry;
+
+    public TranslatorDefaultSourceImpl(Map<Class, Translator> configuration)
+    {
+        _registry = StrategyRegistry.newInstance(Translator.class, configuration);
+    }
+
+    public Translator find(Class valueType)
+    {
+        return _registry.get(valueType);
+    }
+
+    public void objectWasInvalidated()
+    {
+        _registry.clearCache();
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorSourceImpl.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorSourceImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/TranslatorSourceImpl.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,30 @@
+package org.apache.tapestry.internal.services;
+
+import java.util.Map;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+import org.apache.tapestry.services.TranslatorSource;
+
+public class TranslatorSourceImpl implements TranslatorSource
+{
+    private final Map<String, Translator> _translators;
+
+    public TranslatorSourceImpl(final Map<String, Translator> translators)
+    {
+        _translators = translators;
+    }
+
+    public Translator get(String name)
+    {
+
+        Translator result = _translators.get(name);
+
+        if (result == null)
+            throw new RuntimeException(ServicesMessages.unknownTranslatorType(name, InternalUtils
+                    .sortedKeys(_translators)));
+
+        return result;
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java Thu Jan  4 11:42:33 2007
@@ -21,6 +21,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.ComponentEventHandler;
+import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.internal.InternalComponentResources;
@@ -188,6 +189,13 @@
         }
     }
 
+    public Class getBoundType(String parameterName)
+    {
+        Binding b = getBinding(parameterName);
+
+        return b != null ? b.getBindingType() : Object.class;
+    }
+
     @SuppressWarnings("unchecked")
     public <T> void writeParameter(String parameterName, T parameterValue)
     {
@@ -246,6 +254,13 @@
         ComponentPageElement containerElement = _element.getContainerElement();
 
         return containerElement == null ? null : containerElement.getComponent();
+    }
+
+    public ComponentResources getContainerResources()
+    {
+        ComponentPageElement containerElement = _element.getContainerElement();
+
+        return containerElement == null ? null : containerElement.getComponentResources();
     }
 
     public Locale getLocale()

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Thu Jan  4 11:42:33 2007
@@ -20,6 +20,7 @@
 
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.ResourceBundle;
 
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.ComponentResources;
@@ -42,11 +43,13 @@
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.structure.PageElement;
 import org.apache.tapestry.ioc.Location;
+import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.ioc.RegistryBuilder;
 import org.apache.tapestry.ioc.Resource;
 import org.apache.tapestry.ioc.internal.InternalRegistry;
 import org.apache.tapestry.ioc.internal.Module;
+import org.apache.tapestry.ioc.internal.util.MessagesImpl;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.model.EmbeddedComponentModel;
 import org.apache.tapestry.runtime.Component;
@@ -68,6 +71,8 @@
 {
     private static Registry _registry;
 
+    private Messages _validationMessages;
+
     @BeforeSuite
     public final void setup_registry()
     {
@@ -412,5 +417,19 @@
     protected final PageTemplateLocator newPageTemplateLocator()
     {
         return newMock(PageTemplateLocator.class);
+    }
+
+    /** Returns the default validator messages. */
+    protected final Messages validationMessages()
+    {
+        if (_validationMessages == null)
+        {
+            ResourceBundle bundle = ResourceBundle
+                    .getBundle("org.apache.tapestry.internal.ValidationMessages");
+
+            _validationMessages = new MessagesImpl(bundle);
+        }
+
+        return _validationMessages;
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Thu Jan  4 11:42:33 2007
@@ -28,6 +28,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.ComponentEventHandler;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.Translator;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.annotations.AfterRender;
 import org.apache.tapestry.annotations.AfterRenderBody;
@@ -44,6 +45,7 @@
 import org.apache.tapestry.internal.bindings.ComponentBindingFactory;
 import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
 import org.apache.tapestry.internal.bindings.MessageBindingFactory;
+import org.apache.tapestry.internal.bindings.TranslateBindingFactory;
 import org.apache.tapestry.internal.bindings.ValidateBindingFactory;
 import org.apache.tapestry.internal.services.ActionLinkHandler;
 import org.apache.tapestry.internal.services.ActionLinkHandlerImpl;
@@ -104,6 +106,8 @@
 import org.apache.tapestry.internal.services.StaticFilesFilter;
 import org.apache.tapestry.internal.services.StringEventHandler;
 import org.apache.tapestry.internal.services.SupportsInformalParametersWorker;
+import org.apache.tapestry.internal.services.TranslatorDefaultSourceImpl;
+import org.apache.tapestry.internal.services.TranslatorSourceImpl;
 import org.apache.tapestry.internal.services.UnclaimedFieldWorker;
 import org.apache.tapestry.internal.services.UpdateListenerHub;
 import org.apache.tapestry.internal.services.ValidationMessagesSourceImpl;
@@ -130,6 +134,8 @@
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.util.StrategyRegistry;
 import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.translator.IntegerTranslator;
+import org.apache.tapestry.translator.StringTranslator;
 import org.apache.tapestry.validator.Required;
 
 /**
@@ -159,6 +165,8 @@
 
     private final StrategyBuilder _strategyBuilder;
 
+    private final ComponentInstantiatorSource _componentInstantiatorSource;
+
     // Yes, you can inject services defined by this module into this module. The service proxy is
     // created without instantiating the module itself. We're careful about making as many
     // service builder and contributor methods static as possible to avoid recursive build
@@ -174,7 +182,9 @@
     PageResponseRenderer pageResponseRenderer, @Inject("infrastructure:Request")
     Request request, @Inject("infrastructure:Environment")
     Environment environment, @InjectService("tapestry.ioc.StrategyBuilder")
-    StrategyBuilder strategyBuilder)
+    StrategyBuilder strategyBuilder,
+            @InjectService("tapestry.internal.ComponentInstantiatorSource")
+            ComponentInstantiatorSource componentInstantiatorSource)
     {
         _pipelineBuilder = pipelineBuilder;
         _shadowBuilder = shadowBuilder;
@@ -186,6 +196,7 @@
         _request = request;
         _environment = environment;
         _strategyBuilder = strategyBuilder;
+        _componentInstantiatorSource = componentInstantiatorSource;
     }
 
     /**
@@ -441,6 +452,8 @@
                 Request.class,
                 Response.class,
                 ValidationMessagesSource.class,
+                TranslatorSource.class,
+                TranslatorDefaultSource.class,
                 FieldValidatorSource.class);
 
         configuration.add(new InfrastructureContribution("TypeCoercer", typeCoercer));
@@ -500,15 +513,15 @@
         return new ActionLinkHandlerImpl(componentEventHandler, _requestPageCache, linkFactory);
     }
 
-    public static ComponentClassResolver buildComponentClassResolver(
-            @InjectService("tapestry.internal.ComponentInstantiatorSource")
-            ComponentInstantiatorSource source, Collection<LibraryMapping> configuration)
+    public ComponentClassResolver buildComponentClassResolver(
+            Collection<LibraryMapping> configuration)
     {
-        ComponentClassResolverImpl service = new ComponentClassResolverImpl(source, configuration);
+        ComponentClassResolverImpl service = new ComponentClassResolverImpl(
+                _componentInstantiatorSource, configuration);
 
         // Allow the resolver to clean its cache when the source is invalidated
 
-        source.addInvalidationListener(service);
+        _componentInstantiatorSource.addInvalidationListener(service);
 
         return service;
     }
@@ -525,30 +538,33 @@
 
     /**
      * Contributes the factory for serveral built-in binding prefixes ("literal", prop", "component"
-     * "message" and "validate").
+     * "message", "validate", "translate").
      */
     public static void contributeBindingSource(
             MappedConfiguration<String, BindingFactory> configuration,
             @InjectService("tapestry.internal.PropBindingFactory")
             BindingFactory propBindingFactory, @Inject("infrastructure:FieldValidatorSource")
-            FieldValidatorSource fieldValidatorSource)
+            FieldValidatorSource fieldValidatorSource, @Inject("infrastructure:TranslatorSource")
+            TranslatorSource translatorSource)
     {
         configuration.add(InternalConstants.LITERAL_BINDING_PREFIX, new LiteralBindingFactory());
         configuration.add(InternalConstants.PROP_BINDING_PREFIX, propBindingFactory);
         configuration.add("component", new ComponentBindingFactory());
         configuration.add("message", new MessageBindingFactory());
         configuration.add("validate", new ValidateBindingFactory(fieldValidatorSource));
+        configuration.add("translate", new TranslateBindingFactory(translatorSource));
     }
 
     /**
      * Returns a {@link ClassFactory} that can be used to create extra classes around component
      * classes.
      */
-    public ClassFactory buildComponentClassFactory(
-            @InjectService("tapestry.internal.ComponentInstantiatorSource")
-            ComponentInstantiatorSource source)
+    public ClassFactory buildComponentClassFactory()
     {
-        return _shadowBuilder.build(source, "classFactory", ClassFactory.class);
+        return _shadowBuilder.build(
+                _componentInstantiatorSource,
+                "classFactory",
+                ClassFactory.class);
     }
 
     /**
@@ -894,5 +910,52 @@
             MappedConfiguration<String, Validator> configuration)
     {
         configuration.add("required", new Required());
+    }
+
+    public static TranslatorSource buildTranslatorSource(Map<String, Translator> configuration)
+    {
+        return new TranslatorSourceImpl(configuration);
+    }
+
+    public TranslatorDefaultSource buildTranslatorDefaultSource(Map<Class, Translator> configuration)
+    {
+        TranslatorDefaultSourceImpl service = new TranslatorDefaultSourceImpl(configuration);
+
+        _componentInstantiatorSource.addInvalidationListener(service);
+
+        return service;
+    }
+
+    /**
+     * Contributes the basic set of named translators:
+     * <ul>
+     * <li>integer</li>
+     * <li>string</li>
+     * </ul>
+     */
+    public static void contributeTranslatorSource(
+            MappedConfiguration<String, Translator> configuration)
+    {
+        // Fortunately, the translators are tiny, so we don't have to worry about the slight
+        // duplication between this and TranslatorDefaultSource, though it is a pain to keep the two
+        // organized (perhaps they should be joined together into a single service, where we
+        // identify a name and a match type).
+
+        configuration.add("integer", new IntegerTranslator());
+        configuration.add("string", new StringTranslator());
+    }
+
+    /**
+     * Contributes the basic set of default translators:
+     * <ul>
+     * <li>Integer</li>
+     * <li>String</li>
+     * </li>
+     */
+    public static void contributeTranslatorDefaultSource(
+            MappedConfiguration<Class, Translator> configuration)
+    {
+        configuration.add(Integer.class, new IntegerTranslator());
+        configuration.add(String.class, new StringTranslator());
     }
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorDefaultSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorDefaultSource.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorDefaultSource.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorDefaultSource.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,23 @@
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.Translator;
+
+/**
+ * Used by certain form-control element component to obtain a default translator appropriate to the
+ * type of property editted by the component.
+ */
+public interface TranslatorDefaultSource
+{
+    /**
+     * Finds a {@link Translator} that is appropriate to the given type, which is usually obtained
+     * via {@link Binding#getBindingType()}. Performs an inheritanced-based search for the best
+     * match.
+     * 
+     * @param valueType
+     *            the type of value for which a default translator is needed
+     * @return the matching translator
+     * @throws IllegalArgumentException
+     *             if no translator may be found
+     */
+    Translator find(Class valueType);
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorSource.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorSource.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TranslatorSource.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,20 @@
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.Translator;
+
+/**
+ * A source for {@link Translator}s, either by name.
+ */
+public interface TranslatorSource
+{
+    /**
+     * Returns the translator with the given logical name.
+     * 
+     * @param name
+     *            name of translator (as configured)
+     * @return the shared translator instance
+     * @throws RuntimeException
+     *             if no translator is configured for the provided name
+     */
+    Translator get(String name);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Thu Jan  4 11:42:33 2007
@@ -37,6 +37,7 @@
 import org.apache.tapestry.ComponentResourcesCommon;
 import org.apache.tapestry.FieldValidator;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.Translator;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
@@ -592,5 +593,10 @@
     protected final AssetSource newAssetSource()
     {
         return newMock(AssetSource.class);
+    }
+
+    protected final Translator newTranslator()
+    {
+        return newMock(Translator.class);
     }
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/IntegerTranslator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/IntegerTranslator.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/IntegerTranslator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/IntegerTranslator.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,44 @@
+package org.apache.tapestry.translator;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ValidationException;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+
+/**
+ * A translator for type integer.
+ */
+public final class IntegerTranslator implements Translator<Integer>
+{
+    /**
+     * Parses blank values to null, otherwise parses the client value to an integer.
+     * 
+     * @throws ValidationException
+     *             if the clientValue can not be parsed as an integer
+     */
+    public Integer parseClient(String clientValue, Messages messages) throws ValidationException
+    {
+        if (InternalUtils.isBlank(clientValue))
+            return null;
+
+        try
+        {
+            // TODO: Should we trim the client value, or let that be handled upstream?
+
+            return Integer.parseInt(clientValue);
+        }
+        catch (NumberFormatException ex)
+        {
+            throw new ValidationException(messages.format("integer-format-exception", clientValue));
+        }
+    }
+
+    /**
+     * Converts null to the blank string, non-null to a string representation.
+     */
+    public String toClient(Integer value)
+    {
+        return value == null ? "" : value.toString();
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/StringTranslator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/StringTranslator.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/StringTranslator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/translator/StringTranslator.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,21 @@
+package org.apache.tapestry.translator;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ValidationException;
+import org.apache.tapestry.ioc.Messages;
+
+public class StringTranslator implements Translator<String>
+{
+    /** Returns the client value (or the empty string, if the client value is null). */
+    public String parseClient(String clientValue, Messages messages) throws ValidationException
+    {
+        return clientValue == null ? "" : clientValue;
+    }
+
+    /** Returns the value, or the empty string if value is null. */
+    public String toClient(String value)
+    {
+        return value == null ? "" : value;
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties Thu Jan  4 11:42:33 2007
@@ -13,3 +13,4 @@
 # limitations under the License.
 
 required=You must provide a value for %s.
+integer-format-exception=The input value '%s' is not parseable as an integer value. 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Thu Jan  4 11:42:33 2007
@@ -67,4 +67,5 @@
 component-not-assignable-to-field=Component %s is not assignable to field %s (of type %s).
 unknown-validator-type=Unknown validator type '%s'.  Configured validators are %s.
 validator-specification-parse-error=Unexpected character '%s' at position %d of input string: %s
-unexpected-tapestry-attribute=Attribute '%s' is not defined in the Tapestry template schema.
\ No newline at end of file
+unexpected-tapestry-attribute=Attribute '%s' is not defined in the Tapestry template schema.
+unknown-translator-type=Unknown translator type '%s'.  Configured translators are %s.
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt Thu Jan  4 11:42:33 2007
@@ -125,6 +125,8 @@
 *------------+----------------------------------------------------------------------------------+
 | prop:      | The name of a property of the containing component to read or update.            |
 *------------+----------------------------------------------------------------------------------+
+| translate: | The name of a configured translator.                                             |
+*------------+----------------------------------------------------------------------------------+
 | validate:  | A <validator specification> used to create some number of field validators.      |
 *------------+----------------------------------------------------------------------------------+
 
@@ -163,7 +165,7 @@
   
   Such values are read only and invariant.
   
-Validator Bindings
+Validate Bindings
 
   The "validate:" binding prefix is highly specialized. It allows a short string to be
   used to create and configure the objects that perform input validation for 
@@ -180,6 +182,16 @@
   TODO: More ability to escape or quote constraint values. Ability to reference methods
   or properties of the container to perform some of the validation.  Links to
   proper discussion of validation, once the code and documentation is ready.
+  
+Translate Bindings
+
+  The "translate:" binding prefix is also related to input validator. It is the name
+  of a configured {{{../apidocs/org/apache/tapestry/Translator.html}Translator}}, responsible
+  for converting between server-side and client-side representations of data (for instance, between
+  client-side strings and server-side numeric values).
+  
+  The list of available translators is configured by the
+  {{{../apidocs/org/apache/tapestry/services/TranslatorSource.html}TranslatorSource}} service.  
   
 Parameters Are Bi-Directional
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Thu Jan  4 11:42:33 2007
@@ -34,6 +34,7 @@
       <package name="org.apache.tapestry.runtime"/>
       <package name="org.apache.tapestry.internal.bindings"/>
       <package name="org.apache.tapestry.internal.model"/>
+      <package name="org.apache.tapestry.translator"/>
       <package name="org.apache.tapestry.validator"/>
     </packages>
   </test>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java Thu Jan  4 11:42:33 2007
@@ -12,53 +12,79 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.bindings;
-
-import org.apache.tapestry.ComponentResources;
-import org.apache.tapestry.internal.test.InternalBaseTestCase;
+package org.apache.tapestry.internal.bindings;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.internal.util.TapestryException;
 import org.apache.tapestry.services.Binding;
-import org.apache.tapestry.services.BindingFactory;
-import org.testng.annotations.Test;
-
-/**
- * Tests for several of the simpler binding factories.
- * 
- * 
- */
-public class BindingFactoryTest extends InternalBaseTestCase
-{
-
-    @Test
-    public void literal_binding()
-    {
-        ComponentResources res = newInternalComponentResources();
-        Location l = newLocation();
-
-        replay();
-
-        BindingFactory factory = new LiteralBindingFactory();
-
-        Binding b = factory.newBinding("test binding", res, null, "Tapestry5", l);
-
-        assertSame(InternalUtils.locationOf(b), l);
-
-        assertEquals(b.get(), "Tapestry5");
-        assertTrue(b.isInvariant());
-        assertSame(b.getBindingType(), String.class);
-
-        try
-        {
-            b.set(null);
-            unreachable();
-        }
-        catch (TapestryException ex)
-        {
-            assertSame(ex.getLocation(), l);
-        }
-
-        verify();
-    }
-}
+import org.apache.tapestry.services.BindingFactory;
+import org.apache.tapestry.services.TranslatorSource;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for several of the simpler binding factories.
+ */
+public class BindingFactoryTest extends InternalBaseTestCase
+{
+
+    @Test
+    public void literal_binding()
+    {
+        ComponentResources res = newInternalComponentResources();
+        Location l = newLocation();
+
+        replay();
+
+        BindingFactory factory = new LiteralBindingFactory();
+
+        Binding b = factory.newBinding("test binding", res, null, "Tapestry5", l);
+
+        assertSame(InternalUtils.locationOf(b), l);
+
+        assertEquals(b.get(), "Tapestry5");
+        assertTrue(b.isInvariant());
+        assertSame(b.getBindingType(), String.class);
+
+        try
+        {
+            b.set(null);
+            unreachable();
+        }
+        catch (TapestryException ex)
+        {
+            assertSame(ex.getLocation(), l);
+        }
+
+        verify();
+    }
+
+    @Test
+    public void translate_binding()
+    {
+        Translator translator = newTranslator();
+        TranslatorSource source = newMock(TranslatorSource.class);
+        ComponentResources resources = newComponentResources();
+        Location l = newLocation();
+
+        String description = "foo bar";
+        String expression = "mock";
+
+        expect(source.get(expression)).andReturn(translator);
+
+        replay();
+
+        BindingFactory factory = new TranslateBindingFactory(source);
+
+        Binding binding = factory.newBinding(description, resources, resources, expression, l);
+
+        assertSame(binding.get(), translator);
+
+        assertSame(InternalUtils.locationOf(binding), l);
+
+        verify();
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java?view=diff&rev=492704&r1=492703&r2=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImplTest.java Thu Jan  4 11:42:33 2007
@@ -12,290 +12,290 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.services;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLConnection;
-import java.util.UUID;
-
-import javassist.CannotCompileException;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtMethod;
-import javassist.CtNewMethod;
-import javassist.LoaderClassPath;
-import javassist.NotFoundException;
-
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.internal.InternalComponentResources;
-import org.apache.tapestry.internal.test.InternalBaseTestCase;
-import org.apache.tapestry.internal.transform.pages.BasicComponent;
-import org.apache.tapestry.internal.transform.pages.BasicSubComponent;
-import org.apache.tapestry.ioc.Registry;
-import org.apache.tapestry.ioc.RegistryBuilder;
-import org.apache.tapestry.ioc.services.PropertyAccess;
-import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.Infrastructure;
-import org.apache.tapestry.services.TapestryModule;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests for {@link org.apache.tapestry.internal.services.ComponentInstantiatorSourceImpl}. Several
- * of these tests are more of the form of integration tests that instantiate the Tapestry IoC
- * Registry.
- */
-public class ComponentInstantiatorSourceImplTest extends InternalBaseTestCase
-{
-    private static final ClassLoader _contextLoader = Thread.currentThread()
-            .getContextClassLoader();
-
-    private static final String SYNTH_COMPONENT_CLASSNAME = "org.apache.tapestry.internal.transform.pages.SynthComponent";
-
-    private File _extraClasspath;
-
-    private ComponentInstantiatorSource _source;
-
-    private Registry _registry;
-
-    private PropertyAccess _access;
-
-    private ClassLoader _extraLoader;
-
-    private String _tempDir;
-
-    @Test
-    public void controlled_packages() throws Exception
-    {
-        ComponentClassTransformer transformer = newMock(ComponentClassTransformer.class);
-        Log log = newLog();
-
-        replay();
-
-        ComponentInstantiatorSourceImpl e = new ComponentInstantiatorSourceImpl(_contextLoader,
-                transformer, log);
-
-        assertEquals(e.inControlledPackage("foo.bar.Baz"), false);
-
-        // Check that classes in the default package are never controlled
-
-        assertEquals(e.inControlledPackage("Biff"), false);
-
-        // Now add a controlled package
-
-        e.addPackage("foo.bar");
-
-        assertEquals(e.inControlledPackage("foo.bar.Baz"), true);
-
-        // Sub-packages of controlled packages are controlled as well
-
-        assertEquals(e.inControlledPackage("foo.bar.biff.Pop"), true);
-
-        // Parents of controlled packages are not controlled
-
-        assertEquals(e.inControlledPackage("foo.Gloop"), false);
-
-        verify();
-    }
-
-    /** More of an integration test. */
-    @Test
-    public void load_component_via_service() throws Exception
-    {
-        Component target = createComponent(BasicComponent.class);
-
-        // Should not be an instance, since it is loaded by a different class loader.
-        assertFalse(BasicComponent.class.isInstance(target));
-
-        _access.set(target, "value", "some default value");
-        assertEquals(_access.get(target, "value"), "some default value");
-
-        _access.set(target, "retainedValue", "some retained value");
-        assertEquals(_access.get(target, "retainedValue"), "some retained value");
-
-        // Setting a property value before pageDidLoad will cause that value
-        // to be the default when the page detaches.
-
-        target.containingPageDidLoad();
-
-        _access.set(target, "value", "some transient value");
-        assertEquals(_access.get(target, "value"), "some transient value");
-
-        target.containingPageDidDetach();
-
-        assertEquals(_access.get(target, "value"), "some default value");
-        assertEquals(_access.get(target, "retainedValue"), "some retained value");
-    }
-
-    @Test
-    public void load_sub_component_via_service() throws Exception
-    {
-        Component target = createComponent(BasicSubComponent.class);
-
-        target.containingPageDidLoad();
-
-        _access.set(target, "value", "base class");
-        assertEquals(_access.get(target, "value"), "base class");
-
-        _access.set(target, "intValue", 33);
-        assertEquals(_access.get(target, "intValue"), 33);
-
-        target.containingPageDidDetach();
-
-        assertNull(_access.get(target, "value"));
-        assertEquals(_access.get(target, "intValue"), 0);
-    }
-
-    /**
-     * This allows tests the exists() method.
-     */
-    @Test
-    public void component_class_reload() throws Exception
-    {
-        // Ensure it doesn't already exist:
-
-        assertFalse(_source.exists(SYNTH_COMPONENT_CLASSNAME));
-
-        // Create the class on the fly.
-
-        createSynthComponentClass("Original");
-
-        assertTrue(_source.exists(SYNTH_COMPONENT_CLASSNAME));
-
-        Named named = (Named) createComponent(SYNTH_COMPONENT_CLASSNAME);
-
-        assertEquals(named.getName(), "Original");
-
-        String path = _tempDir + "/" + SYNTH_COMPONENT_CLASSNAME.replace('.', '/') + ".class";
-        URL url = new File(path).toURL();
-
-        long dtm = readDTM(url);
-
-        while (true)
-        {
-            if (readDTM(url) != dtm)
-                break;
-            
-            // Keep re-writing the file until we see the DTM change.
-            
-            createSynthComponentClass("Updated");
-        }
-
-        // Detect the change and clear out the internal caches
-
-        UpdateListenerHub hub = _registry.getService(
-                "tapestry.internal.UpdateListenerHub",
-                UpdateListenerHub.class);
-
-        hub.fireUpdateEvent();
-
-        // This will be the new version of the class
-
-        named = (Named) createComponent(SYNTH_COMPONENT_CLASSNAME);
-
-        assertEquals(named.getName(), "Updated");
-    }
-
-    private long readDTM(URL url) throws Exception
-    {
-        URLConnection connection = url.openConnection();
-
-        connection.connect();
-
-        return connection.getLastModified();
-    }
-
-    private void createSynthComponentClass(String name) throws CannotCompileException,
-            NotFoundException, IOException
-    {
-        ClassPool pool = new ClassPool();
-        // Inside Maven Surefire, the system classpath is not sufficient to find all
-        // the necessary files.
-        pool.appendClassPath(new LoaderClassPath(_extraLoader));
-
-        CtClass ctClass = pool.makeClass(SYNTH_COMPONENT_CLASSNAME);
-
-        ctClass.setSuperclass(pool.get(BasicComponent.class.getName()));
-
-        // Implement method getName()
-
-        CtMethod method = CtNewMethod.make(
-                "public String getName() { return \"" + name + "\"; }",
-                ctClass);
-        ctClass.addMethod(method);
-
-        ctClass.addInterface(pool.get(Named.class.getName()));
-
-        ctClass.writeFile(_extraClasspath.getAbsolutePath());
-    }
-
-    private Component createComponent(Class componentClass)
-    {
-        String classname = componentClass.getName();
-
-        return createComponent(classname);
-    }
-
-    private Component createComponent(String classname)
-    {
-        InternalComponentResources resources = newInternalComponentResources();
-
-        replay();
-
-        // Can't wait for the HiveMind code base to start using some generics for this kind of
-        // thing.
-
-        Instantiator inst = _source.findInstantiator(classname);
-
-        Component target = inst.newInstance(resources);
-
-        verify();
-
-        return target;
-    }
-
-    @BeforeClass
-    public void setup_tests() throws Exception
-    {
-        String tempdir = System.getProperty("java.io.tmpdir");
-        String uid = UUID.randomUUID().toString();
-
-        _tempDir = tempdir + "/" + uid;
-        _extraClasspath = new File(_tempDir);
-
-        System.out.println("Creating dir: " + _extraClasspath);
-
-        _extraClasspath.mkdirs();
-
-        URL url = _extraClasspath.toURL();
-
-        _extraLoader = new URLClassLoader(new URL[]
-        { url }, _contextLoader);
-        RegistryBuilder builder = new RegistryBuilder(_extraLoader);
-
-        builder.add(TapestryModule.class);
-
-        _registry = builder.build();
-
-        _registry.getService("tapestry.Infrastructure", Infrastructure.class).setMode("servlet");
-
-        _source = _registry.getService(ComponentInstantiatorSource.class);
-        _access = _registry.getService(PropertyAccess.class);
-
-        _source.addPackage("org.apache.tapestry.internal.transform.pages");
-    }
-
-    @AfterClass
-    public void cleanup_tests()
-    {
-        _registry.shutdown();
-
-        _registry = null;
-        _source = null;
-        _access = null;
-    }
-}
+package org.apache.tapestry.internal.services;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.util.UUID;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.CtNewMethod;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.internal.transform.pages.BasicComponent;
+import org.apache.tapestry.internal.transform.pages.BasicSubComponent;
+import org.apache.tapestry.ioc.Registry;
+import org.apache.tapestry.ioc.RegistryBuilder;
+import org.apache.tapestry.ioc.services.PropertyAccess;
+import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.Infrastructure;
+import org.apache.tapestry.services.TapestryModule;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for {@link org.apache.tapestry.internal.services.ComponentInstantiatorSourceImpl}. Several
+ * of these tests are more of the form of integration tests that instantiate the Tapestry IoC
+ * Registry.
+ */
+public class ComponentInstantiatorSourceImplTest extends InternalBaseTestCase
+{
+    private static final ClassLoader _contextLoader = Thread.currentThread()
+            .getContextClassLoader();
+
+    private static final String SYNTH_COMPONENT_CLASSNAME = "org.apache.tapestry.internal.transform.pages.SynthComponent";
+
+    private File _extraClasspath;
+
+    private ComponentInstantiatorSource _source;
+
+    private Registry _registry;
+
+    private PropertyAccess _access;
+
+    private ClassLoader _extraLoader;
+
+    private String _tempDir;
+
+    @Test
+    public void controlled_packages() throws Exception
+    {
+        ComponentClassTransformer transformer = newMock(ComponentClassTransformer.class);
+        Log log = newLog();
+
+        replay();
+
+        ComponentInstantiatorSourceImpl e = new ComponentInstantiatorSourceImpl(_contextLoader,
+                transformer, log);
+
+        assertEquals(e.inControlledPackage("foo.bar.Baz"), false);
+
+        // Check that classes in the default package are never controlled
+
+        assertEquals(e.inControlledPackage("Biff"), false);
+
+        // Now add a controlled package
+
+        e.addPackage("foo.bar");
+
+        assertEquals(e.inControlledPackage("foo.bar.Baz"), true);
+
+        // Sub-packages of controlled packages are controlled as well
+
+        assertEquals(e.inControlledPackage("foo.bar.biff.Pop"), true);
+
+        // Parents of controlled packages are not controlled
+
+        assertEquals(e.inControlledPackage("foo.Gloop"), false);
+
+        verify();
+    }
+
+    /** More of an integration test. */
+    @Test
+    public void load_component_via_service() throws Exception
+    {
+        Component target = createComponent(BasicComponent.class);
+
+        // Should not be an instance, since it is loaded by a different class loader.
+        assertFalse(BasicComponent.class.isInstance(target));
+
+        _access.set(target, "value", "some default value");
+        assertEquals(_access.get(target, "value"), "some default value");
+
+        _access.set(target, "retainedValue", "some retained value");
+        assertEquals(_access.get(target, "retainedValue"), "some retained value");
+
+        // Setting a property value before pageDidLoad will cause that value
+        // to be the default when the page detaches.
+
+        target.containingPageDidLoad();
+
+        _access.set(target, "value", "some transient value");
+        assertEquals(_access.get(target, "value"), "some transient value");
+
+        target.containingPageDidDetach();
+
+        assertEquals(_access.get(target, "value"), "some default value");
+        assertEquals(_access.get(target, "retainedValue"), "some retained value");
+    }
+
+    @Test
+    public void load_sub_component_via_service() throws Exception
+    {
+        Component target = createComponent(BasicSubComponent.class);
+
+        target.containingPageDidLoad();
+
+        _access.set(target, "value", "base class");
+        assertEquals(_access.get(target, "value"), "base class");
+
+        _access.set(target, "intValue", 33);
+        assertEquals(_access.get(target, "intValue"), 33);
+
+        target.containingPageDidDetach();
+
+        assertNull(_access.get(target, "value"));
+        assertEquals(_access.get(target, "intValue"), 0);
+    }
+
+    /**
+     * This allows tests the exists() method.
+     */
+    @Test
+    public void component_class_reload() throws Exception
+    {
+        // Ensure it doesn't already exist:
+
+        assertFalse(_source.exists(SYNTH_COMPONENT_CLASSNAME));
+
+        // Create the class on the fly.
+
+        createSynthComponentClass("Original");
+
+        assertTrue(_source.exists(SYNTH_COMPONENT_CLASSNAME));
+
+        Named named = (Named) createComponent(SYNTH_COMPONENT_CLASSNAME);
+
+        assertEquals(named.getName(), "Original");
+
+        String path = _tempDir + "/" + SYNTH_COMPONENT_CLASSNAME.replace('.', '/') + ".class";
+        URL url = new File(path).toURL();
+
+        long dtm = readDTM(url);
+
+        while (true)
+        {
+            if (readDTM(url) != dtm)
+                break;
+
+            // Keep re-writing the file until we see the DTM change.
+
+            createSynthComponentClass("Updated");
+        }
+
+        // Detect the change and clear out the internal caches
+
+        UpdateListenerHub hub = _registry.getService(
+                "tapestry.internal.UpdateListenerHub",
+                UpdateListenerHub.class);
+
+        hub.fireUpdateEvent();
+
+        // This will be the new version of the class
+
+        named = (Named) createComponent(SYNTH_COMPONENT_CLASSNAME);
+
+        assertEquals(named.getName(), "Updated");
+    }
+
+    private long readDTM(URL url) throws Exception
+    {
+        URLConnection connection = url.openConnection();
+
+        connection.connect();
+
+        return connection.getLastModified();
+    }
+
+    private void createSynthComponentClass(String name) throws CannotCompileException,
+            NotFoundException, IOException
+    {
+        ClassPool pool = new ClassPool();
+        // Inside Maven Surefire, the system classpath is not sufficient to find all
+        // the necessary files.
+        pool.appendClassPath(new LoaderClassPath(_extraLoader));
+
+        CtClass ctClass = pool.makeClass(SYNTH_COMPONENT_CLASSNAME);
+
+        ctClass.setSuperclass(pool.get(BasicComponent.class.getName()));
+
+        // Implement method getName()
+
+        CtMethod method = CtNewMethod.make(
+                "public String getName() { return \"" + name + "\"; }",
+                ctClass);
+        ctClass.addMethod(method);
+
+        ctClass.addInterface(pool.get(Named.class.getName()));
+
+        ctClass.writeFile(_extraClasspath.getAbsolutePath());
+    }
+
+    private Component createComponent(Class componentClass)
+    {
+        String classname = componentClass.getName();
+
+        return createComponent(classname);
+    }
+
+    private Component createComponent(String classname)
+    {
+        InternalComponentResources resources = newInternalComponentResources();
+
+        replay();
+
+        // Can't wait for the HiveMind code base to start using some generics for this kind of
+        // thing.
+
+        Instantiator inst = _source.findInstantiator(classname);
+
+        Component target = inst.newInstance(resources);
+
+        verify();
+
+        return target;
+    }
+
+    @BeforeClass
+    public void setup_tests() throws Exception
+    {
+        String tempdir = System.getProperty("java.io.tmpdir");
+        String uid = UUID.randomUUID().toString();
+
+        _tempDir = tempdir + "/tapestry-test-classpath/" + uid;
+        _extraClasspath = new File(_tempDir);
+
+        System.out.println("Creating dir: " + _extraClasspath);
+
+        _extraClasspath.mkdirs();
+
+        URL url = _extraClasspath.toURL();
+
+        _extraLoader = new URLClassLoader(new URL[]
+        { url }, _contextLoader);
+        RegistryBuilder builder = new RegistryBuilder(_extraLoader);
+
+        builder.add(TapestryModule.class);
+
+        _registry = builder.build();
+
+        _registry.getService("tapestry.Infrastructure", Infrastructure.class).setMode("servlet");
+
+        _source = _registry.getService(ComponentInstantiatorSource.class);
+        _access = _registry.getService(PropertyAccess.class);
+
+        _source.addPackage("org.apache.tapestry.internal.transform.pages");
+    }
+
+    @AfterClass
+    public void cleanup_tests()
+    {
+        _registry.shutdown();
+
+        _registry = null;
+        _source = null;
+        _access = null;
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/TranslatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/TranslatorSourceImplTest.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/TranslatorSourceImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/TranslatorSourceImplTest.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,58 @@
+package org.apache.tapestry.internal.services;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry.services.TranslatorSource;
+import org.testng.annotations.Test;
+
+public class TranslatorSourceImplTest extends InternalBaseTestCase
+{
+    @Test
+    public void found_translator_by_name()
+    {
+        Translator translator = newTranslator();
+
+        Map<String, Translator> configuration = Collections.singletonMap("mock", translator);
+
+        replay();
+
+        TranslatorSource source = new TranslatorSourceImpl(configuration);
+
+        assertSame(source.get("mock"), translator);
+
+        verify();
+    }
+
+    @Test
+    public void unknown_translator_is_failure()
+    {
+        Translator fred = newTranslator();
+        Translator barney = newTranslator();
+
+        Map<String, Translator> configuration = CollectionFactory.newMap();
+
+        configuration.put("fred", fred);
+        configuration.put("barney", barney);
+
+        replay();
+
+        TranslatorSource source = new TranslatorSourceImpl(configuration);
+
+        try
+        {
+            source.get("wilma");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "Unknown translator type 'wilma'.  Configured translators are barney, fred.");
+        }
+
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/IntegerTranslatorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/IntegerTranslatorTest.java?view=auto&rev=492704
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/IntegerTranslatorTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/translator/IntegerTranslatorTest.java Thu Jan  4 11:42:33 2007
@@ -0,0 +1,68 @@
+package org.apache.tapestry.translator;
+
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.ValidationException;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.Messages;
+import org.testng.annotations.Test;
+
+public class IntegerTranslatorTest extends InternalBaseTestCase
+{
+    @Test
+    public void parse_invalid_format()
+    {
+        Messages messages = validationMessages();
+
+        Translator<Integer> translator = new IntegerTranslator();
+
+        try
+        {
+            translator.parseClient("xyz", messages);
+            unreachable();
+        }
+        catch (ValidationException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "The input value 'xyz' is not parseable as an integer value. ");
+        }
+    }
+
+    @Test
+    public void blank_parses_to_null() throws Exception
+    {
+        Messages messages = validationMessages();
+
+        Translator<Integer> translator = new IntegerTranslator();
+
+        assertNull(translator.parseClient("", messages));
+    }
+
+    @Test
+    public void null_converts_to_client_as_blank()
+    {
+
+        Translator<Integer> translator = new IntegerTranslator();
+
+        assertEquals(translator.toClient(null), "");
+    }
+
+    @Test
+    public void convert_non_null()
+    {
+
+        Translator<Integer> translator = new IntegerTranslator();
+
+        assertEquals(translator.toClient(37), "37");
+    }
+
+    @Test
+    public void successful_parse_from_client() throws Exception
+    {
+        Messages messages = validationMessages();
+
+        Translator<Integer> translator = new IntegerTranslator();
+
+        assertEquals(translator.parseClient("-23823", messages), new Integer(-23823));
+    }
+}



Mime
View raw message