de.betterform.xml.events.impl.DefaultXMLEventService.java Source code

Java tutorial

Introduction

Here is the source code for de.betterform.xml.events.impl.DefaultXMLEventService.java

Source

/*
 * Copyright (c) 2012. betterFORM Project - http://www.betterform.de
 * Licensed under the terms of BSD License
 */

package de.betterform.xml.events.impl;

import de.betterform.xml.events.*;
import de.betterform.xml.xforms.XFormsElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Node;
import org.w3c.dom.events.EventTarget;

import java.util.HashMap;
import java.util.Map;

/**
 * XMLEventService provides a dispatching facility for XML Events. Additionally,
 * default actions can be registered per Event Target and Event type.
 *
 * @author Ulrich Nicolas Lissé
 * @version $Id: DefaultXMLEventService.java 2873 2007-09-28 09:08:48Z lars $
 */
public class DefaultXMLEventService implements XMLEventService {

    private static final Log LOGGER = LogFactory.getLog(DefaultXMLEventService.class);

    private XMLEventFactory eventFactory;
    private XMLEventInitializer eventInitializer;
    private Map defaultActions;

    /**
     * Returns the XML Event Factory.
     *
     * @return the XML Event Factory.
     */
    public XMLEventFactory getXMLEventFactory() {
        return this.eventFactory;
    }

    /**
     * Sets the XML Event Factory.
     *
     * @param eventFactory the XML Event Factory.
     */
    public void setXMLEventFactory(XMLEventFactory eventFactory) {
        this.eventFactory = eventFactory;
    }

    /**
     * Returns the XML Event Initializer.
     *
     * @return the XML Event Initializer.
     */
    public XMLEventInitializer getXMLEventInitializer() {
        return this.eventInitializer;
    }

    /**
     * Sets the XML Event Initializer.
     *
     * @param eventInitializer the XML Event Initializer.
     */
    public void setXMLEventInitializer(XMLEventInitializer eventInitializer) {
        this.eventInitializer = eventInitializer;
    }

    /**
     * Registers a default action for the specified event type occurring on
     * the given event target.
     * <p/>
     * Only one default action can be registered for a particular event type and
     * event target combination.
     *
     * @param target the event target.
     * @param type specifies the event type.
     * @param action the default action.
     */
    public void registerDefaultAction(EventTarget target, String type, DefaultAction action) {
        // check parameters, throw exception ?
        if (target == null || type == null || action == null) {
            return;
        }

        // check master map
        if (this.defaultActions == null) {
            this.defaultActions = new HashMap();
        }

        // check sub-map
        Map types = (Map) this.defaultActions.get(target);
        if (types == null) {
            types = new HashMap();
            this.defaultActions.put(target, types);
        }

        // store type/action association
        types.put(type, action);
    }

    /**
     * Deregisters a default action for the specified event type occurring on
     * the given event target.
     *
     * @param target the event target.
     * @param type specifies the event type.
     * @param action the default action.
     */
    public void deregisterDefaultAction(EventTarget target, String type, DefaultAction action) {
        // check parameters, throw exception ?
        if (target == null || type == null || action == null) {
            return;
        }

        // check master map
        if (this.defaultActions == null) {
            return;
        }

        // check sub-map
        Map types = (Map) this.defaultActions.get(target);
        if (types == null) {
            return;
        }

        // check default action
        DefaultAction current = (DefaultAction) types.get(type);
        if (current == null || !current.equals(action)) {
            return;
        }

        // remove type/action association
        types.remove(type);

        // memory clean-up
        if (types.isEmpty()) {
            this.defaultActions.remove(target);

            if (this.defaultActions.isEmpty()) {
                this.defaultActions = null;
            }
        }
    }

    /**
     * Dispatches the specified event to the given target.
     *
     * @param target the event target.
     * @param type specifies the event type.
     * @param bubbles specifies wether the event can bubble.
     * @param cancelable specifies wether the event's default action can be prevented.
     * @param context optionally specifies contextual information.
     * @return <code>true</code> if one of the event listeners called
     * <code>preventDefault</code>, otherwise <code>false</code>.
     */
    public boolean dispatch(EventTarget target, String type, boolean bubbles, boolean cancelable, Object context) {
        if (LOGGER.isDebugEnabled()) {
            if (target instanceof Node) {
                Node node = (Node) target;
                Object object = node.getUserData("");
                if (object instanceof XFormsElement) {
                    //Note: the cast seems pointless here but makes sure the right toString method is called
                    LOGGER.debug("dispatch event: " + type + " to " + ((XFormsElement) object).toString());
                }
            } else {
                LOGGER.debug("dispatch event: " + type + " to " + target);
            }
        }

        XMLEvent event = this.eventFactory.createXMLEvent(type);
        this.eventInitializer.initXMLEvent(event, type, bubbles, cancelable, context);

        long start;
        long end;

        start = System.currentTimeMillis();
        boolean preventDefault = target.dispatchEvent(event);
        end = System.currentTimeMillis();
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("dispatch event: " + type + " handling needed " + (end - start) + " ms");
        }

        if (!event.getCancelable() || !preventDefault) {
            DefaultAction action = lookup(target, type);

            if (action != null) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("dispatch event: " + type + " default action at " + action);
                }

                // todo: set event phase without downcast ?
                ((XercesXMLEvent) event).eventPhase = XMLEvent.DEFAULT_ACTION;
                start = System.currentTimeMillis();
                action.performDefault(event);
                end = System.currentTimeMillis();
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("dispatch event: " + type + " default action needed " + (end - start) + " ms");
                }
            }
        }

        return preventDefault;
    }

    protected DefaultAction lookup(EventTarget target, String type) {
        // check master map
        if (this.defaultActions == null) {
            return null;
        }

        // check sub-map
        Map types = (Map) this.defaultActions.get(target);
        if (types == null) {
            return null;
        }

        // check default action
        return (DefaultAction) types.get(type);
    }
}