You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by hi...@apache.org on 2001/09/12 10:54:33 UTC
cvs commit: xml-batik/sources/org/apache/batik/dom AbstractDocument.java AbstractElement.java AbstractParentNode.java
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:stephane@hillion.org">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:stephane@hillion.org">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:stephane@hillion.org">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: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org