tng         2002/08/09 13:20:41

  Modified:    c/src/xercesc/dom/impl DOMNodeImpl.cpp DOMNodeImpl.hpp
  Log:
  DOM L3: support compareTreePosition.  Patch from Gareth Reakes.
  
  Revision  Changes    Path
  1.9       +222 -2    xml-xerces/c/src/xercesc/dom/impl/DOMNodeImpl.cpp
  
  Index: DOMNodeImpl.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMNodeImpl.cpp,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DOMNodeImpl.cpp   26 Jul 2002 16:35:16 -0000      1.8
  +++ DOMNodeImpl.cpp   9 Aug 2002 20:20:41 -0000       1.9
  @@ -65,6 +65,7 @@
   
   #include "DOMDocumentTypeImpl.hpp"
   #include "DOMElementImpl.hpp"
  +#include "DOMAttrImpl.hpp"
   #include "DOMCasts.hpp"
   #include "DOMDocumentImpl.hpp"
   
  @@ -492,9 +493,228 @@
   }
   
   short            DOMNodeImpl::compareTreePosition(DOMNode* other){
  -    throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  +    // Questions of clarification for this method - to be answered by the
  +    // DOM WG.   Current assumptions listed - LM
  +    //
  +    // 1. How do ENTITY nodes compare?
  +    //    Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
  +    //    aren't really 'in the tree'
  +    //
  +    // 2. How do NOTATION nodes compare?
  +    //    Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
  +    //    aren't really 'in the tree'
  +    //
  +    // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
  +    //    only relevant for nodes that are "part of the document tree"?
  +    //     <outer>
  +    //         <inner  myattr="true"/>
  +    //     </outer>
  +    //    Is the element node "outer" considered an ancestor of "myattr"?
  +    //    Current assumption: No.
  +    //
  +    // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
  +    //    with children of other attribute nodes with the same element)
  +    //    Current assumption: Children of ATTRIBUTE nodes are treated as if
  +    //    they are the attribute node itself, unless the 2 nodes
  +    //    are both children of the same attribute.
  +    //
  +    // 5. How does an ENTITY_REFERENCE node compare with it's children?
  +    //    Given the DOM, it should precede its children as an ancestor.
  +    //    Given "document order",  does it represent the same position?
  +    //    Current assumption: An ENTITY_REFERENCE node is an ancestor of its
  +    //    children.
  +    //
  +    // 6. How do children of a DocumentFragment compare?
  +    //    Current assumption: If both nodes are part of the same document
  +    //    fragment, there are compared as if they were part of a document.
  +
  +
  +
  +    DOMNode* thisNode = castToNode(this);
  +
  +    // If the nodes are the same...
  +    if (thisNode == other)
  +        return (DOMNode::TREE_POSITION_SAME_NODE | 
DOMNode::TREE_POSITION_EQUIVALENT);
  +
  +    // If either node is of type ENTITY or NOTATION, compare as disconnected
  +    short thisType = thisNode->getNodeType();
  +    short otherType = other->getNodeType();
  +
  +    // If either node is of type ENTITY or NOTATION, compare as disconnected
  +    if (thisType == DOMNode::ENTITY_NODE ||
  +            thisType == DOMNode::NOTATION_NODE ||
  +            otherType == DOMNode::ENTITY_NODE ||
  +            otherType == DOMNode::NOTATION_NODE ) {
  +        return DOMNode::TREE_POSITION_DISCONNECTED;
  +    }
  +
  +    //if this is a custom node, we don't really know what to do, just return
  +    //user should provide its own compareTreePosition logic, and shouldn't reach 
here
  +    if(thisType > 12) {
  +        return 0;
  +    }
  +
  +    //if it is a custom node we must ask it for the order
  +    if(otherType > 12) {
  +        return 
reverseTreeOrderBitPattern(other->compareTreePosition(castToNode(this)));
  +    }
  +
  +    // Find the ancestor of each node, and the distance each node is from
  +    // its ancestor.
  +    // During this traversal, look for ancestor/descendent relationships
  +    // between the 2 nodes in question.
  +    // We do this now, so that we get this info correct for attribute nodes
  +    // and their children.
  +
  +    DOMNode *node;
  +    DOMNode *thisAncestor = castToNode(this);
  +    DOMNode *otherAncestor = other;
  +    int thisDepth=0;
  +    int otherDepth=0;
  +    for (node = castToNode(this); node != 0; node = node->getParentNode()) {
  +        thisDepth +=1;
  +        if (node == other)
  +            // The other node is an ancestor of this one.
  +            return (DOMNode::TREE_POSITION_ANCESTOR | 
DOMNode::TREE_POSITION_PRECEDING);
  +        thisAncestor = node;
  +    }
  +
  +    for (node=other; node != 0; node = node->getParentNode()) {
  +        otherDepth +=1;
  +        if (node == castToNode(this))
  +            // The other node is a descendent of the reference node.
  +            return (DOMNode::TREE_POSITION_DESCENDANT | 
DOMNode::TREE_POSITION_FOLLOWING);
  +        otherAncestor = node;
  +    }
  +
  +
  +    DOMNode *otherNode = other;
  +
  +    short thisAncestorType = thisAncestor->getNodeType();
  +    short otherAncestorType = otherAncestor->getNodeType();
  +
  +    // if the ancestor is an attribute, get owning element.
  +    // we are now interested in the owner to determine position.
  +
  +    if (thisAncestorType == DOMNode::ATTRIBUTE_NODE)  {
  +        thisNode = ((DOMAttrImpl *)thisAncestor)->getOwnerElement();
  +    }
  +    if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) {
  +        otherNode = ((DOMAttrImpl *)otherAncestor)->getOwnerElement();
  +    }
  +
  +    // Before proceeding, we should check if both ancestor nodes turned
  +    // out to be attributes for the same element
  +    if (thisAncestorType == DOMNode::ATTRIBUTE_NODE &&
  +            otherAncestorType == DOMNode::ATTRIBUTE_NODE &&
  +            thisNode==otherNode)
  +        return DOMNode::TREE_POSITION_EQUIVALENT;
  +
  +    // Now, find the ancestor of the owning element, if the original
  +    // ancestor was an attribute
  +
  +    if (thisAncestorType == DOMNode::ATTRIBUTE_NODE) {
  +        thisDepth=0;
  +        for (node=thisNode; node != 0; node = node->getParentNode()) {
  +            thisDepth +=1;
  +            if (node == otherNode)
  +                // The other node is an ancestor of the owning element
  +                return DOMNode::TREE_POSITION_PRECEDING;
  +            thisAncestor = node;
  +        }
  +        for (node=otherNode; node != 0; node = node->getParentNode()) {
  +            if (node == thisNode)
  +                // The other node is an ancestor of the owning element
  +                return DOMNode::TREE_POSITION_FOLLOWING;
  +        }
  +    }
  +
  +    // Now, find the ancestor of the owning element, if the original
  +    // ancestor was an attribute
  +    if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) {
  +        otherDepth=0;
  +        for (node=otherNode; node != 0; node = node->getParentNode()) {
  +            otherDepth +=1;
  +            if (node == thisNode)
  +                // The other node is a descendent of the reference
  +                // node's element
  +                return DOMNode::TREE_POSITION_FOLLOWING;
  +            otherAncestor = node;
  +        }
  +        for (node=thisNode; node != 0; node = node->getParentNode()) {
  +            if (node == otherNode)
  +                // The other node is an ancestor of the owning element
  +                return DOMNode::TREE_POSITION_PRECEDING;
  +        }
  +    }
  +
  +    // thisAncestor and otherAncestor must be the same at this point,
  +    // otherwise, we are not in the same tree or document fragment
  +    if (thisAncestor != otherAncestor)
  +        return DOMNode::TREE_POSITION_DISCONNECTED;
  +
  +    // Determine which node is of the greatest depth.
  +    if (thisDepth > otherDepth) {
  +        for (int i= 0 ; i < thisDepth - otherDepth; i++)
  +            thisNode = thisNode->getParentNode();
  +    }
  +    else {
  +        for (int i = 0; i < otherDepth - thisDepth; i++)
  +            otherNode = otherNode->getParentNode();
  +    }
  +
  +    // We now have nodes at the same depth in the tree.  Find a common
  +    // ancestor.
  +    DOMNode *thisNodeP, *otherNodeP;
  +    for (thisNodeP = thisNode->getParentNode(),
  +                 otherNodeP = otherNode->getParentNode();
  +             thisNodeP != otherNodeP;) {
  +        thisNode = thisNodeP;
  +        otherNode = otherNodeP;
  +        thisNodeP = thisNodeP->getParentNode();
  +        otherNodeP = otherNodeP->getParentNode();
  +    }
  +
  +    // See whether thisNode or otherNode is the leftmost
  +    for (DOMNode *current = thisNodeP->getFirstChild();
  +             current != 0;
  +             current = current->getNextSibling()) {
  +        if (current == otherNode) {
  +            return DOMNode::TREE_POSITION_PRECEDING;
  +        }
  +        else if (current == thisNode) {
  +            return DOMNode::TREE_POSITION_FOLLOWING;
  +        }
  +    }
  +    // REVISIT:  shouldn't get here.   Should probably throw an
  +    // exception
       return 0;
  +
   }
  +
  +short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const {
  +
  +    if(pattern & DOMNode::TREE_POSITION_PRECEDING) {
  +        pattern &= !DOMNode::TREE_POSITION_PRECEDING;
  +        pattern |= DOMNode::TREE_POSITION_FOLLOWING;
  +    }
  +    else if(pattern & DOMNode::TREE_POSITION_FOLLOWING) {
  +        pattern &= !DOMNode::TREE_POSITION_FOLLOWING;
  +        pattern |= DOMNode::TREE_POSITION_PRECEDING;
  +    }
  +
  +    if(pattern & DOMNode::TREE_POSITION_ANCESTOR) {
  +        pattern &= !DOMNode::TREE_POSITION_ANCESTOR;
  +        pattern |= DOMNode::TREE_POSITION_DESCENDANT;
  +    }
  +    else if(pattern & DOMNode::TREE_POSITION_DESCENDANT) {
  +        pattern &= !DOMNode::TREE_POSITION_DESCENDANT;
  +        pattern |= DOMNode::TREE_POSITION_ANCESTOR;
  +    }
  +
  +    return pattern;
  +}
  +
   
   const XMLCh*     DOMNodeImpl::getTextContent() const{
       return 0;
  
  
  
  1.8       +3 -1      xml-xerces/c/src/xercesc/dom/impl/DOMNodeImpl.hpp
  
  Index: DOMNodeImpl.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/dom/impl/DOMNodeImpl.hpp,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DOMNodeImpl.hpp   15 Jul 2002 19:22:22 -0000      1.7
  +++ DOMNodeImpl.hpp   9 Aug 2002 20:20:41 -0000       1.8
  @@ -168,6 +168,8 @@
       void              callUserDataHandlers(DOMUserDataHandler::DOMOperationType 
operation,
                                              const DOMNode* src,
                                              const DOMNode* dst) const;
  +    //reverses the bit pattern given by compareTreePosition
  +    short             reverseTreeOrderBitPattern(short pattern) const;
   
   
       //Utility, not part of DOM Level 2 API
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to