From c67e84151da71c6042fc57a6bb7a13998f2cab75 Mon Sep 17 00:00:00 2001
From: Tinny Ng <tng@apache.org>
Date: Thu, 16 Jan 2003 19:10:41 +0000
Subject: [PATCH] DOM Fix: iterator should be updated when a node is removed
 from the dom tree

git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@174636 13f79535-47bb-0310-9956-ffa450edef68
---
 src/xercesc/dom/impl/DOMDocumentImpl.cpp     | 44 +++++++++++++++++++-
 src/xercesc/dom/impl/DOMDocumentImpl.hpp     |  4 ++
 src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp | 40 +++++++++---------
 src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp |  9 ++--
 src/xercesc/dom/impl/DOMParentNode.cpp       | 15 ++++++-
 5 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
index 6dd541dd0..2b49cd462 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
@@ -118,6 +118,7 @@ DOMDocumentImpl::DOMDocumentImpl()
       fNamePool(0),
       fNodeIDMap(0),
       fRanges(0),
+      fNodeIterators(0),
       fChanges(0),
       fNodeListPool(0),
       fActualEncoding(0),
@@ -148,6 +149,7 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
       fNamePool(0),
       fNodeIDMap(0),
       fRanges(0),
+      fNodeIterators(0),
       fChanges(0),
       fNodeListPool(0),
       fActualEncoding(0),
@@ -207,6 +209,9 @@ DOMDocumentImpl::~DOMDocumentImpl()
     if (fRanges)
         fRanges->cleanup();
 
+    if (fNodeIterators)
+        fNodeIterators->cleanup();
+
     if (fUserDataTable)
         fUserDataTable->cleanup();
 
@@ -386,12 +391,49 @@ DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data)
 DOMNodeIterator* DOMDocumentImpl::createNodeIterator (
           DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
 {
-    return new (this) DOMNodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion);
+    if (!root) {
+        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
+        return 0;
+    }
+
+    DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion);
+
+    if (fNodeIterators == 0L) {
+        fNodeIterators = new (this) NodeIterators(1, false);
+    }
+    fNodeIterators->addElement(nodeIterator);
+
+    return nodeIterator;
 }
 
 
+NodeIterators* DOMDocumentImpl::getNodeIterators() const
+{
+    return fNodeIterators;
+}
+
+void DOMDocumentImpl::removeNodeIterator(DOMNodeIteratorImpl* nodeIterator)
+{
+    if (fNodeIterators != 0) {
+        XMLSize_t sz = fNodeIterators->size();
+        if (sz !=0) {
+            for (XMLSize_t i =0; i<sz; i++) {
+                if (fNodeIterators->elementAt(i) == nodeIterator) {
+                    fNodeIterators->removeElementAt(i);
+                    break;
+                }
+            }
+        }
+    }
+}
+
 DOMTreeWalker* DOMDocumentImpl::createTreeWalker (DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
 {
+    if (!root) {
+        throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
+        return 0;
+    }
+
     return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
 }
 
diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.hpp b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
index 0f0b95a9a..d052077ed 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.hpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
@@ -112,6 +112,7 @@ class DOMStringPool;
 class DOMBuffer;
 
 typedef RefVectorOf<DOMRangeImpl>        Ranges;
+typedef RefVectorOf<DOMNodeIteratorImpl>     NodeIterators;
 typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord;
 typedef RefHashTableOf<DOMUserDataRecord> DOMNodeUserDataTable;
 typedef RefStackOf<DOMNode>               DOMNodePtr;
@@ -190,7 +191,9 @@ public:
 
     virtual DOMRange*            createRange();
     virtual Ranges*              getRanges() const;  //non-standard api
+    virtual NodeIterators*       getNodeIterators() const;  //non-standard api
     virtual void                 removeRange(DOMRangeImpl* range); //non-standard api
+    virtual void                 removeNodeIterator(DOMNodeIteratorImpl* nodeIterator); //non-standard api
 
 
     //
@@ -367,6 +370,7 @@ private:
     DOMStringPool*        fNamePool;
 
     Ranges*               fRanges;
+    NodeIterators*        fNodeIterators;
 
     int                   fChanges;
     bool                  errorChecking;    // Bypass error checking.
diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp
index cd2e8311b..bcd8fb411 100644
--- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp
+++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp
@@ -75,25 +75,7 @@ XERCES_CPP_NAMESPACE_BEGIN
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-DOMNodeIteratorImpl::DOMNodeIteratorImpl ()
-: fDetached(false),
-    fNodeFilter(0)
-{
-}	
-
-DOMNodeIteratorImpl::~DOMNodeIteratorImpl ()
-{
-	fDetached = false;
-}
-
-
-void DOMNodeIteratorImpl::detach ()
-{
-	fDetached = true;
-}
-
-
-DOMNodeIteratorImpl::DOMNodeIteratorImpl (
+DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc,
                                     DOMNode* root,
                                     unsigned long whatToShow,
                                     DOMNodeFilter* nodeFilter,
@@ -104,7 +86,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl (
     fWhatToShow(whatToShow),
     fNodeFilter(nodeFilter),
     fForward(true),
-    fExpandEntityReferences(expandEntityRef)
+    fExpandEntityReferences(expandEntityRef),
+    fDocument(doc)
 {
 	
 }
@@ -117,7 +100,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy)
     fWhatToShow(toCopy.fWhatToShow),
     fNodeFilter(toCopy.fNodeFilter),
     fForward(toCopy.fForward),
-    fExpandEntityReferences(toCopy.fExpandEntityReferences)
+    fExpandEntityReferences(toCopy.fExpandEntityReferences),
+    fDocument(toCopy.fDocument)
 {
 }
 
@@ -130,9 +114,23 @@ DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl&
     fForward                = other.fForward;
     fDetached               = other.fDetached;
     fExpandEntityReferences = other.fExpandEntityReferences;
+    fDocument               = other.fDocument;
     return *this;
 }
 
+DOMNodeIteratorImpl::~DOMNodeIteratorImpl ()
+{
+	fDetached = false;
+}
+
+
+void DOMNodeIteratorImpl::detach ()
+{
+	fDetached = true;
+   ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this);
+}
+
+
 DOMNode* DOMNodeIteratorImpl::getRoot() {
     return fRoot;
 }
diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp
index 255a8410f..578b229a6 100644
--- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp
+++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp
@@ -88,6 +88,9 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator {
         // The root.
         DOMNode* fRoot;
 
+        // The Document used to create this iterator
+        DOMDocument* fDocument;
+
         // The whatToShow mask.
         unsigned long fWhatToShow;
 
@@ -120,12 +123,10 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator {
         //  </pre>
         bool fForward;
 
-    protected:
-        DOMNodeIteratorImpl ();
-
     public:
         virtual ~DOMNodeIteratorImpl ();
         DOMNodeIteratorImpl (
+            DOMDocument* fDocument,
             DOMNode* root,
             unsigned long whatToShow,
             DOMNodeFilter* nodeFilter,
@@ -145,12 +146,12 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator {
         virtual void detach ();
 
         virtual void release();
+        void removeNode (DOMNode* node);
 
     private:
         DOMNode* matchNodeOrParent (DOMNode* node);
         DOMNode* nextNode (DOMNode* node, bool visitChildren);
         DOMNode* previousNode (DOMNode* node);
-        void removeNode (DOMNode* node);
         bool acceptNode (DOMNode* node);
 
 };
diff --git a/src/xercesc/dom/impl/DOMParentNode.cpp b/src/xercesc/dom/impl/DOMParentNode.cpp
index bd3999137..f87c65c46 100644
--- a/src/xercesc/dom/impl/DOMParentNode.cpp
+++ b/src/xercesc/dom/impl/DOMParentNode.cpp
@@ -65,6 +65,7 @@
 #include "DOMDocumentImpl.hpp"
 #include "DOMNodeListImpl.hpp"
 #include "DOMRangeImpl.hpp"
+#include "DOMNodeIteratorImpl.hpp"
 #include "DOMParentNode.hpp"
 #include "DOMCasts.hpp"
 
@@ -310,8 +311,20 @@ DOMNode *DOMParentNode::removeChild(DOMNode *oldChild)
     if (oldChild != 0 && oldChild->getParentNode() != castToNode(this))
         throw DOMException(DOMException::NOT_FOUND_ERR, 0);
 
-    //fix other ranges for change before deleting the node
     if (this->getOwnerDocument() !=  0  ) {
+        //notify iterators
+        NodeIterators* nodeIterators = ((DOMDocumentImpl *)this->getOwnerDocument())->getNodeIterators();
+        if (nodeIterators != 0) {
+            XMLSize_t sz = nodeIterators->size();
+            if (sz != 0) {
+                for (XMLSize_t i =0; i<sz; i++) {
+                    if (nodeIterators->elementAt(i) != 0)
+                        nodeIterators->elementAt(i)->removeNode(oldChild);
+                }
+            }
+        }
+
+        //fix other ranges for change before deleting the node
         Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();
         if (ranges != 0) {
             XMLSize_t sz = ranges->size();
-- 
GitLab