/*

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You 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.batik.bridge.svg12;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeSet;
import java.util.List;
import java.util.Map;

import javax.swing.event.EventListenerList;

import org.apache.batik.anim.dom.BindableElement;
import org.apache.batik.anim.dom.XBLEventSupport;
import org.apache.batik.anim.dom.XBLOMContentElement;
import org.apache.batik.anim.dom.XBLOMDefinitionElement;
import org.apache.batik.anim.dom.XBLOMImportElement;
import org.apache.batik.anim.dom.XBLOMShadowTreeElement;
import org.apache.batik.anim.dom.XBLOMTemplateElement;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.BridgeException;
import org.apache.batik.bridge.ErrorConstants;
import org.apache.batik.dom.AbstractAttrNS;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.dom.AbstractNode;
import org.apache.batik.dom.events.NodeEventTarget;
import org.apache.batik.dom.xbl.NodeXBL;
import org.apache.batik.dom.xbl.ShadowTreeEvent;
import org.apache.batik.dom.xbl.XBLManager;
import org.apache.batik.dom.xbl.XBLManagerData;
import org.apache.batik.dom.xbl.XBLShadowTreeElement;
import org.apache.batik.util.DoublyIndexedTable;
import org.apache.batik.util.XBLConstants;
import org.apache.batik.util.XMLConstants;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MutationEvent;

/**
 * A full featured sXBL manager.
 *
 * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
 * @version $Id$
 */
public class DefaultXBLManager implements XBLManager, XBLConstants {

    /**
     * Whether XBL processing is currently taking place.
     */
    protected boolean isProcessing;

    /**
     * The document.
     */
    protected Document document;

    /**
     * The BridgeContext.
     */
    protected BridgeContext ctx;

    /**
     * Map of namespace URI/local name pairs to ordered sets of
     * definition records.
     */
    protected DoublyIndexedTable definitionLists = new DoublyIndexedTable();

    /**
     * Map of definition element/import element pairs to definition records.
     */
    protected DoublyIndexedTable definitions = new DoublyIndexedTable();

    /**
     * Map of shadow trees to content managers.
     */
    protected Map contentManagers = new HashMap();

    /**
     * Map of import elements to import records.
     */
    protected Map imports = new HashMap();

    /**
     * DOM node inserted listener for the document.
     */
    protected DocInsertedListener docInsertedListener
        = new DocInsertedListener();

    /**
     * DOM node removed listener for the document.
     */
    protected DocRemovedListener docRemovedListener
        = new DocRemovedListener();

    /**
     * DOM subtree mutation listener for the document.
     */
    protected DocSubtreeListener docSubtreeListener
        = new DocSubtreeListener();

    /**
     * DOM attribute listener for import elements.
     */
    protected ImportAttrListener importAttrListener = new ImportAttrListener();

    /**
     * DOM attribute listener for referencing definition elements.
     */
    protected RefAttrListener refAttrListener = new RefAttrListener();

    /**
     * Global event listener list for XBL binding related events.
     */
    protected EventListenerList bindingListenerList = new EventListenerList();

    /**
     * Global event listener list for ContentSelectionChanged events.
     */
    protected EventListenerList contentSelectionChangedListenerList
        = new EventListenerList();

    /**
     * Creates a new DefaultXBLManager for the given document.
     */
    public DefaultXBLManager(Document doc, BridgeContext ctx) {
        document = doc;
        this.ctx = ctx;
        ImportRecord ir = new ImportRecord(null, null);
        imports.put(null, ir);
    }

