You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/09/04 01:38:48 UTC

svn commit: r572450 - in /tapestry/tapestry5/trunk: ./ support/ tapestry-core/src/main/java/org/apache/tapestry/annotations/ tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ tapestry-core/src/main/java/org/apache/tapestry/services/ t...

Author: hlship
Date: Mon Sep  3 16:38:47 2007
New Revision: 572450

URL: http://svn.apache.org/viewvc?rev=572450&view=rev
Log:
TAPESTRY-1676: Add component for editing a single bean property

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/PropertyEditor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/PropertyEditor.properties
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/PropertyEditorTest.java
Modified:
    tapestry/tapestry5/trunk/pom.xml
    tapestry/tapestry5/trunk/support/tapestry-core.launch
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Mixin.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PropertyEditContext.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.html
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.properties
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/beaneditform.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/BeanEditFormTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java

Modified: tapestry/tapestry5/trunk/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/pom.xml?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/pom.xml (original)
+++ tapestry/tapestry5/trunk/pom.xml Mon Sep  3 16:38:47 2007
@@ -235,6 +235,32 @@
         </plugins>
       </build>
     </profile>
+    <!--  Only enable Javadoc as part of the output site when the release profile is active. -->
+    <profile>
+      <id>release</id>
+      <reporting>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <configuration>
+              <linksource>true</linksource>
+              <links>
+                <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
+                <link>http://java.sun.com/j2ee/1.4/docs/api/</link>
+                <link>
+                  http://jakarta.apache.org/commons/logging/apidocs/
+                </link>
+              </links>
+              <stylesheetfile>
+                ${basedir}/src/site/resources/css/jdstyle.css
+              </stylesheetfile>
+              <aggregate>true</aggregate>
+            </configuration>
+          </plugin>
+        </plugins>
+      </reporting>
+    </profile>
   </profiles>
   <reporting>
     <plugins>
@@ -254,22 +280,6 @@
           </reportSet>
         </reportSets>
       </plugin>
-
-      <!--       
-        <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <configuration>
-        <linksource>true</linksource>
-        <links>
-        <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
-        <link>http://java.sun.com/j2ee/1.4/docs/api/</link>
-        <link>http://jakarta.apache.org/commons/logging/apidocs/</link>
-        </links>
-        <stylesheetfile>${basedir}/src/site/resources/css/jdstyle.css</stylesheetfile>
-        <aggregate>true</aggregate>
-        </configuration>
-        </plugin> -->
     </plugins>
   </reporting>
   <repositories>

Modified: tapestry/tapestry5/trunk/support/tapestry-core.launch
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/support/tapestry-core.launch?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/support/tapestry-core.launch (original)
+++ tapestry/tapestry5/trunk/support/tapestry-core.launch Mon Sep  3 16:38:47 2007
@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <launchConfiguration type="org.testng.eclipse.launchconfig">
+<booleanAttribute key="com.mountainminds.eclemma.core.INPLACE_INSTRUMENTATION" value="false"/>
+<listAttribute key="com.mountainminds.eclemma.core.INSTRUMENTATION_PATHS">
+<listEntry value="/tapestry5/bin"/>
+</listAttribute>
 <booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
 <listAttribute key="org.eclipse.debug.ui.favoriteGroups">
 <listEntry value="org.eclipse.debug.ui.launchGroup.run"/>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Mixin.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Mixin.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Mixin.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Mixin.java Mon Sep  3 16:38:47 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -22,7 +22,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Defines an <em>implementation</em> mixin for a comopnent.
+ * Defines an <em>implementation</em> mixin for a component.
  */
 @Target(FIELD)
 @Documented
