You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2007/04/28 05:36:05 UTC

svn commit: r533285 [1/2] - in /tapestry/tapestry4/trunk: tapestry-annotations/src/descriptor/META-INF/ tapestry-annotations/src/java/org/apache/tapestry/annotations/ tapestry-annotations/src/test/org/apache/tapestry/annotations/ tapestry-framework/src...

Author: jkuhnert
Date: Fri Apr 27 20:36:03 2007
New Revision: 533285

URL: http://svn.apache.org/viewvc?view=rev&rev=533285
Log:
Fixes TAPESTRY-1418. 

The component target -> listeners were being mapped with the basic IComponent.getId() value, which isn't globally unique. Refactored the logic for resolving Form enclosures / specified component targets to happen in the PageLoader with a component tree visitor that validates all components specified in @EventListener annotations are actually resolvable. (vs quietly failing without telling anyone). Changed mappings to use IComponent.getIdPath() . 

Still need to move or cache the logic happening in ComponentEventConnectionWorker somehow as it's currently costing a few ms during render.

Added:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java   (with props)
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java   (with props)
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/pageload/TestEventConnectionVisitor.java   (with props)
Modified:
    tapestry/tapestry4/trunk/tapestry-annotations/src/descriptor/META-INF/hivemodule.xml
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationEnhancementWorker.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestEventListenerAnnotationWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.page.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/BaseComponent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IComponent.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/EventBoundListener.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageLoader.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadMessages.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadStrings.properties
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/ComponentSpecification.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/IEventListener.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/ComponentEventPropertyTest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/services/impl/ComponentEventConnectionWorkerTest.java

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/descriptor/META-INF/hivemodule.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/descriptor/META-INF/hivemodule.xml?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/descriptor/META-INF/hivemodule.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/descriptor/META-INF/hivemodule.xml Fri Apr 27 20:36:03 2007
@@ -200,18 +200,6 @@
 
     </service-point>
 
-    <service-point id="EventListenerAnnotationWorker" interface="EventListenerAnnotationWorker">
-
-        Handles EventListener annotations.
-
-        <invoke-factory>
-            <construct class="EventListenerAnnotationWorker">
-                <set-service property="invoker" service-id="tapestry.event.EventInvoker" />
-            </construct>
-        </invoke-factory>
-
-    </service-point>
-
     <configuration-point id="SecondaryAnnotationWorkers">
 
         Configures a list of secondary annotation workers.
@@ -235,7 +223,7 @@
 
     <contribution configuration-id="SecondaryAnnotationWorkers">
         <worker object="instance:InitialValueAnnotationWorker" />
-        <worker object="service:EventListenerAnnotationWorker" />
+        <worker object="instance:EventListenerAnnotationWorker" />
     </contribution>
 
 </module>

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationEnhancementWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationEnhancementWorker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationEnhancementWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationEnhancementWorker.java Fri Apr 27 20:36:03 2007
@@ -44,13 +44,13 @@
 
     private ErrorLog _errorLog;
 
-    private Map _methodWorkers;
+    private Map<Class, MethodAnnotationEnhancementWorker> _methodWorkers;
 
-    private Map _classWorkers;
+    private Map<Class, ClassAnnotationEnhancementWorker> _classWorkers;
 
     private List<SecondaryAnnotationWorker> _secondaryAnnotationWorkers;
 
-    public void setClassWorkers(Map classWorkers)
+    public void setClassWorkers(Map<Class, ClassAnnotationEnhancementWorker> classWorkers)
     {
         _classWorkers = classWorkers;
     }
@@ -80,16 +80,14 @@
     void performClassEnhancement(EnhancementOperation op, IComponentSpecification spec,
             Class clazz, Annotation annotation, Resource classResource)
     {
-        ClassAnnotationEnhancementWorker worker = (ClassAnnotationEnhancementWorker) _classWorkers
-                .get(annotation.annotationType());
+        ClassAnnotationEnhancementWorker worker = _classWorkers.get(annotation.annotationType());
 
         if (worker == null)
             return;
 
         try
         {
-            Location location = new DescribedLocation(classResource, AnnotationMessages
-                    .classAnnotation(annotation, clazz));
+            Location location = new DescribedLocation(classResource, AnnotationMessages.classAnnotation(annotation, clazz));
 
             worker.performEnhancement(op, spec, clazz, location);
         }
@@ -128,8 +126,7 @@
     void performMethodEnhancement(EnhancementOperation op, IComponentSpecification spec,
             Method method, Annotation annotation, Resource classResource)
     {
-        MethodAnnotationEnhancementWorker worker = (MethodAnnotationEnhancementWorker) _methodWorkers
-                .get(annotation.annotationType());
+        MethodAnnotationEnhancementWorker worker = _methodWorkers.get(annotation.annotationType());
 
         if (worker == null)
             return;
@@ -152,7 +149,7 @@
 
     }
 
-    public void setMethodWorkers(Map methodWorkers)
+    public void setMethodWorkers(Map<Class, MethodAnnotationEnhancementWorker> methodWorkers)
     {
         _methodWorkers = methodWorkers;
     }

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/EventListenerAnnotationWorker.java Fri Apr 27 20:36:03 2007
@@ -16,7 +16,6 @@
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.Resource;
 import org.apache.tapestry.enhance.EnhancementOperation;
-import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.spec.IComponentSpecification;
 
 import java.lang.reflect.Method;
@@ -29,8 +28,6 @@
  */
 public class EventListenerAnnotationWorker implements SecondaryAnnotationWorker
 {
-    private IComponentEventInvoker _invoker;
-    
     /** 
      * {@inheritDoc}
      */
@@ -59,34 +56,14 @@
 
         for (int i=0; i < targets.length; i++) {
 
-            String mappedFormId = formId;
-
-            if (mappedFormId == null || mappedFormId.length() < 1) {
-                mappedFormId = _invoker.getPreviouslyMappedFormId(targets[i]);
-            }
-
             spec.addEventListener(targets[i], listener.events(),
-                    method.getName(), mappedFormId, validateForm, async, focus, autoSubmit);
-            
-            _invoker.addEventListener(targets[i], spec);
-            
-            if (mappedFormId != null && mappedFormId.length() > 0)
-                _invoker.addFormEventListener(mappedFormId, spec);
+                    method.getName(), formId, validateForm, async, focus, autoSubmit);
         }
         
         for (int i=0; i < elements.length; i++) {
             
             spec.addElementEventListener(elements[i], listener.events(), 
                     method.getName(), formId, validateForm, async, focus);
-            
-            if (formId != null)
-                _invoker.addFormEventListener(formId, spec);
         }
-    }
-    
-    /** Injected. */
-    public void setInvoker(IComponentEventInvoker invoker)
-    {
-        _invoker = invoker;
     }
 }

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestEventListenerAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestEventListenerAnnotationWorker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestEventListenerAnnotationWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestEventListenerAnnotationWorker.java Fri Apr 27 20:36:03 2007
@@ -18,8 +18,6 @@
 import org.apache.tapestry.enhance.EnhancementOperation;
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 import org.apache.tapestry.internal.event.EventBoundListener;
-import org.apache.tapestry.internal.event.IComponentEventInvoker;
-import org.apache.tapestry.internal.event.impl.ComponentEventInvoker;
 import org.apache.tapestry.spec.ComponentSpecification;
 import org.apache.tapestry.spec.IComponentSpecification;
 import org.testng.annotations.Test;
@@ -41,12 +39,9 @@
         EnhancementOperation op = newOp();
         IComponentSpecification spec = new ComponentSpecification();
         Resource resource = newResource(AnnotatedPage.class);
-        
-        IComponentEventInvoker invoker = new ComponentEventInvoker();
-        
+                
         EventListenerAnnotationWorker worker = new EventListenerAnnotationWorker();
-        worker.setInvoker(invoker);
-        
+
         replay();
         
         Method m = findMethod(AnnotatedPage.class, "eventListener");
@@ -56,9 +51,7 @@
         worker.peformEnhancement(op, spec, m, resource);
         
         verify();
-        
-        assertEquals(1, invoker.getEventListeners("email").size());
-        
+                
         ComponentEventProperty property = spec.getComponentEvents("email");
         assertNotNull(property);
         
@@ -82,11 +75,9 @@
         EnhancementOperation op = newOp();
         IComponentSpecification spec = new ComponentSpecification();
         Resource resource = newResource(AnnotatedPage.class);
-        IComponentEventInvoker invoker = new ComponentEventInvoker();
-        
+
         EventListenerAnnotationWorker worker = new EventListenerAnnotationWorker();
