Author: jkuhnert
Date: Sat Apr 28 12:50:32 2007
New Revision: 533422

URL: http://svn.apache.org/viewvc?view=rev&rev=533422
Log:
-) Made ComponentEventInvoker thread safe.

-) Added caching of component event properties for minor performance 
improvements in overall component rendering.

Modified:
    
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/services/impl/ComponentEventConnectionWorker.java
    
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java

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=533422&r1=533421&r2=533422
==============================================================================
--- 
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
 Sat Apr 28 12:50:32 2007
@@ -51,7 +51,17 @@
      * @return The bound listeners, or null if none exist.
      */
     List getEventListeners(String componentId);
-    
+
+    /**
+     * Gets all bound property event listeners for the specified 
componentIdPath.
+     *
+     * @param componentIdPath
+     *          The unique id path of the component, as returned from [EMAIL 
PROTECTED] org.apache.tapestry.IComponent#getIdPath()}.
+     *
+     * @return The aggregated array of all event properties bound to the 
specified component, empty if none exist.
+     */
+    ComponentEventProperty[] getEventPropertyListeners(String componentIdPath);
+
     /**
      * Adds a mapping for an event listener that should be triggered when the 
specified
      * form component with id of <code>formId</code> is submitted. This will 
later

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=533422&r1=533421&r2=533422
==============================================================================
--- 
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
 Sat Apr 28 12:50:32 2007
@@ -13,6 +13,7 @@
 // limitations under the License.
 package org.apache.tapestry.internal.event.impl;
 
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IActionListener;
 import org.apache.tapestry.IComponent;
@@ -26,6 +27,7 @@
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.listener.ListenerInvoker;
 import org.apache.tapestry.spec.IComponentSpecification;
+import org.apache.tapestry.spec.IEventListener;
 
 import java.util.*;
 
@@ -37,13 +39,18 @@
  */
 public class ComponentEventInvoker implements IComponentEventInvoker, 
ResetEventListener
 {
+    static final ComponentEventProperty[] EMPTY_PROPERTIES = new 
ComponentEventProperty[0];
+
     // Mapped component id path -> List of IEventListeners
-    private Map _components = new HashMap();
+    private Map _components = new ConcurrentHashMap();
     // Mapped form id path -> List of IEventListeners
-    private Map _formComponents = new HashMap();
+    private Map _formComponents = new ConcurrentHashMap();
     // Used to invoke actual listener methods
     private ListenerInvoker _invoker;
 
+    // Cached set of ComponentEventProperty[] arrays mapped to specific 
components
+    private Map _propertyCache = new ConcurrentHashMap();
+
     /**
      * [EMAIL PROTECTED]
      */
@@ -236,6 +243,8 @@
         if (!listeners.contains(listener)) {
             listeners.add(listener);
         }
+        
+        _propertyCache.remove(componentId);
     }
     
     /**
@@ -243,9 +252,40 @@
      */
     public List getEventListeners(String componentId)
     {
+        if (componentId == null)
+            return null;
+        
         return (List)_components.get(componentId);
     }
-    
+
+    public ComponentEventProperty[] getEventPropertyListeners(String 
componentIdPath)
+    {
+        if (componentIdPath == null)
+            return EMPTY_PROPERTIES;
+        
+        ComponentEventProperty[] ret = 
(ComponentEventProperty[])_propertyCache.get(componentIdPath);
+        if (ret != null)
+            return ret;
+
+        List listeners = getEventListeners(componentIdPath);
+        if (listeners == null || listeners.size() < 1)
+            return EMPTY_PROPERTIES;
+
+        List props = new ArrayList();
+        for (int i=0; i < listeners.size(); i++) {
+
+            IEventListener listener = (IEventListener)listeners.get(i);
+
+            props.add(listener.getComponentEvents(componentIdPath));
+        }
+
+        ret = (ComponentEventProperty[])props.toArray(new 
ComponentEventProperty[props.size()]);
+
+        _propertyCache.put(componentIdPath, ret);
+
+        return ret;
+    }
+
     /**
      * [EMAIL PROTECTED]
      */