@@ -30,7 +30,7 @@
 public @interface Mixin {
 
     /**
-     * Defines the type of mixin, using a logical mixin name. This value takes precendence over the
+     * Defines the type of mixin, using a logical mixin name. This value takes precedence over the
      * type of field (to which the annotation is attached). In such cases, it is presumed that the
      * field's type is an interface implemented by the actual mixin. The default value (the empty
      * string) directs Tapestry to use the field type as the mixin class to instantiate and attach

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java Mon Sep  3 16:38:47 2007
@@ -58,6 +58,7 @@
  * 
  * @see BeanModel
  * @see BeanModelSource
+ * @see PropertyEditor
  */
 @SupportsInformalParameters
 public class BeanEditForm implements ClientElement, FormValidationControl
@@ -67,7 +68,7 @@
     private String _submitLabel;
 
     /**
-     * The object to be editted by the BeanEditor. This will be read when the component renders and
+     * The object to be edited by the BeanEditor. This will be read when the component renders and
      * updated when the form for the component is submitted. Typically, the container will listen
      * for a "prepare" event, in order to ensure that a non-null value is ready to be read or
      * updated.
@@ -76,7 +77,8 @@
     private Object _object;
 
     /** If true, the default, then the embedded Form component will use client-side validation. */
-    @Parameter("true")
+    @SuppressWarnings("unused")
+    @Parameter
     private boolean _clientValidation;
 
     @Inject
@@ -85,23 +87,11 @@
     @Inject
     private BeanModelSource _modelSource;
 
-    @Inject
-    private TranslatorDefaultSource _translatorDefaultSource;
-
-    @Inject
-    private FieldValidatorDefaultSource _fieldValidatorDefaultSource;
-
-    @Component(parameters = "clientValidation=clientValidation")
+    @Component(parameters = "clientValidation=inherit:clientValidation")
     private Form _form;
 
-    @Inject
-    private Messages _messages;
-
-    @Inject
-    private Locale _locale;
-
     /**
-     * The model that identifies the parameters to be editted, their order, and every other aspect.
+     * The model that identifies the parameters to be edited, their order, and every other aspect.
      * If not specified, a default bean model will be created from the type of the object bound to
      * the object parameter.
      */
@@ -112,21 +102,9 @@
 
     private String _propertyName;
 
-    private PropertyModel _propertyEditModel;
-
-    private Block _blockForProperty;
-
-    @Inject
-    private Environment _environment;
-
-    @Inject
-    private BeanBlockSource _beanBlockSource;
-
     @Inject
     private ComponentDefaultProvider _defaultProvider;
 
-    private boolean _mustPopBeanEditContext;
-
     /**
      * Defaults the object parameter to a property of the container matching the BeanEditForm's id.
      */
@@ -149,88 +127,10 @@
     {
         _propertyName = propertyName;
 
-        _propertyEditModel = _model.get(propertyName);
-
-        _blockForProperty = null;
-
-        Block override = _resources.getBlockParameter(_propertyEditModel.getId());
-
-        if (override != null)
-        {
-            _blockForProperty = override;
-            return;
-        }
-
-        String dataType = _propertyEditModel.getDataType();
-
-        try
-        {
-            _blockForProperty = _beanBlockSource.getEditBlock(dataType);
-        }
-        catch (RuntimeException ex)
-        {
-            String message = _messages.format("block-error", _propertyName, dataType, _object, ex);
-
-            throw new TapestryException(message, _resources.getLocation(), ex);
-        }
     }
 
     boolean onPrepareFromForm()
     {
-        PropertyEditContext context = new PropertyEditContext()
-        {
-            public Messages getContainerMessages()
-            {
-                return _resources.getContainerMessages();
-            }
-
-            public String getLabel()
-            {
-                return _propertyEditModel.getLabel();
-            }
-
-            public String getPropertyId()
-            {
-                return _propertyEditModel.getId();
-            }
-
-            public Class getPropertyType()
-            {
-                return _propertyEditModel.getPropertyType();
-            }
-
-            public Object getPropertyValue()
-            {
-                return _propertyEditModel.getConduit().get(getObject());
-            }
-
-            public Translator getTranslator()
-            {
-                return _translatorDefaultSource.find(_propertyEditModel.getPropertyType());
-            }
-
-            public FieldValidator getValidator(Field field)
-            {
-                return _fieldValidatorDefaultSource.createDefaultValidator(
-                        field,
-                        _propertyName,
-                        _resources.getContainerMessages(),
-                        _locale,
-                        _propertyEditModel.getPropertyType(),
-                        _propertyEditModel.getConduit());
-            }
-
-            public void setPropertyValue(Object value)
-            {
-                _propertyEditModel.getConduit().set(getObject(), value);
-            }
-        };
-
-        _environment.push(PropertyEditContext.class, context);
-        // Depending on whether we're rendering or processing the form submission we'll have two
-        // different places to clean up the Environment.
-        _mustPopBeanEditContext = true;
-
         // Fire a new prepare event to be consumed by the container. This is the container's
         // chance to ensure that there's an object to edit.
 
@@ -239,7 +139,7 @@
         // Now check to see if the value is null.
 
         // The only problem here is that if the bound property is backed by a persistent field, it
-        // is assigned (and stored to the session, and propogated around the cluster) first,
+        // is assigned (and stored to the session, and propagated around the cluster) first,
         // before values are assigned.
 
         if (_object == null) _object = createDefaultObject();
@@ -253,37 +153,19 @@
             _model = _modelSource.create(beanType, true, _resources.getContainerResources());
         }
 
-        return true; // abort the form's prepare event
-    }
-
-    private void cleanupBeanEditContext()
-    {
-        if (_mustPopBeanEditContext)
-        {
-            _environment.pop(PropertyEditContext.class);
-            _mustPopBeanEditContext = false;
-        }
-    }
-
-    void onSubmit()
-    {
-        cleanupBeanEditContext();
-    }
-
-    void afterRender()
-    {
-        cleanupBeanEditContext();
+        // Abort the form's prepare event, as we've already sent a prepare on its behalf.
+        return true;
     }
 
     /** Used for testing. */
