You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by le...@apache.org on 2001/01/23 18:54:56 UTC
cvs commit: xml-xerces/java/src/org/apache/xerces/dom AttrImpl.java AttributeMap.java ElementImpl.java NodeImpl.java ParentNode.java
lehors 01/01/23 09:54:54
Modified: java/src/org/apache/xerces/dom AttrImpl.java
AttributeMap.java ElementImpl.java NodeImpl.java
ParentNode.java
Log:
This change is an optimized version of the patch from Jay Cain:
This patch modifies AttributeMap.java, AttrImpl.java, ElementImpl.java, and
ParentNode.java to optimize normalization. This is done by performing a
check when the set of a parent node's children have changed (inserted,
removed). If the change causes the parent to be unnormalized, it is flagged
as so, and its ancestors are inherently flagged as unnormalized.
Effectively, a call to the normalize method normalizes only the nodes that
need it, rather than walking through the entire subtree doing a brute-force
check.
This optimization is most effective on documents that are several levels
deep or for applications that blindly and frequently call normalize (such as
Cocoon). I did some tests using Cocoon and achieved an average performance
increase of 10% with a best-case scenario yielding close to 20%.
Revision Changes Path
1.26 +73 -2 xml-xerces/java/src/org/apache/xerces/dom/AttrImpl.java
Index: AttrImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/AttrImpl.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- AttrImpl.java 2001/01/18 22:26:25 1.25
+++ AttrImpl.java 2001/01/23 17:54:36 1.26
@@ -464,9 +464,10 @@
public void normalize() {
- if (hasStringValue()) {
+ // No need to normalize if already normalized or
+ // if value is kept as a String.
+ if (isNormalized() || hasStringValue())
return;
- }
Node kid, next;
ChildNode firstChild = (ChildNode)value;
@@ -496,6 +497,7 @@
}
}
+ isNormalized(true);
} // normalize()
//
@@ -847,6 +849,8 @@
if( (mutationMask&MUTATION_AGGREGATE) != 0)
dispatchAggregateEvents(enclosingAttr);
}
+
+ checkNormalizationAfterInsert(newInternal);
}
return newChild;
@@ -988,6 +992,9 @@
}
}
+ // Save previous sibling for normalization checking.
+ ChildNode oldPreviousSibling = oldInternal.previousSibling();
+
// Remove oldInternal's references to tree
oldInternal.ownerNode = ownerDocument;
oldInternal.isOwned(false);
@@ -1005,6 +1012,8 @@
dispatchAggregateEvents(enclosingAttr);
} // End mutation postprocessing
+ checkNormalizationAfterRemove(oldPreviousSibling);
+
return oldInternal;
} // internalRemoveChild(Node,int):Node
@@ -1226,6 +1235,68 @@
ownerDocument.mutationEvents = orig;
} // synchronizeChildren()
+
+ /**
+ * Checks the normalized state of this node after inserting a child.
+ * If the inserted child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ * <ul>
+ * <li>The inserted child is a text node and one of its adjacent siblings
+ * is also a text node.
+ * <li>The inserted child is is itself unnormalized.
+ * </ul>
+ *
+ * @param insertedChild the child node that was inserted into this node
+ *
+ * @throws NullPointerException if the inserted child is <code>null</code>
+ */
+ void checkNormalizationAfterInsert(ChildNode insertedChild) {
+ // See if insertion caused this node to be unnormalized.
+ if (insertedChild.getNodeType() == Node.TEXT_NODE) {
+ ChildNode prev = insertedChild.previousSibling();
+ ChildNode next = insertedChild.nextSibling;
+ // If an adjacent sibling of the new child is a text node,
+ // flag this node as unnormalized.
+ if ((prev != null && prev.getNodeType() == Node.TEXT_NODE) ||
+ (next != null && next.getNodeType() == Node.TEXT_NODE)) {
+ isNormalized(false);
+ }
+ }
+ else {
+ // If the new child is not normalized,
+ // then this node is inherently not normalized.
+ if (!insertedChild.isNormalized()) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterInsert(ChildNode)
+
+ /**
+ * Checks the normalized of this node after removing a child.
+ * If the removed child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ * <ul>
+ * <li>The removed child had two adjacent siblings that were text nodes.
+ * </ul>
+ *
+ * @param previousSibling the previous sibling of the removed child, or
+ * <code>null</code>
+ */
+ void checkNormalizationAfterRemove(ChildNode previousSibling) {
+ // See if removal caused this node to be unnormalized.
+ // If the adjacent siblings of the removed child were both text nodes,
+ // flag this node as unnormalized.
+ if (previousSibling != null &&
+ previousSibling.getNodeType() == Node.TEXT_NODE) {
+
+ ChildNode next = previousSibling.nextSibling;
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterRemove(ChildNode)
//
// Serialization methods
1.11 +15 -3 xml-xerces/java/src/org/apache/xerces/dom/AttributeMap.java
Index: AttributeMap.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/AttributeMap.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- AttributeMap.java 2001/01/05 19:56:08 1.10
+++ AttributeMap.java 2001/01/23 17:54:38 1.11
@@ -158,8 +158,14 @@
MutationEvent.ADDITION : MutationEvent.MODIFICATION
);
}
- return previous;
+ // If the new attribute is not normalized,
+ // the owning element is inherently not normalized.
+ if (!argn.isNormalized()) {
+ ownerNode.isNormalized(false);
+ }
+ return previous;
+
} // setNamedItem(Node):Node
/**
@@ -236,9 +242,15 @@
MutationEvent.ADDITION : MutationEvent.MODIFICATION
);
}
- return previous;
- } // setNamedItem(Node):Node
+ // If the new attribute is not normalized,
+ // the owning element is inherently not normalized.
+ if (!argn.isNormalized()) {
+ ownerNode.isNormalized(false);
+ }
+ return previous;
+
+ } // setNamedItemNS(Node):Node
/**
* Removes an attribute specified by name.
1.31 +14 -6 xml-xerces/java/src/org/apache/xerces/dom/ElementImpl.java
Index: ElementImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/ElementImpl.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- ElementImpl.java 2001/01/12 00:10:24 1.30
+++ ElementImpl.java 2001/01/23 17:54:40 1.31
@@ -291,9 +291,16 @@
* normal Text or with other CDATASections.
*/
public void normalize() {
- Node kid, next;
- for (kid = getFirstChild(); kid != null; kid = next) {
- next = kid.getNextSibling();
+ // No need to normalize if already normalized.
+ if (isNormalized()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ChildNode kid, next;
+ for (kid = firstChild; kid != null; kid = next) {
+ next = kid.nextSibling;
// If kid is a text node, we need to check for one of two
// conditions:
@@ -317,9 +324,9 @@
}
}
- // Otherwise it might be an Element, which is handled recursively
- else if (kid.getNodeType() == Node.ELEMENT_NODE) {
- ((Element)kid).normalize();
+ // Otherwise it might be an Element, which is handled recursively
+ else if (kid.getNodeType() == Node.ELEMENT_NODE) {
+ kid.normalize();
}
}
@@ -336,6 +343,7 @@
// changed() will have occurred when the removeChild() was done,
// so does not have to be reissued.
+ isNormalized(true);
} // normalize()
/**
1.37 +13 -0 xml-xerces/java/src/org/apache/xerces/dom/NodeImpl.java
Index: NodeImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/NodeImpl.java,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- NodeImpl.java 2001/01/12 00:10:25 1.36
+++ NodeImpl.java 2001/01/23 17:54:43 1.37
@@ -141,6 +141,7 @@
protected final static short IGNORABLEWS = 0x1<<6;
protected final static short SETVALUE = 0x1<<7;
protected final static short HASSTRING = 0x1<<8;
+ protected final static short UNNORMALIZED = 0x1<<9;
//
// Constructors
@@ -1376,6 +1377,18 @@
final void hasStringValue(boolean value) {
flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
+ }
+
+ final boolean isNormalized() {
+ return (flags & UNNORMALIZED) == 0;
+ }
+
+ final void isNormalized(boolean value) {
+ // See if flag should propagate to parent.
+ if (!value && !isNormalized() && ownerNode != null) {
+ ownerNode.isNormalized(false);
+ }
+ flags = (short) (value ? flags & ~UNNORMALIZED : flags | UNNORMALIZED);
}
//
1.20 +86 -10 xml-xerces/java/src/org/apache/xerces/dom/ParentNode.java
Index: ParentNode.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/ParentNode.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- ParentNode.java 2001/01/20 00:51:40 1.19
+++ ParentNode.java 2001/01/23 17:54:44 1.20
@@ -1,4 +1,4 @@
-/* $Id: ParentNode.java,v 1.19 2001/01/20 00:51:40 lehors Exp $ */
+/* $Id: ParentNode.java,v 1.20 2001/01/23 17:54:44 lehors Exp $ */
/*
* The Apache Software License, Version 1.1
*
@@ -180,9 +180,9 @@
// Then, if deep, clone the kids too.
if (deep) {
- for (Node child = firstChild;
+ for (ChildNode child = firstChild;
child != null;
- child = child.getNextSibling()) {
+ child = child.nextSibling) {
newnode.appendChild(child.cloneNode(true));
}
}
@@ -216,9 +216,9 @@
if (needsSyncChildren()) {
synchronizeChildren();
}
- for (Node child = firstChild;
- child != null; child = child.getNextSibling()) {
- ((NodeImpl) child).setOwnerDocument(doc);
+ for (ChildNode child = firstChild;
+ child != null; child = child.nextSibling) {
+ child.setOwnerDocument(doc);
}
ownerDocument = doc;
}
@@ -557,6 +557,8 @@
if( (mutationMask&MUTATION_AGGREGATE) != 0)
dispatchAggregateEvents(enclosingAttr);
}
+
+ checkNormalizationAfterInsert(newInternal);
}
return newChild;
@@ -702,6 +704,9 @@
}
}
+ // Save previous sibling for normalization checking.
+ ChildNode oldPreviousSibling = oldInternal.previousSibling();
+
// Remove oldInternal's references to tree
oldInternal.ownerNode = ownerDocument;
oldInternal.isOwned(false);
@@ -719,6 +724,8 @@
dispatchAggregateEvents(enclosingAttr);
} // End mutation postprocessing
+ checkNormalizationAfterRemove(oldPreviousSibling);
+
return oldInternal;
} // internalRemoveChild(Node,int):Node
@@ -902,11 +909,18 @@
* to take action.
*/
public void normalize() {
-
- Node kid;
- for (kid = firstChild; kid != null; kid = kid.getNextSibling()) {
+ // No need to normalize if already normalized.
+ if (isNormalized()) {
+ return;
+ }
+ if (needsSyncChildren()) {
+ synchronizeChildren();
+ }
+ ChildNode kid;
+ for (kid = firstChild; kid != null; kid = kid.nextSibling) {
kid.normalize();
}
+ isNormalized(true);
}
//
@@ -935,7 +949,7 @@
for (ChildNode mykid = firstChild;
mykid != null;
mykid = mykid.nextSibling) {
- if(!(mykid instanceof EntityReference)) {
+ if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) {
mykid.setReadOnly(readOnly,true);
}
}
@@ -1003,6 +1017,68 @@
ownerDocument.mutationEvents = orig;
} // synchronizeChildren()
+
+ /**
+ * Checks the normalized state of this node after inserting a child.
+ * If the inserted child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ * <ul>
+ * <li>The inserted child is a text node and one of its adjacent siblings
+ * is also a text node.
+ * <li>The inserted child is is itself unnormalized.
+ * </ul>
+ *
+ * @param insertedChild the child node that was inserted into this node
+ *
+ * @throws NullPointerException if the inserted child is <code>null</code>
+ */
+ void checkNormalizationAfterInsert(ChildNode insertedChild) {
+ // See if insertion caused this node to be unnormalized.
+ if (insertedChild.getNodeType() == Node.TEXT_NODE) {
+ ChildNode prev = insertedChild.previousSibling();
+ ChildNode next = insertedChild.nextSibling;
+ // If an adjacent sibling of the new child is a text node,
+ // flag this node as unnormalized.
+ if ((prev != null && prev.getNodeType() == Node.TEXT_NODE) ||
+ (next != null && next.getNodeType() == Node.TEXT_NODE)) {
+ isNormalized(false);
+ }
+ }
+ else {
+ // If the new child is not normalized,
+ // then this node is inherently not normalized.
+ if (!insertedChild.isNormalized()) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterInsert(ChildNode)
+
+ /**
+ * Checks the normalized of this node after removing a child.
+ * If the removed child causes this node to be unnormalized, then this
+ * node is flagged accordingly.
+ * The conditions for changing the normalized state are:
+ * <ul>
+ * <li>The removed child had two adjacent siblings that were text nodes.
+ * </ul>
+ *
+ * @param previousSibling the previous sibling of the removed child, or
+ * <code>null</code>
+ */
+ void checkNormalizationAfterRemove(ChildNode previousSibling) {
+ // See if removal caused this node to be unnormalized.
+ // If the adjacent siblings of the removed child were both text nodes,
+ // flag this node as unnormalized.
+ if (previousSibling != null &&
+ previousSibling.getNodeType() == Node.TEXT_NODE) {
+
+ ChildNode next = previousSibling.nextSibling;
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ isNormalized(false);
+ }
+ }
+ } // checkNormalizationAfterRemove(Node)
//
// Serialization methods