    /**
     * Starts XBL processing on the document.
     */
    public void startProcessing() {
        if (isProcessing) {
            return;
        }

        // Get list of all current definitions in the document.
        NodeList nl = document.getElementsByTagNameNS(XBL_NAMESPACE_URI,
                                                      XBL_DEFINITION_TAG);
        XBLOMDefinitionElement[] defs
            = new XBLOMDefinitionElement[nl.getLength()];
        for (int i = 0; i < defs.length; i++) {
            defs[i] = (XBLOMDefinitionElement) nl.item(i);
        }

        // Get list of all imports in the document.
        nl = document.getElementsByTagNameNS(XBL_NAMESPACE_URI,
                                             XBL_IMPORT_TAG);
        Element[] imports
            = new Element[nl.getLength()];
        for (int i = 0; i < imports.length; i++) {
            imports[i] = (Element) nl.item(i);
        }

        // Add document listeners.
        AbstractDocument doc = (AbstractDocument) document;
        XBLEventSupport es = (XBLEventSupport) doc.initializeEventSupport();
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             docRemovedListener, true);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             docInsertedListener, true);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMSubtreeModified",
             docSubtreeListener, true);

        // Add definitions.
        for (XBLOMDefinitionElement def : defs) {
            if (def.getAttributeNS(null, XBL_REF_ATTRIBUTE).length() != 0) {
                addDefinitionRef(def);
            } else {
                String ns = def.getElementNamespaceURI();
                String ln = def.getElementLocalName();
                addDefinition(ns, ln, def, null);
            }
        }

        // Add imports.
        for (Element anImport : imports) {
            addImport(anImport);
        }

        // Bind all of the bindable elements in the document that have a
        // matching definition.
        isProcessing = true;
        bind(document.getDocumentElement());
    }

    /**
     * Stops XBL processing on the document.
     */
    public void stopProcessing() {
        if (!isProcessing) {
            return;
        }
        isProcessing = false;

        // Remove document listeners.
        AbstractDocument doc = (AbstractDocument) document;
        XBLEventSupport es = (XBLEventSupport) doc.initializeEventSupport();
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             docRemovedListener, true);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             docInsertedListener, true);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMSubtreeModified",
             docSubtreeListener, true);

        // Remove all imports.
        int nSlots = imports.values().size();
        ImportRecord[] irs = new ImportRecord[ nSlots ];
        imports.values().toArray( irs );
        for (ImportRecord ir : irs) {
            if (ir.importElement.getLocalName().equals(XBL_DEFINITION_TAG)) {
                removeDefinitionRef(ir.importElement);
            } else {
                removeImport(ir.importElement);
            }
        }

        // Remove all bindings.
        Object[] defRecs = definitions.getValuesArray();
        definitions.clear();
        for (Object defRec1 : defRecs) {
            DefinitionRecord defRec = (DefinitionRecord) defRec1;
            TreeSet defs = (TreeSet) definitionLists.get(defRec.namespaceURI,
                    defRec.localName);
            if (defs != null) {
                while (!defs.isEmpty()) {
                    defRec = (DefinitionRecord) defs.first();
                    defs.remove(defRec);
                    removeDefinition(defRec);
                }
                definitionLists.put(defRec.namespaceURI, defRec.localName, null);
            }
        }
        definitionLists = new DoublyIndexedTable();
        contentManagers.clear();
    }

    /**
     * Returns whether XBL processing is currently enabled.
     */
    public boolean isProcessing() {
        return isProcessing;
    }

    /**
     * Adds a definition through its referring definition element (one
     * with a 'ref' attribute).
     */
    protected void addDefinitionRef(Element defRef) {
        String ref = defRef.getAttributeNS(null, XBL_REF_ATTRIBUTE);
        Element e = ctx.getReferencedElement(defRef, ref);
        if (!XBL_NAMESPACE_URI.equals(e.getNamespaceURI())
                || !XBL_DEFINITION_TAG.equals(e.getLocalName())) {
            throw new BridgeException
                (ctx, defRef, ErrorConstants.ERR_URI_BAD_TARGET,
                 new Object[] { ref });
        }
        ImportRecord ir = new ImportRecord(defRef, e);
        imports.put(defRef, ir);

        NodeEventTarget et = (NodeEventTarget) defRef;
        et.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMAttrModified",
             refAttrListener, false, null);

        XBLOMDefinitionElement d = (XBLOMDefinitionElement) defRef;
        String ns = d.getElementNamespaceURI();
        String ln = d.getElementLocalName();
        addDefinition(ns, ln, (XBLOMDefinitionElement) e, defRef);
    }

    /**
     * Removes a definition through its referring definition element (one
     * with a 'ref' attribute).
     */
    protected void removeDefinitionRef(Element defRef) {
        ImportRecord ir = (ImportRecord) imports.get(defRef);
        NodeEventTarget et = (NodeEventTarget) defRef;
        et.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMAttrModified",
             refAttrListener, false);
        DefinitionRecord defRec
            = (DefinitionRecord) definitions.get(ir.node, defRef);
        removeDefinition(defRec);
        imports.remove(defRef);
    }

    /**
     * Imports bindings from another document.
     */
    protected void addImport(Element imp) {
        String bindings = imp.getAttributeNS(null, XBL_BINDINGS_ATTRIBUTE);
        Node n = ctx.getReferencedNode(imp, bindings);
        if (n.getNodeType() == Node.ELEMENT_NODE
                && !(XBL_NAMESPACE_URI.equals(n.getNamespaceURI())
                        && XBL_XBL_TAG.equals(n.getLocalName()))) {
            throw new BridgeException
                (ctx, imp, ErrorConstants.ERR_URI_BAD_TARGET,
                 new Object[] { n });
        }
        ImportRecord ir = new ImportRecord(imp, n);
        imports.put(imp, ir);

        NodeEventTarget et = (NodeEventTarget) imp;
        et.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMAttrModified",
             importAttrListener, false, null);

        et = (NodeEventTarget) n;
        et.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeInserted",
             ir.importInsertedListener, false, null);
        et.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeRemoved",
             ir.importRemovedListener, false, null);
        et.addEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
             ir.importSubtreeListener, false, null);
        addImportedDefinitions(imp, n);
    }

    /**
     * Adds the definitions in the given imported subtree.
     */
    protected void addImportedDefinitions(Element imp, Node n) {
        if (n instanceof XBLOMDefinitionElement) {
            XBLOMDefinitionElement def = (XBLOMDefinitionElement) n;
            String ns = def.getElementNamespaceURI();
            String ln = def.getElementLocalName();
            addDefinition(ns, ln, def, imp);
        } else {
            n = n.getFirstChild();
            while (n != null) {
                addImportedDefinitions(imp, n);
                n = n.getNextSibling();
            }
        }
    }

    /**
     * Removes an import.
     */
    protected void removeImport(Element imp) {
        ImportRecord ir = (ImportRecord) imports.get(imp);
        NodeEventTarget et = (NodeEventTarget) ir.node;
        et.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeInserted",
             ir.importInsertedListener, false);
        et.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMNodeRemoved",
             ir.importRemovedListener, false);
        et.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMSubtreeModified",
             ir.importSubtreeListener, false);

        et = (NodeEventTarget) imp;
        et.removeEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMAttrModified",
             importAttrListener, false);

        Object[] defRecs = definitions.getValuesArray();
        for (Object defRec1 : defRecs) {
            DefinitionRecord defRec = (DefinitionRecord) defRec1;
            if (defRec.importElement == imp) {
                removeDefinition(defRec);
            }
        }
        imports.remove(imp);
    }

    /**
     * Adds an xbl:definition element to the list of definitions that
     * could possibly affect elements with the specified QName.  This
     * may or may not actually cause a new binding to come in to effect,
     * as this new definition element may be added earlier in the
     * document than another already in effect.
     *
     * @param namespaceURI the namespace URI of the bound elements
     * @param localName the local name of the bound elements
     * @param def the xbl:definition element
     * @param imp the xbl:import or xbl;definition element through which
     *            this definition is being added, or null if the binding
     *            is in the original document
     */
    protected void addDefinition(String namespaceURI,
                                 String localName,
                                 XBLOMDefinitionElement def,
                                 Element imp) {
        ImportRecord ir = (ImportRecord) imports.get(imp);
        DefinitionRecord oldDefRec = null;
        DefinitionRecord defRec;
        TreeSet defs = (TreeSet) definitionLists.get(namespaceURI, localName);
        if (defs == null) {
            defs = new TreeSet();
            definitionLists.put(namespaceURI, localName, defs);
        } else if (defs.size() > 0) {
            oldDefRec = (DefinitionRecord) defs.first();
        }
        XBLOMTemplateElement template = null;
        for (Node n = def.getFirstChild(); n != null; n = n.getNextSibling()) {
            if (n instanceof XBLOMTemplateElement) {
                template = (XBLOMTemplateElement) n;
                break;
            }
        }
        defRec = new DefinitionRecord(namespaceURI, localName, def,
                template, imp);
        defs.add(defRec);
        definitions.put(def, imp, defRec);
        addDefinitionElementListeners(def, ir);
        if (defs.first() != defRec) {
            return;
        }
        if (oldDefRec != null) {
            XBLOMDefinitionElement oldDef = oldDefRec.definition;
            XBLOMTemplateElement oldTemplate = oldDefRec.template;
            if (oldTemplate != null) {
                removeTemplateElementListeners(oldTemplate, ir);
            }
            removeDefinitionElementListeners(oldDef, ir);
        }
        if (template != null) {
            addTemplateElementListeners(template, ir);
        }
        if (isProcessing) {
            rebind(namespaceURI, localName, document.getDocumentElement());
        }
    }

    /**
     * Adds DOM mutation listeners to the given definition element.
     */
    protected void addDefinitionElementListeners(XBLOMDefinitionElement def,
                                                 ImportRecord ir) {
        XBLEventSupport es = (XBLEventSupport) def.initializeEventSupport();
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMAttrModified",
             ir.defAttrListener, false);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             ir.defNodeInsertedListener, false);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             ir.defNodeRemovedListener, false);
    }

    /**
     * Adds DOM mutation listeners to the given template element.
     */
    protected void addTemplateElementListeners(XBLOMTemplateElement template,
                                               ImportRecord ir) {
        XBLEventSupport es
            = (XBLEventSupport) template.initializeEventSupport();
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMAttrModified",
             ir.templateMutationListener, false);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             ir.templateMutationListener, false);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             ir.templateMutationListener, false);
        es.addImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMCharacterDataModified",
             ir.templateMutationListener, false);
    }

    /**
     * Removes an xbl:definition element from the list of definitions that
     * could possibly affect elements with the specified QName.  This
     * will only cause a new binding to come in to effect if it is currently
     * active.
     */
    protected void removeDefinition(DefinitionRecord defRec) {
        TreeSet defs = (TreeSet) definitionLists.get(defRec.namespaceURI,
                                                     defRec.localName);
        if (defs == null) {
            return;
        }
        Element imp = defRec.importElement;
        ImportRecord ir = (ImportRecord) imports.get(imp);
        DefinitionRecord activeDefRec = (DefinitionRecord) defs.first();
        defs.remove(defRec);
        definitions.remove(defRec.definition, imp);
        removeDefinitionElementListeners(defRec.definition, ir);
        if (defRec != activeDefRec) {
            return;
        }
        if (defRec.template != null) {
            removeTemplateElementListeners(defRec.template, ir);
        }
        rebind(defRec.namespaceURI, defRec.localName,
               document.getDocumentElement());
    }

    /**
     * Removes DOM mutation listeners from the given definition element.
     */
    protected void removeDefinitionElementListeners
            (XBLOMDefinitionElement def,
             ImportRecord ir) {
        XBLEventSupport es = (XBLEventSupport) def.initializeEventSupport();
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMAttrModified",
             ir.defAttrListener, false);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             ir.defNodeInsertedListener, false);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             ir.defNodeRemovedListener, false);
    }

    /**
     * Removes DOM mutation listeners from the given template element.
     */
    protected void removeTemplateElementListeners
            (XBLOMTemplateElement template,
             ImportRecord ir) {
        XBLEventSupport es
            = (XBLEventSupport) template.initializeEventSupport();
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMAttrModified",
             ir.templateMutationListener, false);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeInserted",
             ir.templateMutationListener, false);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMNodeRemoved",
             ir.templateMutationListener, false);
        es.removeImplementationEventListenerNS
            (XMLConstants.XML_EVENTS_NAMESPACE_URI,
             "DOMCharacterDataModified",
             ir.templateMutationListener, false);
    }

    /**
     * Returns the definition record of the active definition for namespace
     * URI/local name pair.
     */
    protected DefinitionRecord getActiveDefinition(String namespaceURI,
                                                   String localName) {
        TreeSet defs = (TreeSet) definitionLists.get(namespaceURI, localName);
        if (defs == null || defs.size() == 0) {
            return null;
        }
        return (DefinitionRecord) defs.first();
    }

    /**
     * Unbinds each bindable element in the given element's subtree.
     */
    protected void unbind(Element e) {
        if (e instanceof BindableElement) {
            setActiveDefinition((BindableElement) e, null);
        } else {
            NodeList nl = getXblScopedChildNodes(e);
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item(i);
                if (n.getNodeType() == Node.ELEMENT_NODE) {
                    unbind((Element) n);
                }
            }
        }
    }

    /**
     * Binds each bindable element in the given element's subtree.
     */
    protected void bind(Element e) {
        AbstractDocument doc = (AbstractDocument) e.getOwnerDocument();
        if (doc != document) {
            XBLManager xm = doc.getXBLManager();
            if (xm instanceof DefaultXBLManager) {
                ((DefaultXBLManager) xm).bind(e);
                return;
            }
        }

        if (e instanceof BindableElement) {
            DefinitionRecord defRec
                = getActiveDefinition(e.getNamespaceURI(),
                                      e.getLocalName());
            setActiveDefinition((BindableElement) e, defRec);
        } else {
            NodeList nl = getXblScopedChildNodes(e);
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item(i);
                if (n.getNodeType() == Node.ELEMENT_NODE) {
                    bind((Element) n);
                }
            }
        }
    }

    /**
     * Rebinds each bindable element of the given name in the given element's
     * subtree.
     */
    protected void rebind(String namespaceURI, String localName, Element e) {
        AbstractDocument doc = (AbstractDocument) e.getOwnerDocument();
        if (doc != document) {
            XBLManager xm = doc.getXBLManager();
            if (xm instanceof DefaultXBLManager) {
                ((DefaultXBLManager) xm).rebind(namespaceURI, localName, e);
                return;
            }
        }

        if (e instanceof BindableElement
                && namespaceURI.equals(e.getNamespaceURI())
                && localName.equals(e.getLocalName())) {
            DefinitionRecord defRec
                = getActiveDefinition(e.getNamespaceURI(),
                                      e.getLocalName());
            setActiveDefinition((BindableElement) e, defRec);
        } else {
            NodeList nl = getXblScopedChildNodes(e);
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item(i);
                if (n.getNodeType() == Node.ELEMENT_NODE) {
                    rebind(namespaceURI, localName, (Element) n);
                }
            }
        }
    }

    /**
     * Sets the given definition as the active one for a particular
     * bindable element.
     */
    protected void setActiveDefinition(BindableElement elt,
                                       DefinitionRecord defRec) {
        XBLRecord rec = getRecord(elt);
        rec.definitionElement = defRec == null ? null : defRec.definition;
        if (defRec != null
                && defRec.definition != null
                && defRec.template != null) {
            setXblShadowTree(elt, cloneTemplate(defRec.template));
        } else {
            setXblShadowTree(elt, null);
        }
    }

    /**
     * Sets the shadow tree for the given bindable element.
     */
    protected void setXblShadowTree(BindableElement elt,
                                    XBLOMShadowTreeElement newShadow) {
        XBLOMShadowTreeElement oldShadow
            = (XBLOMShadowTreeElement) getXblShadowTree(elt);
        if (oldShadow != null) {
            fireShadowTreeEvent(elt, XBL_UNBINDING_EVENT_TYPE, oldShadow);
            ContentManager cm = getContentManager(oldShadow);
            if (cm != null) {
                cm.dispose();
            }
            elt.setShadowTree(null);
            XBLRecord rec = getRecord(oldShadow);
            rec.boundElement = null;
            oldShadow.removeEventListenerNS
                (XMLConstants.XML_EVENTS_NAMESPACE_URI,
                 "DOMSubtreeModified",
                 docSubtreeListener, false);
        }
        if (newShadow != null) {
            newShadow.addEventListenerNS
                (XMLConstants.XML_EVENTS_NAMESPACE_URI,
                 "DOMSubtreeModified",
                 docSubtreeListener, false, null);
            fireShadowTreeEvent(elt, XBL_PREBIND_EVENT_TYPE, newShadow);
            elt.setShadowTree(newShadow);
            XBLRecord rec = getRecord(newShadow);
            rec.boundElement = elt;
            AbstractDocument doc
                = (AbstractDocument) elt.getOwnerDocument();
            XBLManager xm = doc.getXBLManager();
            ContentManager cm = new ContentManager(newShadow, xm);
            setContentManager(newShadow, cm);
        }
        invalidateChildNodes(elt);
        if (newShadow != null) {
            NodeList nl = getXblScopedChildNodes(elt);
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item(i);
                if (n.getNodeType() == Node.ELEMENT_NODE) {
                    bind((Element) n);
                }
            }
            dispatchBindingChangedEvent(elt, newShadow);
            fireShadowTreeEvent(elt, XBL_BOUND_EVENT_TYPE, newShadow);
        } else {
            dispatchBindingChangedEvent(elt, newShadow);
        }
    }

    /**
     * Fires a ShadowTreeEvent of the given type on this element.
     */
    protected void fireShadowTreeEvent(BindableElement elt,
                                       String type,
                                       XBLShadowTreeElement e) {
        DocumentEvent de = (DocumentEvent) elt.getOwnerDocument();
        ShadowTreeEvent evt
            = (ShadowTreeEvent) de.createEvent("ShadowTreeEvent");
        evt.initShadowTreeEventNS(XBL_NAMESPACE_URI, type, true, false, e);
        elt.dispatchEvent(evt);
    }

    /**
     * Clones a template element for use as a shadow tree.
     */
    protected XBLOMShadowTreeElement cloneTemplate
            (XBLOMTemplateElement template) {
        XBLOMShadowTreeElement clone =
            (XBLOMShadowTreeElement)
            template.getOwnerDocument().createElementNS(XBL_NAMESPACE_URI,
                                                        XBL_SHADOW_TREE_TAG);
        NamedNodeMap attrs = template.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            Attr attr = (Attr) attrs.item(i);
            if (attr instanceof AbstractAttrNS) {
                clone.setAttributeNodeNS(attr);
            } else {
                clone.setAttributeNode(attr);
            }
        }
        for (Node n = template.getFirstChild();
                n != null;
                n = n.getNextSibling()) {
            clone.appendChild(n.cloneNode(true));
        }
        return clone;
    }

    /**
     * Get the parent of a node in the fully flattened tree.
     */
    public Node getXblParentNode(Node n) {
        Node contentElement = getXblContentElement(n);
        Node parent = contentElement == null
                        ? n.getParentNode()
                        : contentElement.getParentNode();
        if (parent instanceof XBLOMContentElement) {
            parent = parent.getParentNode();
        }
        if (parent instanceof XBLOMShadowTreeElement) {
            parent = getXblBoundElement(parent);
        }
        return parent;
    }

    /**
     * Get the list of child nodes of a node in the fully flattened tree.
     */
    public NodeList getXblChildNodes(Node n) {
        XBLRecord rec = getRecord(n);
        if (rec.childNodes == null) {
            rec.childNodes = new XblChildNodes(rec);
        }
        return rec.childNodes;
    }

    /**
     * Get the list of child nodes of a node in the fully flattened tree
     * that are within the same shadow scope.
     */
    public NodeList getXblScopedChildNodes(Node n) {
        XBLRecord rec = getRecord(n);
        if (rec.scopedChildNodes == null) {
            rec.scopedChildNodes = new XblScopedChildNodes(rec);
        }
        return rec.scopedChildNodes;
    }

    /**
     * Get the first child node of a node in the fully flattened tree.
     */
    public Node getXblFirstChild(Node n) {
        NodeList nl = getXblChildNodes(n);
        return nl.item(0);
    }

    /**
     * Get the last child node of a node in the fully flattened tree.
     */
    public Node getXblLastChild(Node n) {
        NodeList nl = getXblChildNodes(n);
        return nl.item(nl.getLength() - 1);
    }

    /**
     * Get the node which directly precedes a node in the xblParentNode's
     * xblChildNodes list.
     */
    public Node getXblPreviousSibling(Node n) {
        Node p = getXblParentNode(n);
        if (p == null || getRecord(p).childNodes == null) {
            return n.getPreviousSibling();
        }
        XBLRecord rec = getRecord(n);
        if (!rec.linksValid) {
            updateLinks(n);
        }
        return rec.previousSibling;
    }

    /**
     * Get the node which directly follows a node in the xblParentNode's
     * xblChildNodes list.
     */
    public Node getXblNextSibling(Node n) {
        Node p = getXblParentNode(n);
        if (p == null || getRecord(p).childNodes == null) {
            return n.getNextSibling();
        }
        XBLRecord rec = getRecord(n);
        if (!rec.linksValid) {
            updateLinks(n);
        }
        return rec.nextSibling;
    }

    /**
     * Get the first element child of a node in the fully flattened tree.
     */
    public Element getXblFirstElementChild(Node n) {
        n = getXblFirstChild(n);
        while (n != null && n.getNodeType() != Node.ELEMENT_NODE) {
            n = getXblNextSibling(n);
        }
        return (Element) n;
    }

    /**
     * Get the last element child of a node in the fully flattened tree.
     */
    public Element getXblLastElementChild(Node n) {
        n = getXblLastChild(n);
        while (n != null && n.getNodeType() != Node.ELEMENT_NODE) {
            n = getXblPreviousSibling(n);
        }
        return (Element) n;
    }

    /**
     * Get the first element that precedes the a node in the
     * xblParentNode's xblChildNodes list.
     */
    public Element getXblPreviousElementSibling(Node n) {
        do {
            n = getXblPreviousSibling(n);
        } while (n != null && n.getNodeType() != Node.ELEMENT_NODE);
        return (Element) n;
    }

    /**
     * Get the first element that follows a node in the
     * xblParentNode's xblChildNodes list.
     */
    public Element getXblNextElementSibling(Node n) {
        do {
            n = getXblNextSibling(n);
        } while (n != null && n.getNodeType() != Node.ELEMENT_NODE);
        return (Element) n;
    }

    /**
     * Get the bound element whose shadow tree a node resides in.
     */
    public Element getXblBoundElement(Node n) {
        while (n != null && !(n instanceof XBLShadowTreeElement)) {
            XBLOMContentElement content = getXblContentElement(n);
            if (content != null) {
                n = content;
            }
            n = n.getParentNode();
        }
        if (n == null) {
            return null;
        }
        return getRecord(n).boundElement;
    }

    /**
     * Get the shadow tree of a node.
     */
    public Element getXblShadowTree(Node n) {
        if (n instanceof BindableElement) {
            BindableElement elt = (BindableElement) n;
            return elt.getShadowTree();
        }
        return null;
    }

    /**
     * Get the xbl:definition elements currently binding an element.
     */
    public NodeList getXblDefinitions(Node n) {
        final String namespaceURI = n.getNamespaceURI();
        final String localName = n.getLocalName();
        return new NodeList() {
            public Node item(int i) {
                TreeSet defs = (TreeSet) definitionLists.get(namespaceURI, localName);
                if (defs != null && defs.size() != 0 && i == 0) {
                    DefinitionRecord defRec = (DefinitionRecord) defs.first();
                    return defRec.definition;
                }
                return null;
            }
            public int getLength() {
                Set defs = (TreeSet) definitionLists.get(namespaceURI, localName);
                return defs != null && defs.size() != 0 ? 1 : 0;
            }
        };
    }

    /**
     * Returns the XBL record for the given node.
     */
    protected XBLRecord getRecord(Node n) {
        XBLManagerData xmd = (XBLManagerData) n;
        XBLRecord rec = (XBLRecord) xmd.getManagerData();
        if (rec == null) {
            rec = new XBLRecord();
            rec.node = n;
            xmd.setManagerData(rec);
        }
        return rec;
    }

    /**
     * Updates the xblPreviousSibling and xblNextSibling properties of the
     * given XBL node.
     */
    protected void updateLinks(Node n) {
        XBLRecord rec = getRecord(n);
        rec.previousSibling = null;
        rec.nextSibling = null;
        rec.linksValid = true;
        Node p = getXblParentNode(n);
        if (p != null) {
            NodeList xcn = getXblChildNodes(p);
            if (xcn instanceof XblChildNodes) {
                ((XblChildNodes) xcn).update();
            }
        }
    }

    /**
     * Returns the content element that caused the given node to be
     * present in the flattened tree.
     */
    public XBLOMContentElement getXblContentElement(Node n) {
        return getRecord(n).contentElement;
    }

    /**
     * Determines the number of nodes events should bubble if the
     * mouse pointer has moved from one element to another.
     * @param from the element from which the mouse pointer moved
     * @param to   the element to which the mouse pointer moved
     */
    public static int computeBubbleLimit(Node from, Node to) {
        ArrayList fromList = new ArrayList(10);
        ArrayList toList = new ArrayList(10);
        while (from != null) {
            fromList.add(from);
            from = ((NodeXBL) from).getXblParentNode();
        }
        while (to != null) {
            toList.add(to);
            to = ((NodeXBL) to).getXblParentNode();
        }
        int fromSize = fromList.size();
        int toSize = toList.size();
        for (int i = 0; i < fromSize && i < toSize; i++) {
            Node n1 = (Node) fromList.get(fromSize - i - 1);
            Node n2 = (Node) toList.get(toSize - i - 1);
            if (n1 != n2) {
                Node prevBoundElement = ((NodeXBL) n1).getXblBoundElement();
                while (i > 0 && prevBoundElement != fromList.get(fromSize - i - 1)) {
                    i--;
                }
                return fromSize - i - 1;
            }
        }
        return 1;
    }

    /**
     * Returns the ContentManager that handles the shadow tree the given
     * node resides in.
     */
    public ContentManager getContentManager(Node n) {
        Node b = getXblBoundElement(n);
        if (b != null) {
            Element s = getXblShadowTree(b);
            if (s != null) {
                ContentManager cm;
                Document doc = b.getOwnerDocument();
                if (doc != document) {
                    DefaultXBLManager xm = (DefaultXBLManager)
                        ((AbstractDocument) doc).getXBLManager();
                    cm = (ContentManager) xm.contentManagers.get(s);
                } else {
                    cm = (ContentManager) contentManagers.get(s);
                }
                return cm;
            }
        }
        return null;
    }

    /**
     * Records the ContentManager that handles the given shadow tree.
     */
    void setContentManager(Element shadow, ContentManager cm) {
        if (cm == null) {
            contentManagers.remove(shadow);
        } else {
            contentManagers.put(shadow, cm);
        }
    }

    /**
     * Mark the xblChildNodes and xblScopedChildNodes variables
     * as invalid.
     */
    public void invalidateChildNodes(Node n) {
        XBLRecord rec = getRecord(n);
        if (rec.childNodes != null) {
            rec.childNodes.invalidate();
        }
        if (rec.scopedChildNodes != null) {
            rec.scopedChildNodes.invalidate();
        }
    }

    /**
     * Adds the specified ContentSelectionChangedListener to the
     * global listener list.
     */
    public void addContentSelectionChangedListener
            (ContentSelectionChangedListener l) {
        contentSelectionChangedListenerList.add
            (ContentSelectionChangedListener.class, l);
    }

    /**
     * Removes the specified ContentSelectionChangedListener from the
     * global listener list.
     */
    public void removeContentSelectionChangedListener
            (ContentSelectionChangedListener l) {
        contentSelectionChangedListenerList.remove
            (ContentSelectionChangedListener.class, l);
    }

    /**
     * Returns an array of the gloabl ContentSelectionChangedListeners.
     */
    protected Object[] getContentSelectionChangedListeners() {
        return contentSelectionChangedListenerList.getListenerList();
    }

    /**
     * Called by the ContentManager of a shadow tree to indicate some
     * selected nodes have changed.
     */
    void shadowTreeSelectedContentChanged(Set deselected, Set selected) {
        Iterator i = deselected.iterator();
        while (i.hasNext()) {
            Node n = (Node) i.next();
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                unbind((Element) n);
            }
        }
        i = selected.iterator();
        while (i.hasNext()) {
            Node n = (Node) i.next();
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                bind((Element) n);
            }
        }
    }

    /**
     * Adds the specified BindingListener to the global listener list.
     */
    public void addBindingListener(BindingListener l) {
        bindingListenerList.add(BindingListener.class, l);
    }

    /**
     * Removes the specified BindingListener from the global listener list.
     */
    public void removeBindingListener(BindingListener l) {
        bindingListenerList.remove(BindingListener.class, l);
    }

    /**
     * Dispatches a BindingEvent the registered listeners.
     * @param bindableElement the bindable element whose binding has changed
     * @param shadowTree the new shadow tree of the bindable element
     */
    protected void dispatchBindingChangedEvent(Element bindableElement,
                                               Element shadowTree) {
        Object[] ls = bindingListenerList.getListenerList();
        for (int i = ls.length - 2; i >= 0; i -= 2) {
            BindingListener l = (BindingListener) ls[i + 1];
            l.bindingChanged(bindableElement, shadowTree);
        }
    }

    /**
     * Returns whether the given definition element is the active one
     * for its element name.
     */
    protected boolean isActiveDefinition(XBLOMDefinitionElement def,
                                         Element imp) {
        DefinitionRecord defRec = (DefinitionRecord) definitions.get(def, imp);
        if (defRec == null) {
            return false;
        }
        return defRec == getActiveDefinition(defRec.namespaceURI,
                                             defRec.localName);
    }

    /**
     * Record class for storing information about an XBL definition.
     */
    protected static class DefinitionRecord implements Comparable {

        /**
         * The namespace URI.
         */
        public String namespaceURI;

        /**
         * The local name.
         */
        public String localName;

        /**
         * The definition element.
         */
        public XBLOMDefinitionElement definition;

        /**
         * The template element for this definition.
         */
        public XBLOMTemplateElement template;

        /**
         * The import element that imported this definition.
         */
        public Element importElement;

        /**
         * Creates a new DefinitionRecord.
         */
        public DefinitionRecord(String ns,
                                String ln,
                                XBLOMDefinitionElement def,
                                XBLOMTemplateElement t,
                                Element imp) {
            namespaceURI = ns;
            localName = ln;
            definition = def;
            template = t;
            importElement = imp;
        }

        /**
         * Returns whether two definition records are the same.
         */
        public boolean equals(Object other) {
            return compareTo(other) == 0;
        }

        /**
         * Compares two definition records.
         */
        public int compareTo(Object other) {
            DefinitionRecord rec = (DefinitionRecord) other;
            AbstractNode n1, n2;
            if (importElement == null) {
                n1 = definition;
                if (rec.importElement == null) {
                    n2 = rec.definition;
                } else {
                    n2 = (AbstractNode) rec.importElement;
                }
            } else if (rec.importElement == null) {
                n1 = (AbstractNode) importElement;
                n2 = rec.definition;
            } else if (definition.getOwnerDocument()
                        == rec.definition.getOwnerDocument()) {
                n1 = definition;
                n2 = rec.definition;
            } else {
                n1 = (AbstractNode) importElement;
                n2 = (AbstractNode) rec.importElement;
            }
            short comp = n1.compareDocumentPosition(n2);
            if ((comp & AbstractNode.DOCUMENT_POSITION_PRECEDING) != 0) {
                return -1;
            }
            if ((comp & AbstractNode.DOCUMENT_POSITION_FOLLOWING) != 0) {
                return 1;
            }
            return 0;
        }
    }

    /**
     * Record class for storing information about an XBL import.
     */
    protected class ImportRecord {

        /**
         * The import element.
         */
        public Element importElement;

        /**
         * The imported tree.
         */
        public Node node;

        /**
         * The DOM node inserted listener for definitions accessed through
         * this import.
         */
        public DefNodeInsertedListener defNodeInsertedListener;

        /**
         * The DOM node removed listener for definitions accessed through
         * this import.
         */
        public DefNodeRemovedListener defNodeRemovedListener;

        /**
         * The DOM attribute mutation listener for definitions accessed through
         * this import.
         */
        public DefAttrListener defAttrListener;

        /**
         * The DOM node inserted listener for the imported tree.
         */
        public ImportInsertedListener importInsertedListener;

        /**
         * The DOM node removed listener for the imported tree.
         */
        public ImportRemovedListener importRemovedListener;

        /**
         * The DOM subtree modified listener for the imported tree.
         */
        public ImportSubtreeListener importSubtreeListener;

        /**
         * The DOM subtree modified listener for templates of definitions
         * accessed through this import.
         */
        public TemplateMutationListener templateMutationListener;

        /**
         * Creates a new ImportRecord.
         */
        public ImportRecord(Element imp, Node n) {
            importElement = imp;
            node = n;
            defNodeInsertedListener = new DefNodeInsertedListener(imp);
            defNodeRemovedListener = new DefNodeRemovedListener(imp);
            defAttrListener = new DefAttrListener(imp);
            importInsertedListener = new ImportInsertedListener(imp);
            importRemovedListener = new ImportRemovedListener();
            importSubtreeListener
                = new ImportSubtreeListener(imp, importRemovedListener);
            templateMutationListener = new TemplateMutationListener(imp);
        }
    }

    /**
     * DOM node inserted listener for imported XBL trees.
     */
    protected class ImportInsertedListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * Creates a new ImportInsertedListener.
         */
        public ImportInsertedListener(Element importElement) {
            this.importElement = importElement;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (target instanceof XBLOMDefinitionElement) {
                XBLOMDefinitionElement def = (XBLOMDefinitionElement) target;
                addDefinition(def.getElementNamespaceURI(),
                              def.getElementLocalName(),
                              def,
                              importElement);
            }
        }
    }

    /**
     * DOM node removed listener for imported XBL trees.
     */
    protected static class ImportRemovedListener implements EventListener {

        /**
         * List of definition elements to be removed from the document.
         */
        protected LinkedList toBeRemoved = new LinkedList();

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            toBeRemoved.add(evt.getTarget());
        }
    }

    /**
     * DOM subtree listener for imported XBL trees.
     */
    protected class ImportSubtreeListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * The ImportedRemovedListener to check for to-be-removed definitions.
         */
        protected ImportRemovedListener importRemovedListener;

        /**
         * Creates a new ImportSubtreeListener.
         */
        public ImportSubtreeListener(Element imp,
                                     ImportRemovedListener irl) {
            importElement = imp;
            importRemovedListener = irl;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            Object[] defs = importRemovedListener.toBeRemoved.toArray();
            importRemovedListener.toBeRemoved.clear();
            for (Object def1 : defs) {
                XBLOMDefinitionElement def = (XBLOMDefinitionElement) def1;
                DefinitionRecord defRec
                        = (DefinitionRecord) definitions.get(def, importElement);
                removeDefinition(defRec);
            }
        }
    }

    /**
     * DOM node inserted listener for the document.
     */
    protected class DocInsertedListener implements EventListener {

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (target instanceof XBLOMDefinitionElement) {
                // only handle definition elements in document-level scope
                if (getXblBoundElement((Node) target) == null) {       // ??? suspect cast ???
                    XBLOMDefinitionElement def
                        = (XBLOMDefinitionElement) target;
                    if (def.getAttributeNS(null, XBL_REF_ATTRIBUTE).length()
                            == 0) {
                        addDefinition(def.getElementNamespaceURI(),
                                      def.getElementLocalName(),
                                      def,
                                      null);
                    } else {
                        addDefinitionRef(def);
                    }
                }
            } else if (target instanceof XBLOMImportElement) {
                // only handle import elements in document-level scope
                if (getXblBoundElement((Node) target) == null) {      // ??? suspect cast ???
                    addImport((Element) target);
                }
            } else {
                evt = XBLEventSupport.getUltimateOriginalEvent(evt);
                target = evt.getTarget();
                Node parent = getXblParentNode((Node) target);
                if (parent != null) {
                    invalidateChildNodes(parent);
                }
                if (target instanceof BindableElement) {
                    // Only bind it if it's not the descendent of a bound
                    // element.  If it is, and this new element will be
                    // selected by an xbl:content element in the shadow tree,
                    // the ContentManager will bind it.
                    for (Node n = ((Node) target).getParentNode();
                            n != null;
                            n = n.getParentNode()) {
                        if (n instanceof BindableElement
                                && getRecord(n).definitionElement != null) {
                            return;
                        }
                    }
                    bind((Element) target);
                }
            }
        }
    }

    /**
     * DOM node removed listener for the document.
     */
    protected class DocRemovedListener implements EventListener {

        /**
         * List of definition elements to be removed from the document.
         */
        protected LinkedList defsToBeRemoved = new LinkedList();

        /**
         * List of import elements to be removed from the document.
         */
        protected LinkedList importsToBeRemoved = new LinkedList();

        /**
         * List of nodes to have their XBL child lists invalidated.
         */
        protected LinkedList nodesToBeInvalidated = new LinkedList();

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (target instanceof XBLOMDefinitionElement) {
                // only handle definition elements in document-level scope
                if (getXblBoundElement((Node) target) == null) {
                    defsToBeRemoved.add(target);
                }
            } else if (target instanceof XBLOMImportElement) {
                // only handle import elements in document-level scope
                if (getXblBoundElement((Node) target) == null) {
                    importsToBeRemoved.add(target);
                }
            }

            Node parent = getXblParentNode((Node) target);
            if (parent != null) {
                nodesToBeInvalidated.add(parent);
            }
        }
    }

    /**
     * DOM subtree mutation listener for the document.
     */
    protected class DocSubtreeListener implements EventListener {

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            Object[] defs = docRemovedListener.defsToBeRemoved.toArray();
            docRemovedListener.defsToBeRemoved.clear();
            for (Object def1 : defs) {
                XBLOMDefinitionElement def = (XBLOMDefinitionElement) def1;
                if (def.getAttributeNS(null, XBL_REF_ATTRIBUTE).length() == 0) {
                    DefinitionRecord defRec
                            = (DefinitionRecord) definitions.get(def, null);
                    removeDefinition(defRec);
                } else {
                    removeDefinitionRef(def);
                }
            }

            Object[] imps = docRemovedListener.importsToBeRemoved.toArray();
            docRemovedListener.importsToBeRemoved.clear();
            for (Object imp : imps) {
                removeImport((Element) imp);
            }

            Object[] nodes = docRemovedListener.nodesToBeInvalidated.toArray();
            docRemovedListener.nodesToBeInvalidated.clear();
            for (Object node : nodes) {
                invalidateChildNodes((Node) node);
            }
        }
    }

    /**
     * DOM mutation listener for template elements.
     */
    protected class TemplateMutationListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * Creates a new TemplateMutationListener.
         */
        public TemplateMutationListener(Element imp) {
            importElement = imp;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            Node n = (Node) evt.getTarget();
            while (n != null && !(n instanceof XBLOMDefinitionElement)) {
                n = n.getParentNode();
            }

            DefinitionRecord defRec
                = (DefinitionRecord) definitions.get(n, importElement);
            if (defRec == null) {
                return;
            }

            rebind(defRec.namespaceURI, defRec.localName,
                   document.getDocumentElement());
        }
    }

    /**
     * DOM attribute mutation listener for definition elements.
     */
    protected class DefAttrListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * Creates a new DefAttrListener.
         */
        public DefAttrListener(Element imp) {
            importElement = imp;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (!(target instanceof XBLOMDefinitionElement)) {
                return;
            }

            XBLOMDefinitionElement def = (XBLOMDefinitionElement) target;
            if (!isActiveDefinition(def, importElement)) {
                return;
            }

            MutationEvent mevt = (MutationEvent) evt;
            String attrName = mevt.getAttrName();
            if (attrName.equals(XBL_ELEMENT_ATTRIBUTE)) {
                DefinitionRecord defRec =
                    (DefinitionRecord) definitions.get(def, importElement);
                removeDefinition(defRec);

                addDefinition(def.getElementNamespaceURI(),
                              def.getElementLocalName(),
                              def,
                              importElement);
            } else if (attrName.equals(XBL_REF_ATTRIBUTE)) {
                if (mevt.getNewValue().length() != 0) {
                    DefinitionRecord defRec =
                        (DefinitionRecord) definitions.get(def, importElement);
                    removeDefinition(defRec);
                    addDefinitionRef(def);
                }
            }
        }
    }

    /**
     * DOM node inserted listener for definition elements.
     */
    protected class DefNodeInsertedListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * Creates a new DefNodeInsertedListener.
         */
        public DefNodeInsertedListener(Element imp) {
            importElement = imp;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            MutationEvent mevt = (MutationEvent) evt;
            Node parent = mevt.getRelatedNode();
            if (!(parent instanceof XBLOMDefinitionElement)) {
                return;
            }

            EventTarget target = evt.getTarget();
            if (!(target instanceof XBLOMTemplateElement)) {
                return;
            }
            XBLOMTemplateElement template = (XBLOMTemplateElement) target;

            DefinitionRecord defRec
                = (DefinitionRecord) definitions.get(parent, importElement);
            if (defRec == null) {
                return;
            }

            ImportRecord ir = (ImportRecord) imports.get(importElement);

            if (defRec.template != null) {
                for (Node n = parent.getFirstChild();
                        n != null;
                        n = n.getNextSibling()) {
                    if (n == template) {
                        removeTemplateElementListeners(defRec.template, ir);
                        defRec.template = template;
                        break;
                    } else if (n == defRec.template) {
                        return;
                    }
                }
            } else {
                defRec.template = template;
            }
            addTemplateElementListeners(template, ir);
            rebind(defRec.namespaceURI, defRec.localName,
                   document.getDocumentElement());
        }
    }

    /**
     * DOM node removed listener for definition elements.
     */
    protected class DefNodeRemovedListener implements EventListener {

        /**
         * The import element.
         */
        protected Element importElement;

        /**
         * Creates a new DefNodeRemovedListener.
         */
        public DefNodeRemovedListener(Element imp) {
            importElement = imp;
        }

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            MutationEvent mevt = (MutationEvent) evt;
            Node parent = mevt.getRelatedNode();
            if (!(parent instanceof XBLOMDefinitionElement)) {
                return;
            }

            EventTarget target = evt.getTarget();
            if (!(target instanceof XBLOMTemplateElement)) {
                return;
            }
            XBLOMTemplateElement template = (XBLOMTemplateElement) target;

            DefinitionRecord defRec
                = (DefinitionRecord) definitions.get(parent, importElement);
            if (defRec == null || defRec.template != template) {
                return;
            }

            ImportRecord ir = (ImportRecord) imports.get(importElement);

            removeTemplateElementListeners(template, ir);
            defRec.template = null;

            for (Node n = template.getNextSibling();
                    n != null;
                    n = n.getNextSibling()) {
                if (n instanceof XBLOMTemplateElement) {
                    defRec.template = (XBLOMTemplateElement) n;
                    break;
                }
            }

            addTemplateElementListeners(defRec.template, ir);
            rebind(defRec.namespaceURI, defRec.localName,
                   document.getDocumentElement());
        }
    }

    /**
     * DOM attribute mutation listener for import elements.
     */
    protected class ImportAttrListener implements EventListener {

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (target != evt.getCurrentTarget()) {
                return;
            }

            MutationEvent mevt = (MutationEvent) evt;
            if (mevt.getAttrName().equals(XBL_BINDINGS_ATTRIBUTE)) {
                Element imp = (Element) target;
                removeImport(imp);
                addImport(imp);
            }
        }
    }

    /**
     * DOM attribute mutation listener for referencing definition elements.
     */
    protected class RefAttrListener implements EventListener {

        /**
         * Handles the event.
         */
        public void handleEvent(Event evt) {
            EventTarget target = evt.getTarget();
            if (target != evt.getCurrentTarget()) {
                return;
            }

            MutationEvent mevt = (MutationEvent) evt;
            if (mevt.getAttrName().equals(XBL_REF_ATTRIBUTE)) {
                Element defRef = (Element) target;
                removeDefinitionRef(defRef);
                if (mevt.getNewValue().length() == 0) {
                    XBLOMDefinitionElement def
                        = (XBLOMDefinitionElement) defRef;
                    String ns = def.getElementNamespaceURI();
                    String ln = def.getElementLocalName();
                    addDefinition(ns, ln,
                                  (XBLOMDefinitionElement) defRef, null);
                } else {
                    addDefinitionRef(defRef);
                }
            }
        }
    }

    /**
     * XBL record.
     */
    protected class XBLRecord {

        /**
         * The node.
         */
        public Node node;

        /**
         * The xblChildNodes NodeList for this node.
         */
        public XblChildNodes childNodes;

        /**
         * The xblScopedChildNodes NodeList for this node.
         */
        public XblScopedChildNodes scopedChildNodes;

        /**
         * The content element which caused this node to appear in the
         * flattened tree.
         */
        public XBLOMContentElement contentElement;

        /**
         * The definition element that applies to this element.
         */
        public XBLOMDefinitionElement definitionElement;

        /**
         * The bound element that owns this shadow tree, if this node
         * is an XBLOMShadowTreeElement.
         */
        public BindableElement boundElement;

        /**
         * Whether the next/previous links are valid.
         */
        public boolean linksValid;

        /**
         * The following sibling in the flattened tree.
         */
        public Node nextSibling;

        /**
         * The previous sibling in the flattened tree.
         */
        public Node previousSibling;
    }

    /**
     * To iterate over the XBL child nodes.
     */
    protected class XblChildNodes implements NodeList {

        /**
         * The XBLRecord.
         */
        protected XBLRecord record;

        /**
         * The nodes.
         */
        protected List nodes;

        /**
         * The number of nodes.
         */
        protected int size;

        /**
         * Creates a new XblChildNodes.
         */
        public XblChildNodes(XBLRecord rec) {
            record = rec;
            nodes = new ArrayList();
            size = -1;
        }

        /**
         * Update the NodeList.
         */
        protected void update() {
            size = 0;
            Node shadowTree = getXblShadowTree(record.node);
            Node last = null;
            Node m = shadowTree == null ? record.node.getFirstChild()
                                        : shadowTree.getFirstChild();
            while (m != null) {
                last = collectXblChildNodes(m, last);
                m = m.getNextSibling();
            }
            if (last != null) {
                XBLRecord rec = getRecord(last);
                rec.nextSibling = null;
                rec.linksValid = true;
            }
        }

        /**
         * Find the XBL child nodes of this element.
         */
        protected Node collectXblChildNodes(Node n, Node prev) {
            boolean isChild = false;
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                if (!XBL_NAMESPACE_URI.equals(n.getNamespaceURI())) {
                    isChild = true;
                } else if (n instanceof XBLOMContentElement) {
                    ContentManager cm = getContentManager(n);
                    if (cm != null) {
                        NodeList selected =
                            cm.getSelectedContent((XBLOMContentElement) n);
                        for (int i = 0; i < selected.getLength(); i++) {
                            prev = collectXblChildNodes(selected.item(i),
                                                        prev);
                        }
                    }
                }
            } else {
                isChild = true;
            }
            if (isChild) {
                nodes.add(n);
                size++;
                if (prev != null) {
                    XBLRecord rec = getRecord(prev);
                    rec.nextSibling = n;
                    rec.linksValid = true;
                }
                XBLRecord rec = getRecord(n);
                rec.previousSibling = prev;
                rec.linksValid = true;
                prev = n;
            }
            return prev;
        }

        /**
         * Mark the xblNextSibling and xblPreviousSibling variables
         * on each node in the list as invalid, then invalidate the
         * NodeList.
         */
        public void invalidate() {
            for (int i = 0; i < size; i++) {
                XBLRecord rec = getRecord((Node) nodes.get(i));
                rec.previousSibling = null;
                rec.nextSibling = null;
                rec.linksValid = false;
            }
            nodes.clear();
            size = -1;
        }

        /**
         * Returns the first node in the list.
         */
        public Node getFirstNode() {
            if (size == -1) {
                update();
            }
            return size == 0 ? null : (Node) nodes.get(0);
        }

        /**
         * Returns the last node in the list.
         */
        public Node getLastNode() {
            if (size == -1) {
                update();
            }
            return size == 0 ? null : (Node) nodes.get( nodes.size() -1 );
        }

        /**
         * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#item(int)}.
         */
        public Node item(int index) {
            if (size == -1) {
                update();
            }
            if (index < 0 || index >= size) {
                return null;
            }
            return (Node) nodes.get(index);
        }

        /**
         * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#getLength()}.
         */
        public int getLength() {
            if (size == -1) {
                update();
            }
            return size;
        }
    }

    /**
     * To iterate over the scoped XBL child nodes.
     */
    protected class XblScopedChildNodes extends XblChildNodes {

        /**
         * Creates a new XblScopedChildNodes object.
         */
        public XblScopedChildNodes(XBLRecord rec) {
            super(rec);
        }

        /**
         * Update the NodeList.
         */
        protected void update() {
            size = 0;
            Node shadowTree = getXblShadowTree(record.node);
            Node n = shadowTree == null ? record.node.getFirstChild()
                                        : shadowTree.getFirstChild();
            while (n != null) {
                collectXblScopedChildNodes(n);
                n = n.getNextSibling();
            }
        }

        /**
         * Find the XBL child nodes of this element.
         */
        protected void collectXblScopedChildNodes(Node n) {
            boolean isChild = false;
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                if (!n.getNamespaceURI().equals(XBL_NAMESPACE_URI)) {
                    isChild = true;
                } else if (n instanceof XBLOMContentElement) {
                    ContentManager cm = getContentManager(n);
                    if (cm != null) {
                        NodeList selected =
                            cm.getSelectedContent((XBLOMContentElement) n);
                        for (int i = 0; i < selected.getLength(); i++) {
                            collectXblScopedChildNodes(selected.item(i));
                        }
                    }
                }
            } else {
                isChild = true;
            }
            if (isChild) {
                nodes.add(n);
                size++;
            }
        }
    }
}