-    void inject(ComponentResources resources, BeanModelSource modelSource, Environment environment)
+    void inject(ComponentResources resources, BeanModelSource modelSource)
     {
         _resources = resources;
         _modelSource = modelSource;
-        _environment = environment;
     }
 
-    Object getObject()
+    /** Returns the object being edited. */
+    public Object getObject()
     {
         return _object;
     }
@@ -305,11 +187,6 @@
         }
     }
 
-    public Block getBlockForProperty()
-    {
-        return _blockForProperty;
-    }
-
     /** Returns the client id of the embedded form. */
     public String getClientId()
     {
@@ -319,11 +196,6 @@
     public String getSubmitLabel()
     {
         return _submitLabel;
-    }
-
-    public boolean getClientValidation()
-    {
-        return _clientValidation;
     }
 
     public void clearErrors()

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/PropertyEditor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/PropertyEditor.java?rev=572450&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/PropertyEditor.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/PropertyEditor.java Mon Sep  3 16:38:47 2007
@@ -0,0 +1,270 @@
+// Copyright 2007 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.tapestry.corelib.components;
+
+import java.util.Locale;
+
+import org.apache.tapestry.Block;
+import org.apache.tapestry.ComponentAction;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.Field;
+import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.Translator;
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.beaneditor.BeanModel;
+import org.apache.tapestry.beaneditor.PropertyModel;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.TapestryException;
+import org.apache.tapestry.services.BeanBlockSource;
+import org.apache.tapestry.services.Environment;
+import org.apache.tapestry.services.FieldValidatorDefaultSource;
+import org.apache.tapestry.services.FormSupport;
+import org.apache.tapestry.services.PropertyEditContext;
+import org.apache.tapestry.services.TranslatorDefaultSource;
+
+/**
+ * Used to edit a single property of a bean. This is used primarily by {@link BeanEditForm}. Unlike
+ * BeanEditForm, the object to be edited must already exist and the {@linkplain BeanModel model}
+ * must be passed in explicitly.
+ */
+public class PropertyEditor
+{
+    /**
+     * Configures and stores a {@link PropertyEditContext} into the {@link Environment}.
+     */
+    static class SetupEnvironment implements ComponentAction<PropertyEditor>
+    {
+        private static final long serialVersionUID = 5337049721509981997L;
+
+        private final String _property;
+
+        public SetupEnvironment(String property)
+        {
+            _property = property;
+        }
+
+        public void execute(PropertyEditor component)
+        {
+            component.setupEnvironment(_property);
+        }
+    };
+
+    static class CleanupEnvironment implements ComponentAction<PropertyEditor>
+    {
+        private static final long serialVersionUID = 7878694042753046523L;
+
+        public void execute(PropertyEditor component)
+        {
+            component.cleanupEnvironment();
+        }
+    };
+
+    /**
+     * The object to be edited by the BeanEditor. This will be read when the component renders and
+     * updated when the form for the component is submitted. Typically, the container will listen
+     * for a "prepare" event, in order to ensure that a non-null value is ready to be read or
+     * updated.
+     */
+    @Parameter(required = true)
+    private Object _object;
+
+    /**
+     * Where to search for local overrides of property editing blocks as block parameters. Further,
+     * the container of the overrides is used as the source for overridden validation messages. This
+     * is normally the component itself, but when the component is used within a BeanEditForm, it
+     * will be the BeanEditForm's block parameter that will be searched.
+     */
+    @Parameter(value = "componentResources")
+    private ComponentResources _overrides;
+
+    /**
+     * Identifies the property to be edited by the editor.
+     */
+    @Parameter(required = true)
+    private String _property;
+
+    /**
+     * The model that identifies the parameters to be edited, their order, and every other aspect.
+     */
+    @Parameter(required = true)
+    private BeanModel _model;
+
+    @Inject
+    private TranslatorDefaultSource _translatorDefaultSource;
+
+    @Inject
+    private FieldValidatorDefaultSource _fieldValidatorDefaultSource;
+
+    @Inject
+    private Environment _environment;
+
+    @Inject
+    private BeanBlockSource _beanBlockSource;
+
+    @Inject
+    private Messages _messages;
+
+    @Inject
+    private Locale _locale;
+
+    @Inject
+    private ComponentResources _resources;
+
+    @Environmental
+    private FormSupport _formSupport;
+
+    private PropertyModel _propertyModel;
+
+    /** Creates a {@link PropertyEditContext} and pushes it onto the {@link Environment} stack. */
+    void setupEnvironment(final String propertyName)
+    {
+        _propertyModel = _model.get(propertyName);
+
+        PropertyEditContext context = new PropertyEditContext()
+        {
+            public Messages getContainerMessages()
+            {
+                return _resources.getContainerMessages();
+            }
+
+            public String getLabel()
+            {
+                return _propertyModel.getLabel();
+            }
+
+            public String getPropertyId()
+            {
+                return _propertyModel.getId();
+            }
+
+            public Class getPropertyType()
+            {
+                return _propertyModel.getPropertyType();
+            }
+
+            public Object getPropertyValue()
+            {
+                return _propertyModel.getConduit().get(_object);
+            }
+
+            public Translator getTranslator()
+            {
+                return _translatorDefaultSource.find(_propertyModel.getPropertyType());
+            }
+
+            public FieldValidator getValidator(Field field)
+            {
+                return _fieldValidatorDefaultSource.createDefaultValidator(
+                        field,
+                        propertyName,
+                        _overrides.getContainerMessages(),
+                        _locale,
+                        _propertyModel.getPropertyType(),
+                        _propertyModel.getConduit());
+            }
+
+            public void setPropertyValue(Object value)
+            {
+                _propertyModel.getConduit().set(_object, value);
+            }
+        };
+
+        _environment.push(PropertyEditContext.class, context);
+    }
+
+    /**
+     * Called at the end of the form render (or at the end of the form submission) to clean up the
+     * {@link Environment} stack.
+     */
+    void cleanupEnvironment()
+    {
+        _environment.pop(PropertyEditContext.class);
+    }
+
+    /**
+     * Record into the Form what's needed to process the property.
+     */
+    void setupRender()
+    {
+        // Sets up the PropertyEditContext for the duration of the render of this component
+        // (which will include the duration of the editor block).
+
+        _formSupport.storeAndExecute(this, new SetupEnvironment(_property));
+    }
+
+    /**
+     * Records into the Form the cleanup logic for the property.
+     */
+    void cleanupRender()
+    {
+        // Removes the PropertyEditContext after this component (including the editor block)
+        // has rendered.
+
+        _formSupport.storeAndExecute(this, new CleanupEnvironment());
+    }
+
+    /**
+     * Returns a Block for rendering the property. The Block will be able to access the
+     * {@link PropertyEditContext} via the {@link Environmental} annotation.
+     */
+    Block beginRender()
+    {
+        Block override = _overrides.getBlockParameter(_propertyModel.getId());
+
+        if (override != null) { return override; }
+
+        String dataType = _propertyModel.getDataType();
+
+        try
+        {
+            return _beanBlockSource.getEditBlock(dataType);
+        }
+        catch (RuntimeException ex)
+        {
+            String message = _messages.format(
+                    "block-error",
+                    _propertyModel.getPropertyName(),
+                    dataType,
+                    _object,
+                    ex);
+
+            throw new TapestryException(message, _resources.getLocation(), ex);
+        }
+
+    }
+
+    /**
+     * Returns false, to prevent the rendering of the body of the component. PropertyEditor should
+     * not have a body.
+     */
+    boolean beforeRenderBody()
+    {
+        return false;
+    }
+
+    /** Used for testing. */
+    void inject(ComponentResources resources, ComponentResources overrides, PropertyModel propertyModel,
+            BeanBlockSource beanBlockSource, Messages messages, Object object)
+    {
+        _resources = resources;
+        _overrides = overrides;
+        _propertyModel = propertyModel;
+        _beanBlockSource = beanBlockSource;
+        _messages = messages;
+        _object = object;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PropertyEditContext.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PropertyEditContext.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PropertyEditContext.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PropertyEditContext.java Mon Sep  3 16:38:47 2007
@@ -24,7 +24,7 @@
 import org.apache.tapestry.ioc.Messages;
 
 /**
- * Defines a context for editting a property of a bean via {@link BeanEditForm}. This value is made
+ * Defines a context for editing a property of a bean via {@link BeanEditForm}. This value is made
  * available to blocks via the {@link Environmental} annotation.
  * 
  * @see BeanBlockSource
@@ -32,13 +32,13 @@
 public interface PropertyEditContext
 {
     /**
-     * Returns the current value of the property being editted (the context encapsulates the object
+     * Returns the current value of the property being edited (the context encapsulates the object
      * containing the property).
      */
     Object getPropertyValue();
 
     /**
-     * Updates the value of the property being editted (the context encapsulates the object
+     * Updates the value of the property being edited (the context encapsulates the object
      * containing the property).
      * 
      * @param value
@@ -74,7 +74,7 @@
     String getPropertyId();
 
     /**
-     * Returns the type of the property being editted.
+     * Returns the type of the property being edited.
      */
     Class getPropertyType();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Mon Sep  3 16:38:47 2007
@@ -26,7 +26,9 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.logging.Log;
 import org.apache.tapestry.Asset;
+import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.PageRenderSupport;
@@ -187,6 +189,7 @@
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.util.StrategyRegistry;
 import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.runtime.ComponentResourcesAware;
 import org.apache.tapestry.runtime.RenderCommand;
 import org.apache.tapestry.translator.DoubleTranslator;
 import org.apache.tapestry.translator.IntegerTranslator;
@@ -726,6 +729,7 @@
      * <li>null to {@link GridDataSource}
      * <li>String to {@link GridPagerPosition}
      * <li>List to {@link SelectModel}
+     * <li>{@link ComponentResourcesAware} (typically, a component) to {@link ComponentResources}
      * </ul>
      */
     public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration)
@@ -788,6 +792,18 @@
             }
         });
 
