Coverage Report - org.apache.tapestry.internal.event.impl.ComponentEventInvoker
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentEventInvoker
0%
0/110
0%
0/56
3.923
ComponentEventInvoker$FormRunnable
0%
0/7
N/A
3.923
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 package org.apache.tapestry.internal.event.impl;
 15  
 
 16  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 17  
 import org.apache.hivemind.util.Defense;
 18  
 import org.apache.tapestry.*;
 19  
 import org.apache.tapestry.event.BrowserEvent;
 20  
 import org.apache.tapestry.event.ResetEventListener;
 21  
 import org.apache.tapestry.form.FormSupport;
 22  
 import org.apache.tapestry.internal.event.ComponentEventProperty;
 23  
 import org.apache.tapestry.internal.event.EventBoundListener;
 24  
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 25  
 import org.apache.tapestry.listener.ListenerInvoker;
 26  
 import org.apache.tapestry.spec.IComponentSpecification;
 27  
 import org.apache.tapestry.spec.IEventListener;
 28  
 
 29  
 import java.util.ArrayList;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 
 33  
 
 34  
 /**
 35  
  * Implementation of {@link IComponentEventInvoker}.
 36  
  */
 37  0
 public class ComponentEventInvoker implements IComponentEventInvoker, ResetEventListener
 38  
 {
 39  0
     static final ComponentEventProperty[] EMPTY_PROPERTIES = new ComponentEventProperty[0];
 40  
 
 41  
     // Mapped component id path -> List of IEventListeners
 42  0
     private Map _components = new ConcurrentHashMap();
 43  
     // Mapped form id path -> List of IEventListeners
 44  0
     private Map _formComponents = new ConcurrentHashMap();
 45  
     // Used to invoke actual listener methods
 46  
     private ListenerInvoker _invoker;
 47  
 
 48  
     // Cached set of ComponentEventProperty[] arrays mapped to specific components
 49  0
     private Map _propertyCache = new ConcurrentHashMap();
 50  
 
 51  
     /**
 52  
      * {@inheritDoc}
 53  
      */
 54  
     public void invokeListeners(IComponent component, IRequestCycle cycle, BrowserEvent event)
 55  
     {
 56  0
         Defense.notNull(component, "component");
 57  0
         Defense.notNull(cycle, "cycle");
 58  0
         Defense.notNull(event, "event");
 59  
 
 60  0
         invokeComponentListeners(component, cycle, event);
 61  
 
 62  0
         invokeElementListeners(component, cycle, event);
 63  0
     }
 64  
 
 65  
     /**
 66  
      * {@inheritDoc}
 67  
      */
 68  
     public void invokeFormListeners(FormSupport formSupport, final IRequestCycle cycle, final BrowserEvent event)
 69  
     {
 70  0
         Defense.notNull(formSupport, "formSupport");
 71  0
         Defense.notNull(cycle, "cycle");
 72  0
         Defense.notNull(event, "event");
 73  
 
 74  0
         IForm form = formSupport.getForm();
 75  0
         String formIdPath = form.getExtendedId();
 76  
 
 77  0
         String targetId = (String)event.getTarget().get("id");
 78  0
         String componentIdPath = event.getComponentIdPath();
 79  
 
 80  0
         if (targetId == null || componentIdPath == null)
 81  0
             return;
 82  
 
 83  0
         List comps = getFormEventListeners(formIdPath);
 84  0
         if (comps == null)
 85  0
             return;
 86  
 
 87  0
         boolean disableFocus = false;
 88  
 
 89  0
         for (int i=0; i < comps.size(); i++)
 90  
         {
 91  0
             IComponentSpecification spec = (IComponentSpecification)comps.get(i);
 92  0
             EventBoundListener[] listeners = spec.getFormEvents(formIdPath, event);
 93  
 
 94  0
             IPage page = form.getPage();
 95  
             
 96  0
             for (int e=0; e < listeners.length; e++)
 97  
             {
 98  
                 // ensure ~only~ the method that targeted this event gets called!
 99  
 
 100  0
                 if (!listeners[e].getComponentId().equals(componentIdPath))
 101  0
                     continue;
 102  
 
 103  
                 // clear validation errors but not input if async validation is
 104  
                 // disabled
 105  
 
 106  0
                 if (!listeners[e].isValidateForm())
 107  
                 {
 108  0
                     form.getDelegate().clearErrors();
 109  
                 }
 110  
 
 111  
                 // handle disabling focus
 112  0
                 if (!disableFocus && !listeners[e].shouldFocusForm())
 113  0
                     disableFocus = true;
 114  
 
 115  0
                 IComponent target = page.getNestedComponent(listeners[e].getComponentIdPath());
 116  
 
 117  
                 // defer execution until after form is done rewinding
 118  
 
 119  0
                 form.addDeferredRunnable(
 120  
                         new FormRunnable(target.getListeners().getListener(listeners[e].getMethodName()),
 121  
                                          target,
 122  
                                          cycle));
 123  
             }
 124  
         }
 125  
 
 126  
         // Form uses cycle attributes to test whether or not to focus .
 127  
         // The attribute existing at all is enough to bypass focusing.
 128  
 
 129  0
         if (disableFocus)
 130  
         {
 131  0
             cycle.disableFocus();
 132  
         }
 133  0
     }
 134  
 
 135  
     void invokeComponentListeners(IComponent component, IRequestCycle cycle, BrowserEvent event)
 136  
     {
 137  0
         String idPath = component.getExtendedId();
 138  0
         List listeners = getEventListeners(idPath);
 139  
         
 140  0
         if (listeners == null)
 141  0
             return;
 142  
 
 143  0
         IPage page = component.getPage();
 144  
 
 145  0
         for (int i = 0; i < listeners.size(); i++)
 146  
         {
 147  0
             IComponentSpecification listener = (IComponentSpecification)listeners.get(i);
 148  
 
 149  0
             ComponentEventProperty props = listener.getComponentEvents(idPath);
 150  
             
 151  0
             if (props == null)
 152  0
                 continue;
 153  
 
 154  0
             List clisteners = props.getEventListeners(event.getName());
 155  0
             for (int e=0; e < clisteners.size(); e++)
 156  
             {
 157  0
                 EventBoundListener eventListener = (EventBoundListener)clisteners.get(e);
 158  
 
 159  0
                 IComponent target = page.getNestedComponent(eventListener.getComponentIdPath());
 160  
                 
 161  0
                 _invoker.invokeListener(target.getListeners().getListener(eventListener.getMethodName()), target, cycle);
 162  
             }
 163  
 
 164  
         }
 165  0
     }
 166  
 
 167  
     void invokeElementListeners(IComponent component, IRequestCycle cycle, BrowserEvent event)
 168  
     {
 169  0
         String targetId = (String)event.getTarget().get("id");
 170  0
         if (targetId == null)
 171  0
             return;
 172  
 
 173  0
         ComponentEventProperty prop = component.getSpecification().getElementEvents(targetId);
 174  0
         if (prop == null)
 175  0
             return;
 176  
 
 177  0
         List listeners = prop.getEventListeners(event.getName());
 178  
 
 179  0
         for (int i=0; i < listeners.size(); i++)
 180  
         {
 181  0
             EventBoundListener listener = (EventBoundListener)listeners.get(i);
 182  
 
 183  0
             _invoker.invokeListener(component.getListeners().getListener(listener.getMethodName()), component, cycle);
 184  
         }
 185  0
     }
 186  
 
 187  
     /** Local runnable for deferred form connections. */
 188  0
     class FormRunnable implements Runnable {
 189  
 
 190  
         private IActionListener _listener;
 191  
         private IComponent _component;
 192  
         private IRequestCycle _cycle;
 193  
 
 194  
         public FormRunnable(IActionListener listener, IComponent comp, IRequestCycle cycle)
 195  0
         {
 196  0
             _listener = listener;
 197  0
             _component = comp;
 198  0
             _cycle = cycle;
 199  0
         }
 200  
 
 201  
         public void run()
 202  
         {
 203  0
             _invoker.invokeListener(_listener, _component, _cycle);
 204  0
         }
 205  
     }
 206  
 
 207  
     /**
 208  
      * {@inheritDoc}
 209  
      */
 210  
     public void addEventListener(String componentId, IComponentSpecification listener)
 211  
     {
 212  0
         List listeners = (List)_components.get(componentId);
 213  
 
 214  0
         if (listeners == null)
 215  
         {
 216  0
             listeners = new ArrayList();
 217  0
             _components.put(componentId, listeners);
 218  
         }
 219  
 
 220  0
         if (!listeners.contains(listener))
 221  
         {
 222  0
             listeners.add(listener);
 223  
         }
 224  
 
 225  0
         _propertyCache.remove(componentId);
 226  0
     }
 227  
 
 228  
     /**
 229  
      * {@inheritDoc}
 230  
      */
 231  
     public List getEventListeners(String componentId)
 232  
     {
 233  0
         if (componentId == null)
 234  0
             return null;
 235  
 
 236  0
         return (List)_components.get(componentId);
 237  
     }
 238  
 
 239  
     public ComponentEventProperty[] getEventPropertyListeners(String componentIdPath)
 240  
     {
 241  0
         if (componentIdPath == null)
 242  0
             return EMPTY_PROPERTIES;
 243  
 
 244  0
         ComponentEventProperty[] ret = (ComponentEventProperty[])_propertyCache.get(componentIdPath);
 245  0
         if (ret != null)
 246  0
             return ret;
 247  
 
 248  0
         List listeners = getEventListeners(componentIdPath);
 249  0
         if (listeners == null || listeners.size() < 1)
 250  0
             return EMPTY_PROPERTIES;
 251  
 
 252  0
         List props = new ArrayList();
 253  0
         for (int i=0; i < listeners.size(); i++)
 254  
         {
 255  0
             IEventListener listener = (IEventListener)listeners.get(i);
 256  
 
 257  0
             props.add(listener.getComponentEvents(componentIdPath));
 258  
         }
 259  
 
 260  0
         ret = (ComponentEventProperty[])props.toArray(new ComponentEventProperty[props.size()]);
 261  
 
 262  0
         _propertyCache.put(componentIdPath, ret);
 263  
 
 264  0
         return ret;
 265  
     }
 266  
 
 267  
     /**
 268  
      * {@inheritDoc}
 269  
      */
 270  
     public void addFormEventListener(String formId, IComponentSpecification listener)
 271  
     {
 272  0
         List listeners = (List)_formComponents.get(formId);
 273  
 
 274  0
         if (listeners == null)
 275  
         {
 276  0
             listeners = new ArrayList();
 277  0
             _formComponents.put(formId, listeners);
 278  
         }
 279  
 
 280  0
         if (!listeners.contains(listener))
 281  
         {
 282  0
             listeners.add(listener);
 283  
         }
 284  0
     }
 285  
 
 286  
     /**
 287  
      * {@inheritDoc}
 288  
      */
 289  
     public List getFormEventListeners(String formId)
 290  
     {
 291  0
         if (formId == null)
 292  0
             return null;
 293  
 
 294  0
         return (List)_formComponents.get(formId);
 295  
     }
 296  
 
 297  
     /**
 298  
      * {@inheritDoc}
 299  
      */
 300  
     public void resetEventDidOccur()
 301  
     {
 302  0
         _components.clear();
 303  0
         _formComponents.clear();
 304  0
         _propertyCache.clear();
 305  0
     }
 306  
 
 307  
     /** Injected. */
 308  
     public void setInvoker(ListenerInvoker invoker)
 309  
     {
 310  0
         _invoker = invoker;
 311  0
     }
 312  
 }