You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by ca...@apache.org on 2005/09/13 15:31:09 UTC

svn commit: r280553 [6/9] - in /xmlgraphics/batik/trunk: ./ resources/org/apache/batik/apps/svgbrowser/resources/ sources/org/apache/batik/bridge/ sources/org/apache/batik/bridge/svg12/ sources/org/apache/batik/css/engine/ sources/org/apache/batik/dom/...

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/XPathSubsetContentSelector.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/XPathSubsetContentSelector.java?rev=280553&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/XPathSubsetContentSelector.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/XPathSubsetContentSelector.java Tue Sep 13 06:29:29 2005
@@ -0,0 +1,513 @@
+/*
+
+   Copyright 2005  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.batik.bridge.svg12;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.batik.dom.svg12.XBLOMContentElement;
+import org.apache.batik.parser.AbstractScanner;
+import org.apache.batik.parser.ParseException;
+import org.apache.batik.xml.XMLUtilities;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A class to handle the XPath subset syntax for XBL content elements.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id$
+ */
+public class XPathSubsetContentSelector extends AbstractContentSelector {
+
+    protected static final int SELECTOR_INVALID = -1;
+    protected static final int SELECTOR_ANY = 0;
+    protected static final int SELECTOR_QNAME = 1;
+    protected static final int SELECTOR_ID = 2;
+
+    /**
+     * The type of XPath subset expression.
+     */
+    protected int selectorType;
+
+    /**
+     * The QName prefix used for selection.
+     */
+    protected String prefix;
+
+    /**
+     * The local name or ID used for selection.
+     */
+    protected String localName;
+
+    /**
+     * The index for selection.  0 means select all elements that match.
+     */
+    protected int index;
+
+    /**
+     * The selected nodes.
+     */
+    protected SelectedNodes selectedContent;
+
+    /**
+     * Creates a new XPathSubsetContentSelector object.
+     */
+    public XPathSubsetContentSelector(ContentManager cm,
+                                      XBLOMContentElement content,
+                                      Element bound,
+                                      String selector) {
+        super(cm, content, bound);
+        parseSelector(selector);
+    }
+
+    /**
+     * Parses the selector string.
+     */
+    protected void parseSelector(String selector) {
+        selectorType = SELECTOR_INVALID;
+        Scanner scanner = new Scanner(selector);
+        int token = scanner.next();
+        if (token == Scanner.NAME) {
+            String name1 = scanner.getStringValue();
+            token = scanner.next();
+            if (token == Scanner.EOF) {
+                selectorType = SELECTOR_QNAME;
+                prefix = null;
+                localName = name1;
+                index = 0;
+                return;
+            } else if (token == Scanner.COLON) {
+                token = scanner.next();
+                if (token == Scanner.NAME) {
+                    String name2 = scanner.getStringValue();
+                    token = scanner.next();
+                    if (token == Scanner.EOF) {
+                        selectorType = SELECTOR_QNAME;
+                        prefix = name1;
+                        localName = name2;
+                        index = 0;
+                        return;
+                    } else if (token == Scanner.LEFT_SQUARE_BRACKET) {
+                        token = scanner.next();
+                        if (token == Scanner.NUMBER) {
+                            int number = Integer.parseInt(scanner.getStringValue());
+                            token = scanner.next();
+                            if (token == Scanner.RIGHT_SQUARE_BRACKET) {
+                                token = scanner.next();
+                                if (token == Scanner.EOF) {
+                                    selectorType = SELECTOR_QNAME;
+                                    prefix = name1;
+                                    localName = name2;
+                                    index = number;
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                } else if (token == Scanner.LEFT_SQUARE_BRACKET) {
+                    token = scanner.next();
+                    if (token == Scanner.NUMBER) {
+                        int number = Integer.parseInt(scanner.getStringValue());
+                        token = scanner.next();
+                        if (token == Scanner.RIGHT_SQUARE_BRACKET) {
+                            token = scanner.next();
+                            if (token == Scanner.EOF) {
+                                selectorType = SELECTOR_QNAME;
+                                prefix = null;
+                                localName = name1;
+                                index = number;
+                                return;
+                            }
+                        }
+                    }
+                } else if (token == Scanner.LEFT_PARENTHESIS) {
+                    if (name1.equals("id")) {
+                        token = scanner.next();
+                        if (token == Scanner.STRING) {
+                            String id = scanner.getStringValue();
+                            token = scanner.next();
+                            if (token == Scanner.RIGHT_PARENTHESIS) {
+                                token = scanner.next();
+                                if (token == Scanner.EOF) {
+                                    selectorType = SELECTOR_ID;
+                                    localName = id;
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } else if (token == Scanner.ASTERISK) {
+            token = scanner.next();
+            if (token == Scanner.EOF) {
+                selectorType = SELECTOR_ANY;
+                return;
+            } else if (token == Scanner.LEFT_SQUARE_BRACKET) {
+                token = scanner.next();
+                if (token == Scanner.NUMBER) {
+                    int number = Integer.parseInt(scanner.getStringValue());
+                    token = scanner.next();
+                    if (token == Scanner.RIGHT_SQUARE_BRACKET) {
+                        token = scanner.next();
+                        if (token == Scanner.EOF) {
+                            selectorType = SELECTOR_ANY;
+                            index = number;
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a list of nodes that were matched by the given selector
+     * string.
+     */
+    public NodeList getSelectedContent() {
+        if (selectedContent == null) {
+            selectedContent = new SelectedNodes();
+        }
+        return selectedContent;
+    }
+
+    /**
+     * Forces this selector to update its selected nodes list.
+     * Returns true if the selected node list needed updating.
+     * This assumes that the previous content elements in this
+     * shadow tree (in document order) have up-to-date selectedContent
+     * lists.
+     */
+    boolean update() {
+        if (selectedContent == null) {
+            selectedContent = new SelectedNodes();
+            return true;
+        }
+        return selectedContent.update();
+    }
+
+    /**
+     * Implementation of NodeList that contains the nodes that matched
+     * this selector.
+     */
+    protected class SelectedNodes implements NodeList {
+
+        /**
+         * The selected nodes.
+         */
+        protected ArrayList nodes = new ArrayList(10);
+
+        /**
+         * Creates a new SelectedNodes object.
+         */
+        public SelectedNodes() {
+            update();
+        }
+
+        protected boolean update() {
+            ArrayList oldNodes = (ArrayList) nodes.clone();
+            nodes.clear();
+            int nth = 0;
+            for (Node n = boundElement.getFirstChild(); n != null; n = n.getNextSibling()) {
+                if (n.getNodeType() != Node.ELEMENT_NODE) {
+                    continue;
+                }
+                Element e = (Element) n;
+                boolean matched = selectorType == SELECTOR_ANY;
+                switch (selectorType) {
+                    case SELECTOR_ID:
+                        matched = e.getAttributeNS(null, "id").equals(localName);
+                        break;
+                    case SELECTOR_QNAME:
+                        if (prefix == null) {
+                            matched = e.getNamespaceURI() == null;
+                        } else {
+                            String ns = contentElement.lookupNamespaceURI(prefix);
+                            if (ns == null) {
+                                // XXX throw invalid prefix exception
+                            } else {
+                                matched = e.getNamespaceURI().equals(ns);
+                            }
+                        }
+                        matched = matched && localName.equals(e.getLocalName());
+                        break;
+                }
+                if (selectorType == SELECTOR_ANY
+                        || selectorType == SELECTOR_QNAME) {
+                    matched = matched && (index == 0 || ++nth == index);
+                }
+                if (matched && !isSelected(n)) {
+                    nodes.add(e);
+                }
+            }
+            int nodesSize = nodes.size();
+            if (oldNodes.size() != nodesSize) {
+                return true;
+            }
+            for (int i = 0; i < nodesSize; i++) {
+                if (oldNodes.get(i) != nodes.get(i)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#item(int)}.
+         */
+        public Node item(int index) {
+            if (index < 0 || index >= nodes.size()) {
+                return null;
+            }
+            return (Node) nodes.get(index);
+        }
+
+        /**
+         * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#getLength()}.
+         * @return {@link #children}.
+         */
+        public int getLength() {
+            return nodes.size();
+        }
+    }
+
+    /**
+     * A scanner for XPath subset selectors.
+     */
+    protected static class Scanner extends AbstractScanner {
+
+        public static final int EOF = 0;
+        public static final int NAME = 1;
+        public static final int COLON = 2;
+        public static final int LEFT_SQUARE_BRACKET = 3;
+        public static final int RIGHT_SQUARE_BRACKET = 4;
+        public static final int LEFT_PARENTHESIS = 5;
+        public static final int RIGHT_PARENTHESIS = 6;
+        public static final int STRING = 7;
+        public static final int NUMBER = 8;
+        public static final int ASTERISK = 9;
+
+        /**
+         * Creates a new Scanner object.
+         */
+        public Scanner(String s) {
+            super(s);
+        }
+
+        /**
+         * Returns the end gap of the current lexical unit.
+         */
+        protected int endGap() {
+            return (current == -1) ? 0 : 1;
+        }
+
+//         public int next() {
+//             int i = super.next();
+//             System.err.print("\t\t");
+//             switch (i) {
+//                 case EOF:
+//                     System.err.println("EOF");
+//                     break;
+//                 case NAME:
+//                     System.err.println("NAME " + getStringValue());
+//                     break;
+//                 case COLON:
+//                     System.err.println("COLON");
+//                     break;
+//                 case LEFT_SQUARE_BRACKET:
+//                     System.err.println("LEFT_SQUARE_BRACKET");
+//                     break;
+//                 case RIGHT_SQUARE_BRACKET:
+//                     System.err.println("RIGHT_SQUARE_BRACKET");
+//                     break;
+//                 case LEFT_PARENTHESIS:
+//                     System.err.println("LEFT_PARENTHESIS");
+//                     break;
+//                 case RIGHT_PARENTHESIS:
+//                     System.err.println("RIGHT_PARENTHESIS");
+//                     break;
+//                 case STRING:
+//                     System.err.println("STRING \"" + getStringValue() + "\"");
+//                     break;
+//                 case NUMBER:
+//                     System.err.println("NUMBER " + getStringValue());
+//                     break;
+//                 case ASTERISK:
+//                     System.err.println("ASTERISK");
+//                     break;
+//                 default:
+//                     System.err.println("?");
+//             }
+//             return i;
+//         }
+
+        /**
+         * Returns the next token.
+         */
+        protected void nextToken() throws ParseException {
+            try {
+                switch (current) {
+                    case -1:
+                        type = EOF;
+                        return;
+                    case ':':
+                        nextChar();
+                        type = COLON;
+                        return;
+                    case '[':
+                        nextChar();
+                        type = LEFT_SQUARE_BRACKET;
+                        return;
+                    case ']':
+                        nextChar();
+                        type = RIGHT_SQUARE_BRACKET;
+                        return;
+                    case '(':
+                        nextChar();
+                        type = LEFT_PARENTHESIS;
+                        return;
+                    case ')':
+                        nextChar();
+                        type = RIGHT_PARENTHESIS;
+                        return;
+                    case '*':
+                        nextChar();
+                        type = ASTERISK;
+                        return;
+                    case ' ':
+                    case '\t':
+                    case '\r':
+                    case '\n':
+                    case '\f':
+                        do {
+                            nextChar();
+                        } while (XMLUtilities.isXMLSpace((char) current));
+                        nextToken();
+                        return;
+                    case '\'':
+                        type = string1();
+                        return;
+                    case '"':
+                        type = string2();
+                        return;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        type = number();
+                        return;
+                    default:
+                        if (XMLUtilities.isXMLNameFirstCharacter((char) current)) {
+                            do {
+                                nextChar();
+                            } while (current != -1
+                                     && current != ':'
+                                     && XMLUtilities.isXMLNameCharacter((char) current));
+                            type = NAME;
+                            return;
+                        }
+                        nextChar();
+                        throw new ParseException("identifier.character",
+                                                 reader.getLine(),
+                                                 reader.getColumn());
+                }
+            } catch (IOException e) {
+                throw new ParseException(e);
+            }
+        }
+
+        /**
+         * Scans a single quoted string.
+         */
+        protected int string1() throws IOException {
+            start = position;
+            loop: for (;;) {
+                switch (nextChar()) {
+                case -1:
+                    throw new ParseException("eof",
+                                             reader.getLine(),
+                                             reader.getColumn());
+                case '\'':
+                    break loop;
+                }
+            }
+            nextChar();
+            return STRING;
+        }
+
+        /**
+         * Scans a double quoted string.
+         */
+        protected int string2() throws IOException {
+            start = position;
+            loop: for (;;) {
+                switch (nextChar()) {
+                case -1:
+                    throw new ParseException("eof",
+                                             reader.getLine(),
+                                             reader.getColumn());
+                case '"':
+                    break loop;
+                }
+            }
+            nextChar();
+            return STRING;
+        }
+
+        /**
+         * Scans a number.
+         */
+        protected int number() throws IOException {
+            loop: for (;;) {
+                switch (nextChar()) {
+                case '.':
+                    switch (nextChar()) {
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        return dotNumber();
+                    }
+                    throw new ParseException("character",
+                                             reader.getLine(),
+                                             reader.getColumn());
+                default:
+                    break loop;
+                case '0': case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                }
+            }
+            return NUMBER;
+        }        
+
+        /**
+         * Scans the decimal part of a number.
+         */
+        protected int dotNumber() throws IOException {
+            loop: for (;;) {
+                switch (nextChar()) {
+                default:
+                    break loop;
+                case '0': case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                }
+            }
+            return NUMBER;
+        }
+    }
+}

Propchange: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/XPathSubsetContentSelector.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java Tue Sep 13 06:29:29 2005
@@ -1,6 +1,6 @@
 /*
 
-   Copyright 2002-2004  The Apache Software Foundation 
+   Copyright 2002-2005  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.
@@ -45,6 +45,7 @@
 import org.w3c.css.sac.LexicalUnit;
 import org.w3c.css.sac.SACMediaList;
 import org.w3c.css.sac.SelectorList;
+import org.w3c.dom.Attr;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -64,75 +65,63 @@
 public abstract class CSSEngine {
 
     /**
-     * List of StyleMap objects, one for each @font-face rule
-     * encountered by this CSSEngine.
+     * Returns the CSS parent node of the given node.
      */
-    protected List fontFaces = new LinkedList();
+    public static Node getCSSParentNode(Node n) {
+        if (n instanceof CSSNavigableNode) {
+            return ((CSSNavigableNode) n).getCSSParentNode();
+        }
+        return n.getParentNode();
+    }
 
     /**
-     * Get's the StyleMaps generated by @font-face rules
-     * encountered by this CSSEngine thus far.
+     * Returns the CSS first child node of the given node.
      */
-    public List getFontFaces() { return fontFaces; }
-
-    CSSEngineUserAgent userAgent = null;
+    protected static Node getCSSFirstChild(Node n) {
+        if (n instanceof CSSNavigableNode) {
+            return ((CSSNavigableNode) n).getCSSFirstChild();
+        }
+        return n.getFirstChild();
+    }
 
     /**
-     * Returns the next stylable parent of the given element.
+     * Returns the CSS next sibling node of the given node.
      */
-    public static CSSStylableElement getParentCSSStylableElement(Element elt) {
-        Element e = getParentElement(elt);
-        while (e != null) {
-            if (e instanceof CSSStylableElement) {
-                return (CSSStylableElement)e;
-            }
-            e = getParentElement(e);
+    protected static Node getCSSNextSibling(Node n) {
+        if (n instanceof CSSNavigableNode) {
+            return ((CSSNavigableNode) n).getCSSNextSibling();
         }
-        return null;
+        return n.getNextSibling();
     }
 
     /**
-     * Returns the next parent element of the given element, from the
-     * CSS point of view.
+     * Returns the CSS previous sibling node of the given node.
      */
-    public static Element getParentElement(Element elt) {
-        Node n = elt.getParentNode();
-        while (n != null) {
-            n = getLogicalParentNode(n);
-            if (n.getNodeType() == Node.ELEMENT_NODE) {
-                return (Element)n;
-            }
-            n = n.getParentNode();
+    protected static Node getCSSPreviousSibling(Node n) {
+        if (n instanceof CSSNavigableNode) {
+            return ((CSSNavigableNode) n).getCSSPreviousSibling();
         }
-        return null;
+        return n.getPreviousSibling();
     }
 
     /**
-     * Returns the logical parent of a node, given its physical parent.
+     * Returns the next stylable parent of the given element.
      */
-    public static Node getLogicalParentNode(Node parent) {
-        Node node = parent;
-        if (node != null) {
-            if (node instanceof CSSImportedElementRoot) {
-                return ((CSSImportedElementRoot)node).getCSSParentElement();
-            } else {
-                return node;
+    public static CSSStylableElement getParentCSSStylableElement(Element elt) {
+        Node n = getCSSParentNode(elt);
+        while (n != null) {
+            if (n instanceof CSSStylableElement) {
+                return (CSSStylableElement) n;
             }
+            n = getCSSParentNode(n);
         }
         return null;
     }
 
     /**
-     * Returns the imported child of the given node, if any.
+     * The user agent used for showing error messages.
      */
-    public static CSSImportedElementRoot getImportedChild(Node node) {
-        if (node instanceof CSSImportNode) {
-            CSSImportNode inode = (CSSImportNode)node;
-            CSSImportedElementRoot r = inode.getCSSImportedElementRoot();
-            return r;
-        }
-        return null;
-    }
+    protected CSSEngineUserAgent userAgent;
 
     /**
      * The CSS context.
@@ -150,6 +139,11 @@
     protected URL documentURI;
 
     /**
+     * Whether the document is a CSSNavigableDocument.
+     */
+    protected boolean isCSSNavigableDocument;
+
+    /**
      * The property/int mappings.
      */
     protected StringIntMap indexes;
@@ -215,6 +209,12 @@
     protected List styleSheetNodes;
 
     /**
+     * List of StyleMap objects, one for each @font-face rule
+     * encountered by this CSSEngine.
+     */
+    protected List fontFaces = new LinkedList();
+
+    /**
      * The style attribute namespace URI.
      */
     protected String styleNamespaceURI;
@@ -284,6 +284,11 @@
     protected String alternateStyleSheet;
 
     /**
+     * Listener for CSSNavigableDocument events.
+     */
+    protected CSSNavigableDocumentHandler cssNavigableDocumentListener;
+
+    /**
      * The DOMAttrModified event listener.
      */
     protected EventListener domAttrModifiedListener;
@@ -380,6 +385,8 @@
         classLocalName = cln;
         cssContext = ctx;
 
+        isCSSNavigableDocument = doc instanceof CSSNavigableDocument;
+
         cssConditionFactory = new CSSConditionFactory(cns, cln, null, "id");
 
         int len = vm.length;
@@ -425,38 +432,76 @@
             }
         }
 
-        if (cssContext.isDynamic() &&
-            (document instanceof EventTarget)) {
+        if (cssContext.isDynamic() && document instanceof EventTarget) {
             // Attach the mutation events listeners.
-            EventTarget et = (EventTarget)document;
+            addEventListeners((EventTarget) document);
+            styleDeclarationUpdateHandler =
+                new StyleDeclarationUpdateHandler();
+        }
+
+        ALL_PROPERTIES = new int[getNumberOfProperties()];
+        for (int i = getNumberOfProperties() - 1; i >= 0; --i) {
+            ALL_PROPERTIES[i] = i;
+        }
+    }
+
+    /**
+     * Adds event listeners to the document to track CSS changes.
+     */
+    protected void addEventListeners(EventTarget doc) {
+        if (isCSSNavigableDocument) {
+            cssNavigableDocumentListener = new CSSNavigableDocumentHandler();
+            CSSNavigableDocument cnd = (CSSNavigableDocument) doc;
+            cnd.addCSSNavigableDocumentListener(cssNavigableDocumentListener);
+        } else {
             domAttrModifiedListener = new DOMAttrModifiedListener();
-            et.addEventListener("DOMAttrModified",
-                                domAttrModifiedListener,
-                                false);
+            doc.addEventListener("DOMAttrModified",
+                                 domAttrModifiedListener,
+                                 false);
             domNodeInsertedListener = new DOMNodeInsertedListener();
-            et.addEventListener("DOMNodeInserted",
-                                domNodeInsertedListener,
-                                false);
+            doc.addEventListener("DOMNodeInserted",
+                                 domNodeInsertedListener,
+                                 false);
             domNodeRemovedListener = new DOMNodeRemovedListener();
-            et.addEventListener("DOMNodeRemoved",
-                                domNodeRemovedListener,
-                                false);
+            doc.addEventListener("DOMNodeRemoved",
+                                 domNodeRemovedListener,
+                                 false);
             domSubtreeModifiedListener = new DOMSubtreeModifiedListener();
-            et.addEventListener("DOMSubtreeModified",
-                                domSubtreeModifiedListener,
-                                false);
+            doc.addEventListener("DOMSubtreeModified",
+                                 domSubtreeModifiedListener,
+                                 false);
             domCharacterDataModifiedListener =
                 new DOMCharacterDataModifiedListener();
-            et.addEventListener("DOMCharacterDataModified",
-                                domCharacterDataModifiedListener,
-                                false);
-            styleDeclarationUpdateHandler =
-                new StyleDeclarationUpdateHandler();
+            doc.addEventListener("DOMCharacterDataModified",
+                                 domCharacterDataModifiedListener,
+                                 false);
         }
+    }
 
-        ALL_PROPERTIES = new int[getNumberOfProperties()];
-        for (int i = getNumberOfProperties() - 1; i >= 0; --i) {
-            ALL_PROPERTIES[i] = i;
+    /**
+     * Removes the event listeners from the document.
+     */
+    protected void removeEventListeners(EventTarget doc) {
+        if (isCSSNavigableDocument) {
+            CSSNavigableDocument cnd = (CSSNavigableDocument) doc;
+            cnd.removeCSSNavigableDocumentListener
+                (cssNavigableDocumentListener);
+        } else {
+            doc.removeEventListener("DOMAttrModified",
+                                    domAttrModifiedListener,
+                                    false);
+            doc.removeEventListener("DOMNodeInserted",
+                                    domNodeInsertedListener,
+                                    false);
+            doc.removeEventListener("DOMNodeRemoved",
+                                    domNodeRemovedListener,
+                                    false);
+            doc.removeEventListener("DOMSubtreeModified",
+                                    domSubtreeModifiedListener,
+                                    false);
+            doc.removeEventListener("DOMCharacterDataModified",
+                                    domCharacterDataModifiedListener,
+                                    false);
         }
     }
 
@@ -468,39 +513,23 @@
         disposeStyleMaps(document.getDocumentElement());
         if (document instanceof EventTarget) {
             // Detach the mutation events listeners.
-            EventTarget et = (EventTarget)document;
-            et.removeEventListener("DOMAttrModified",
-                                   domAttrModifiedListener,
-                                   false);
-            et.removeEventListener("DOMNodeInserted",
-                                   domNodeInsertedListener,
-                                   false);
-            et.removeEventListener("DOMNodeRemoved",
-                                   domNodeRemovedListener,
-                                   false);
-            et.removeEventListener("DOMSubtreeModified",
-                                   domSubtreeModifiedListener,
-                                   false);
-            et.removeEventListener("DOMCharacterDataModified",
-                                   domCharacterDataModifiedListener,
-                                   false);
+            removeEventListeners((EventTarget) document);
         }
     }
 
-    private void disposeStyleMaps(Node node) {
+    /**
+     * Removes the style maps from each CSSStylableElement in the document.
+     */
+    protected void disposeStyleMaps(Node node) {
         if (node instanceof CSSStylableElement) {
             ((CSSStylableElement)node).setComputedStyleMap(null, null);
         }
-        for (Node n = node.getFirstChild();
+        for (Node n = getCSSFirstChild(node);
              n != null;
-             n = n.getNextSibling()) {
+             n = getCSSNextSibling(n)) {
             if (n.getNodeType() == Node.ELEMENT_NODE) {
                 disposeStyleMaps(n);
             }
-            Node c = getImportedChild(n);
-            if (c != null) {
-                disposeStyleMaps(c);
-            }
         }
     }
 
@@ -597,6 +626,14 @@
     }
 
     /**
+     * Gets the StyleMaps generated by @font-face rules
+     * encountered by this CSSEngine thus far.
+     */
+    public List getFontFaces() {
+        return fontFaces;
+    }
+
+    /**
      * Sets the media to use to compute the styles.
      */
     public void setMedia(String str) {
@@ -643,9 +680,9 @@
             }
         }
 
-        for (Node dn = dest.getFirstChild(), sn = src.getFirstChild();
+        for (Node dn = getCSSFirstChild(dest), sn = getCSSFirstChild(src);
              dn != null;
-             dn = dn.getNextSibling(), sn = sn.getNextSibling()) {
+             dn = getCSSNextSibling(dn), sn = getCSSNextSibling(sn)) {
             if (sn.getNodeType() == Node.ELEMENT_NODE) {
                 importCascadedStyleMaps((Element)sn, srceng, (Element)dn);
             }
@@ -689,28 +726,28 @@
         element = elt;
         try {
             // Apply the non-CSS presentational hints to the result.
-            ShorthandManager.PropertyHandler ph =
-                new ShorthandManager.PropertyHandler() {
-                    public void property(String pname, LexicalUnit lu,
-                                         boolean important) {
-                        int idx = getPropertyIndex(pname);
-                        if (idx != -1) {
-                            ValueManager vm = valueManagers[idx];
-                            Value v = vm.createValue(lu, CSSEngine.this);
-                            putAuthorProperty(result, idx, v, important,
-                                              StyleMap.NON_CSS_ORIGIN);
-                            return;
+            if (nonCSSPresentationalHints != null) {
+                ShorthandManager.PropertyHandler ph =
+                    new ShorthandManager.PropertyHandler() {
+                        public void property(String pname, LexicalUnit lu,
+                                             boolean important) {
+                            int idx = getPropertyIndex(pname);
+                            if (idx != -1) {
+                                ValueManager vm = valueManagers[idx];
+                                Value v = vm.createValue(lu, CSSEngine.this);
+                                putAuthorProperty(result, idx, v, important,
+                                                  StyleMap.NON_CSS_ORIGIN);
+                                return;
+                            }
+                            idx = getShorthandIndex(pname);
+                            if (idx == -1)
+                                return; // Unknown property...
+                            // Shorthand value
+                            shorthandManagers[idx].setValues
+                                (CSSEngine.this, this, lu, important);
                         }
-                        idx = getShorthandIndex(pname);
-                        if (idx == -1)
-                            return; // Unknown property...
-                        // Shorthand value
-                        shorthandManagers[idx].setValues
-                            (CSSEngine.this, this, lu, important);
-                    }
-                };
+                    };
 
-            if (nonCSSPresentationalHints != null) {
                 NamedNodeMap attrs = elt.getAttributes();
                 int len = attrs.getLength();
                 for (int i = 0; i < len; i++) {
@@ -738,7 +775,8 @@
             }
 
             // Apply the document style-sheets to the result.
-            List snodes = getStyleSheetNodes();
+            CSSEngine eng = cssContext.getCSSEngineForElement(elt);
+            List snodes = eng.getStyleSheetNodes();
             int slen = snodes.size();
             if (slen > 0) {
                 List rules = new ArrayList();
@@ -872,9 +910,9 @@
         if (n instanceof CSSStyleSheetNode) {
             styleSheetNodes.add(n);
         }
-        for (Node nd = n.getFirstChild();
+        for (Node nd = getCSSFirstChild(n);
              nd != null;
-             nd = nd.getNextSibling()) {
+             nd = getCSSNextSibling(nd)) {
             findStyleSheetNodes(nd);
         }
     }
@@ -1155,7 +1193,7 @@
                                 URL uri) throws DOMException {
         try {
             parseStyleSheet(ss, new InputSource(new StringReader(rules)), uri);
-	} catch (Exception e) {
+        } catch (Exception e) {
             // e.printStackTrace();
             String m = e.getMessage();
             if (m == null) m = "";
@@ -1775,25 +1813,25 @@
      */
     protected void inlineStyleAttributeUpdated(CSSStylableElement elt,
                                                StyleMap style,
-                                               MutationEvent evt) {
+                                               short attrChange,
+                                               String prevValue,
+                                               String newValue) {
         boolean[] updated = styleDeclarationUpdateHandler.updatedProperties;
         for (int i = getNumberOfProperties() - 1; i >= 0; --i) {
             updated[i] = false;
         }
 
-        switch (evt.getAttrChange()) {
+        switch (attrChange) {
         case MutationEvent.ADDITION:
         case MutationEvent.MODIFICATION:
-            String decl = evt.getNewValue();
-            // System.err.println("Inline Style Update: '" + decl + "'");
-            if (decl.length() > 0) {
+            if (newValue.length() > 0) {
                 element = elt;
                 try {
                     parser.setSelectorFactory(CSSSelectorFactory.INSTANCE);
                     parser.setConditionFactory(cssConditionFactory);
                     styleDeclarationUpdateHandler.styleMap = style;
                     parser.setDocumentHandler(styleDeclarationUpdateHandler);
-                    parser.parseStyleDeclaration(decl);
+                    parser.parseStyleDeclaration(newValue);
                     styleDeclarationUpdateHandler.styleMap = null;
                 } catch (Exception e) {
                     String m = e.getMessage();
@@ -1802,7 +1840,7 @@
                                 documentURI.toString());
                     String s = Messages.formatMessage
                         ("style.syntax.error.at",
-                         new Object[] { u, styleLocalName, decl, m });
+                         new Object[] { u, styleLocalName, newValue, m });
                     DOMException de = new DOMException(DOMException.SYNTAX_ERR, s);
                     if (userAgent == null) throw de;
                     userAgent.displayError(de);
@@ -1816,8 +1854,7 @@
         case MutationEvent.REMOVAL:
             boolean removed = false;
 
-            if (evt.getPrevValue() != null &&
-                evt.getPrevValue().length() > 0) {
+            if (prevValue != null && prevValue.length() > 0) {
                 // Check if the style map has cascaded styles which
                 // come from the inline style attribute.
                 for (int i = getNumberOfProperties() - 1; i >= 0; --i) {
@@ -1923,8 +1960,9 @@
         int count =0;
         if (!recascade) {
             for (int i=0; i<diffs.length; i++) {
-                if (diffs[i])
+                if (diffs[i]) {
                     count++;
+                }
             }
         } else {
             StyleMap newStyle = getCascadedStyleMap(elt, null);
@@ -2058,22 +2096,13 @@
             }
         }
 
-        CSSImportedElementRoot ier = getImportedChild(node);
-        if (ier != null) {
-            Element e = (Element)ier.getFirstChild();
-            // Don't recascade trees that have been imported.
-            // If you do it will use the stylesheets from this
-            // document instead of the original document.  Also
-            // currently there isn't any supported way to modify
-            // the content imported from the other document so
-            // the cascade can't change.
-            CSSEngine subEng = cssContext.getCSSEngineForElement(e);
-            subEng.invalidateProperties(e, inherited, null, recascade);
-        }
-        for (Node n = node.getFirstChild();
+        for (Node n = getCSSFirstChild(node);
              n != null;
-             n = n.getNextSibling()) {
-            invalidateProperties(n, inherited, null, recascade);
+             n = getCSSNextSibling(n)) {
+            if (n.getNodeType() == Node.ELEMENT_NODE) {
+                CSSEngine eng = cssContext.getCSSEngineForElement((Element) n);
+                invalidateProperties(n, inherited, null, recascade);
+            }
         }
     }
 
@@ -2127,8 +2156,8 @@
     protected void nonCSSPresentationalHintUpdated(CSSStylableElement elt,
                                                    StyleMap style,
                                                    String property,
-                                                   MutationEvent evt) {
-        // System.err.println("update: " + property);
+                                                   short attrChange,
+                                                   String newValue) {
         int idx = getPropertyIndex(property);
 
         if (style.isImportant(idx)) {
@@ -2144,13 +2173,13 @@
             return;
         }
         
-        switch (evt.getAttrChange()) {
+        switch (attrChange) {
         case MutationEvent.ADDITION:
         case MutationEvent.MODIFICATION:
             element = elt;
             try {
                 LexicalUnit lu;
-                lu = parser.parsePropertyValue(evt.getNewValue());
+                lu = parser.parsePropertyValue(newValue);
                 ValueManager vm = valueManagers[idx];
                 Value v = vm.createValue(lu, CSSEngine.this);
                 style.putMask(idx, (short)0);
@@ -2163,7 +2192,7 @@
                             documentURI.toString());
                 String s = Messages.formatMessage
                     ("property.syntax.error.at",
-                     new Object[] { u, property, evt.getNewValue(), m });
+                     new Object[] { u, property, newValue, m });
                 DOMException de = new DOMException(DOMException.SYNTAX_ERR, s);
                 if (userAgent == null) throw de;
                 userAgent.displayError(de);
@@ -2218,6 +2247,162 @@
     }
 
     /**
+     * Handles an attribute change in the document.
+     */
+    protected void handleAttrModified(Element e,
+                                      Attr attr,
+                                      short attrChange,
+                                      String prevValue,
+                                      String newValue) {
+        if (!(e instanceof CSSStylableElement)) {
+            // Not a stylable element.
+            return;
+        }
+
+        if (newValue.equals(prevValue)) {
+            return;  // no change really...
+        }
+
+        String attrNS = attr.getNamespaceURI();
+        String name   = ((attrNS == null) ? 
+                         attr.getNodeName() :
+                         attr.getLocalName());
+            
+        CSSStylableElement elt = (CSSStylableElement)e;
+        StyleMap style = elt.getComputedStyleMap(null);
+        if (style != null) {
+            if ((attrNS == styleNamespaceURI) ||
+                ((attrNS != null) && attrNS.equals(styleNamespaceURI))) {
+                if (name.equals(styleLocalName)) {
+                    // The style declaration attribute has been modified.
+                    inlineStyleAttributeUpdated
+                        (elt, style, attrChange, prevValue, newValue);
+                    return;
+                }
+            }
+
+            if (nonCSSPresentationalHints != null) {
+                if ((attrNS == nonCSSPresentationalHintsNamespaceURI) ||
+                    ((attrNS != null) &&
+                     attrNS.equals(nonCSSPresentationalHintsNamespaceURI))) {
+                    if (nonCSSPresentationalHints.contains(name)) {
+                        // The 'name' attribute which represents a non CSS
+                        // presentational hint has been modified.
+                        nonCSSPresentationalHintUpdated
+                            (elt, style, name, attrChange, newValue);
+                        return;
+                    }
+                }
+            }
+        }
+
+        if (selectorAttributes != null &&
+            selectorAttributes.contains(name)) {
+            // An attribute has been modified, invalidate all the
+            // properties to correctly match attribute selectors.
+            invalidateProperties(elt, null, null, true);
+            for (Node n = getCSSNextSibling(elt);
+                 n != null;
+                 n = getCSSNextSibling(n)) {
+                invalidateProperties(n, null, null, true);
+            }
+        }
+    }
+
+    /**
+     * To handle mutations of a CSSNavigableDocument.
+     */
+    protected class CSSNavigableDocumentHandler
+            implements CSSNavigableDocumentListener {
+
+        /**
+         * A node has been inserted into the CSSNavigableDocument tree.
+         */
+        public void nodeInserted(Node newNode) {
+            if (newNode instanceof CSSStyleSheetNode) {
+                styleSheetNodes = null;
+                // Invalidate all the CSSStylableElements in the document.
+                invalidateProperties(document.getDocumentElement(), 
+                                     null, null, true);
+            } else if (newNode instanceof CSSStylableElement) {
+                // Invalidate the CSSStylableElement siblings, to
+                // correctly match the adjacent selectors and
+                // first-child pseudo-class.
+                for (Node n = getCSSNextSibling(newNode);
+                     n != null;
+                     n = getCSSNextSibling(n)) {
+                    invalidateProperties(n, null, null, true);
+                }
+            }
+        }
+
+        /**
+         * A node is about to be removed from the CSSNavigableDocument tree.
+         */
+        public void nodeToBeRemoved(Node oldNode) {
+            if (oldNode instanceof CSSStyleSheetNode) {
+                // Wait for the DOMSubtreeModified to do the invalidations
+                // because at this time the node is in the tree.
+                styleSheetRemoved = true;
+            } else if (oldNode instanceof CSSStylableElement) {
+                // Wait for the DOMSubtreeModified to do the invalidations
+                // because at this time the node is in the tree.
+                removedStylableElementSibling = getCSSNextSibling(oldNode);
+            }
+            // Clears the computed styles in the removed tree.
+            disposeStyleMaps(oldNode);
+        }
+
+        /**
+         * A subtree of the CSSNavigableDocument tree has been modified
+         * in some way.
+         */
+        public void subtreeModified(Node rootOfModifications) {
+            if (styleSheetRemoved) {
+                styleSheetRemoved = false;
+                styleSheetNodes = null;
+
+                // Invalidate all the CSSStylableElements in the document.
+                invalidateProperties(document.getDocumentElement(), 
+                                     null, null, true);
+            } else if (removedStylableElementSibling != null) {
+                // Invalidate the CSSStylableElement siblings, to
+                // correctly match the adjacent selectors and
+                // first-child pseudo-class.
+                for (Node n = removedStylableElementSibling;
+                     n != null;
+                     n = getCSSNextSibling(n)) {
+                    invalidateProperties(n, null, null, true);
+                }
+                removedStylableElementSibling = null;
+            }
+        }
+
+        /**
+         * Character data in the CSSNavigableDocument tree has been modified.
+         */
+        public void characterDataModified(Node text) {
+            if (getCSSParentNode(text) instanceof CSSStyleSheetNode) {
+                styleSheetNodes = null;
+                // Invalidate all the CSSStylableElements in the document.
+                invalidateProperties(document.getDocumentElement(), 
+                                     null, null, true);
+            }
+        }
+
+        /**
+         * An attribute has changed in the CSSNavigableDocument.
+         */
+        public void attrModified(Element e,
+                                 Attr attr,
+                                 short attrChange,
+                                 String prevValue,
+                                 String newValue) {
+            handleAttrModified(e, attr, attrChange, prevValue, newValue);
+        }
+    }
+
+    /**
      * To handle the insertion of a CSSStyleSheetNode in the
      * associated document.
      */
@@ -2313,60 +2498,12 @@
      */
     protected class DOMAttrModifiedListener implements EventListener {
         public void handleEvent(Event evt) {
-            EventTarget et = evt.getTarget();
-            if (!(et instanceof CSSStylableElement)) {
-                // Not a stylable element.
-                return;
-            }
-
-            MutationEvent mevt = (MutationEvent)evt;
-            if (mevt.getNewValue().equals(mevt.getPrevValue()))
-                return;  // no change really...
-
-            Node attr = mevt.getRelatedNode();
-            String attrNS = attr.getNamespaceURI();
-            String name   = ((attrNS == null) ? 
-                             attr.getNodeName() :
-                             attr.getLocalName());
-                
-            CSSStylableElement elt = (CSSStylableElement)et;
-            StyleMap style = elt.getComputedStyleMap(null);
-            if (style != null) {
-                if ((attrNS == styleNamespaceURI) ||
-                    ((attrNS != null) && attrNS.equals(styleNamespaceURI))) {
-                    if (name.equals(styleLocalName)) {
-                        // The style declaration attribute has been modified.
-                        inlineStyleAttributeUpdated(elt, style, mevt);
-                        return;
-                    }
-                }
-
-                if (nonCSSPresentationalHints != null) {
-                    if ((attrNS == nonCSSPresentationalHintsNamespaceURI) ||
-                        ((attrNS != null) &&
-                         attrNS.equals(nonCSSPresentationalHintsNamespaceURI))) {
-                        if (nonCSSPresentationalHints.contains(name)) {
-                            // The 'name' attribute which represents a non CSS
-                            // presentational hint has been modified.
-                            nonCSSPresentationalHintUpdated(elt, style, name,
-                                                            mevt);
-                            return;
-                        }
-                    }
-                }
-            }
-
-            if (selectorAttributes != null &&
-                selectorAttributes.contains(name)) {
-                // An attribute has been modified, invalidate all the
-                // properties to correctly match attribute selectors.
-                invalidateProperties(elt, null, null, true);
-                for (Node n = elt.getNextSibling();
-                     n != null;
-                     n = n.getNextSibling()) {
-                    invalidateProperties(n, null, null, true);
-                }
-            }
+            MutationEvent mevt = (MutationEvent) evt;
+            handleAttrModified((Element) evt.getTarget(),
+                               (Attr) mevt.getRelatedNode(),
+                               mevt.getAttrChange(),
+                               mevt.getPrevValue(),
+                               mevt.getNewValue());
         }
     }
 }

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocument.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocument.java?rev=280553&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocument.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocument.java Tue Sep 13 06:29:29 2005
@@ -0,0 +1,39 @@
+/*
+
+   Copyright 2005  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.batik.css.engine;
+
+/**
+ * An interface for documents that have CSSNavigableNodes.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id$
+ */
+public interface CSSNavigableDocument {
+
+    /**
+     * Adds an event listener for mutations on the
+     * CSSNavigableDocument tree.
+     */
+    void addCSSNavigableDocumentListener(CSSNavigableDocumentListener l);
+
+    /**
+     * Removes an event listener for mutations on the
+     * CSSNavigableDocument tree.
+     */
+    void removeCSSNavigableDocumentListener(CSSNavigableDocumentListener l);
+}

Propchange: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocument.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocumentListener.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocumentListener.java?rev=280553&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocumentListener.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocumentListener.java Tue Sep 13 06:29:29 2005
@@ -0,0 +1,60 @@
+/*
+
+   Copyright 2005  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.batik.css.engine;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * An interface for listeners of CSSNavigableDocument events.  The
+ * events parallel the DOM events, but apply to the CSS view of
+ * the tree rather than the actual DOM tree.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id$
+ */
+public interface CSSNavigableDocumentListener {
+
+    /**
+     * A node has been inserted into the CSSNavigableDocument tree.
+     */
+    void nodeInserted(Node newNode);
+
+    /**
+     * A node is about to be removed from the CSSNavigableDocument tree.
+     */
+    void nodeToBeRemoved(Node oldNode);
+
+    /**
+     * A subtree of the CSSNavigableDocument tree has been modified
+     * in some way.
+     */
+    void subtreeModified(Node rootOfModifications);
+
+    /**
+     * Character data in the CSSNavigableDocument tree has been modified.
+     */
+    void characterDataModified(Node text);
+
+    /**
+     * An attribute has changed in the CSSNavigableDocument.
+     */
+    void attrModified(Element e, Attr attr, short attrChange,
+                      String prevValue, String newValue);
+}

Propchange: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableDocumentListener.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableNode.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableNode.java?rev=280553&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableNode.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableNode.java Tue Sep 13 06:29:29 2005
@@ -0,0 +1,62 @@
+/*
+
+   Copyright 2005  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.batik.css.engine;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * An interface for DOM classes that can be navigated for CSS selector
+ * matching and cascade computation.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id$
+ */
+public interface CSSNavigableNode {
+
+    /**
+     * Returns the CSS parent node of this node.
+     */
+    Node getCSSParentNode();
+
+    /**
+     * Returns the CSS previous sibling node of this node.
+     */
+    Node getCSSPreviousSibling();
+
+    /**
+     * Returns the CSS next sibling node of this node.
+     */
+    Node getCSSNextSibling();
+
+    /**
+     * Returns the CSS first child node of this node.
+     */
+    Node getCSSFirstChild();
+
+    /**
+     * Returns the CSS last child of this node.
+     */
+    Node getCSSLastChild();
+
+    /**
+     * Returns whether this node is the root of a (conceptual) hidden tree
+     * that selectors will not work across.
+     */
+    boolean isHiddenFromSelectors();
+}

Propchange: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSNavigableNode.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/SVG12CSSEngine.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/SVG12CSSEngine.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/SVG12CSSEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/SVG12CSSEngine.java Tue Sep 13 06:29:29 2005
@@ -1,6 +1,6 @@
 /*
 
-   Copyright 2002-2003  The Apache Software Foundation 
+   Copyright 2002-2003,2005  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.
@@ -41,7 +41,7 @@
 public class SVG12CSSEngine extends SVGCSSEngine {
     
     /**
-     * Creates a new SVGCSSEngine.
+     * Creates a new SVG12CSSEngine.
      * @param doc The associated document.
      * @param uri The document URI.
      * @param p The CSS parser to use.
@@ -59,7 +59,7 @@
     }
 
     /**
-     * Creates a new SVGCSSEngine.
+     * Creates a new SVG12CSSEngine.
      * @param doc The associated document.
      * @param uri The document URI.
      * @param p The CSS parser to use.

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDOMImplementation.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDOMImplementation.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDOMImplementation.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDOMImplementation.java Tue Sep 13 06:29:29 2005
@@ -1,6 +1,6 @@
 /*
 
-   Copyright 2000-2003  The Apache Software Foundation 
+   Copyright 2000-2003,2005  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.
@@ -20,7 +20,9 @@
 import java.io.Serializable;
 
 import org.apache.batik.dom.events.DocumentEventSupport;
+import org.apache.batik.dom.events.EventSupport;
 import org.apache.batik.dom.util.HashTable;
+
 import org.w3c.dom.DOMImplementation;
 
 /**
@@ -118,5 +120,12 @@
      */
     public DocumentEventSupport createDocumentEventSupport() {
         return new DocumentEventSupport();
+    }
+
+    /**
+     * Creates an EventSupport object for a given node.
+     */
+    public EventSupport createEventSupport(AbstractNode n) {
+        return new EventSupport(n);
     }
 }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDocument.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDocument.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDocument.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractDocument.java Tue Sep 13 06:29:29 2005
@@ -1,6 +1,6 @@
 /*
 
-   Copyright 2000-2003  The Apache Software Foundation 
+   Copyright 2000-2003,2005  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.
@@ -35,13 +35,22 @@
 import org.apache.batik.dom.events.EventSupport;
 import org.apache.batik.dom.traversal.TraversalSupport;
 import org.apache.batik.dom.util.DOMUtilities;
+import org.apache.batik.dom.xbl.GenericXBLManager;
+import org.apache.batik.dom.xbl.XBLManager;
 import org.apache.batik.i18n.Localizable;
 import org.apache.batik.i18n.LocalizableSupport;
 import org.apache.batik.util.CleanerThread;
 import org.apache.batik.util.DOMConstants;
 import org.apache.batik.util.SoftDoublyIndexedTable;
 import org.apache.batik.util.XMLConstants;
+import org.apache.xml.utils.PrefixResolver;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
+
 import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
 import org.w3c.dom.DOMConfiguration;
 import org.w3c.dom.DOMError;
 import org.w3c.dom.DOMErrorHandler;
@@ -49,26 +58,19 @@
 import org.w3c.dom.DOMImplementation;
 import org.w3c.dom.DOMLocator;
 import org.w3c.dom.DOMStringList;
-import org.w3c.dom.Document;
-import org.w3c.dom.DocumentType;
 import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.Text;
-import org.w3c.dom.UserDataHandler;
 import org.w3c.dom.events.DocumentEvent;
 import org.w3c.dom.events.Event;
 import org.w3c.dom.events.MutationNameEvent;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
 import org.w3c.dom.traversal.DocumentTraversal;
 import org.w3c.dom.traversal.NodeFilter;
 import org.w3c.dom.traversal.NodeIterator;
 import org.w3c.dom.traversal.TreeWalker;
-
-import org.apache.xml.utils.PrefixResolver;
-import org.apache.xpath.XPath;
-import org.apache.xpath.XPathContext;
-import org.apache.xpath.objects.XObject;
-import org.w3c.dom.NodeList;
+import org.w3c.dom.UserDataHandler;
 import org.w3c.dom.xpath.XPathEvaluator;
 import org.w3c.dom.xpath.XPathException;
 import org.w3c.dom.xpath.XPathExpression;
@@ -168,6 +170,11 @@
     protected DocumentConfiguration domConfig;
 
     /**
+     * The XBL manager for this document.
+     */
+    protected XBLManager xblManager = new GenericXBLManager();
+
+    /**
      * The elementsById lists.
      * This is keyed on 'id'.  the entry is either
      * a IdSoftReference to the element or a List of
@@ -1078,7 +1085,9 @@
             if (es1 != null) {
                 EventSupport es2 = e.getEventSupport();
                 if (es2 == null) {
-                    es2 = new EventSupport(e);
+                    AbstractDOMImplementation di
+                        = (AbstractDOMImplementation) implementation;
+                    es2 = di.createEventSupport(e);
                     setEventsEnabled(true);
                     e.eventSupport = es2;
                 }
@@ -1699,6 +1708,28 @@
     }
 
     /**
+     * Sets the XBLManager used for this document.
+     */
+    public void setXBLManager(XBLManager m) {
+        boolean wasProcessing = xblManager.isProcessing();
+        xblManager.stopProcessing();
+        if (m == null) {
+            m = new GenericXBLManager();
+        }
+        xblManager = m;
+        if (wasProcessing) {
+            xblManager.startProcessing();
+        }
+    }
+
+    /**
+     * Returns the XBLManager used for this document.
+     */
+    public XBLManager getXBLManager() {
+        return xblManager;
+    }
+
+    /**
      * DOMError implementation.
      */
     protected class DocumentError implements DOMError {
@@ -2556,6 +2587,111 @@
         public String lookupNamespaceURI(String prefix) {
             return ((AbstractNode) contextNode).lookupNamespaceURI(prefix);
         }
+    }
+
+    // NodeXBL //////////////////////////////////////////////////////////////
+
+    /**
+     * Get the parent of this node in the fully flattened tree.
+     */
+    public Node getXblParentNode() {
+        return xblManager.getXblParentNode(this);
+    }
+
+    /**
+     * Get the list of child nodes of this node in the fully flattened tree.
+     */
+    public NodeList getXblChildNodes() {
+        return xblManager.getXblChildNodes(this);
+    }
+
+    /**
+     * Get the list of child nodes of this node in the fully flattened tree
+     * that are within the same shadow scope.
+     */
+    public NodeList getXblScopedChildNodes() {
+        return xblManager.getXblScopedChildNodes(this);
+    }
+
+    /**
+     * Get the first child node of this node in the fully flattened tree.
+     */
+    public Node getXblFirstChild() {
+        return xblManager.getXblFirstChild(this);
+    }
+
+    /**
+     * Get the last child node of this node in the fully flattened tree.
+     */
+    public Node getXblLastChild() {
+        return xblManager.getXblLastChild(this);
+    }
+
+    /**
+     * Get the node which directly precedes the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Node getXblPreviousSibling() {
+        return xblManager.getXblPreviousSibling(this);
+    }
+
+    /**
+     * Get the node which directly follows the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Node getXblNextSibling() {
+        return xblManager.getXblNextSibling(this);
+    }
+
+    /**
+     * Get the first element child of this node in the fully flattened tree.
+     */
+    public Element getXblFirstElementChild() {
+        return xblManager.getXblFirstElementChild(this);
+    }
+
+    /**
+     * Get the last element child of this node in the fully flattened tree.
+     */
+    public Element getXblLastElementChild() {
+        return xblManager.getXblLastElementChild(this);
+    }
+
+    /**
+     * Get the first element that precedes the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Element getXblPreviousElementSibling() {
+        return xblManager.getXblPreviousElementSibling(this);
+    }
+
+    /**
+     * Get the first element that follows the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Element getXblNextElementSibling() {
+        return xblManager.getXblNextElementSibling(this);
+    }
+
+    /**
+     * Get the bound element whose shadow tree this current node resides in.
+     */
+    public Element getXblBoundElement() {
+        return xblManager.getXblBoundElement(this);
+    }
+
+    /**
+     * Get the shadow tree of this node.
+     */
+    public Element getXblShadowTree() {
+        return xblManager.getXblShadowTree(this);
+    }
+
+    /**
+     * Get the xbl:definition elements currently binding this element.
+     */
+    public NodeList getXblDefinitions() {
+        return xblManager.getXblDefinitions(this);
     }
 
     // Serializable /////////////////////////////////////////////////

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractElement.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractElement.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractElement.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractElement.java Tue Sep 13 06:29:29 2005
@@ -19,7 +19,10 @@
 
 import java.io.Serializable;
 
+import org.apache.batik.dom.events.DOMMutationEvent;
 import org.apache.batik.dom.util.DOMUtilities;
+import org.apache.batik.util.XMLConstants;
+
 import org.w3c.dom.Attr;
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Element;
@@ -610,15 +613,17 @@
 	AbstractDocument doc = getCurrentDocument();
 	if (doc.getEventsEnabled() && !oldv.equals(newv)) {
 	    DocumentEvent de = (DocumentEvent)doc;
-	    MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
-	    ev.initMutationEvent("DOMAttrModified",
-				 true,    // canBubbleArg
-				 false,   // cancelableArg
-				 node,    // relatedNodeArg
-				 oldv,    // prevValueArg
-				 newv,    // newValueArg
-				 name,    // attrNameArg
-                                 change); // attrChange
+	    DOMMutationEvent ev
+                = (DOMMutationEvent) de.createEvent("MutationEvents");
+	    ev.initMutationEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
+                                   "DOMAttrModified",
+                                   true,    // canBubbleArg
+                                   false,   // cancelableArg
+                                   node,    // relatedNodeArg
+                                   oldv,    // prevValueArg
+                                   newv,    // newValueArg
+                                   name,    // attrNameArg
+                                   change); // attrChange
 	    dispatchEvent(ev);
 	}
     }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractNode.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractNode.java?rev=280553&r1=280552&r2=280553&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractNode.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/AbstractNode.java Tue Sep 13 06:29:29 2005
@@ -1,6 +1,6 @@
 /*
 
-   Copyright 2000-2003  The Apache Software Foundation 
+   Copyright 2000-2003,2005  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.
@@ -23,10 +23,13 @@
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.batik.dom.events.DOMMutationEvent;
 import org.apache.batik.dom.events.EventSupport;
 import org.apache.batik.dom.events.NodeEventTarget;
 import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.dom.util.XMLSupport;
+import org.apache.batik.dom.xbl.NodeXBL;
+import org.apache.batik.dom.xbl.XBLManagerData;
 import org.apache.batik.util.ParsedURL;
 import org.apache.batik.util.XMLConstants;
 import org.w3c.dom.Attr;
@@ -37,7 +40,6 @@
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-import org.w3c.dom.TypeInfo;
 import org.w3c.dom.UserDataHandler;
 import org.w3c.dom.events.DocumentEvent;
 import org.w3c.dom.events.Event;
@@ -53,12 +55,14 @@
  */
 public abstract class AbstractNode
     implements ExtendedNode,
+               NodeXBL,
+               XBLManagerData,
                Serializable {
 
     /**
      * An empty instance of NodeList.
      */
-    protected final static NodeList EMPTY_NODE_LIST = new NodeList() {
+    public final static NodeList EMPTY_NODE_LIST = new NodeList() {
         public Node item(int i) { return null; }
         public int  getLength() { return 0; }
     };
@@ -84,6 +88,11 @@
     protected HashMap userDataHandlers;
 
     /**
+     * The XBL manager data.
+     */
+    protected Object managerData;
+
+    /**
      * Sets the name of this node.
      * Do nothing.
      */
@@ -447,6 +456,10 @@
         return getCascadedXMLBase(this);
     }
 
+    public static String getBaseURI(Node n) {
+        return ((AbstractNode) n).getBaseURI();
+    }
+
     // DocumentPosition constants from DOM Level 3 Core org.w3c.dom.Node
     // interface.
 
@@ -739,6 +752,9 @@
                         Node attr = nnm.item(i);
                         String attrPrefix = attr.getPrefix();
                         String localName = attr.getLocalName();
+                        if (localName == null) {
+                            localName = attr.getNodeName();
+                        }
                         if (XMLConstants.XMLNS_PREFIX.equals(attrPrefix)
                                 && compareStrings(localName, prefix)
                                 || XMLConstants.XMLNS_PREFIX.equals(localName)
@@ -913,9 +929,7 @@
                                  EventListener listener,
                                  boolean useCapture) {
         if (eventSupport == null) {
-            eventSupport = new EventSupport(this);
-            AbstractDocument doc = getCurrentDocument();
-            doc.setEventsEnabled(true);
+            initializeEventSupport();
         }
         eventSupport.addEventListener(type, listener, useCapture);
     }
@@ -931,15 +945,13 @@
                                    boolean useCapture,
                                    Object evtGroup) {
         if (eventSupport == null) {
-            eventSupport = new EventSupport(this);
-            AbstractDocument doc = getCurrentDocument();
-            doc.setEventsEnabled(true);
+            initializeEventSupport();
         }
         eventSupport.addEventListenerNS(namespaceURI,
                                         type,
-                                        evtGroup,
                                         listener,
-                                        useCapture);
+                                        useCapture,
+                                        evtGroup);
     }
 
     /**
@@ -965,10 +977,10 @@
                                       EventListener listener,
                                       boolean useCapture) {
         if (eventSupport != null) {
-            eventSupport.removeEventListener(namespaceURI,
-                                             type,
-                                             listener,
-                                             useCapture);
+            eventSupport.removeEventListenerNS(namespaceURI,
+                                               type,
+                                               listener,
+                                               useCapture);
         }
     }
 
@@ -977,7 +989,7 @@
      * org.apache.batik.dom.events.NodeEventTarget#getParentNodeEventTarget()}.
      */
     public NodeEventTarget getParentNodeEventTarget() {
-        return (NodeEventTarget)getParentNode();
+        return (NodeEventTarget) getXblParentNode();
     }
 
     /**
@@ -986,9 +998,7 @@
      */
     public boolean dispatchEvent(Event evt) throws EventException {
         if (eventSupport == null) {
-            eventSupport = new EventSupport(this);
-            AbstractDocument doc = getCurrentDocument();
-            doc.setEventsEnabled(true);
+            initializeEventSupport();
         }
         return eventSupport.dispatchEvent(this, evt);
     }
@@ -1020,21 +1030,37 @@
     }
 
     /**
+     * Initializes the event support instance for this node if it has not
+     * been already, and returns it.
+     */
+    public EventSupport initializeEventSupport() {
+        if (eventSupport == null) {
+            AbstractDocument doc = getCurrentDocument();
+            AbstractDOMImplementation di
+                = (AbstractDOMImplementation) doc.getImplementation();
+            eventSupport = di.createEventSupport(this);
+            doc.setEventsEnabled(true);
+        }
+        return eventSupport;
+    }
+
+    /**
      * Recursively fires a DOMNodeInsertedIntoDocument event.
      */
     public void fireDOMNodeInsertedIntoDocumentEvent() {
         AbstractDocument doc = getCurrentDocument();
         if (doc.getEventsEnabled()) {
             DocumentEvent de = (DocumentEvent)doc;
-            MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
-            ev.initMutationEvent("DOMNodeInsertedIntoDocument",
-                                 true,   // canBubbleArg
-                                 false,  // cancelableArg
-                                 null,   // relatedNodeArg
-                                 null,   // prevValueArg
-                                 null,   // newValueArg
-                                 null,   // attrNameArg
-                                 MutationEvent.ADDITION);
+            DOMMutationEvent ev = (DOMMutationEvent)de.createEvent("MutationEvents");
+            ev.initMutationEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
+                                   "DOMNodeInsertedIntoDocument",
+                                   true,   // canBubbleArg
+                                   false,  // cancelableArg
+                                   null,   // relatedNodeArg
+                                   null,   // prevValueArg
+                                   null,   // newValueArg
+                                   null,   // attrNameArg
+                                   MutationEvent.ADDITION);
             dispatchEvent(ev);
         }
     }
@@ -1046,15 +1072,17 @@
         AbstractDocument doc = getCurrentDocument();
         if (doc.getEventsEnabled()) {
             DocumentEvent de = (DocumentEvent)doc;
-            MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
-            ev.initMutationEvent("DOMNodeRemovedFromDocument",
-                                 true,   // canBubbleArg
-                                 false,  // cancelableArg
-                                 null,   // relatedNodeArg
-                                 null,   // prevValueArg
-                                 null,   // newValueArg
-                                 null,   // attrNameArg
-                                 MutationEvent.REMOVAL);
+            DOMMutationEvent ev
+                = (DOMMutationEvent) de.createEvent("MutationEvents");
+            ev.initMutationEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
+                                   "DOMNodeRemovedFromDocument",
+                                   true,   // canBubbleArg
+                                   false,  // cancelableArg
+                                   null,   // relatedNodeArg
+                                   null,   // prevValueArg
+                                   null,   // newValueArg
+                                   null,   // attrNameArg
+                                   MutationEvent.REMOVAL);
             dispatchEvent(ev);
         }
     }
@@ -1067,15 +1095,17 @@
         AbstractDocument doc = getCurrentDocument();
         if (doc.getEventsEnabled()) {
             DocumentEvent de = (DocumentEvent)doc;
-            MutationEvent ev = (MutationEvent)de.createEvent("MutationEvents");
-            ev.initMutationEvent("DOMCharacterDataModified",
-                                 true,  // canBubbleArg
-                                 false, // cancelableArg
-                                 null,  // relatedNodeArg
-                                 oldv,  // prevValueArg
-                                 newv,  // newValueArg
-                                 null,  // attrNameArg
-                                 MutationEvent.MODIFICATION);
+            DOMMutationEvent ev
+                = (DOMMutationEvent) de.createEvent("MutationEvents");
+            ev.initMutationEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
+                                   "DOMCharacterDataModified",
+                                   true,  // canBubbleArg
+                                   false, // cancelableArg
+                                   null,  // relatedNodeArg
+                                   oldv,  // prevValueArg
+                                   newv,  // newValueArg
+                                   null,  // attrNameArg
+                                   MutationEvent.MODIFICATION);
             dispatchEvent(ev);
         }
     }
@@ -1142,10 +1172,124 @@
                                                 getNodeName() });
     }
 
+    // NodeXBL //////////////////////////////////////////////////////////////
+
     /**
-     * Gets the base URI of the given node.
+     * Get the parent of this node in the fully flattened tree.
      */
-    public static String getBaseURI(Node n) {
-        return ((AbstractNode) n).getBaseURI();
+    public Node getXblParentNode() {
+        return ownerDocument.getXBLManager().getXblParentNode(this);
+    }
+
+    /**
+     * Get the list of child nodes of this node in the fully flattened tree.
+     */
+    public NodeList getXblChildNodes() {
+        return ownerDocument.getXBLManager().getXblChildNodes(this);
+    }
+
+    /**
+     * Get the list of child nodes of this node in the fully flattened tree
+     * that are within the same shadow scope.
+     */
+    public NodeList getXblScopedChildNodes() {
+        return ownerDocument.getXBLManager().getXblScopedChildNodes(this);
+    }
+
+    /**
+     * Get the first child node of this node in the fully flattened tree.
+     */
+    public Node getXblFirstChild() {
+        return ownerDocument.getXBLManager().getXblFirstChild(this);
+    }
+
+    /**
+     * Get the last child node of this node in the fully flattened tree.
+     */
+    public Node getXblLastChild() {
+        return ownerDocument.getXBLManager().getXblLastChild(this);
+    }
+
+    /**
+     * Get the node which directly precedes the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Node getXblPreviousSibling() {
+        return ownerDocument.getXBLManager().getXblPreviousSibling(this);
+    }
+
+    /**
+     * Get the node which directly follows the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Node getXblNextSibling() {
+        return ownerDocument.getXBLManager().getXblNextSibling(this);
+    }
+
+    /**
+     * Get the first element child of this node in the fully flattened tree.
+     */
+    public Element getXblFirstElementChild() {
+        return ownerDocument.getXBLManager().getXblFirstElementChild(this);
+    }
+
+    /**
+     * Get the last element child of this node in the fully flattened tree.
+     */
+    public Element getXblLastElementChild() {
+        return ownerDocument.getXBLManager().getXblLastElementChild(this);
+    }
+
+    /**
+     * Get the first element that precedes the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Element getXblPreviousElementSibling() {
+        return ownerDocument.getXBLManager().getXblPreviousElementSibling(this);
+    }
+
+    /**
+     * Get the first element that follows the current node in the
+     * xblParentNode's xblChildNodes list.
+     */
+    public Element getXblNextElementSibling() {
+        return ownerDocument.getXBLManager().getXblNextElementSibling(this);
+    }
+
+    /**
+     * Get the bound element whose shadow tree this current node resides in.
+     */
+    public Element getXblBoundElement() {
+        return ownerDocument.getXBLManager().getXblBoundElement(this);
+    }
+
+    /**
+     * Get the shadow tree of this node.
+     */
+    public Element getXblShadowTree() {
+        return ownerDocument.getXBLManager().getXblShadowTree(this);
+    }
+
+    /**
+     * Get the xbl:definition elements currently binding this element.
+     */
+    public NodeList getXblDefinitions() {
+        return ownerDocument.getXBLManager().getXblDefinitions(this);
+    }
+
+    // XBLManagerData ////////////////////////////////////////////////////////
+
+    /**
+     * Returns the XBL manager associated data for this node.
+     */
+    public Object getManagerData() {
+        return managerData;
+    }
+
+    /**
+     * Sets the XBL manager associated data for this node.
+     */
+    public void setManagerData(Object data) {
+        managerData = data;
     }
 }