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

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: AttrImpl.cpp,v 1.27 2001/05/11 13:25:17 tng Exp $
  58.  *
  59.  * <p><b>WARNING</b>: Some of the code here is partially duplicated in
  60.  * ParentNode, be careful to keep these two classes in sync!
  61.  */
  62. #include "AttrImpl.hpp"
  63. #include "DOM_DOMException.hpp"
  64. #include "DocumentImpl.hpp"
  65. #include "TextImpl.hpp"
  66. #include "ElementImpl.hpp"
  67. #include "DStringPool.hpp"
  68. #include "NodeIDMap.hpp"
  69. #include "RangeImpl.hpp"
  70. /*
  71.  * The handling of the value field being either the first child node (a
  72.  * ChildNode*) or directly the value (a DOMString) is rather tricky. In the
  73.  * DOMString case we need to get the field in the right type so that the
  74.  * compiler is happy and the appropriate operator gets called. This is
  75.  * essential for the reference counts of the DOMStrings involved to be updated
  76.  * as due.
  77.  * This is consistently achieved by taking the address of the value field and
  78.  * changing it into a DOMString*, and then dereferencing it to get a DOMString.
  79.  * The typical piece of code is:
  80.  * DOMString *x = (DOMString *)&value;
  81.  *  ... use of *x which is the DOMString ...
  82.  */
  83. AttrImpl::AttrImpl(DocumentImpl *ownerDoc, const DOMString &aName)
  84.     : NodeImpl (ownerDoc)
  85. {
  86.     name = aName.clone();
  87.     isSpecified(true);
  88.     hasStringValue(true);
  89.     value = null;
  90. };
  91. AttrImpl::AttrImpl(const AttrImpl &other, bool deep)
  92.     : NodeImpl(other)
  93. {
  94.     name = other.name.clone();
  95.     isSpecified(other.isSpecified());
  96.     /* We must initialize the void* value to null in *all* cases. Failing to do
  97.      * so would cause, in case of assignment to a DOMString later, its content
  98.      * to be derefenced as a DOMString, which would lead the ref count code to
  99.      * be called on something that is not actually a DOMString... Really bad
  100.      * things would then happen!!!
  101.      */
  102.     value = null;
  103.     hasStringValue(other.hasStringValue());
  104.     if (other.isIdAttr())
  105.     {
  106.         isIdAttr(true);
  107.         this->getOwnerDocument()->getNodeIDMap()->add(this);
  108.     }
  109.     // take care of case where there are kids
  110.     if (!hasStringValue()) {
  111.         cloneChildren(other);
  112.     }
  113.     else {
  114.         // get the address of the value field of this as a DOMString*
  115.         DOMString *x = (DOMString*) &value;
  116.         // and the address of the value field of other as a DOMString*
  117.         DOMString *y = (DOMString*) &(other.value);
  118.         // We can now safely do the cloning and assignement, both operands
  119.         // being a DOMString their ref counts will be updated appropriately
  120.         *x = y->clone();
  121.     }
  122. };
  123. AttrImpl::~AttrImpl() {
  124.     if (hasStringValue()) {
  125.         // if value is a DOMString we must make sure its ref count is updated.
  126.         // this is achieved by changing the address of the value field into a
  127.         // DOMString* and setting the value field to null
  128.         DOMString *x = (DOMString *) &value;
  129.         *x = null;
  130.     }
  131. }
  132. // create a real Text node as child if we don't have one yet
  133. void AttrImpl::makeChildNode() {
  134.     if (hasStringValue()) {
  135.         if (value != null) {
  136.             // change the address of the value field into a DOMString*
  137.             DOMString *x = (DOMString *) &value;
  138.             // create a Text node passing the DOMString it points to
  139.             TextImpl *text =
  140.               (TextImpl *) getOwnerDocument()->createTextNode(*x);
  141.             // get the DOMString ref count to be updated by setting the value
  142.             // field to null
  143.             *x = null;
  144.             // finally reassign the value to the node address
  145.             value = text;
  146.             text->isFirstChild(true);
  147.             text->previousSibling = text;
  148.             text->ownerNode = this;
  149.             text->isOwned(true);
  150.         }
  151.         hasStringValue(false);
  152.     }
  153. }
  154. NodeImpl * AttrImpl::cloneNode(bool deep)
  155. {
  156.     return new AttrImpl(*this, deep);
  157. };
  158. DOMString AttrImpl::getNodeName() {
  159.     return name;
  160. };
  161. short AttrImpl::getNodeType() {
  162.     return DOM_Node::ATTRIBUTE_NODE;
  163. };
  164. DOMString AttrImpl::getName()
  165. {
  166.     return name;
  167. };
  168. DOMString AttrImpl::getNodeValue()
  169. {
  170.     return getValue();
  171. };
  172. bool AttrImpl::getSpecified()
  173. {
  174.     return isSpecified();
  175. };
  176. DOMString AttrImpl::getValue()
  177. {
  178.     if (value == null) {
  179.         return 0; // return "";
  180.     }
  181.     if (hasStringValue()) {
  182.         // change value into a DOMString*
  183.         DOMString *x = (DOMString *) &value;
  184.         // return the DOMString it points to
  185.         return *x;
  186.     }
  187.     ChildNode *firstChild = (ChildNode *) value;
  188.     ChildNode *node = firstChild->nextSibling;
  189.     if (node == null) {
  190.         return firstChild->getNodeValue().clone();
  191.     }
  192.     int             length = 0;
  193.     for (node = firstChild; node != null; node = node->nextSibling)
  194.         length += node->getNodeValue().length();
  195.     DOMString retString;
  196.     retString.reserve(length);
  197.     for (node = firstChild; node != null; node = node->nextSibling)
  198.     {
  199.         retString.appendData(node->getNodeValue());
  200.     };
  201.     return retString;
  202. };
  203. bool AttrImpl::isAttrImpl()
  204. {
  205.     return true;
  206. };
  207. void AttrImpl::setNodeValue(const DOMString &val)
  208. {
  209.     setValue(val);
  210. };
  211. void AttrImpl::setSpecified(bool arg)
  212. {
  213.     isSpecified(arg);
  214. };
  215. void AttrImpl::setValue(const DOMString &newvalue)
  216. {
  217.     if (isReadOnly())
  218.     {
  219.         throw DOM_DOMException
  220.         (
  221.             DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null
  222.         );
  223.     }
  224.     //  If this attribute was of type ID and in the map, take it out,
  225.     //    then put it back in with the new name.  For now, we don't worry
  226.     //    about what happens if the new name conflicts
  227.     //
  228.     if (isIdAttr())
  229.         this->getOwnerDocument()->getNodeIDMap()->remove(this);
  230.     if (!hasStringValue() && value != null) {
  231.         NodeImpl *kid;
  232.         while ((kid = (ChildNode *) value) != null) { // Remove existing kids
  233.             removeChild(kid);
  234.             if (kid->nodeRefCount == 0)
  235.                 NodeImpl::deleteIf(kid);
  236.         }
  237.     }
  238.     // directly store the string as the value by changing the value field
  239.     // into a DOMString
  240.     DOMString *x = (DOMString *) &value;
  241.     if (newvalue != null) {
  242.         *x = newvalue.clone();
  243.     }
  244.     else {
  245.         *x = null;
  246.     }
  247.     hasStringValue(true);
  248.     isSpecified(true);
  249.     changed();
  250.     if (isIdAttr())
  251.         this->getOwnerDocument()->getNodeIDMap()->add(this);
  252. };
  253. DOMString AttrImpl::toString()
  254. {
  255.     DOMString retString;
  256.     retString.appendData(name);
  257.     retString.appendData(DOMString("=""));
  258.     retString.appendData(getValue());
  259.     retString.appendData(DOMString("""));
  260.     return retString;
  261. }
  262. //Introduced in DOM Level 2
  263. ElementImpl *AttrImpl::getOwnerElement()
  264. {
  265.     // if we have an owner, ownerNode is our ownerElement, otherwise it's
  266.     // our ownerDocument and we don't have an ownerElement
  267.     return (ElementImpl *) (isOwned() ? ownerNode : null);
  268. }
  269. //internal use by parser only
  270. void AttrImpl::setOwnerElement(ElementImpl *ownerElem)
  271. {
  272.     ownerNode = ownerElem;
  273.     isOwned(false);
  274. }
  275. // ParentNode stuff
  276. void AttrImpl::cloneChildren(const NodeImpl &other) {
  277.   //    for (NodeImpl *mykid = other.getFirstChild();
  278.     for (NodeImpl *mykid = ((NodeImpl&)other).getFirstChild();
  279.          mykid != null;
  280.          mykid = mykid->getNextSibling()) {
  281.         this->appendChild(mykid->cloneNode(true));
  282.     }
  283. }
  284. NodeListImpl *AttrImpl::getChildNodes() {
  285.     return this;
  286. }
  287. NodeImpl * AttrImpl::getFirstChild() {
  288.     makeChildNode();
  289.     return (ChildNode *) value;
  290. }
  291. NodeImpl * AttrImpl::getLastChild() {
  292.     return lastChild();
  293. }
  294. ChildNode * AttrImpl::lastChild() {
  295.     // last child is stored as the previous sibling of first child
  296.     makeChildNode();
  297.     return value != null ? ((ChildNode *) value)->previousSibling : null;
  298. }
  299. void AttrImpl::lastChild(ChildNode *node) {
  300.     // store lastChild as previous sibling of first child
  301.     if (value != null) {
  302.         ((ChildNode *) value)->previousSibling = node;
  303.     }
  304. }
  305. unsigned int AttrImpl::getLength() {
  306.     if (hasStringValue()) {
  307.         return 1;
  308.     }
  309.     ChildNode *node = (ChildNode *) value;
  310.     int length = 0;
  311.     while (node != null) {
  312.         length++;
  313.         node = node->nextSibling;
  314.     }
  315.     return length;
  316. }
  317. bool AttrImpl::hasChildNodes()
  318. {
  319.     return value != null;
  320. };
  321. NodeImpl *AttrImpl::insertBefore(NodeImpl *newChild, NodeImpl *refChild) {
  322.     DocumentImpl *ownerDocument = getOwnerDocument();
  323.     bool errorChecking = ownerDocument->getErrorChecking();
  324.     if (newChild->isDocumentFragmentImpl()) {
  325.         // SLOW BUT SAFE: We could insert the whole subtree without
  326.         // juggling so many next/previous pointers. (Wipe out the
  327.         // parent's child-list, patch the parent pointers, set the
  328.         // ends of the list.) But we know some subclasses have special-
  329.         // case behavior they add to insertBefore(), so we don't risk it.
  330.         // This approch also takes fewer bytecodes.
  331.         // NOTE: If one of the children is not a legal child of this
  332.         // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
  333.         // have been transferred. (Alternative behaviors would be to
  334.         // reparent up to the first failure point or reparent all those
  335.         // which are acceptable to the target node, neither of which is
  336.         // as robust. PR-DOM-0818 isn't entirely clear on which it
  337.         // recommends?????
  338.         // No need to check kids for right-document; if they weren't,
  339.         // they wouldn't be kids of that DocFrag.
  340.         if (errorChecking) {
  341.             for (NodeImpl *kid = newChild->getFirstChild(); // Prescan
  342.                  kid != null; kid = kid->getNextSibling()) {
  343.                 if (!DocumentImpl::isKidOK(this, kid)) {
  344.                     throw DOM_DOMException(
  345.                                        DOM_DOMException::HIERARCHY_REQUEST_ERR,
  346.                                        null);
  347.                 }
  348.             }
  349.         }
  350.         while (newChild->hasChildNodes()) {    // Move
  351.             insertBefore(newChild->getFirstChild(), refChild);
  352.         }
  353.         return newChild;
  354.     }
  355.     // it's a no-op if refChild is the same as newChild
  356.     if (refChild == newChild) {
  357.         return newChild;
  358.     }
  359.     if (errorChecking) {
  360.         if (isReadOnly()) {
  361.             throw DOM_DOMException(
  362.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  363.                                  null);
  364.         }
  365.         if (newChild->getOwnerDocument() != ownerDocument) {
  366.             throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null);
  367.         }
  368.         if (!DocumentImpl::isKidOK(this, newChild)) {
  369.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  370.                                    null);
  371.         }
  372.         // refChild must be a child of this node (or null)
  373.         if (refChild != null && refChild->getParentNode() != this) {
  374.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  375.         }
  376.         // Prevent cycles in the tree
  377.         // newChild cannot be ancestor of this Node,
  378.         // and actually cannot be this
  379.         bool treeSafe = true;
  380.         for (NodeImpl *a = this; treeSafe && a != null; a = a->getParentNode())
  381.         {
  382.             treeSafe = (newChild != a);
  383.         }
  384.         if (!treeSafe) {
  385.             throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,
  386.                                    null);
  387.         }
  388.     }
  389.     makeChildNode(); // make sure we have a node and not a string
  390.     // Convert to internal type, to avoid repeated casting
  391.     ChildNode * newInternal = (ChildNode *)newChild;
  392.     NodeImpl *oldparent = newInternal->getParentNode();
  393.     if (oldparent != null) {
  394.         oldparent->removeChild(newInternal);
  395.     }
  396.     // Convert to internal type, to avoid repeated casting
  397.     ChildNode *refInternal = (ChildNode *)refChild;
  398.     // Attach up
  399.     newInternal->ownerNode = this;
  400.     newInternal->isOwned(true);
  401.     // Attach before and after
  402.     // Note: firstChild.previousSibling == lastChild!!
  403.     ChildNode *firstChild = (ChildNode *) value;
  404.     if (firstChild == null) {
  405.         // this our first and only child
  406.         value = newInternal; // firstChild = newInternal
  407.         newInternal->isFirstChild(true);
  408.         newInternal->previousSibling = newInternal;
  409.     }
  410.     else {
  411.         if (refInternal == null) {
  412.             // this is an append
  413.             ChildNode *lastChild = firstChild->previousSibling;
  414.             lastChild->nextSibling = newInternal;
  415.             newInternal->previousSibling = lastChild;
  416.             firstChild->previousSibling = newInternal;
  417.         }
  418.         else {
  419.             // this is an insert
  420.             if (refChild == firstChild) {
  421.                 // at the head of the list
  422.                 firstChild->isFirstChild(false);
  423.                 newInternal->nextSibling = firstChild;
  424.                 newInternal->previousSibling = firstChild->previousSibling;
  425.                 firstChild->previousSibling = newInternal;
  426.                 value = newInternal; // firstChild = newInternal;
  427.                 newInternal->isFirstChild(true);
  428.             }
  429.             else {
  430.                 // somewhere in the middle
  431.                 ChildNode *prev = refInternal->previousSibling;
  432.                 newInternal->nextSibling = refInternal;
  433.                 prev->nextSibling = newInternal;
  434.                 refInternal->previousSibling = newInternal;
  435.                 newInternal->previousSibling = prev;
  436.             }
  437.         }
  438.     }
  439.     changed();
  440.     if (this->getOwnerDocument() != null) {
  441.         typedef RefVectorOf<RangeImpl> RangeImpls;
  442.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  443.         if ( ranges != null) {
  444.             unsigned int sz = ranges->size();
  445.             for (unsigned int i =0; i<sz; i++) {
  446.                 ranges->elementAt(i)->updateRangeForInsertedNode(newInternal);
  447.             }
  448.         }
  449.     }
  450.     return newInternal;
  451. }
  452. NodeImpl *AttrImpl::item(unsigned int index) {
  453.     if (hasStringValue()) {
  454.         if (index != 0 || value == null) {
  455.             return null;
  456.         }
  457.         else {
  458.             makeChildNode();
  459.             return (NodeImpl *) value;
  460.         }
  461.     }
  462.     ChildNode *nodeListNode = (ChildNode *) value;
  463.     for (unsigned int nodeListIndex = 0;
  464.          nodeListIndex < index && nodeListNode != null;
  465.          nodeListIndex++) {
  466.         nodeListNode = nodeListNode->nextSibling;
  467.     }
  468.     return nodeListNode;
  469. }
  470. NodeImpl *AttrImpl::removeChild(NodeImpl *oldChild) {
  471.     DocumentImpl *ownerDocument = getOwnerDocument();
  472.     if (ownerDocument->getErrorChecking()) {
  473.         if (isReadOnly()) {
  474.             throw DOM_DOMException(
  475.                                  DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR,
  476.                                  null);
  477.         }
  478.         if (oldChild != null && oldChild->getParentNode() != this) {
  479.             throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null);
  480.         }
  481.     }
  482.     // fix other ranges for change before deleting the node
  483.     if (getOwnerDocument() !=  null) {
  484.         typedef RefVectorOf<RangeImpl> RangeImpls;
  485.         RangeImpls* ranges = this->getOwnerDocument()->getRanges();
  486.         if (ranges != null) {
  487.             unsigned int sz = ranges->size();
  488.             if (sz != 0) {
  489.                 for (unsigned int i =0; i<sz; i++) {
  490.                     if (ranges->elementAt(i) != null)
  491.                         ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);
  492.                 }
  493.             }
  494.         }
  495.     }
  496.     ChildNode * oldInternal = (ChildNode *) oldChild;
  497.     // Patch linked list around oldChild
  498.     // Note: lastChild == firstChild->previousSibling
  499.     if (oldInternal == value) {
  500.         // removing first child
  501.         oldInternal->isFirstChild(false);
  502.         value = oldInternal->nextSibling; // firstChild = oldInternal->nextSibling
  503.         ChildNode *firstChild = (ChildNode *) value;
  504.         if (firstChild != null) {
  505.             firstChild->isFirstChild(true);
  506.             firstChild->previousSibling = oldInternal->previousSibling;
  507.         }
  508.     } else {
  509.         ChildNode *prev = oldInternal->previousSibling;
  510.         ChildNode *next = oldInternal->nextSibling;
  511.         prev->nextSibling = next;
  512.         if (next == null) {
  513.             // removing last child
  514.             ChildNode *firstChild = (ChildNode *) value;
  515.             firstChild->previousSibling = prev;
  516.         } else {
  517.             // removing some other child in the middle
  518.             next->previousSibling = prev;
  519.         }
  520.     }
  521.     // Remove oldInternal's references to tree
  522.     oldInternal->ownerNode = getOwnerDocument();
  523.     oldInternal->isOwned(false);
  524.     oldInternal->nextSibling = null;
  525.     oldInternal->previousSibling = null;
  526.     changed();
  527.     return oldInternal;
  528. };
  529. NodeImpl *AttrImpl::replaceChild(NodeImpl *newChild, NodeImpl *oldChild) {
  530.     insertBefore(newChild, oldChild);
  531.     if (newChild != oldChild) {
  532.         removeChild(oldChild);
  533.     }
  534.     // changed() already done.
  535.     return oldChild;
  536. }
  537. void AttrImpl::setReadOnly(bool readOnl, bool deep) {
  538.     NodeImpl::setReadOnly(readOnl, deep);
  539.     if (deep) {
  540.         if (hasStringValue()) {
  541.             return;
  542.         }
  543.         // Recursively set kids
  544.         for (ChildNode *mykid = (ChildNode *) value;
  545.              mykid != null;
  546.              mykid = mykid->nextSibling)
  547.             if(! (mykid->isEntityReference()))
  548.                 mykid->setReadOnly(readOnl,true);
  549.     }
  550. }
  551. //Introduced in DOM Level 2
  552. void AttrImpl::normalize()
  553. {
  554.     if (hasStringValue()) {
  555.         return;
  556.     }
  557.     ChildNode *kid, *next;
  558.     for (kid = (ChildNode *) value; kid != null; kid = next)
  559.     {
  560.         next = kid->nextSibling;
  561.         // If kid and next are both Text nodes (but _not_ CDATASection,
  562.         // which is a subclass of Text), they can be merged.
  563.         if (next != null &&
  564.             kid->isTextImpl()   && !(kid->isCDATASectionImpl())  &&
  565.             next->isTextImpl()  && !(next->isCDATASectionImpl()) )
  566.         {
  567.             ((TextImpl *) kid)->appendData(((TextImpl *) next)->getData());
  568.             removeChild(next);
  569.             if (next->nodeRefCount == 0)
  570.                 deleteIf(next);
  571.             next = kid; // Don't advance; there might be another.
  572.         }
  573.         // Otherwise it might be an Element, which is handled recursively
  574.         else
  575.             if (kid->isElementImpl())
  576.                 kid->normalize();
  577.     };
  578.     // changed() will have occurred when the removeChild() was done,
  579.     // so does not have to be reissued.
  580. };