@@ -268,6 +308,9 @@
      */
     public List getFormEventListeners(String formId)
     {
+        if (formId == null)
+            return null;
+        
         return (List)_formComponents.get(formId);
     }
     
@@ -278,6 +321,7 @@
     {
         _components.clear();
         _formComponents.clear();
+        _propertyCache.clear();
     }
     
     /** Injected. */

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=533422&r1=533421&r2=533422
==============================================================================
--- 
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
 Sat Apr 28 12:50:32 2007
@@ -26,7 +26,6 @@
 import org.apache.tapestry.internal.event.EventBoundListener;
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.services.ComponentRenderWorker;
-import org.apache.tapestry.spec.IEventListener;
 import org.apache.tapestry.util.ScriptUtils;
 
 import java.util.*;
@@ -96,7 +95,7 @@
     
     void linkComponentEvents(IRequestCycle cycle, IComponent component)
     {
-        ComponentEventProperty[] props = getComponentEvents(component);
+        ComponentEventProperty[] props = 
_invoker.getEventPropertyListeners(component.getIdPath());
         if (props == null)
             return;
         
@@ -128,24 +127,6 @@
         }
     }
     
-    ComponentEventProperty[] getComponentEvents(IComponent comp)
-    {
-        List listeners = _invoker.getEventListeners(comp.getIdPath());
-        if (listeners == null || listeners.size() < 1)
-            return null;
-
-        List ret = new ArrayList();
-        
-        for (int i=0; i < listeners.size(); i++) {
-            
-            IEventListener listener = (IEventListener)listeners.get(i);
-            
-            ret.add(listener.getComponentEvents(comp.getIdPath()));
-        }
-        
-        return (ComponentEventProperty[])ret.toArray(new 
ComponentEventProperty[ret.size()]);
-    }
-    
     void linkElementEvents(IRequestCycle cycle, IComponent component)
     {
         if (!component.getSpecification().hasElementEvents())
@@ -227,7 +208,7 @@
             
             linkElementEvents(cycle, component);
             
-            ComponentEventProperty[] props = getComponentEvents(component);
+            ComponentEventProperty[] props = 
_invoker.getEventPropertyListeners(component.getIdPath());
             if (props == null)
                 continue;
             

Modified: 
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java?view=diff&rev=533422&r1=533421&r2=533422
==============================================================================
--- 
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java
 (original)
+++ 
tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java
 Sat Apr 28 12:50:32 2007
@@ -73,6 +73,32 @@
         assertEquals(p.getFormEvents().size(), 1);
     }
 
+    public void test_Get_Event_Property_Listeners()
+    {
+        IComponentSpecification spec = new ComponentSpecification();
+        spec.setComponentClassName("first.test");
+        spec.addEventListener("comp1", new String[] {"onClick"}, "testFoo", 
null, false, true, false, false);
+        spec.addEventListener("comp1", new String[] {"onClick"}, "testBar", 
null, false, true, false, false);
+
+        IComponentSpecification spec2 = new ComponentSpecification();
+        spec.setComponentClassName("second.test"); // to make .equals unique
+        spec2.addEventListener("comp1", new String[] {"onClick"}, "testFoo", 
null, false, true, false, false);
+        spec2.addEventListener("comp1", new String[] {"onClick"}, "testBar", 
null, false, true, false, false);
+
+        ComponentEventInvoker invoker = new ComponentEventInvoker();
+        invoker.addEventListener("comp1", spec);
+        invoker.addEventListener("comp1", spec2);
+
+        ComponentEventProperty[] empty = 
invoker.getEventPropertyListeners("bogus");
+        assert empty != null;
+        assertEquals(empty.length, 0);
+
+        ComponentEventProperty[] props = 
invoker.getEventPropertyListeners("comp1");
+        assertEquals(props.length, 2);
+
+        assert invoker.getEventPropertyListeners("comp1") == props;
+    }
+
     public void test_Invoke_Component_Listener()
     {
         IRequestCycle cycle = newCycle();


Reply via email to