hillion 01/09/12 01:54:33 Modified: sources/org/apache/batik/dom AbstractDocument.java AbstractElement.java AbstractParentNode.java Log: The NodeList objects returned by getElementsByTagName* are now live objects. Revision Changes Path 1.9 +39 -30 xml-batik/sources/org/apache/batik/dom/AbstractDocument.java Index: AbstractDocument.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/AbstractDocument.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- AbstractDocument.java 2001/07/31 13:00:49 1.8 +++ AbstractDocument.java 2001/09/12 08:54:33 1.9 @@ -16,9 +16,11 @@ import java.util.Locale; import java.util.MissingResourceException; +import java.util.WeakHashMap; import org.apache.batik.dom.events.DocumentEventSupport; import org.apache.batik.dom.traversal.TraversalSupport; +import org.apache.batik.dom.util.SoftDoublyIndexedTable; import org.apache.batik.i18n.Localizable; import org.apache.batik.i18n.LocalizableSupport; @@ -42,7 +44,7 @@ * This class implements the {@link org.w3c.dom.Document} interface. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: AbstractDocument.java,v 1.8 2001/07/31 13:00:49 hillion Exp $ + * @version $Id: AbstractDocument.java,v 1.9 2001/09/12 08:54:33 hillion Exp $ */ public abstract class AbstractDocument extends AbstractParentNode @@ -84,6 +86,11 @@ protected transient boolean eventsEnabled; /** + * The ElementsByTagName lists. + */ + protected transient WeakHashMap elementsByTagNames; + + /** * Creates a new document. */ protected AbstractDocument() { @@ -194,20 +201,6 @@ /** * <b>DOM</b>: Implements {@link - * org.w3c.dom.Document#getElementsByTagName(String)}. - */ - public NodeList getElementsByTagName(String tagname) { - Element e = getDocumentElement(); - if (e == null) { - return EMPTY_NODE_LIST; - } - Nodes result = new Nodes(); - getElementsByTagName(e, tagname, result); - return result; - } - - /** - * <b>DOM</b>: Implements {@link * org.w3c.dom.Document#importNode(Node,boolean)}. */ public Node importNode(Node importedNode, boolean deep) @@ -285,21 +278,6 @@ } /** - * <b>DOM</b>: Implements {@link - * org.w3c.dom.Document#getElementsByTagNameNS(String,String)}. - */ - public NodeList getElementsByTagNameNS(String namespaceURI, - String localName) { - Element e = getDocumentElement(); - if (e == null) { - return EMPTY_NODE_LIST; - } - Nodes result = new Nodes(); - getElementsByTagNameNS(e, namespaceURI, localName, result); - return result; - } - - /** * <b>DOM</b>: Implements {@link org.w3c.dom.Node#cloneNode(boolean)}. */ public Node cloneNode(boolean deep) { @@ -313,6 +291,37 @@ } } return n; + } + + /** + * Returns an ElementsByTagName object from the cache, if any. + */ + public ElementsByTagName getElementsByTagName(Node n, String ns, String ln) { + if (elementsByTagNames == null) { + return null; + } + SoftDoublyIndexedTable t; + t = (SoftDoublyIndexedTable)elementsByTagNames.get(n); + if (t == null) { + return null; + } + return (ElementsByTagName)t.get(ns, ln); + } + + /** + * Puts an ElementsByTagName object in the cache. + */ + public void putElementsByTagName(Node n, String ns, String ln, + ElementsByTagName l) { + if (elementsByTagNames == null) { + elementsByTagNames = new WeakHashMap(11); + } + SoftDoublyIndexedTable t; + t = (SoftDoublyIndexedTable)elementsByTagNames.get(n); + if (t == null) { + elementsByTagNames.put(n, t = new SoftDoublyIndexedTable()); + } + t.put(ns, ln, l); } // DocumentEvent ///////////////////////////////////////////////////////// 1.10 +44 -31 xml-batik/sources/org/apache/batik/dom/AbstractElement.java Index: AbstractElement.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/AbstractElement.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- AbstractElement.java 2001/05/18 06:20:44 1.9 +++ AbstractElement.java 2001/09/12 08:54:33 1.10 @@ -29,7 +29,7 @@ * This class implements the {@link org.w3c.dom.Element} interface. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: AbstractElement.java,v 1.9 2001/05/18 06:20:44 hillion Exp $ + * @version $Id: AbstractElement.java,v 1.10 2001/09/12 08:54:33 hillion Exp $ */ public abstract class AbstractElement extends AbstractParentChildNode @@ -180,23 +180,6 @@ } /** - * <b>DOM</b>: Implements {@link - * org.w3c.dom.Element#getElementsByTagName(String)}. - */ - public NodeList getElementsByTagName(String name) { - Node n = getFirstChild(); - if (n == null || name == null) { - return EMPTY_NODE_LIST; - } - Nodes result = new Nodes(); - while (n != null) { - getElementsByTagName(n, name, result); - n = n.getNextSibling(); - } - return result; - } - - /** * <b>DOM</b>: Implements {@link org.w3c.dom.Node#normalize()}. */ public void normalize() { @@ -287,21 +270,51 @@ } /** - * <b>DOM</b>: Implements {@link - * org.w3c.dom.Element#getElementsByTagNameNS(String,String)}. + * Called when a child node has been added. + */ + protected void nodeAdded(Node node) { + invalidateElementsByTagName(node); + } + + /** + * Called when a child node is going to be removed. + */ + protected void nodeToBeRemoved(Node node) { + invalidateElementsByTagName(node); + } + + /** + * Invalidates the ElementsByTagName objects of this node and its parents. */ - public NodeList getElementsByTagNameNS(String namespaceURI, - String localName) { - Node n = getFirstChild(); - if (n == null || localName == null) { - return EMPTY_NODE_LIST; - } - Nodes result = new Nodes(); - while (n != null) { - getElementsByTagNameNS(n, namespaceURI, localName, result); - n = n.getNextSibling(); + private void invalidateElementsByTagName(Node node) { + if (node.getNodeType() != ELEMENT_NODE) { + return; + } + AbstractDocument ad = getCurrentDocument(); + String ns = node.getNamespaceURI(); + String ln = (ns == null) ? node.getNodeName() : node.getLocalName(); + for (Node n = this; n != null; n = n.getParentNode()) { + switch (n.getNodeType()) { + case ELEMENT_NODE: + case DOCUMENT_NODE: + ElementsByTagName l = ad.getElementsByTagName(n, ns, ln); + if (l != null) { + l.invalidate(); + } + l = ad.getElementsByTagName(n, "*", ln); + if (l != null) { + l.invalidate(); + } + l = ad.getElementsByTagName(n, ns, "*"); + if (l != null) { + l.invalidate(); + } + l = ad.getElementsByTagName(n, "*", "*"); + if (l != null) { + l.invalidate(); + } + } } - return result; } /** 1.10 +122 -52 xml-batik/sources/org/apache/batik/dom/AbstractParentNode.java Index: AbstractParentNode.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/AbstractParentNode.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- AbstractParentNode.java 2001/08/03 04:27:23 1.9 +++ AbstractParentNode.java 2001/09/12 08:54:33 1.10 @@ -24,7 +24,7 @@ * This class implements the Node interface with support for children. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: AbstractParentNode.java,v 1.9 2001/08/03 04:27:23 bella Exp $ + * @version $Id: AbstractParentNode.java,v 1.10 2001/09/12 08:54:33 hillion Exp $ */ public abstract class AbstractParentNode extends AbstractNode { @@ -92,6 +92,8 @@ (ExtendedNode)refChild); n.setParentNode(this); + nodeAdded(n); + // Mutation event fireDOMNodeInsertedEvent(n); fireDOMSubtreeModifiedEvent(); @@ -131,6 +133,7 @@ fireDOMNodeRemovedEvent(oldChild); getCurrentDocument().nodeToBeRemoved(oldChild); + nodeToBeRemoved(oldChild); // Node modification ExtendedNode n = (ExtendedNode)newChild; @@ -138,6 +141,8 @@ n.setParentNode(this); o.setParentNode(null); + nodeAdded(n); + // Mutation event fireDOMNodeInsertedEvent(n); fireDOMSubtreeModifiedEvent(); @@ -167,6 +172,7 @@ fireDOMNodeRemovedEvent(oldChild); getCurrentDocument().nodeToBeRemoved(oldChild); + nodeToBeRemoved(oldChild); // Node modification ExtendedNode result = childNodes.remove((ExtendedNode)oldChild); @@ -199,6 +205,8 @@ ExtendedNode n = childNodes.append((ExtendedNode)newChild); n.setParentNode(this); + nodeAdded(n); + // Mutation event fireDOMNodeInsertedEvent(n); fireDOMSubtreeModifiedEvent(); @@ -240,6 +248,42 @@ } /** + * <b>DOM</b>: Implements {@link + * org.w3c.dom.Element#getElementsByTagName(String)}. + */ + public NodeList getElementsByTagName(String name) { + if (name == null) { + return EMPTY_NODE_LIST; + } + AbstractDocument ad = getCurrentDocument(); + ElementsByTagName result = ad.getElementsByTagName(this, null, name); + if (result == null) { + result = new ElementsByTagName(null, name); + ad.putElementsByTagName(this, null, name, result); + } + return result; + } + + /** + * <b>DOM</b>: Implements {@link + * org.w3c.dom.Element#getElementsByTagNameNS(String,String)}. + */ + public NodeList getElementsByTagNameNS(String namespaceURI, + String localName) { + if (localName == null) { + return EMPTY_NODE_LIST; + } + AbstractDocument ad = getCurrentDocument(); + ElementsByTagName result = ad.getElementsByTagName(this, namespaceURI, + localName); + if (result == null) { + result = new ElementsByTagName(namespaceURI, localName); + ad.putElementsByTagName(this, namespaceURI, localName, result); + } + return result; + } + + /** * Recursively fires a DOMNodeInsertedIntoDocument event. */ public void fireDOMNodeInsertedIntoDocumentEvent() { @@ -265,57 +309,16 @@ } } - /** - * An auxiliary method of getElementsByTagName. - */ - protected static void getElementsByTagName(Node node, String name, - Nodes list) { - if (node.getNodeType() == ELEMENT_NODE) { - if (name.equals("*") || name.equals(node.getNodeName())) { - list.append(node); - } - } - for (Node n = node.getFirstChild(); - n != null; - n = n.getNextSibling()) { - getElementsByTagName(n, name, list); - } - } - /** - * An auxiliary method for getElementsByTagNameNS. + * Called when a child node has been added. */ - protected static void getElementsByTagNameNS(Node node, - String ns, - String name, - Nodes list) { - if (node.getNodeType() == ELEMENT_NODE) { - if (stringMatches(ns, node.getNamespaceURI()) && - (name.equals("*") || name.equals(node.getLocalName()))) { - list.append(node); - } - } - for (Node n = node.getFirstChild(); - n != null; - n = n.getNextSibling()) { - getElementsByTagNameNS(n, ns, name, list); - } + protected void nodeAdded(Node n) { } /** - * String matching for getElementsByTagNameNS function. + * Called when a child node is going to be removed. */ - private static boolean stringMatches(String s1, String s2) { - if (s1 == null && s2 == null) { - return true; - } - if (s1 == null || s2 == null) { - return false; - } - if (s1.equals("*")) { - return true; - } - return s1.equals(s2); + protected void nodeToBeRemoved(Node n) { } /** @@ -445,7 +448,8 @@ /** * To manage a list of nodes. */ - protected static class Nodes implements NodeList { + protected class ElementsByTagName implements NodeList { + /** * The table. */ @@ -454,18 +458,33 @@ /** * The number of nodes. */ - protected int size; + protected int size = -1; + /** + * The namespace URI identifier. + */ + protected String namespaceURI; + + /** + * The local name identifier. + */ + protected String localName; + /** * Creates a new Nodes object. */ - public Nodes() { + public ElementsByTagName(String ns, String ln) { + namespaceURI = ns; + localName = ln; } /** - * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#item(int)}. + * <b>DOM</b>: Implements {@link NodeList#item(int)}. */ public Node item(int index) { + if (size == -1) { + initialize(); + } if (table == null || index < 0 || index > size) { return null; } @@ -473,17 +492,27 @@ } /** - * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#getLength()}. + * <b>DOM</b>: Implements {@link NodeList#getLength()}. * @return {@link #size}. */ public int getLength() { + if (size == -1) { + initialize(); + } return size; } + /** + * Invalidates the list. + */ + public void invalidate() { + size = -1; + } + /** * Appends a node to the list. */ - public void append(Node n) { + protected void append(Node n) { if (table == null) { table = new Node[11]; } else if (size == table.length - 1) { @@ -495,6 +524,47 @@ } table[size++] = n; } + + /** + * Initializes the list. + */ + protected void initialize() { + size = 0; + for (Node n = AbstractParentNode.this.getFirstChild(); + n != null; + n = n.getNextSibling()) { + initialize(n); + } + } + + private void initialize(Node node) { + if (node.getNodeType() == ELEMENT_NODE) { + String ns = node.getNamespaceURI(); + String nm = (ns == null) ? node.getNodeName() : node.getLocalName(); + if (nsMatch(namespaceURI, node.getNamespaceURI()) && + (localName.equals("*") || localName.equals(nm))) { + append(node); + } + } + for (Node n = node.getFirstChild(); + n != null; + n = n.getNextSibling()) { + initialize(n); + } + } + + private boolean nsMatch(String s1, String s2) { + if (s1 == null && s2 == null) { + return true; + } + if (s1 == null || s2 == null) { + return false; + } + if (s1.equals("*")) { + return true; + } + return s1.equals(s2); + } } /** --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]