Package org.apache.tapestry.services.impl

Source Code of org.apache.tapestry.services.impl.ComponentEventInvoker

// Copyright May 20, 2006 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.tapestry.services.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.hivemind.util.Defense;
import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IForm;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.event.BrowserEvent;
import org.apache.tapestry.event.ResetEventListener;
import org.apache.tapestry.form.FormSupport;
import org.apache.tapestry.internal.event.ComponentEventProperty;
import org.apache.tapestry.internal.event.EventBoundListener;
import org.apache.tapestry.listener.ListenerInvoker;


/**
* Managed and handles invoking listener methods for components
* in response to requested event listener invocations.
*
* @author jkuhnert
*/
public class ComponentEventInvoker implements ResetEventListener
{
    private Map _components = new HashMap();
   
    private Map _elements = new HashMap();
   
    private ListenerInvoker _invoker;
   
    /**
     * Causes the configured listeners for the passed component to
     * be invoked.
     * @param component
     *          The component that recieved the invocations.
     * @param cycle
     *          The associated request.
     * @param event
     *          The event that started it all.
     */
    public void invokeListeners(IComponent component, IRequestCycle cycle,
            BrowserEvent event)
    {
        Defense.notNull(component, "component");
        Defense.notNull(cycle, "cycle");
        Defense.notNull(event, "event");
       
        String id = component.getId();
       
        if (hasEvents(id)) {
           
            ComponentEventProperty prop = getComponentEvents(id);
            invokeListeners(prop, component, cycle, event);
        }
       
        // else, may be an element invoked event
        String targetId = (String)event.getTarget().get("id");
       
        if (hasElementEvents(targetId)) {
           
            ComponentEventProperty prop = getElementEvents(id);
            invokeListeners(prop, component, cycle, event);
        }
    }
   
    void invokeListeners(ComponentEventProperty prop, IComponent component,
            IRequestCycle cycle, BrowserEvent event)
    {
        List listeners = prop.getEventListeners(event.getName());
        for (int i=0; i < listeners.size(); i++) {
            EventBoundListener eventListener = (EventBoundListener)listeners.get(i);
           
            IComponent container = component.getContainer();
            if (container == null) // only IPage has no container
                container = component;
           
            IActionListener listener =
                container.getListeners().getListener(eventListener.getMethodName());
            _invoker.invokeListener(listener, container, cycle);
        }
    }
   
    /**
     * Causes the configured listeners for the passed {@link FormSupport}'s {@link IForm) to
     * be invoked, if mapped to this request/event.
     *
     * @param formSupport
     *          The form support object being rendered.
     * @param cycle
     *          The associated request.
     * @param event
     *          The event that started it all.
     */
    public void invokeFormListeners(FormSupport formSupport, final IRequestCycle cycle,
            BrowserEvent event)
    {
        IForm component = formSupport.getForm();
        String id = component.getId();
       
        List listeners = getFormEvents(id, event);
       
        for (int i=0; i < listeners.size(); i++) {
            EventBoundListener eventListener = (EventBoundListener)listeners.get(i);
           
            final IComponent container =
                (component.getContainer() == null) ? component : component.getContainer();
           
            final IActionListener listener =
                container.getListeners().getListener(eventListener.getMethodName());
           
            // defer execution until after form is done rewinding
            component.addDeferredRunnable(new Runnable()
            {
                public void run()
                {
                    _invoker.invokeListener(listener, container, cycle);
                }
            });
        }
    }
   
    /**
     * Adds a deferred event listener binding for the specified component.
     *
     * @param componentId
     *          The component this is for.
     * @param events
     *          The events that should cause the listener to be executed.
     * @param methodName
     *          The page/component listener name that should be executed when
     *          one of the supplied events occurs.
     * @param async
     *          If submitting a form, whether or not to do it asynchronously.
     */
    public void addEventListener(String componentId, String[] events,
            String methodName, String formId, boolean validateForm, boolean async)
    {
        ComponentEventProperty property = getComponentEvents(componentId);
       
        property.addListener(events, methodName, formId, validateForm, async);
    }
   
    /**
     * Adds a deferred event listener binding for the specified html element.
     *
     * @param elementId
     * @param events
     * @param methodName
     * @param async
     *          If submitting a form, whether or not to do it asynchronously.
     */
    public void addElementEventListener(String elementId, String[] events,
            String methodName, String formId, boolean validateForm, boolean async)
    {
        ComponentEventProperty property = getElementEvents(elementId);
       
        property.addListener(events, methodName, formId, validateForm, async);
    }
   
    /**
     * Returns whether or not the specified component has any
     * connected events.
     *
     * @param componentId
     *          The unique component id to check.
     * @return True, if at least one listener is connected to the specified
     *          component.
     */
    public boolean hasEvents(String componentId)
    {
        return _components.get(componentId) != null;
    }
   
    /**
     *
     * @return True, if any html element events exist.
     */
    public boolean hasElementEvents()
    {
        return _elements.size() > 0;
    }
   
    /**
     *
     * @return True, if the html element has events.
     */
    public boolean hasElementEvents(String id)
    {
        return _elements.get(id) != null;
    }
   
    /**
     * Gets event properties fro the specified component, creates a new
     * instance if one doesn't exist already.
     *
     * @param id The component id
     * @return A new/existing instance.
     */
    public ComponentEventProperty getComponentEvents(String id)
    {
        ComponentEventProperty prop = (ComponentEventProperty)_components.get(id);
        if (prop == null) {
            prop = new ComponentEventProperty(id);
            _components.put(id, prop);
        }
       
        return prop;
    }
   
    /**
     * Listeners mapped with a submitForm=formId binding are a special case for the
     * invokers, as we can't just invoke them but must plug the EventListener in to
     * the normal form rewind logic. This handles mapping an incoming form submission
     * to our pre-mapped form event invokers.
     *
     * @param id
     *          The component id of the form.
     * @param event
     *          The browser event based on.
     * @return List of listeners on specified form/event combination, will be empty
     *          list if none found.
     */
    List getFormEvents(String id, BrowserEvent event)
    {
        List ret = new ArrayList();
       
        Iterator it = _components.values().iterator();
        while (it.hasNext()) {
            ComponentEventProperty prop = (ComponentEventProperty)it.next();
            prop.getFormEventListeners(id, event, ret);
        }
       
        it = _elements.values().iterator();
        while (it.hasNext()) {
            ComponentEventProperty prop = (ComponentEventProperty)it.next();
            prop.getFormEventListeners(id, event, ret);
        }
       
        return ret;
    }
   
    /**
     * Gets event properties fro the specified component, creates a new
     * instance if one doesn't exist already.
     *
     * @param id The component id
     * @return A new/existing instance.
     */
    public ComponentEventProperty getElementEvents(String id)
    {
        ComponentEventProperty prop = (ComponentEventProperty)_elements.get(id);
        if (prop == null) {
            prop = new ComponentEventProperty(id);
            _elements.put(id, prop);
        }
       
        return prop;
    }
   
    /**
     * Returns the {@link Map} being managed for element events.
     * @return
     */
    public Map getElementEvents()
    {
        return _elements;
    }
   
    public void resetEventDidOccur()
    {
        _components.clear();
        _elements.clear();
    }
   
    /**
     * Injected.
     * @param invoker
     */
    public void setListenerInvoker(ListenerInvoker invoker)
    {
        _invoker = invoker;
    }
}
TOP

Related Classes of org.apache.tapestry.services.impl.ComponentEventInvoker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.