ParentNode.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:17k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2002 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.4 2003/01/29 16:22:57 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. XERCES_CPP_NAMESPACE_BEGIN
  68. ParentNode::ParentNode(DocumentImpl *ownerDoc)
  69.     : ChildNode(ownerDoc)
  70. {
  71.     this->ownerDocument = ownerDoc;
  72.     this->firstChild = null;
  73.     fCachedLength = -1;
  74.     fCachedChild = null;
  75.     fCachedChildIndex = -1;
  76. };
  77. // This only makes a shallow copy, cloneChildren must also be called for a
  78. // deep clone
  79. ParentNode::ParentNode(const ParentNode &other)
  80.     : ChildNode(other)
  81. {
  82.     this->ownerDocument = other.ownerDocument;
  83.     // Need to break the association w/ original kids
  84.     this->firstChild = null;
  85.     fCachedLength = -1;
  86.     fCachedChild = null;
  87.     fCachedChildIndex = -1;
  88. };
  89. void ParentNode::cloneChildren(const NodeImpl &other) {
  90.   //    for (NodeImpl *mykid = other.getFirstChild();
  91.     for (NodeImpl *mykid = ((NodeImpl&)other).getFirstChild();
  92.          mykid != null;
  93.          mykid = mykid->getNextSibling()) {
  94.         this->appendChild(mykid->cloneNode(true));
  95.     }
  96. }
  97. DocumentImpl * ParentNode::getOwnerDocument() {
  98.     return ownerDocument;
  99. }
  100. // unlike getOwnerDocument this is not overriden by DocumentImpl to return null
  101. DocumentImpl * ParentNode::getDocument() {
  102.     return ownerDocument;
  103. }
  104. void ParentNode::setOwnerDocument(DocumentImpl *doc) {
  105.     ownerDocument = doc;
  106.     for (NodeImpl *child = firstChild;
  107.          child != null; child = child->getNextSibling()) {
  108.         child->setOwnerDocument(doc);
  109.     }
  110. }
  111. NodeListImpl *ParentNode::getChildNodes() {
  112.     return this;
  113. };
  114. NodeImpl * ParentNode::getFirstChild() {
  115.     return firstChild;
  116. };
  117. NodeImpl * ParentNode::getLastChild()
  118. {
  119.     return lastChild();
  120. };
  121. ChildNode * ParentNode::lastChild()
  122. {
  123.     // last child is stored as the previous sibling of first child
  124.     return firstChild != null ? firstChild->previousSibling : null;
  125. };
  126. void ParentNode::lastChild(ChildNode *node) {
  127.         // store lastChild as previous sibling of first child
  128.         if (firstChild != null) {
  129.             firstChild->previousSibling = node;
  130.         }
  131.     }
  132. unsigned int ParentNode::getLength() {
  133.     if (fCachedLength == -1) { // is the cached length invalid ?
  134.         ChildNode *node;
  135.         // start from the cached node if we have one
  136.         if (fCachedChildIndex != -1 && fCachedChild != null) {
  137.             fCachedLength = fCachedChildIndex;
  138.             node = fCachedChild;
  139.         } else {
  140.             node = firstChild;
  141.             fCachedLength = 0;
  142.         }
  143.         while (node != null) {
  144.             fCachedLength++;
  145.             node = node->nextSibling;
  146.         }
  147.     }
  148.     return fCachedLength;
  149. };
  150. bool ParentNode::hasChildNodes()
  151. {
  152.     return firstChild!=null;
  153. };
  154. NodeImpl *ParentNode::insertBefore(NodeImpl *newChild, NodeImpl *refChild) {
  155.     bool errorChecking = ownerDocument->getErrorChecking();
  156.     if (newChild->isDocumentFragmentImpl()) {
  157.         // SLOW BUT SAFE: We could insert the whole subtree without
  158.         // juggling so many next/previous pointers. (Wipe out the
  159.         // parent's child-list, patch the parent pointers, set the
  160.         // ends of the list.) But we know some subclasses have special-
  161.         // case behavior they add to insertBefore(), so we don't risk it.
  162.         // This approch also takes fewer bytecodes.
  163.         // NOTE: If one of the children is not a legal child of this
  164.         // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
  165.         // have been transferred. (Alternative behaviors would be to
  166.         // reparent up to the first failure point or reparent all those
  167.         // which are acceptable to the target node, neither of which is
  168.         // as robust. PR-DOM-0818 isn't entirely clear on which it
  169.         // recommends?????
  170.         // No need to check kids for right-document; if they weren't,
  171.         // they wouldn't be kids of that DocFrag.
  172.         if (errorChecking) {
  173.             for (NodeImpl *kid = newChild->getFirstChild(); // Prescan
  174.                  kid != null; kid = kid->getNextSibling()) {
  175.                 if (!DocumentImpl::isKidOK(this, kid)) {
  176.                     throw DOM_DOMException(
  177.                                        DOM_DOMException::HIERARCHY_REQUEST_ERR,
  178.                                        null);
  179.                 }
  180.             }
  181.         }
  182.         while (newChild->hasChildNodes()) {    // Move
  183.             insertBefore(newChild->getFirstChild(),refChild);
  184.         }
  185.         return newChild;
  186.     }
  187.     // it's a no-op if refChild is the same as newChild
  188.     if (refChild == newChild) {
  189.         return newChild;
  190.     }
  191.     if (errorChecking) {
  192.         if (isReadOnly()) {
  193.             throw DOM_DOMException(
  194.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  195.                                  null);
  196.         }
  197.         if (newChild->getOwnerDocument() != ownerDocument) {
  198.             throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null);
  199.         }
  200.         if (!DocumentImpl::isKidOK(this, newChild)) {
  201.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  202.                                    null);
  203.         }
  204.         // refChild must be a child of this node (or null)
  205.         if (refChild != null && refChild->getParentNode() != this) {
  206.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  207.         }
  208.         // Prevent cycles in the tree
  209.         // newChild cannot be ancestor of this Node,
  210.         // and actually cannot be this
  211.         bool treeSafe = true;
  212.         for (NodeImpl *a = this; treeSafe && a != null; a = a->getParentNode())
  213.         {
  214.             treeSafe = (newChild != a);
  215.         }
  216.         if (!treeSafe) {
  217.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  218.                                    null);
  219.         }
  220.     }
  221.     // Convert to internal type, to avoid repeated casting
  222.     ChildNode * newInternal = (ChildNode *)newChild;
  223.     NodeImpl *oldparent = newInternal->getParentNode();
  224.     if (oldparent != null) {
  225.         oldparent->removeChild(newInternal);
  226.     }
  227.     // Convert to internal type, to avoid repeated casting
  228.     ChildNode *refInternal = (ChildNode *)refChild;
  229.     // Attach up
  230.     newInternal->ownerNode = this;
  231.     newInternal->isOwned(true);
  232.     // Attach before and after
  233.     // Note: firstChild.previousSibling == lastChild!!
  234.     if (firstChild == null) {
  235.         // this our first and only child
  236.         firstChild = newInternal;
  237.         newInternal->isFirstChild(true);
  238.         newInternal->previousSibling = newInternal;
  239.     }
  240.     else {
  241.         if (refInternal == null) {
  242.             // this is an append
  243.             ChildNode *lastChild = firstChild->previousSibling;
  244.             lastChild->nextSibling = newInternal;
  245.             newInternal->previousSibling = lastChild;
  246.             firstChild->previousSibling = newInternal;
  247.         }
  248.         else {
  249.             // this is an insert
  250.             if (refChild == firstChild) {
  251.                 // at the head of the list
  252.                 firstChild->isFirstChild(false);
  253.                 newInternal->nextSibling = firstChild;
  254.                 newInternal->previousSibling = firstChild->previousSibling;
  255.                 firstChild->previousSibling = newInternal;
  256.                 firstChild = newInternal;
  257.                 newInternal->isFirstChild(true);
  258.             }
  259.             else {
  260.                 // somewhere in the middle
  261.                 ChildNode *prev = refInternal->previousSibling;
  262.                 newInternal->nextSibling = refInternal;
  263.                 prev->nextSibling = newInternal;
  264.                 refInternal->previousSibling = newInternal;
  265.                 newInternal->previousSibling = prev;
  266.             }
  267.         }
  268.     }
  269.     changed();
  270.     // update cached length if we have any
  271.     if (fCachedLength != -1) {
  272.         fCachedLength++;
  273.     }
  274.     if (fCachedChildIndex != -1) {
  275.         // if we happen to insert just before the cached node, update
  276.         // the cache to the new node to match the cached index
  277.         if (fCachedChild == refInternal) {
  278.             fCachedChild = newInternal;
  279.         }
  280.         else {
  281.             // otherwise just invalidate the cache
  282.             fCachedChildIndex = -1;
  283.         }
  284.     }
  285.     if (this->getOwnerDocument() != null) {
  286.         typedef RefVectorOf<RangeImpl> RangeImpls;
  287.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  288.         if ( ranges != null) {
  289.             unsigned int sz = ranges->size();
  290.             for (unsigned int i =0; i<sz; i++) {
  291.                 ranges->elementAt(i)->updateRangeForInsertedNode(newInternal);
  292.             }
  293.         }
  294.     }
  295.     return newInternal;
  296. };
  297. NodeImpl *ParentNode::item(unsigned int uindex) {
  298.     // short way
  299.     int index = uindex;
  300.     if (fCachedChildIndex != -1 && fCachedChild != null) {
  301.         if (fCachedChildIndex < index) {
  302.             while (fCachedChildIndex < index && fCachedChild != null) {
  303.                 fCachedChildIndex++;
  304.                 fCachedChild = fCachedChild->nextSibling;
  305.             }
  306.         }
  307.         else if (fCachedChildIndex > index) {
  308.             while (fCachedChildIndex > index && fCachedChild != null) {
  309.                 fCachedChildIndex--;
  310.                 fCachedChild = (ChildNode *)fCachedChild->getPreviousSibling();
  311.             }
  312.         }
  313.         return fCachedChild;
  314.     }
  315.     // long way
  316.     fCachedChild = firstChild;
  317.     for (fCachedChildIndex = 0;
  318.          fCachedChildIndex < index && fCachedChild != null;
  319.          fCachedChildIndex++) {
  320.         fCachedChild = fCachedChild->nextSibling;
  321.     }
  322.     return fCachedChild;
  323. };
  324. NodeImpl *ParentNode::removeChild(NodeImpl *oldChild)
  325. {
  326.     if (ownerDocument->getErrorChecking()) {
  327.         if (isReadOnly()) {
  328.             throw DOM_DOMException(
  329.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  330.                                  null);
  331.         }
  332.         if (oldChild == null || oldChild->getParentNode() != this) {
  333.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  334.         }
  335.     }
  336.     //fix other ranges for change before deleting the node
  337.     if (getOwnerDocument() !=  null) {
  338.         typedef RefVectorOf<RangeImpl> RangeImpls;
  339.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  340.         if (ranges != null) {
  341.             unsigned int sz = ranges->size();
  342.             if (sz != 0) {
  343.                 for (unsigned int i =0; i<sz; i++) {
  344.                     if (ranges->elementAt(i) != null)
  345.                         ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);
  346.                 }
  347.             }
  348.         }
  349.     }
  350.     ChildNode * oldInternal = (ChildNode *) oldChild;
  351.     // update cached length if we have any
  352.     if (fCachedLength != -1) {
  353.         fCachedLength--;
  354.     }
  355.     if (fCachedChildIndex != -1) {
  356.         // if the removed node is the cached node
  357.         // move the cache to its (soon former) previous sibling
  358.         if (fCachedChild == oldInternal) {
  359.             fCachedChildIndex--;
  360.             fCachedChild = (ChildNode *)oldInternal->getPreviousSibling();
  361.         } else {
  362.             // otherwise just invalidate the cache
  363.             fCachedChildIndex = -1;
  364.         }
  365.     }
  366.     // Patch linked list around oldChild
  367.     // Note: lastChild == firstChild->previousSibling
  368.     if (oldInternal == firstChild) {
  369.         // removing first child
  370.         oldInternal->isFirstChild(false);
  371.         firstChild = oldInternal->nextSibling;
  372.         if (firstChild != null) {
  373.             firstChild->isFirstChild(true);
  374.             firstChild->previousSibling = oldInternal->previousSibling;
  375.         }
  376.     } else {
  377.         ChildNode *prev = oldInternal->previousSibling;
  378.         ChildNode *next = oldInternal->nextSibling;
  379.         prev->nextSibling = next;
  380.         if (next == null) {
  381.             // removing last child
  382.             firstChild->previousSibling = prev;
  383.         } else {
  384.             // removing some other child in the middle
  385.             next->previousSibling = prev;
  386.         }
  387.     }
  388.     // Remove oldInternal's references to tree
  389.     oldInternal->ownerNode = ownerDocument;
  390.     oldInternal->isOwned(false);
  391.     oldInternal->nextSibling = null;
  392.     oldInternal->previousSibling = null;
  393.     changed();
  394.     return oldInternal;
  395. };
  396. NodeImpl *ParentNode::replaceChild(NodeImpl *newChild, NodeImpl *oldChild)
  397. {
  398.     insertBefore(newChild, oldChild);
  399.     if (newChild != oldChild) {
  400.         removeChild(oldChild);
  401.     }
  402.     // changed() already done.
  403.     return oldChild;
  404. };
  405. void ParentNode::setReadOnly(bool readOnl, bool deep)
  406. {
  407.     NodeImpl::setReadOnly(readOnl, deep);
  408.     if (deep)
  409.         // Recursively set kids
  410.         for (ChildNode *mykid = firstChild;
  411.              mykid != null;
  412.              mykid = mykid->nextSibling)
  413.             if(! (mykid->isEntityReference()))
  414.                 mykid->setReadOnly(readOnl,true);
  415. };
  416. //Introduced in DOM Level 2
  417. void ParentNode::normalize()
  418. {
  419.     ChildNode *kid, *next;
  420.     for (kid = firstChild; kid != null; kid = next)
  421.     {
  422.         next = kid->nextSibling;
  423.         // If kid and next are both Text nodes (but _not_ CDATASection,
  424.         // which is a subclass of Text), they can be merged.
  425.         if (next != null &&
  426.             kid->isTextImpl()   && !(kid->isCDATASectionImpl())  &&
  427.             next->isTextImpl()  && !(next->isCDATASectionImpl()) )
  428.         {
  429.             ((TextImpl *) kid)->appendData(((TextImpl *) next)->getData());
  430.             removeChild(next);
  431.             if (next->nodeRefCount == 0)
  432.                 deleteIf(next);
  433.             next = kid; // Don't advance; there might be another.
  434.         }
  435.         // Otherwise it might be an Element, which is handled recursively
  436.         else
  437.             if (kid->isElementImpl())
  438.                 kid->normalize();
  439.     };
  440.     // changed() will have occurred when the removeChild() was done,
  441.     // so does not have to be reissued.
  442. };
  443. XERCES_CPP_NAMESPACE_END