-        worker.setInvoker(invoker);
-        
+
         replay();
         
         Method m = findMethod(AnnotatedPage.class, "formListener");
@@ -95,10 +86,7 @@
         worker.peformEnhancement(op, spec, m, resource);
         
         verify();
-        
-        assertEquals(1, invoker.getEventListeners("email").size());
-        assertEquals(1, invoker.getFormEventListeners("testForm").size());
-        
+                
         ComponentEventProperty property = spec.getComponentEvents("email");
         assertNotNull(property);
         

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.page.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.page.xml?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.page.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.page.xml Fri Apr 27 20:36:03 2007
@@ -16,199 +16,212 @@
 -->
 
 <module id="tapestry.page" version="4.0.0" package="org.apache.tapestry.pageload">
-  
-  Module for services related to page loading and pooling.
-  
-  <service-point id="PageSource" interface="org.apache.tapestry.engine.IPageSource">
-    
-    <invoke-factory>
-      <construct class="PageSource">
-        <set-service property="pool" service-id="PagePool"/>
-        <set-service property="pageSpecificationResolver" service-id="PageSpecificationResolver"/>
-        <set-service property="loader" service-id="PageLoader"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <service-point id="PageLoader" interface="org.apache.tapestry.engine.IPageLoader">
-    
-    <invoke-factory model="pooled">
-      <construct class="PageLoader">
-        <set-service property="componentConstructorFactory" service-id="tapestry.enhance.ComponentConstructorFactory"/>
-        <set-service property="componentResolver" service-id="ComponentSpecificationResolver"/>      
-        <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
-        <set-service property="componentTemplateLoader" service-id="ComponentTemplateLoader"/>
-        <set-service property="establishDefaultParameterValuesVisitor"
-          service-id="EstablishDefaultParameterValuesVisitor"/>
-        <set-service property="assetSource" service-id="tapestry.asset.AssetSource"/>
-        <set-service property="pageClassProvider" service-id="PageClassProvider"/>
-        <set-service property="componentClassProvider" service-id="ComponentClassProvider"/>
-        <set-object property="componentPropertySource" value="infrastructure:componentPropertySource"/>
-        <set-service property="threadLocale" service-id="hivemind.ThreadLocale"/>
-      </construct>
-    </invoke-factory>
-  </service-point>
-  
-  <service-point id="EstablishDefaultParameterValuesVisitor" interface="IComponentVisitor">
-    
-    Visits all the components of a page, locates unbound parameters, and plugs in a default value (if available)
-    for each. Used by the PageLoader.
-    
-    <invoke-factory>
-      <construct class="EstablishDefaultParameterValuesVisitor">
-        <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <service-point id="PagePool" interface="org.apache.tapestry.services.ObjectPool">
-    <invoke-factory>
-      <construct class="org.apache.tapestry.services.impl.ObjectPoolImpl">
-        <event-listener service-id="tapestry.ResetEventHub"/>
-        <event-listener service-id="tapestry.describe.ReportStatusHub"/>        
-      </construct>
-    </invoke-factory>
-  </service-point>
-  
-  <service-point id="PageSpecificationResolver" interface="org.apache.tapestry.resolver.PageSpecificationResolver">
-    
-    <invoke-factory model="threaded">
-      <construct class="org.apache.tapestry.resolver.PageSpecificationResolverImpl">
-        <set-object property="specificationSource" value="infrastructure:specificationSource"/>
-        <set-object property="componentPropertySource" value="infrastructure:componentPropertySource"/>
-        <set-service property="delegate" service-id="SpecificationResolverDelegate"/>
-        <set-object property="applicationId" value="infrastructure:applicationId"/>
-        <set-object property="contextRoot" value="infrastructure:contextRoot"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <service-point id="SpecificationResolverDelegate" interface="org.apache.tapestry.resolver.ISpecificationResolverDelegate">
-    
-    <invoke-factory service-id="tapestry.ExtensionLookupFactory">
-      <lookup extension-name="org.apache.tapestry.specification-resolver-delegate"/>
-    </invoke-factory>
-  </service-point>
-  
-  <service-point id="ComponentSpecificationResolver" interface="org.apache.tapestry.resolver.ComponentSpecificationResolver">
-    
-    Locates the specification for a component or page.
-    
-    <invoke-factory model="threaded">
-      <construct class="org.apache.tapestry.resolver.ComponentSpecificationResolverImpl">
-        <set-object property="specificationSource" value="infrastructure:specificationSource"/>
-        <set-service property="delegate" service-id="SpecificationResolverDelegate"/>
-        <set-object property="applicationId" value="infrastructure:applicationId"/>
-        <set-object property="contextRoot" value="infrastructure:contextRoot"/>
-		<set-object property="classFinder" value="infrastructure:classFinder"/>
-      </construct>
-    </invoke-factory>    
-  </service-point>
-  
-  <service-point id="ComponentTemplateLoader" interface="org.apache.tapestry.services.ComponentTemplateLoader">
-    
-    Locates and loads the template for a component (or page).
-    
-    <invoke-factory>
-      <construct class="org.apache.tapestry.services.impl.ComponentTemplateLoaderImpl">
-        <set-object property="templateSource" value="infrastructure:templateSource"/>
-        <set-service property="pageLoader" service-id="PageLoader"/>
-        <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <configuration-point id="PageClassProviderChain" schema-id="hivemind.lib.ChainContribution">
-    
-    Chain of objects implementing ComponentClassProvider that are used to locate  the page class
-    for a particular page.
-    
-  </configuration-point>
-  
-  <service-point id="PageClassProvider" interface="ComponentClassProvider">
-    
-    Chain built around thePgaeClassProviderChain configuration point, used to determine
-    the class to instantiate for a particular page (within a namespace).
-    
-    <invoke-factory service-id="hivemind.lib.ChainFactory">
-      <construct configuration-id="PageClassProviderChain"/>
-    </invoke-factory>
-  </service-point>
-  
-  <contribution configuration-id="PageClassProviderChain">
-    <command id="specification" before="*" object="instance:SpecificationComponentClassProvider"/>
-    <command id="namespace-class-search" object="service:NamespaceClassSearchPageClassProvider"/>
-    <command id="namespace-default" object="instance:NamespaceDefaultPageClassProvider" after="namespace-class-search"/>
-    <command id="global-default" object="service:GlobalDefaultPageClassProvider" after="*"/>
-  </contribution>
-  
-  <service-point id="NamespaceClassSearchPageClassProvider" interface="ComponentClassProvider">
-    
-    Searches for a class with a name matching the page name in the default package
-    (and in packages defined by the namespace's org.apache.tapestry.page-class-packages meta property).
-    
-    <invoke-factory>
-      <construct class="NamespaceClassSearchComponentClassProvider">
-        <set property="packagesName" value="org.apache.tapestry.page-class-packages"/>
-        <set-object property="classFinder" value="infrastructure:classFinder"/>
-      </construct>
-    </invoke-factory>    
-    
-  </service-point>
-  
-  <service-point id="GlobalDefaultPageClassProvider" interface="ComponentClassProvider">
-    
-    Final command in the chain; returns a fixed value based on a global property.
-    
-    <invoke-factory>
-      <construct class="GlobalDefaultComponentClassProvider">
-        <set-object property="componentClassName" value="global-property:org.apache.tapestry.default-page-class"/>        
-      </construct>
-    </invoke-factory>
-  </service-point>
-  
-  <configuration-point id="ComponentClassProviderChain" schema-id="hivemind.lib.ChainContribution">
-    
-    Chain of objects implement ComponentClassProvider that are used to locate the
-    component class for a particular component.
-  </configuration-point>
-  
-  <service-point id="ComponentClassProvider">
-    
-    Chain built around ComponentClassProviderChain configuration point, used to
-    determine the class to instantiate for a particular component (within a namespace).
-    
-    <invoke-factory service-id="hivemind.lib.ChainFactory">
-      <construct configuration-id="ComponentClassProviderChain"/>
-    </invoke-factory>
-        
-  </service-point>
-    
-  <contribution configuration-id="ComponentClassProviderChain">
-    <command id="specification" before="*" object="instance:SpecificationComponentClassProvider"/>
-    <command id="namespace-class-search" object="service:NamespaceClassSearchComponentClassProvider"/>
-    <command id="global-default" object="instance:GlobalDefaultComponentClassProvider,componentClassName=org.apache.tapestry.BaseComponent" after="*"/>
-  </contribution>  
-  
-  <service-point id="NamespaceClassSearchComponentClassProvider" interface="ComponentClassProvider">
-    
-    Searches for a class with a name matching the component type in the default package
-    (and in packages defined by the namespace's org.apache.tapestry.component-class-packages meta property).
-    
-    <invoke-factory>
-      <construct class="NamespaceClassSearchComponentClassProvider">
-        <set property="packagesName" value="org.apache.tapestry.component-class-packages"/>
-        <set-object property="classFinder" value="infrastructure:classFinder"/>        
-      </construct>
-    </invoke-factory>    
-    
-  </service-point>
-    
-  <contribution configuration-id="tapestry.Infrastructure">
-    <property name="pageSource" object="service:PageSource"/>    
-  </contribution>
+
+    Module for services related to page loading and pooling.
+
+    <service-point id="PageSource" interface="org.apache.tapestry.engine.IPageSource">
+
+        <invoke-factory>
+            <construct class="PageSource">
+                <set-service property="pool" service-id="PagePool"/>
+                <set-service property="pageSpecificationResolver" service-id="PageSpecificationResolver"/>
+                <set-service property="loader" service-id="PageLoader"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="PageLoader" interface="org.apache.tapestry.engine.IPageLoader">
+
+        <invoke-factory model="pooled">
+            <construct class="PageLoader">
+                <set-service property="componentConstructorFactory" service-id="tapestry.enhance.ComponentConstructorFactory"/>
+                <set-service property="componentResolver" service-id="ComponentSpecificationResolver"/>
+                <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
+                <set-service property="componentTemplateLoader" service-id="ComponentTemplateLoader"/>
+                <set-service property="establishDefaultParameterValuesVisitor" service-id="EstablishDefaultParameterValuesVisitor"/>
+                <set-service property="assetSource" service-id="tapestry.asset.AssetSource"/>
+                <set-service property="pageClassProvider" service-id="PageClassProvider"/>
+                <set-service property="componentClassProvider" service-id="ComponentClassProvider"/>
+                <set-object property="componentPropertySource" value="infrastructure:componentPropertySource"/>
+                <set-service property="threadLocale" service-id="hivemind.ThreadLocale"/>
+                <set-service property="eventConnectionVisitor" service-id="EventConnectionVisitor" />
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="EstablishDefaultParameterValuesVisitor" interface="IComponentVisitor">
+
+        Visits all the components of a page, locates unbound parameters, and plugs in a default value (if available)
+        for each. Used by the PageLoader.
+
+        <invoke-factory>
+            <construct class="EstablishDefaultParameterValuesVisitor">
+                <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="EventConnectionVisitor" interface="IComponentVisitor">
+
+        Visits all the components of a page and wires up their @EventListener connections to the actual components
+        targeted once a valid instance of the page is available to resolve them against.
+
+        <invoke-factory model="pooled">
+            <construct class="EventConnectionVisitor">
+                <set-service property="eventInvoker" service-id="tapestry.event.EventInvoker"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="PagePool" interface="org.apache.tapestry.services.ObjectPool">
+        <invoke-factory>
+            <construct class="org.apache.tapestry.services.impl.ObjectPoolImpl">
+                <event-listener service-id="tapestry.ResetEventHub"/>
+                <event-listener service-id="tapestry.describe.ReportStatusHub"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="PageSpecificationResolver" interface="org.apache.tapestry.resolver.PageSpecificationResolver">
+
+        <invoke-factory model="threaded">
+            <construct class="org.apache.tapestry.resolver.PageSpecificationResolverImpl">
+                <set-object property="specificationSource" value="infrastructure:specificationSource"/>
+                <set-object property="componentPropertySource" value="infrastructure:componentPropertySource"/>
+                <set-service property="delegate" service-id="SpecificationResolverDelegate"/>
+                <set-object property="applicationId" value="infrastructure:applicationId"/>
+                <set-object property="contextRoot" value="infrastructure:contextRoot"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="SpecificationResolverDelegate" interface="org.apache.tapestry.resolver.ISpecificationResolverDelegate">
+
+        <invoke-factory service-id="tapestry.ExtensionLookupFactory">
+            <lookup extension-name="org.apache.tapestry.specification-resolver-delegate"/>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="ComponentSpecificationResolver" interface="org.apache.tapestry.resolver.ComponentSpecificationResolver">
+
+        Locates the specification for a component or page.
+
+        <invoke-factory model="threaded">
+            <construct class="org.apache.tapestry.resolver.ComponentSpecificationResolverImpl">
+                <set-object property="specificationSource" value="infrastructure:specificationSource"/>
+                <set-service property="delegate" service-id="SpecificationResolverDelegate"/>
+                <set-object property="applicationId" value="infrastructure:applicationId"/>
+                <set-object property="contextRoot" value="infrastructure:contextRoot"/>
+                <set-object property="classFinder" value="infrastructure:classFinder"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="ComponentTemplateLoader" interface="org.apache.tapestry.services.ComponentTemplateLoader">
+
+        Locates and loads the template for a component (or page).
+
+        <invoke-factory>
+            <construct class="org.apache.tapestry.services.impl.ComponentTemplateLoaderImpl">
+                <set-object property="templateSource" value="infrastructure:templateSource"/>
+                <set-service property="pageLoader" service-id="PageLoader"/>
+                <set-service property="bindingSource" service-id="tapestry.bindings.BindingSource"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <configuration-point id="PageClassProviderChain" schema-id="hivemind.lib.ChainContribution">
+
+        Chain of objects implementing ComponentClassProvider that are used to locate  the page class
+        for a particular page.
+
+    </configuration-point>
+
+    <service-point id="PageClassProvider" interface="ComponentClassProvider">
+
+        Chain built around thePgaeClassProviderChain configuration point, used to determine
+        the class to instantiate for a particular page (within a namespace).
+
+        <invoke-factory service-id="hivemind.lib.ChainFactory">
+            <construct configuration-id="PageClassProviderChain"/>
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="PageClassProviderChain">
+        <command id="specification" before="*" object="instance:SpecificationComponentClassProvider"/>
+        <command id="namespace-class-search" object="service:NamespaceClassSearchPageClassProvider"/>
+        <command id="namespace-default" object="instance:NamespaceDefaultPageClassProvider" after="namespace-class-search"/>
+        <command id="global-default" object="service:GlobalDefaultPageClassProvider" after="*"/>
+    </contribution>
+
+    <service-point id="NamespaceClassSearchPageClassProvider" interface="ComponentClassProvider">
+
+        Searches for a class with a name matching the page name in the default package
+        (and in packages defined by the namespace's org.apache.tapestry.page-class-packages meta property).
+
+        <invoke-factory>
+            <construct class="NamespaceClassSearchComponentClassProvider">
+                <set property="packagesName" value="org.apache.tapestry.page-class-packages"/>
+                <set-object property="classFinder" value="infrastructure:classFinder"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="GlobalDefaultPageClassProvider" interface="ComponentClassProvider">
+
+        Final command in the chain; returns a fixed value based on a global property.
+
+        <invoke-factory>
+            <construct class="GlobalDefaultComponentClassProvider">
+                <set-object property="componentClassName" value="global-property:org.apache.tapestry.default-page-class"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <configuration-point id="ComponentClassProviderChain" schema-id="hivemind.lib.ChainContribution">
+
+        Chain of objects implement ComponentClassProvider that are used to locate the
+        component class for a particular component.
+    </configuration-point>
+
+    <service-point id="ComponentClassProvider">
+
+        Chain built around ComponentClassProviderChain configuration point, used to
+        determine the class to instantiate for a particular component (within a namespace).
+
+        <invoke-factory service-id="hivemind.lib.ChainFactory">
+            <construct configuration-id="ComponentClassProviderChain"/>
+        </invoke-factory>
+
+    </service-point>
+
+    <contribution configuration-id="ComponentClassProviderChain">
+        <command id="specification" before="*" object="instance:SpecificationComponentClassProvider"/>
+        <command id="namespace-class-search" object="service:NamespaceClassSearchComponentClassProvider"/>
+        <command id="global-default" object="instance:GlobalDefaultComponentClassProvider,componentClassName=org.apache.tapestry.BaseComponent" after="*"/>
+    </contribution>
+
+    <service-point id="NamespaceClassSearchComponentClassProvider" interface="ComponentClassProvider">
+
+        Searches for a class with a name matching the component type in the default package
+        (and in packages defined by the namespace's org.apache.tapestry.component-class-packages meta property).
+
+        <invoke-factory>
+            <construct class="NamespaceClassSearchComponentClassProvider">
+                <set property="packagesName" value="org.apache.tapestry.component-class-packages"/>
+                <set-object property="classFinder" value="infrastructure:classFinder"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <contribution configuration-id="tapestry.Infrastructure">
+        <property name="pageSource" object="service:PageSource"/>
+    </contribution>
 </module>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/AbstractComponent.java Fri Apr 27 20:36:03 2007
@@ -22,6 +22,7 @@
 import org.apache.tapestry.engine.IPageLoader;
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.PageEvent;
+import org.apache.tapestry.internal.Component;
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.listener.ListenerMap;
 import org.apache.tapestry.services.ComponentRenderWorker;
@@ -36,8 +37,8 @@
  * @author Howard Lewis Ship
  */
 
-public abstract class AbstractComponent extends BaseLocatable implements IDirectEvent
-{   
+public abstract class AbstractComponent extends BaseLocatable implements IDirectEvent, Component {
+    
     private static final int MAP_SIZE = 5;
     
     private static final int BODY_INIT_SIZE = 5;
@@ -216,7 +217,7 @@
      * 
      * @return The values, if any. Null otherwise.
      */
-    protected IRender[] getContainedRenderers()
+    public IRender[] getContainedRenderers()
     {
         return _body;
     }
@@ -424,11 +425,13 @@
     
     public String getIdPath()
     {
+        if (_idPath != null)
+            return _idPath;
+        
         String containerIdPath;
         
         if (_container == null)
-            throw new NullPointerException(Tapestry
-                    .format("AbstractComponent.null-container", this));
+            throw new NullPointerException(Tapestry.format("AbstractComponent.null-container", this));
         
         containerIdPath = _container.getIdPath();
         
@@ -495,8 +498,7 @@
     public void setTemplateTagName(String tag)
     {
         if (_templateTagName != null)
-            throw new ApplicationRuntimeException(Tapestry
-                    .getMessage("AbstractComponent.attempt-to-change-template-tag"));
+            throw new ApplicationRuntimeException(Tapestry.getMessage("AbstractComponent.attempt-to-change-template-tag"));
         
         _templateTagName = tag;
     }
@@ -509,8 +511,7 @@
     public void setPage(IPage value)
     {
         if (_page != null)
-            throw new ApplicationRuntimeException(Tapestry
-                    .getMessage("AbstractComponent.attempt-to-change-page"));
+            throw new ApplicationRuntimeException(Tapestry.getMessage("AbstractComponent.attempt-to-change-page"));
 
         _page = value;
     }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/BaseComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/BaseComponent.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/BaseComponent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/BaseComponent.java Fri Apr 27 20:36:03 2007
@@ -68,6 +68,11 @@
         _outer[_outerCount++] = element;
     }
 
+    public IRender[] getContainedRenderers()
+    {
+        return _outer;
+    }
+
     /**
      * Reads the receiver's template and figures out which elements wrap which other elements.
      */

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IComponent.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IComponent.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/IComponent.java Fri Apr 27 20:36:03 2007
@@ -14,9 +14,6 @@
 
 package org.apache.tapestry;
 
-import java.util.Collection;
-import java.util.Map;
-
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.LocationHolder;
 import org.apache.hivemind.Messages;
@@ -27,6 +24,9 @@
 import org.apache.tapestry.spec.IComponentSpecification;
 import org.apache.tapestry.spec.IContainedComponent;
 
+import java.util.Collection;
+import java.util.Map;
+
 /**
  * Defines an object which may be used to provide dynamic content on a Tapestry web page.
  * <p>
@@ -41,14 +41,21 @@
 
     /**
      * Adds an asset to the component. This is invoked from the page loader.
+     *
+     * @param name
+     *          The lookup name the asset will be bound to and referenacable as.
+     * @param asset
+     *          The asset to add.
      */
 
     void addAsset(String name, IAsset asset);
 
     /**
      * Adds a component to a container. Should only be called during the page loading process, which
-     * is responsible for any checking.
-     * 
+     * is responsible for doing all the necessary work of managing component state.
+     *
+     * @param component
+     *          The component to add.
      * @see IPageLoader
      */
 
@@ -308,17 +315,11 @@
      * <p>
      * The exact timing is not specified, but any components contained by the receiving component
      * will also have been constructed before this method is invoked.
-     * <p>
-     * As of release 1.0.6, this method is invoked <em>before</em> bindings are set. This should
-     * not affect anything, as bindings should only be used during renderring.
-     * <p>
-     * Release 2.2 added the cycle parameter which is, regretfully, not backwards compatible.
      * 
      * @since 0.2.12
      */
 
-    void finishLoad(IRequestCycle cycle, IPageLoader loader,
-            IComponentSpecification specification);
+    void finishLoad(IRequestCycle cycle, IPageLoader loader, IComponentSpecification specification);
 
     /**
      * Returns component strings for the component. Starting in release 4.0, this method is

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java?view=auto&rev=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java Fri Apr 27 20:36:03 2007
@@ -0,0 +1,24 @@
+package org.apache.tapestry.internal;
+
+import org.apache.tapestry.IRender;
+
+/**
+ * Represents the <em>internal</em> component api exposed for use by core framework code only.
+ *
+ * <p>
+ * Use at your own risk as everything in this API is subject to change without notice from release to
+ * release.
+ * </p>
+ */
+public interface Component {
+
+    /**
+     * Returns the list of of {@link IRender} elements contained by this component. Ie whatever
+     * has been added via {@link org.apache.tapestry.IComponent#addBody(IRender)}.
+     *
+     * @return The values, if any. Null otherwise.
+     */
+    IRender[] getContainedRenderers();
+
+    
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/Component.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/ComponentEventProperty.java Fri Apr 27 20:36:03 2007
@@ -31,9 +31,10 @@
     private String _componentId;
     
     /**
-     * Creates a new component event property with
-     * the specified component id.
+     * Creates a new component event property mapped to the specified component id.
+     *
      * @param componentId
+     *          The component which is the target of all mappings in this property.
      */
     public ComponentEventProperty(String componentId)
     {
@@ -107,7 +108,7 @@
             listeners.add(listener);
     }
 
-    public void connectAutoSubmitEvents(String formId)
+    public void connectAutoSubmitEvents(String formIdPath)
     {
         Iterator it = getEvents().iterator();
         while (it.hasNext()) {
@@ -119,7 +120,7 @@
                 
                 EventBoundListener listener = (EventBoundListener) lit.next();
 
-                listener.setFormId(formId);
+                listener.setFormId(formIdPath);
                 lit.remove();
 
                 List formListeners = getFormEventListeners(key);
@@ -131,6 +132,45 @@
             
             if (listeners.size() == 0)
                 it.remove();
+        }
+    }
+
+    /**
+     * Replaces all instances of the existing component id mapped for this property with the new
+     * {@link org.apache.tapestry.IComponent#getIdPath()} version.
+     *
+     * @param idPath The component id path.
+     */
+    public void rewireComponentId(String idPath)
+    {
+        _componentId = idPath;
+
+        Iterator it = getEvents().iterator();
+        while (it.hasNext())
+        {
+            String key = (String) it.next();
+
+            List listeners = (List)_eventMap.get(key);
+
+            for (int i=0; i < listeners.size(); i++) {
+
+                EventBoundListener listener = (EventBoundListener) listeners.get(i);
+                listener.setComponentId(idPath);
+            }
+        }
+
+        it = getFormEvents().iterator();
+        while (it.hasNext())
+        {
+            String key = (String) it.next();
+
+            List listeners = (List)_formEventMap.get(key);
+
+            for (int i=0; i < listeners.size(); i++) {
+
+                EventBoundListener listener = (EventBoundListener) listeners.get(i);
+                listener.setComponentId(idPath);
+            }
         }
     }
 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/EventBoundListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/EventBoundListener.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/EventBoundListener.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/EventBoundListener.java Fri Apr 27 20:36:03 2007
@@ -17,8 +17,6 @@
 /**
  * Provides a mapping for listener methods that are bound to events, used
  * internally by {@link ComponentEventProperty}.
- * 
- * @author jkuhnert
  */
 public class EventBoundListener
 {
@@ -31,11 +29,6 @@
     // The targeted component to listen to events on
     private String _componentId;
     
-    // The component id path of component to recieve event listener calls on (or page name in the case of page listeners)
-    private String _recieverIdPath;
-    // Whether or not receiver is page
-    private boolean _isPage;
-    
     // If targeting a form, whether or not to submit it asynchronously
     private boolean _async;
     // Whether or not to focus the form
@@ -128,6 +121,11 @@
         return _componentId;
     }
 
+    public void setComponentId(String id)
+    {
+        _componentId = id;
+    }
+
     /**
      * @return the validateForm
      */
@@ -145,38 +143,6 @@
     public boolean isAsync()
     {
         return _async;
-    }
-    
-    /**
-     * @return Returns the recieverIdPath.
-     */
-    public String getRecieverIdPath()
-    {
-        return _recieverIdPath;
-    }
-    
-    /**
-     * @param recieverIdPath The recieverIdPath to set.
-     */
-    public void setRecieverIdPath(String recieverIdPath)
-    {
-        _recieverIdPath = recieverIdPath;
-    }
-    
-    /**
-     * @return Returns the isPage.
-     */
-    public boolean isPage()
-    {
-        return _isPage;
-    }
-    
-    /**
-     * @param isPage The isPage to set.
-     */
-    public void setPage(boolean isPage)
-    {
-        _isPage = isPage;
     }
     
     public boolean shouldFocusForm()

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java Fri Apr 27 20:36:03 2007
@@ -19,7 +19,6 @@
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.ResetEventListener;
 import org.apache.tapestry.form.FormSupport;
-import org.apache.tapestry.form.IFormComponent;
 import org.apache.tapestry.spec.IComponentSpecification;
 
 import java.util.List;
@@ -67,23 +66,6 @@
      *          The listener that has form bound event listeners.
      */
     void addFormEventListener(String formId, IComponentSpecification listener);
-
-    /**
-     * Invoked to auto connect and re-wire any events on the specified component to whatever
-     * containing form it is in.
-     * 
-     * @param component The component to re-wire for submission to its form.
-     */
-    void connectAutoSubmitEvents(IFormComponent component);
-
-    /**
-     * Utility method used for autoSubmit bindings with listeners bound to {@link IFormComponent}s
-     * that don't know what their enclosing form id is until they are rendered.
-     * 
-     * @param formComponentId The components id.
-     * @return The previously mapped form id for that component, may be null.
-     */
-    String getPreviouslyMappedFormId(String formComponentId);
 
     /**
      * Gets a list of form bound event listeners previously bound via {@link #addFormEventListener(String, IComponentSpecification)}.

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java Fri Apr 27 20:36:03 2007
@@ -21,7 +21,6 @@
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.event.ResetEventListener;
 import org.apache.tapestry.form.FormSupport;
-import org.apache.tapestry.form.IFormComponent;
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 import org.apache.tapestry.internal.event.EventBoundListener;
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
@@ -38,14 +37,13 @@
  */
 public class ComponentEventInvoker implements IComponentEventInvoker, ResetEventListener
 {
+    // Mapped component id path -> List of IEventListeners
     private Map _components = new HashMap();
-    
+    // Mapped form id path -> List of IEventListeners
     private Map _formComponents = new HashMap();
-    
+    // Used to invoke actual listener methods
     private ListenerInvoker _invoker;
 
-    private Map _formIdMappings = new HashMap();
-
     /**
      * {@inheritDoc}
      */
@@ -70,12 +68,13 @@
         Defense.notNull(event, "event");
         
         IForm form = formSupport.getForm();
-        
+        String formIdPath = form.getIdPath();
+
         String targetId = (String)event.getTarget().get("id");
         if (targetId == null)
             return;
-        
-        List comps = getFormEventListeners(form.getId());
+
+        List comps = getFormEventListeners(formIdPath);
         if (comps == null)
             return;
         
@@ -84,7 +83,7 @@
         for (int i=0; i < comps.size(); i++) {
             
             IComponentSpecification spec = (IComponentSpecification)comps.get(i);
-            EventBoundListener[] listeners = spec.getFormEvents(form.getId(), event);
+            EventBoundListener[] listeners = spec.getFormEvents(formIdPath, event);
             
             IComponent target = null;
             if (spec.isPageSpecification()) {
@@ -99,7 +98,7 @@
                 
                 // ensure ~only~ the method that targeted this event gets called!
                 
-                if (!targetId.startsWith(listeners[e].getComponentId()))
+                if (!listeners[e].getComponentId().endsWith(targetId))
                     continue;
                 
                 // handle disabling focus 
@@ -125,7 +124,8 @@
     
     void invokeComponentListeners(IComponent component, IRequestCycle cycle, BrowserEvent event)
     {
-        List listeners = getEventListeners(component.getId());
+        String idPath = component.getIdPath();
+        List listeners = getEventListeners(idPath);
         if (listeners == null)
             return;
         
@@ -139,11 +139,11 @@
             if (listener.isPageSpecification()) {
                 
                 target = component.getPage();
-                props = listener.getComponentEvents(component.getId());
+                props = listener.getComponentEvents(idPath);
             } else {
                 
                 target = findComponent(component.getPage().getComponents().values(), listener);
-                props = target.getSpecification().getComponentEvents(component.getId());
+                props = target.getSpecification().getComponentEvents(idPath);
             }
             if (props == null)
                 continue;
@@ -262,36 +262,7 @@
             listeners.add(listener);
         }
     }
-
-    public void connectAutoSubmitEvents(IFormComponent component)
-    {
-        IForm form = component.getForm();
-        Defense.notNull(form, "form");
-        
-        String formId = form.getId();
-        Defense.notNull(formId, "formId");
-
-        List listeners = (List)_components.get(component.getId());
-        if (listeners == null)
-            return;
-
-        for (int i=0; i < listeners.size(); i++) {
-
-            IComponentSpecification spec = (IComponentSpecification)listeners.get(i);
-
-            spec.connectAutoSubmitEvents(component.getId(), form);
-            
-            addFormEventListener(formId, spec);
-            
-            _formIdMappings.put(component.getId(), formId);
-        }
-    }
-
-    public String getPreviouslyMappedFormId(String formComponentId)
-    {
-        return (String)_formIdMappings.get(formComponentId);
-    }
-
+    
     /**
      * {@inheritDoc}
      */

Added: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java?view=auto&rev=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java Fri Apr 27 20:36:03 2007
@@ -0,0 +1,240 @@
+package org.apache.tapestry.pageload;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.PoolManageable;
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IForm;
+import org.apache.tapestry.IRender;
+import org.apache.tapestry.form.IFormComponent;
+import org.apache.tapestry.internal.Component;
+import org.apache.tapestry.internal.event.ComponentEventProperty;
+import org.apache.tapestry.internal.event.EventBoundListener;
+import org.apache.tapestry.internal.event.IComponentEventInvoker;
+import org.apache.tapestry.spec.IComponentSpecification;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Handles connecting up components and forms targeted with the EventListener annotation.
+ */
+public class EventConnectionVisitor implements IComponentVisitor, PoolManageable {
+
+    IComponentEventInvoker _invoker;
+
+    List _forms = new ArrayList();
+
+    public void visitComponent(IComponent component)
+    {
+        if (component.getSpecification().getTargetsResolved())
+            return;
+
+        Map events = component.getSpecification().getComponentEvents();
+        Iterator it = events.keySet().iterator();
+
+        String[] idPaths = new String[events.size()];
+        String[] ids = new String[events.size()];
+        int count = 0;
+        
+        while (it.hasNext())
+        {
+            String compId = (String)it.next();
+            ComponentEventProperty property = (ComponentEventProperty) events.get(compId);
+
+            // find the targeted component
+
+            IComponent comp = findComponent(compId, component.getPage());
+
+            if (comp == null)
+                throw new ApplicationRuntimeException(PageloadMessages.componentNotFound(compId), component, component.getLocation(), null);
+
+            // wire up with idPath
+
+            String idPath = comp.getIdPath();
+
+            idPaths[count] = idPath;
+            ids[count] = compId;
+
+            _invoker.addEventListener(idPath, component.getSpecification());
+            wireFormEvents(comp, component.getSpecification());
+            
+            count++;
+        }
+
+        for (int i=0; i < idPaths.length; i++) {
+            
+            component.getSpecification().rewireComponentId(ids[i], idPaths[i]);
+        }
+
+        // find form element targets for re-mapping with proper idpath && IEventInvoker connection
+
+        events = component.getSpecification().getElementEvents();
+        it = events.keySet().iterator();
+
+        while (it.hasNext())
+        {
+            String elementId = (String) it.next();
+            ComponentEventProperty property = (ComponentEventProperty) events.get(elementId);
+
+            Iterator bindingIt  = property.getFormEvents().iterator();
+            while (bindingIt.hasNext())
+            {
+                String key = (String) bindingIt.next();
+                List listeners = property.getFormEventListeners(key);
+
+                for (int i=0; i < listeners.size(); i++) {
+                    
+                    EventBoundListener listener = (EventBoundListener) listeners.get(i);
+                    wireElementFormEvents(listener, component, component.getSpecification());
+                }
+            }
+        }
+
+        // set resolved so we don't do it again
+
+        component.getSpecification().setTargetsResolved(true);
+    }
+
+    void wireElementFormEvents(EventBoundListener listener, IComponent component, IComponentSpecification spec)
+    {
+        if (listener.getFormId() == null)
+            return;
+
+        if (_forms.size() < 1)
+            discoverPageForms(component.getPage());
+
+        IForm form = null;
+        for (int i=0; i < _forms.size(); i++) {
+
+            IForm f = (IForm) _forms.get(i);
+            if (listener.getFormId().equals(f.getId())) {
+                form = f;
+                break;
+            }
+        }
+
+        // couldn't find the form they specified
+
+        if (form == null)
+            throw new ApplicationRuntimeException(PageloadMessages.componentNotFound(listener.getFormId()), component, component.getLocation(), null);
+
+        String idPath = form.getIdPath();
+        
+        listener.setFormId(idPath);
+        _invoker.addFormEventListener(idPath, spec);
+    }
+
+    void wireFormEvents(IComponent component, IComponentSpecification listener)
+    {
+        if (!IFormComponent.class.isInstance(component))
+            return;
+
+        IFormComponent fcomp = (IFormComponent) component;
+
+        if (_forms.size() < 1)
+            discoverPageForms(fcomp.getPage());
+
+        IForm form = findComponentForm(fcomp);
+        if (form == null)
+            return;
+
+        listener.connectAutoSubmitEvents(component.getId(), form);
+        _invoker.addFormEventListener(form.getIdPath(), listener);
+    }
+
+    IComponent findComponent(String id, IComponent target)
+    {
+        Map components = target.getComponents();
+        if (components == null)
+            return null;
+        
+        IComponent comp = (IComponent) components.get(id);
+        if (comp != null)
+            return comp;
+
+        Iterator children = components.values().iterator();
+
+        while (children.hasNext())
+        {
+            IComponent child = (IComponent) children.next();
+
+            comp = findComponent(id, child);
+            if (comp != null)
+                return comp;
+        }
+
+        return null;
+    }
+
+    void discoverPageForms(IComponent parent)
+    {
+        if (IForm.class.isInstance(parent))
+            _forms.add(parent);
+
+        Iterator it = parent.getComponents().values().iterator();
+        while (it.hasNext())
+        {
+            IComponent comp = (IComponent)it.next();
+
+            discoverPageForms(comp);
+        }
+    }
+
+    IForm findComponentForm(IFormComponent child)
+    {
+        for (int i = 0; i < _forms.size(); i++) {
+
+            IForm form = (IForm) _forms.get(i);
+
+            IComponent match = findContainedComponent(child.getIdPath(), (Component)form);
+            if (match != null)
+                return form;
+        }
+
+        return null;
+    }
+
+    IComponent findContainedComponent(String idPath, Component container)
+    {
+        IComponent comp = (IComponent) container;
+
+        if (idPath.equals(comp.getIdPath()))
+            return comp;
+
+        IRender[] children = container.getContainedRenderers();
+        if (children == null)
+            return null;
+
+        for (int i=0; i < children.length; i++) {
+
+            if (children[i] == null)
+                return null;
+
+            if (!Component.class.isInstance(children[i]))
+                continue;
+
+            IComponent found = findContainedComponent(idPath, (Component)children[i]);
+            if (found != null)
+                return found;
+        }
+        
+        return null;
+    }
+
+    public void activateService()
+    {
+    }
+
+    public void passivateService()
+    {
+        _forms.clear();
+    }
+
+    // injected
+    public void setEventInvoker(IComponentEventInvoker invoker)
+    {
+        _invoker = invoker;
+    }
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/EventConnectionVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageLoader.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageLoader.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageLoader.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageLoader.java Fri Apr 27 20:36:03 2007
@@ -48,7 +48,7 @@
 
 public class PageLoader implements IPageLoader
 {
-
+    
     private Log _log;
 
     /** @since 4.0 */
@@ -72,6 +72,9 @@
 
     private ComponentTreeWalker _verifyRequiredParametersWalker;
 
+    private IComponentVisitor _eventConnectionVisitor;
+    private ComponentTreeWalker _eventConnectionWalker;
+
     /** @since 4.0 */
 
     private ComponentConstructorFactory _componentConstructorFactory;
@@ -151,11 +154,14 @@
         // complete
         IComponentVisitor verifyRequiredParametersVisitor = new VerifyRequiredParametersVisitor();
         
-        _verifyRequiredParametersWalker = new ComponentTreeWalker(
-                new IComponentVisitor[] { verifyRequiredParametersVisitor });
+        _verifyRequiredParametersWalker =
+                new ComponentTreeWalker( new IComponentVisitor[] { verifyRequiredParametersVisitor });
         
-        _establishDefaultParameterValuesWalker = new ComponentTreeWalker(
-                new IComponentVisitor[] { _establishDefaultParameterValuesVisitor });
+        _establishDefaultParameterValuesWalker =
+                new ComponentTreeWalker( new IComponentVisitor[] { _establishDefaultParameterValuesVisitor });
+
+        _eventConnectionWalker =
+                new ComponentTreeWalker( new IComponentVisitor[] { _eventConnectionVisitor });
     }
 
     /**
@@ -190,17 +196,13 @@
                         .inheritInformalInvalidComponentFormalOnly(component),
                         component, contained.getLocation(), null);
 
-            IComponentSpecification containerSpec = container
-                    .getSpecification();
+            IComponentSpecification containerSpec = container.getSpecification();
 
             if (!containerSpec.getAllowInformalParameters())
-                throw new ApplicationRuntimeException(PageloadMessages
-                        .inheritInformalInvalidContainerFormalOnly(container,
-                                component), component, contained.getLocation(),
-                        null);
+                throw new ApplicationRuntimeException(PageloadMessages.inheritInformalInvalidContainerFormalOnly(container, component),
+                        component, contained.getLocation(), null);
 
-            IQueuedInheritedBinding queued = new QueuedInheritInformalBindings(
-                    component);
+            IQueuedInheritedBinding queued = new QueuedInheritInformalBindings(component);
             _inheritedBindingQueue.add(queued);
         }
 
@@ -223,14 +225,14 @@
             // a formal parameter.
 
             if (formalOnly && !isFormal)
-                throw new ApplicationRuntimeException(PageloadMessages
-                        .formalParametersOnly(component, name), component,
-                        bspec.getLocation(), null);
+                throw new ApplicationRuntimeException(PageloadMessages.formalParametersOnly(component, name),
+                        component, bspec.getLocation(), null);
 
             // If an informal parameter that conflicts with a reserved name,
             // then skip it.
 
-            if (!isFormal && spec.isReservedParameterName(name)) continue;
+            if (!isFormal && spec.isReservedParameterName(name))
+                continue;
 
             if (isFormal)
             {
@@ -240,8 +242,7 @@
                             name, parameterName, bspec.getLocation()));
                 }
                 else if (pspec.isDeprecated())
-                    _log.warn(PageloadMessages.deprecatedParameter(name, bspec
-                            .getLocation(), contained.getType()));
+                    _log.warn(PageloadMessages.deprecatedParameter(name, bspec.getLocation(), contained.getType()));
             }
 
             // The type determines how to interpret the value:
@@ -263,16 +264,14 @@
 
             if (type == BindingType.INHERITED)
             {
-                QueuedInheritedBinding queued = new QueuedInheritedBinding(
-                        component, bspec.getValue(), parameterName);
+                QueuedInheritedBinding queued = new QueuedInheritedBinding(component, bspec.getValue(), parameterName);
                 _inheritedBindingQueue.add(queued);
                 continue;
             }
 
             String description = PageloadMessages.parameterName(name);
 
-            IBinding binding = convert(container, description,
-                    defaultBindingPrefix, bspec);
+            IBinding binding = convert(container, description, defaultBindingPrefix, bspec);
 
             addBindingToComponent(component, parameterName, binding);
         }
@@ -301,9 +300,8 @@
         IBinding existing = component.getBinding(parameterName);
 
         if (existing != null)
-            throw new ApplicationRuntimeException(PageloadMessages
-                    .duplicateParameter(parameterName, existing), component,
-                    binding.getLocation(), null);
+            throw new ApplicationRuntimeException(PageloadMessages.duplicateParameter(parameterName, existing),
+                    component, binding.getLocation(), null);
 
         component.setBinding(parameterName, binding);
     }
@@ -347,11 +345,10 @@
             INamespace namespace)
     {
         _depth++;
-        if (_depth > _maxDepth) _maxDepth = _depth;
+        if (_depth > _maxDepth)
+            _maxDepth = _depth;
 
-        String defaultBindingPrefix = _componentPropertySource
-                .getComponentProperty(container,
-                        TapestryConstants.DEFAULT_BINDING_PREFIX_NAME);
+        String defaultBindingPrefix = _componentPropertySource.getComponentProperty(container, TapestryConstants.DEFAULT_BINDING_PREFIX_NAME);
 
         List ids = new ArrayList(containerSpec.getComponentIds());
         int count = ids.size();
@@ -391,8 +388,7 @@
                 // Now construct the component recusively; it gets its chance
                 // to create its subcomponents and set their bindings.
 
-                constructComponent(cycle, page, component,
-                        componentSpecification, componentNamespace);
+                constructComponent(cycle, page, component, componentSpecification, componentNamespace);
             }
             
             addAssets(container, containerSpec);
@@ -402,8 +398,7 @@
             // Properties with initial values will be set here (or the
             // initial value will be recorded for later use in pageDetach().
             // That may cause yet more components to be created, and more
-            // bindings to be set, so we defer some checking until
-            // later.
+            // bindings to be set, so we defer some checking until later.
 
             container.finishLoad(cycle, this, containerSpec);
 
@@ -417,9 +412,8 @@
         }
         catch (RuntimeException ex)
         {
-            throw new ApplicationRuntimeException(PageloadMessages
-                    .unableToInstantiateComponent(container, ex), container,
-                    null, ex);
+            throw new ApplicationRuntimeException(PageloadMessages.unableToInstantiateComponent(container, ex),
+                    container, null, ex);
         }
 
         _depth--;
@@ -440,16 +434,15 @@
     {
         IPage page = container.getPage();
 
-        _componentResolver.resolve(cycle, container.getNamespace(),
-                componentType, location);
-
+        _componentResolver.resolve(cycle, container.getNamespace(), componentType, location);
+        
         INamespace componentNamespace = _componentResolver.getNamespace();
         IComponentSpecification spec = _componentResolver.getSpecification();
 
         IContainedComponent contained = new ContainedComponent();
         contained.setLocation(location);
         contained.setType(componentType);
-
+        
         IComponent result = instantiateComponent(page, container, componentId,
                 spec, _componentResolver.getType(), componentNamespace,
                 contained);
@@ -502,14 +495,12 @@
             Class componentClass = _classResolver.findClass(className);
 
             if (!IComponent.class.isAssignableFrom(componentClass))
-                throw new ApplicationRuntimeException(PageloadMessages
-                        .classNotComponent(componentClass), container, spec
-                        .getLocation(), null);
+                throw new ApplicationRuntimeException(PageloadMessages.classNotComponent(componentClass),
+                        container, spec.getLocation(), null);
 
             if (IPage.class.isAssignableFrom(componentClass))
-                throw new ApplicationRuntimeException(PageloadMessages
-                        .pageNotAllowed(id), container, spec.getLocation(),
-                        null);
+                throw new ApplicationRuntimeException(PageloadMessages.pageNotAllowed(id),
+                        container, spec.getLocation(), null);
         }
 
         ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(spec, className);
@@ -548,21 +539,18 @@
     private IPage instantiatePage(String name, INamespace namespace, IComponentSpecification spec)
     {
         Location location = spec.getLocation();
-        ComponentClassProviderContext context = new ComponentClassProviderContext(
-                name, spec, namespace);
-        String className = _pageClassProvider
-                .provideComponentClassName(context);
+        ComponentClassProviderContext context = new ComponentClassProviderContext(name, spec, namespace);
+        
+        String className = _pageClassProvider.provideComponentClassName(context);
 
         Class pageClass = _classResolver.findClass(className);
 
         if (!IPage.class.isAssignableFrom(pageClass))
-            throw new ApplicationRuntimeException(PageloadMessages
-                    .classNotPage(pageClass), location, null);
+            throw new ApplicationRuntimeException(PageloadMessages.classNotPage(pageClass), location, null);
 
         String pageName = namespace.constructQualifiedName(name);
 
-        ComponentConstructor cc = _componentConstructorFactory
-                .getComponentConstructor(spec, className);
+        ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(spec, className);
 
         IPage result = (IPage) cc.newInstance();
 
@@ -608,7 +596,12 @@
             
             // Walk through the complete component tree to ensure that required
             // parameters are bound
+
             _verifyRequiredParametersWalker.walkComponentTree(page);
+            
+            // connect @EventListener style client side events
+
+            _eventConnectionWalker.walkComponentTree(page);
         }
         finally
         {
@@ -617,8 +610,7 @@
         }
 
         if (_log.isDebugEnabled())
-            _log.debug("Loaded page " + page + " with " + _count
-                    + " components (maximum depth " + _maxDepth + ")");
+            _log.debug("Loaded page " + page + " with " + _count + " components (maximum depth " + _maxDepth + ")");
 
         return page;
     }
@@ -639,8 +631,7 @@
 
         for(int i = 0; i < count; i++)
         {
-            IQueuedInheritedBinding queued = (IQueuedInheritedBinding) _inheritedBindingQueue
-                    .get(i);
+            IQueuedInheritedBinding queued = (IQueuedInheritedBinding) _inheritedBindingQueue.get(i);
 
             queued.connect();
         }
@@ -660,92 +651,74 @@
 
             IAssetSpecification assetSpec = specification.getAsset(name);
             
-            IAsset asset = _assetSource.findAsset(specification, assetSpec.getLocation().getResource(), assetSpec.getPath(), _locale, assetSpec.getLocation());
+            IAsset asset = _assetSource.findAsset(specification, assetSpec.getLocation().getResource(),
+                    assetSpec.getPath(), _locale, assetSpec.getLocation());
             
             component.addAsset(name, asset);
         }
     }
 
-    /** @since 4.0 */
-
     public void setLog(Log log)
     {
         _log = log;
     }
 
-    /** @since 4.0 */
-
     public void setComponentResolver(ComponentSpecificationResolver resolver)
     {
         _componentResolver = resolver;
     }
 
-    /** @since 4.0 */
-
     public void setBindingSource(BindingSource bindingSource)
     {
         _bindingSource = bindingSource;
     }
 
-    /**
-     * @since 4.0
-     */
-    public void setComponentTemplateLoader(
-            ComponentTemplateLoader componentTemplateLoader)
+    public void setComponentTemplateLoader(ComponentTemplateLoader componentTemplateLoader)
     {
         _componentTemplateLoader = componentTemplateLoader;
     }
 
-    /** @since 4.0 */
-    public void setEstablishDefaultParameterValuesVisitor(
-            IComponentVisitor establishDefaultParameterValuesVisitor)
+    public void setEstablishDefaultParameterValuesVisitor(IComponentVisitor establishDefaultParameterValuesVisitor)
     {
         _establishDefaultParameterValuesVisitor = establishDefaultParameterValuesVisitor;
     }
 
-    /** @since 4.0 */
-    public void setComponentConstructorFactory(
-            ComponentConstructorFactory componentConstructorFactory)
+    public void setEventConnectionVisitor(IComponentVisitor eventConnectionVisitor)
+    {
+        _eventConnectionVisitor = eventConnectionVisitor; 
+    }
+
+    public void setComponentConstructorFactory(ComponentConstructorFactory componentConstructorFactory)
     {
         _componentConstructorFactory = componentConstructorFactory;
     }
 
-    /** @since 4.0 */
     public void setAssetSource(AssetSource assetSource)
     {
         _assetSource = assetSource;
     }
 
-    /** @since 4.0 */
     public void setPageClassProvider(ComponentClassProvider pageClassProvider)
     {
         _pageClassProvider = pageClassProvider;
     }
 
-    /** @since 4.0 */
     public void setClassResolver(ClassResolver classResolver)
     {
         _classResolver = classResolver;
     }
 
-    /**
-     * @since 4.0
-     */
-    public void setComponentClassProvider(
-            ComponentClassProvider componentClassProvider)
+    public void setComponentClassProvider(ComponentClassProvider componentClassProvider)
     {
         _componentClassProvider = componentClassProvider;
     }
 
-    /** @since 4.0 */
     public void setThreadLocale(ThreadLocale threadLocale)
     {
         _threadLocale = threadLocale;
     }
 
-    /** @since 4.0 */
-    public void setComponentPropertySource(
-            ComponentPropertySource componentPropertySource)
+    public void setComponentPropertySource(ComponentPropertySource componentPropertySource)
     {
         _componentPropertySource = componentPropertySource;
     }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadMessages.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadMessages.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadMessages.java Fri Apr 27 20:36:03 2007
@@ -29,9 +29,7 @@
  */
 final class PageloadMessages
 {
-
-    private static final MessageFormatter _formatter = new MessageFormatter(
-            PageloadMessages.class);
+    private static final MessageFormatter _formatter = new MessageFormatter(PageloadMessages.class);
 
     /* defeat instantiation */
     private PageloadMessages()
@@ -144,4 +142,8 @@
                 HiveMind.getLocationString(location), componentType);
     }
 
+    public static String componentNotFound(String id)
+    {
+        return _formatter.format("component-not-found", id);
+    }
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadStrings.properties?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadStrings.properties (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/pageload/PageloadStrings.properties Fri Apr 27 20:36:03 2007
@@ -29,3 +29,4 @@
 duplicate-parameter=A binding for parameter {0} conflicts with a previous binding (at {1}).
 used-parameter-alias=Parameter {2} (for component {1}, at {0}) was bound; this parameter has been deprecated, bind parameter {3} instead.
 deprecated-parameter=Parameter {0} (at {1}) has been deprecated, and may be removed in a future release. Consult the documentation for component {2} to determine an appropriate replacement.
+component-not-found=No component found in tree for EventListener binding with a matching component id of {0}.

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java Fri Apr 27 20:36:03 2007
@@ -21,7 +21,6 @@
 import org.apache.tapestry.engine.DirectEventServiceParameter;
 import org.apache.tapestry.engine.IEngineService;
 import org.apache.tapestry.engine.IScriptSource;
-import org.apache.tapestry.form.IFormComponent;
 import org.apache.tapestry.html.Body;
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 import org.apache.tapestry.internal.event.EventBoundListener;
@@ -76,8 +75,7 @@
      */
     public void renderComponent(IRequestCycle cycle, IComponent component)
     {
-        if (cycle.isRewinding() 
-                || TapestryUtils.getOptionalPageRenderSupport(cycle) == null) 
+        if (cycle.isRewinding() || TapestryUtils.getOptionalPageRenderSupport(cycle) == null)
             return;
         
         // Don't render fields being pre-rendered, otherwise we'll render twice 
@@ -132,29 +130,17 @@
     
     ComponentEventProperty[] getComponentEvents(IComponent comp)
     {
-        List listeners = _invoker.getEventListeners(comp.getId());
+        List listeners = _invoker.getEventListeners(comp.getIdPath());
         if (listeners == null || listeners.size() < 1)
             return null;
 
-        if (IFormComponent.class.isInstance(comp)) {
-            IFormComponent formComp = (IFormComponent)comp;
-            
-            _invoker.connectAutoSubmitEvents(formComp);
-
-            // re-wire form related events
-
-            comp.getSpecification().connectAutoSubmitEvents(comp.getId(), formComp.getForm());
-
-            listeners = _invoker.getEventListeners(comp.getId());
-        }
-
         List ret = new ArrayList();
         
         for (int i=0; i < listeners.size(); i++) {
             
             IEventListener listener = (IEventListener)listeners.get(i);
             
-            ret.add(listener.getComponentEvents(comp.getId()));
+            ret.add(listener.getComponentEvents(comp.getIdPath()));
         }
         
         return (ComponentEventProperty[])ret.toArray(new ComponentEventProperty[ret.size()]);
@@ -211,12 +197,12 @@
     
     void mapFormNames(IRequestCycle cycle, IForm form)
     {
-        List names = (List)cycle.getAttribute(FORM_NAME_LIST + form.getId());
+        List names = (List)cycle.getAttribute(FORM_NAME_LIST + form.getIdPath());
         
         if (names == null) {
             names = new ArrayList();
             
-            cycle.setAttribute(FORM_NAME_LIST + form.getId(), names);
+            cycle.setAttribute(FORM_NAME_LIST + form.getIdPath(), names);
         }
         
         names.add(form.getName());
@@ -224,7 +210,7 @@
     
     void linkDeferredForm(IRequestCycle cycle, IForm form)
     {
-        List deferred = (List)_deferredFormConnections.remove(form.getId());
+        List deferred = (List)_deferredFormConnections.remove(form.getIdPath());
         
         for (int i=0; i < deferred.size(); i++) {
             
@@ -247,7 +233,7 @@
             
             for (int e=0; e < props.length; e++) {
                 
-                Object[][] formEvents = buildFormEvents(cycle, form.getId(), 
+                Object[][] formEvents = buildFormEvents(cycle, form.getIdPath(), 
                         props[e].getFormEvents(), (Boolean)val[1], (Boolean)val[2], val[3]);
                 
                 scriptParms.put("formEvents", formEvents);
@@ -303,8 +289,8 @@
             
             String event = (String)it.next();
             
-            retval.add(new Object[]{event, formNames, async, 
-                    validate, ScriptUtils.functionHash(new String(uniqueHash + event)) });
+            retval.add(new Object[]{event, formNames, async, validate,
+                    ScriptUtils.functionHash(new String(uniqueHash + event)) });
         }
         
         return (Object[][])retval.toArray(new Object[retval.size()][5]);
@@ -337,7 +323,7 @@
     boolean isDeferredForm(IComponent component)
     {
         if (IForm.class.isInstance(component) 
-                && _deferredFormConnections.get(((IForm)component).getId()) != null)
+                && _deferredFormConnections.get(((IForm)component).getIdPath()) != null)
             return true;
         
         return false;

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/HiveMindExpressionCompiler.java Fri Apr 27 20:36:03 2007
@@ -163,6 +163,8 @@
 
             } catch (Throwable t) {
 
+                _log.error("Error generating OGNL getter for expression " + expression + " with root " + root + " and body:\n" + getBody, t);
+
                 t.printStackTrace();
 
                 generateFailSafe(context, expression, root);
@@ -174,11 +176,8 @@
                 setBody = generateSetter(context, classFab, valueSetter, expression, root);
 
             } catch (UnsupportedCompilationException uc) {
-
-                // uc.printStackTrace();
                 
-                if (_log.isDebugEnabled())
-                    _log.warn("Unsupported setter compilation caught: " + uc.getMessage() + " for expression: " + expression.toString());
+                //_log.warn("Unsupported setter compilation caught: " + uc.getMessage() + " for expression: " + expression.toString(), uc);
 
                 setBody = generateOgnlSetter(classFab, valueSetter);
 
@@ -212,6 +211,7 @@
 
             }  catch (Throwable t) {
 
+                _log.error("Error generating OGNL statements for expression " + expression + " with root " + root, t);
                 t.printStackTrace();
 
                 generateFailSafe(context, expression, root);

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/ComponentSpecification.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/ComponentSpecification.java?view=diff&rev=533285&r1=533284&r2=533285
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/ComponentSpecification.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/spec/ComponentSpecification.java Fri Apr 27 20:36:03 2007
@@ -164,9 +164,10 @@
     private boolean _deprecated = false;
     
     private Map _componentEvents = new HashMap();
-    
     private Map _elementEvents = new HashMap();
-    
+
+    private boolean _targetsResolved = false;
+
     /**
      * @throws ApplicationRuntimeException
      *             if the name already exists.
@@ -733,7 +734,19 @@
         if (property == null)
             return;
         
-        property.connectAutoSubmitEvents(form.getId());
+        property.connectAutoSubmitEvents(form.getIdPath());
+    }
+
+    public void rewireComponentId(String componentId, String idPath)
+    {
+        ComponentEventProperty prop = getComponentEvents(componentId);
+        if (prop == null)
+            return;
+
+        prop.rewireComponentId(idPath);
+        
+        _componentEvents.remove(componentId);
+        _componentEvents.put(idPath, prop);
     }
 
     /**
@@ -743,7 +756,12 @@
     {
         return (ComponentEventProperty)_componentEvents.get(id);
     }
-    
+
+    public Map getComponentEvents()
+    {
+        return _componentEvents;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -794,6 +812,16 @@
     public boolean hasElementEvents()
     {
         return _elementEvents.size() > 0;
+    }
+
+    public boolean getTargetsResolved()
+    {
+        return _targetsResolved;
+    }
+
+    public void setTargetsResolved(boolean resolved)
+    {
+        _targetsResolved = resolved;
     }
 
     /**