ParentNode.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:16k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: ParentNode.cpp,v 1.11 2001/05/29 12:30:01 tng Exp $
  58.  *
  59.  * <p><b>WARNING</b>: Some of the code here is partially duplicated in
  60.  * AttrImpl, be careful to keep these two classes in sync!
  61.  */
  62. #include "ParentNode.hpp"
  63. #include "DOM_DOMException.hpp"
  64. #include "TextImpl.hpp"
  65. #include "DocumentImpl.hpp"
  66. #include "RangeImpl.hpp"
  67. ParentNode::ParentNode(DocumentImpl *ownerDoc)
  68.     : ChildNode(ownerDoc)
  69. {
  70.     this->ownerDocument = ownerDoc;
  71.     this->firstChild = null;
  72.     fCachedLength = -1;
  73.     fCachedChild = null;
  74.     fCachedChildIndex = -1;
  75. };
  76. // This only makes a shallow copy, cloneChildren must also be called for a
  77. // deep clone
  78. ParentNode::ParentNode(const ParentNode &other)
  79.     : ChildNode(other)
  80. {
  81.     this->ownerDocument = other.ownerDocument;
  82.     // Need to break the association w/ original kids
  83.     this->firstChild = null;
  84.     fCachedLength = -1;
  85.     fCachedChild = null;
  86.     fCachedChildIndex = -1;
  87. };
  88. void ParentNode::cloneChildren(const NodeImpl &other) {
  89.   //    for (NodeImpl *mykid = other.getFirstChild();
  90.     for (NodeImpl *mykid = ((NodeImpl&)other).getFirstChild();
  91.          mykid != null;
  92.          mykid = mykid->getNextSibling()) {
  93.         this->appendChild(mykid->cloneNode(true));
  94.     }
  95. }
  96. DocumentImpl * ParentNode::getOwnerDocument() {
  97.     return ownerDocument;
  98. }
  99. // unlike getOwnerDocument this is not overriden by DocumentImpl to return null
  100. DocumentImpl * ParentNode::getDocument() {
  101.     return ownerDocument;
  102. }
  103. void ParentNode::setOwnerDocument(DocumentImpl *doc) {
  104.     ownerDocument = doc;
  105.     for (NodeImpl *child = firstChild;
  106.          child != null; child = child->getNextSibling()) {
  107.         child->setOwnerDocument(doc);
  108.     }
  109. }
  110. NodeListImpl *ParentNode::getChildNodes() {
  111.     return this;
  112. };
  113. NodeImpl * ParentNode::getFirstChild() {
  114.     return firstChild;
  115. };
  116. NodeImpl * ParentNode::getLastChild()
  117. {
  118.     return lastChild();
  119. };
  120. ChildNode * ParentNode::lastChild()
  121. {
  122.     // last child is stored as the previous sibling of first child
  123.     return firstChild != null ? firstChild->previousSibling : null;
  124. };
  125. void ParentNode::lastChild(ChildNode *node) {
  126.         // store lastChild as previous sibling of first child
  127.         if (firstChild != null) {
  128.             firstChild->previousSibling = node;
  129.         }
  130.     }
  131. unsigned int ParentNode::getLength() {
  132.     if (fCachedLength == -1) { // is the cached length invalid ?
  133.         ChildNode *node;
  134.         // start from the cached node if we have one
  135.         if (fCachedChildIndex != -1 && fCachedChild != null) {
  136.             fCachedLength = fCachedChildIndex;
  137.             node = fCachedChild;
  138.         } else {
  139.             node = firstChild;
  140.             fCachedLength = 0;
  141.         }
  142.         while (node != null) {
  143.             fCachedLength++;
  144.             node = node->nextSibling;
  145.         }
  146.     }
  147.     return fCachedLength;
  148. };
  149. bool ParentNode::hasChildNodes()
  150. {
  151.     return firstChild!=null;
  152. };
  153. NodeImpl *ParentNode::insertBefore(NodeImpl *newChild, NodeImpl *refChild) {
  154.     bool errorChecking = ownerDocument->getErrorChecking();
  155.     if (newChild->isDocumentFragmentImpl()) {
  156.         // SLOW BUT SAFE: We could insert the whole subtree without
  157.         // juggling so many next/previous pointers. (Wipe out the
  158.         // parent's child-list, patch the parent pointers, set the
  159.         // ends of the list.) But we know some subclasses have special-
  160.         // case behavior they add to insertBefore(), so we don't risk it.
  161.         // This approch also takes fewer bytecodes.
  162.         // NOTE: If one of the children is not a legal child of this
  163.         // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
  164.         // have been transferred. (Alternative behaviors would be to
  165.         // reparent up to the first failure point or reparent all those
  166.         // which are acceptable to the target node, neither of which is
  167.         // as robust. PR-DOM-0818 isn't entirely clear on which it
  168.         // recommends?????
  169.         // No need to check kids for right-document; if they weren't,
  170.         // they wouldn't be kids of that DocFrag.
  171.         if (errorChecking) {
  172.             for (NodeImpl *kid = newChild->getFirstChild(); // Prescan
  173.                  kid != null; kid = kid->getNextSibling()) {
  174.                 if (!DocumentImpl::isKidOK(this, kid)) {
  175.                     throw DOM_DOMException(
  176.                                        DOM_DOMException::HIERARCHY_REQUEST_ERR,
  177.                                        null);
  178.                 }
  179.             }
  180.         }
  181.         while (newChild->hasChildNodes()) {    // Move
  182.             insertBefore(newChild->getFirstChild(),refChild);
  183.         }
  184.         return newChild;
  185.     }
  186.     // it's a no-op if refChild is the same as newChild
  187.     if (refChild == newChild) {
  188.         return newChild;
  189.     }
  190.     if (errorChecking) {
  191.         if (isReadOnly()) {
  192.             throw DOM_DOMException(
  193.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  194.                                  null);
  195.         }
  196.         if (newChild->getOwnerDocument() != ownerDocument) {
  197.             throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null);
  198.         }
  199.         if (!DocumentImpl::isKidOK(this, newChild)) {
  200.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  201.                                    null);
  202.         }
  203.         // refChild must be a child of this node (or null)
  204.         if (refChild != null && refChild->getParentNode() != this) {
  205.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  206.         }
  207.         // Prevent cycles in the tree
  208.         // newChild cannot be ancestor of this Node,
  209.         // and actually cannot be this
  210.         bool treeSafe = true;
  211.         for (NodeImpl *a = this; treeSafe && a != null; a = a->getParentNode())
  212.         {
  213.             treeSafe = (newChild != a);
  214.         }
  215.         if (!treeSafe) {
  216.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  217.                                    null);
  218.         }
  219.     }
  220.     // Convert to internal type, to avoid repeated casting
  221.     ChildNode * newInternal = (ChildNode *)newChild;
  222.     NodeImpl *oldparent = newInternal->getParentNode();
  223.     if (oldparent != null) {
  224.         oldparent->removeChild(newInternal);
  225.     }
  226.     // Convert to internal type, to avoid repeated casting
  227.     ChildNode *refInternal = (ChildNode *)refChild;
  228.     // Attach up
  229.     newInternal->ownerNode = this;
  230.     newInternal->isOwned(true);
  231.     // Attach before and after
  232.     // Note: firstChild.previousSibling == lastChild!!
  233.     if (firstChild == null) {
  234.         // this our first and only child
  235.         firstChild = newInternal;
  236.         newInternal->isFirstChild(true);
  237.         newInternal->previousSibling = newInternal;
  238.     }
  239.     else {
  240.         if (refInternal == null) {
  241.             // this is an append
  242.             ChildNode *lastChild = firstChild->previousSibling;
  243.             lastChild->nextSibling = newInternal;
  244.             newInternal->previousSibling = lastChild;
  245.             firstChild->previousSibling = newInternal;
  246.         }
  247.         else {
  248.             // this is an insert
  249.             if (refChild == firstChild) {
  250.                 // at the head of the list
  251.                 firstChild->isFirstChild(false);
  252.                 newInternal->nextSibling = firstChild;
  253.                 newInternal->previousSibling = firstChild->previousSibling;
  254.                 firstChild->previousSibling = newInternal;
  255.                 firstChild = newInternal;
  256.                 newInternal->isFirstChild(true);
  257.             }
  258.             else {
  259.                 // somewhere in the middle
  260.                 ChildNode *prev = refInternal->previousSibling;
  261.                 newInternal->nextSibling = refInternal;
  262.                 prev->nextSibling = newInternal;
  263.                 refInternal->previousSibling = newInternal;
  264.                 newInternal->previousSibling = prev;
  265.             }
  266.         }
  267.     }
  268.     changed();
  269.     // update cached length if we have any
  270.     if (fCachedLength != -1) {
  271.         fCachedLength++;
  272.     }
  273.     if (fCachedChildIndex != -1) {
  274.         // if we happen to insert just before the cached node, update
  275.         // the cache to the new node to match the cached index
  276.         if (fCachedChild == refInternal) {
  277.             fCachedChild = newInternal;
  278.         }
  279.         else {
  280.             // otherwise just invalidate the cache
  281.             fCachedChildIndex = -1;
  282.         }
  283.     }
  284.     if (this->getOwnerDocument() != null) {
  285.         typedef RefVectorOf<RangeImpl> RangeImpls;
  286.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  287.         if ( ranges != null) {
  288.             unsigned int sz = ranges->size();
  289.             for (unsigned int i =0; i<sz; i++) {
  290.                 ranges->elementAt(i)->updateRangeForInsertedNode(newInternal);
  291.             }
  292.         }
  293.     }
  294.     return newInternal;
  295. };
  296. NodeImpl *ParentNode::item(unsigned int uindex) {
  297.     // short way
  298.     int index = uindex;
  299.     if (fCachedChildIndex != -1 && fCachedChild != null) {
  300.         if (fCachedChildIndex < index) {
  301.             while (fCachedChildIndex < index && fCachedChild != null) {
  302.                 fCachedChildIndex++;
  303.                 fCachedChild = fCachedChild->nextSibling;
  304.             }
  305.         }
  306.         else if (fCachedChildIndex > index) {
  307.             while (fCachedChildIndex > index && fCachedChild != null) {
  308.                 fCachedChildIndex--;
  309.                 fCachedChild = (ChildNode *)fCachedChild->getPreviousSibling();
  310.             }
  311.         }
  312.         return fCachedChild;
  313.     }
  314.     // long way
  315.     fCachedChild = firstChild;
  316.     for (fCachedChildIndex = 0;
  317.          fCachedChildIndex < index && fCachedChild != null;
  318.          fCachedChildIndex++) {
  319.         fCachedChild = fCachedChild->nextSibling;
  320.     }
  321.     return fCachedChild;
  322. };
  323. NodeImpl *ParentNode::removeChild(NodeImpl *oldChild)
  324. {
  325.     if (ownerDocument->getErrorChecking()) {
  326.         if (isReadOnly()) {
  327.             throw DOM_DOMException(
  328.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  329.                                  null);
  330.         }
  331.         if (oldChild != null && oldChild->getParentNode() != this) {
  332.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  333.         }
  334.     }
  335.     //fix other ranges for change before deleting the node
  336.     if (getOwnerDocument() !=  null) {
  337.         typedef RefVectorOf<RangeImpl> RangeImpls;
  338.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  339.         if (ranges != null) {
  340.             unsigned int sz = ranges->size();
  341.             if (sz != 0) {
  342.                 for (unsigned int i =0; i<sz; i++) {
  343.                     if (ranges->elementAt(i) != null)
  344.                         ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);
  345.                 }
  346.             }
  347.         }
  348.     }
  349.     ChildNode * oldInternal = (ChildNode *) oldChild;
  350.     // update cached length if we have any
  351.     if (fCachedLength != -1) {
  352.         fCachedLength--;
  353.     }
  354.     if (fCachedChildIndex != -1) {
  355.         // if the removed node is the cached node
  356.         // move the cache to its (soon former) previous sibling
  357.         if (fCachedChild == oldInternal) {
  358.             fCachedChildIndex--;
  359.             fCachedChild = (ChildNode *)oldInternal->getPreviousSibling();
  360.         } else {
  361.             // otherwise just invalidate the cache
  362.             fCachedChildIndex = -1;
  363.         }
  364.     }
  365.     // Patch linked list around oldChild
  366.     // Note: lastChild == firstChild->previousSibling
  367.     if (oldInternal == firstChild) {
  368.         // removing first child
  369.         oldInternal->isFirstChild(false);
  370.         firstChild = oldInternal->nextSibling;
  371.         if (firstChild != null) {
  372.             firstChild->isFirstChild(true);
  373.             firstChild->previousSibling = oldInternal->previousSibling;
  374.         }
  375.     } else {
  376.         ChildNode *prev = oldInternal->previousSibling;
  377.         ChildNode *next = oldInternal->nextSibling;
  378.         prev->nextSibling = next;
  379.         if (next == null) {
  380.             // removing last child
  381.             firstChild->previousSibling = prev;
  382.         } else {
  383.             // removing some other child in the middle
  384.             next->previousSibling = prev;
  385.         }
  386.     }
  387.     // Remove oldInternal's references to tree
  388.     oldInternal->ownerNode = ownerDocument;
  389.     oldInternal->isOwned(false);
  390.     oldInternal->nextSibling = null;
  391.     oldInternal->previousSibling = null;
  392.     changed();
  393.     return oldInternal;
  394. };
  395. NodeImpl *ParentNode::replaceChild(NodeImpl *newChild, NodeImpl *oldChild)
  396. {
  397.     insertBefore(newChild, oldChild);
  398.     if (newChild != oldChild) {
  399.         removeChild(oldChild);
  400.     }
  401.     // changed() already done.
  402.     return oldChild;
  403. };
  404. void ParentNode::setReadOnly(bool readOnl, bool deep)
  405. {
  406.     NodeImpl::setReadOnly(readOnl, deep);
  407.     if (deep)
  408.         // Recursively set kids
  409.         for (ChildNode *mykid = firstChild;
  410.              mykid != null;
  411.              mykid = mykid->nextSibling)
  412.             if(! (mykid->isEntityReference()))
  413.                 mykid->setReadOnly(readOnl,true);
  414. };
  415. //Introduced in DOM Level 2
  416. void ParentNode::normalize()
  417. {
  418.     ChildNode *kid, *next;
  419.     for (kid = firstChild; kid != null; kid = next)
  420.     {
  421.         next = kid->nextSibling;
  422.         // If kid and next are both Text nodes (but _not_ CDATASection,
  423.         // which is a subclass of Text), they can be merged.
  424.         if (next != null &&
  425.             kid->isTextImpl()   && !(kid->isCDATASectionImpl())  &&
  426.             next->isTextImpl()  && !(next->isCDATASectionImpl()) )
  427.         {
  428.             ((TextImpl *) kid)->appendData(((TextImpl *) next)->getData());
  429.             removeChild(next);
  430.             if (next->nodeRefCount == 0)
  431.                 deleteIf(next);
  432.             next = kid; // Don't advance; there might be another.
  433.         }
  434.         // Otherwise it might be an Element, which is handled recursively
  435.         else
  436.             if (kid->isElementImpl())
  437.                 kid->normalize();
  438.     };
  439.     // changed() will have occurred when the removeChild() was done,
  440.     // so does not have to be reissued.
  441. };