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