+        add(
+                configuration,
+                ComponentResourcesAware.class,
+                ComponentResources.class,
+                new Coercion<ComponentResourcesAware, ComponentResources>()
+                {
+
+                    public ComponentResources coerce(ComponentResourcesAware input)
+                    {
+                        return input.getComponentResources();
+                    }
+                });
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Mon Sep  3 16:38:47 2007
@@ -295,7 +295,7 @@
         return newMock(PropertyConduit.class);
     }
 
-    protected final PropertyModel mockPropertyEditModel()
+    protected final PropertyModel mockPropertyModel()
     {
         return newMock(PropertyModel.class);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.html?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.html (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.html Mon Sep  3 16:38:47 2007
@@ -2,9 +2,9 @@
     <t:errors/>
 
     <div class="t-beaneditor">
-        <div class="t-beaneditor-row" t:type="loop" t:source="model.propertyNames"
+        <div class="t-beaneditor-row" t:type="loop" t:source="model.propertyNames" t:volatile="true"
             t:value="propertyName">
-            <t:delegate to="blockForProperty"/>
+            <t:propertyEditor property="propertyName" object="object" model="model" overrides="this"/>
         </div>
         <div class="t-beaneditor-row">
             <input type="submit" value="${submitLabel}"/>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.properties?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/BeanEditForm.properties Mon Sep  3 16:38:47 2007
@@ -13,4 +13,3 @@
 # limitations under the License.
 
 submit-label=Create/Update
-block-error=Unable to locate a block to edit property '%s' (with data type '%s') of object %s: %s
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/PropertyEditor.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/PropertyEditor.properties?rev=572450&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/PropertyEditor.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/corelib/components/PropertyEditor.properties Mon Sep  3 16:38:47 2007
@@ -0,0 +1,15 @@
+# Copyright 2007 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.
+
+block-error=Unable to locate a block to edit property '%s' (with data type '%s') of object %s: %s
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/beaneditform.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/beaneditform.apt?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/beaneditform.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/beaneditform.apt Mon Sep  3 16:38:47 2007
@@ -6,7 +6,7 @@
 
   Tapestry includes a powerful component capable of generating a complete create/edit user interface for a typical JavaBean, BeanEditForm.
   
-  BeanEditForm analyzes the the properties of the bean, locating just those properties that are readable and writeable. It filters down
+  BeanEditForm analyzes the the properties of the bean, locating just those properties that are readable and writable. It filters down
   to properties whose type is mapped to a known editor (this is described in more detail below).
   
   The default ordering for properties is in the order in which the <getter methods> for the properties are defined.
@@ -26,11 +26,13 @@
   
   []
   
-  Resolving a property type to an editor type involves a search up the inheritance hiearchy: thus the super-type of Integer, Long, BigDecimal, etc. is
+  Resolving a property type to an editor type involves a search up the inheritance hierarchy: thus the super-type of Integer, Long, BigDecimal, etc. is
   Number, which uses a text field for data entry.
+  
+  The list of supported property types is extensible (this is documented below).
     
     
-* Automatic Creation
+* Automatic Object Creation
 
   When a page is rendered, the BeanEditForm component will read its object parameter as the JavaBean to edit (with the current properties
   of the JavaBean becoming the defaults for the various fields).  Likewise, when the form is submitted by the user, the object parameter
@@ -47,14 +49,14 @@
   
 * Non-Visual Properties
 
-  In some cases, a property may be updatable and of a supported type for editting, but should not be presented to the user for editting: for example,
+  In some cases, a property may be updatable and of a supported type for editing, but should not be presented to the user for editing: for example,
   a property that holds the primary key of a database entity. In such a case, the
   {{{../../apidocs/org/apache/tapestry/beaneditor/NonVisual.html}NonVisual}} annotation may be applied to the property (either the getter
   or the setter method). 
     
 * Default Validation
 
-  Default validation for fields is primarly determined by property type.
+  Default validation for fields is primary determined by property type.
   
   If desired, additional validation may be specified using the 
   {{{../../apidocs/org/apache/tapestry/beaneditor/Validate.html}Validate}} annotation.
@@ -66,12 +68,12 @@
   
 * Default Label
 
-  Tapestry will attempt to provide a reasonable default label for each field, based on the property name being editted.  The property name
+  Tapestry will attempt to provide a reasonable default label for each field, based on the property name being emitted.  The property name
   is capitalized, and spaces are added before case changes, thus property "name" becomes label "Name" and property "streetAddress" becomes label
-  "Street Adresss".  
+  "Street Address".  
   
   BeanEditForm also searches for a label for the field in the containing component's message catalog.  The message key is the property name suffixed with "-label".
-  If such a label is found, it takes precendence.
+  If such a label is found, it takes precedence.
   
 Property Editor Overrides
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/BeanEditFormTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/BeanEditFormTest.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/BeanEditFormTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/BeanEditFormTest.java Mon Sep  3 16:38:47 2007
@@ -37,12 +37,9 @@
         ComponentResources containerResources = mockComponentResources();
         BeanModelSource source = mockBeanModelSource();
         BeanModel model = mockBeanModel();
-        Environment environment = mockEnvironment();
 
         expect(resources.triggerEvent(Form.PREPARE, null, null)).andReturn(false);
 
-        train_push(environment, PropertyEditContext.class);
-
         train_getBoundType(resources, RegistrationData.class);
 
         train_getContainerResources(resources, containerResources);
@@ -53,7 +50,7 @@
 
         BeanEditForm component = new BeanEditForm();
 
-        component.inject(resources, source, environment);
+        component.inject(resources, source);
 
         assertTrue(component.onPrepareFromForm());
 
@@ -70,12 +67,9 @@
     {
         ComponentResources resources = mockComponentResources();
         Location l = mockLocation();
-        Environment environment = mockEnvironment();
 
         expect(resources.triggerEvent(Form.PREPARE, null, null)).andReturn(false);
 
-        train_push(environment, PropertyEditContext.class);
-
         train_getBoundType(resources, Runnable.class);
 
         train_getCompleteId(resources, "Foo.bar");
@@ -86,7 +80,7 @@
 
         BeanEditForm component = new BeanEditForm();
 
-        component.inject(resources, null, environment);
+        component.inject(resources, null);
 
         try
         {

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/PropertyEditorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/PropertyEditorTest.java?rev=572450&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/PropertyEditorTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/corelib/components/PropertyEditorTest.java Mon Sep  3 16:38:47 2007
@@ -0,0 +1,81 @@
+// Copyright 2007 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.tapestry.corelib.components;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.beaneditor.PropertyModel;
+import org.apache.tapestry.ioc.Location;
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.TapestryException;
+import org.apache.tapestry.services.BeanBlockSource;
+import org.apache.tapestry.test.TapestryTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * Tests an error case for the PropertyEditor component. The success cases are mixed into the
+ * BeanEditForm component's integration tests.
+ */
+public class PropertyEditorTest extends TapestryTestCase
+{
+    @Test
+    public void no_editor_block_available()
+    {
+        PropertyModel model = mockPropertyModel();
+        ComponentResources overrides = mockComponentResources();
+        ComponentResources resources = mockComponentResources();
+        BeanBlockSource source = newMock(BeanBlockSource.class);
+        RuntimeException exception = new RuntimeException("Simulated failure.");
+        Messages messages = mockMessages();
+        Location l = mockLocation();
+
+        String propertyId = "foo";
+        String dataType = "unk";
+        String propertyName = "fooProp";
+        Object object = "[OBJECT]";
+        String formattedMessage = "formatted-message";
+
+        expect(model.getId()).andReturn(propertyId);
+
+        expect(overrides.getBlockParameter(propertyId)).andReturn(null);
+
+        expect(model.getDataType()).andReturn(dataType);
+
+        expect(source.getEditBlock(dataType)).andThrow(exception);
+        expect(model.getPropertyName()).andReturn(propertyName);
+
+        train_getLocation(resources, l);
+
+        expect(messages.format("block-error", propertyName, dataType, object, exception))
+                .andReturn(formattedMessage);
+
+        replay();
+
+        PropertyEditor pe = new PropertyEditor();
+
+        pe.inject(resources, overrides, model, source, messages, object);
+
+        try
+        {
+            pe.beginRender();
+            unreachable();
+        }
+        catch (TapestryException ex)
+        {
+            assertEquals(ex.getMessage(), formattedMessage);
+            assertSame(ex.getLocation(), l);
+        }
+
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java?rev=572450&r1=572449&r2=572450&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java Mon Sep  3 16:38:47 2007
@@ -25,6 +25,7 @@
 import java.util.TreeMap;
 import java.util.regex.Pattern;
 
+import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.OptionModel;
 import org.apache.tapestry.PropertyConduit;
 import org.apache.tapestry.SelectModel;
@@ -35,6 +36,7 @@
 import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
 import org.apache.tapestry.ioc.services.PropertyAccess;
 import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.runtime.ComponentResourcesAware;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -476,4 +478,23 @@
         assertEquals(pattern.toString(), input);
     }
 
+    @Test
+    public void type_coersion_from_component_resources_aware_to_component_resources()
+    {
+        ComponentResourcesAware input = newMock(ComponentResourcesAware.class);
+        ComponentResources resources = mockComponentResources();
+
+        expect(input.getComponentResources()).andReturn(resources);
+
+        TypeCoercer coercer = getObject(TypeCoercer.class, null);
+
+        replay();
+
+        ComponentResources actual = coercer.coerce(input, ComponentResources.class);
+
+        assertSame(actual, resources);
+
+        verify();
+
+    }
 }