/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmlsecurity.hxx"

#include "saxeventkeeperimpl.hxx"
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>

namespace cssu = com::sun::star::uno;
namespace cssl = com::sun::star::lang;
namespace cssxc = com::sun::star::xml::crypto;
namespace cssxcsax = com::sun::star::xml::csax;
namespace cssxw = com::sun::star::xml::wrapper;
namespace cssxs = com::sun::star::xml::sax;

#define SERVICE_NAME "com.sun.star.xml.crypto.sax.SAXEventKeeper"
#define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl"

#define _USECOMPRESSEDDOCUMENTHANDLER

SAXEventKeeperImpl::SAXEventKeeperImpl( )
	:m_pRootBufferNode(NULL),
	 m_pCurrentBufferNode(NULL),
     m_nNextElementMarkId(1),
	 m_pNewBlocker(NULL),
	 m_pCurrentBlockingBufferNode(NULL),
	 m_bIsReleasing(false),
	 m_bIsForwarding(false)
{
	m_vElementMarkBuffers.reserve(2);
	m_vNewElementCollectors.reserve(2);
	m_vReleasedElementMarkBuffers.reserve(2);
}

SAXEventKeeperImpl::~SAXEventKeeperImpl()
{
	/*
	 * delete the BufferNode tree
	 */
	if (m_pRootBufferNode != NULL)
	{
        m_pRootBufferNode->freeAllChildren();
		delete m_pRootBufferNode;
	}

	m_pRootBufferNode = m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = NULL;

	/*
	 * delete all unfreed ElementMarks
	 */
	m_vNewElementCollectors.clear();
	m_pNewBlocker = NULL;

	std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();
	for( ; ii != m_vElementMarkBuffers.end(); ++ii )
	{
		delete (*ii);
	}
	m_vElementMarkBuffers.clear();
}

void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
/****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
 *
 *   NAME
 *	setCurrentBufferNode -- set a new active BufferNode.
 *
 *   SYNOPSIS
 *	setCurrentBufferNode( pBufferNode );
 *
 *   FUNCTION
 *	connects this BufferNode into the BufferNode tree as a child of the
 *	current active BufferNode. Then makes this BufferNode as the current
 *	active BufferNode.
 *	If the previous active BufferNode points to the root
 *	BufferNode, which means that no buffering operation was proceeding,
 *	then notifies the status change listener that buffering  operation
 *	will begin at once.
 *
 *   INPUTS
 *	pBufferNode - a BufferNode which will be the new active BufferNode
 *
 *   RESULT
 *	empty
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	if (pBufferNode != m_pCurrentBufferNode)
	{
		if ( m_pCurrentBufferNode == m_pRootBufferNode &&
		     m_xSAXEventKeeperStatusChangeListener.is())
		{
			m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_True);
		}

		if (pBufferNode->getParent() == NULL)
		{
			m_pCurrentBufferNode->addChild(pBufferNode);
			pBufferNode->setParent(m_pCurrentBufferNode);
		}

		m_pCurrentBufferNode = pBufferNode;
	}
}

BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
/****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
 *
 *   NAME
 *	addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
 *
 *   SYNOPSIS
 *	pBufferNode = addNewElementMarkBuffers( );
 *
 *   FUNCTION
 *	if there are new ElementCollector or new Blocker to be added, then
 *	connect all of them with the current BufferNode. In case of the
 *	current BufferNode doesn't exist, creates one.
 *	Clears up the new ElementCollector list and the new Blocker pointer.
 *
 *   INPUTS
 *	empty
 *
 *   RESULT
 *	pBufferNode - the BufferNode that has been connected with both new
 *	              ElementCollectors and new Blocker.
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	BufferNode* pBufferNode = NULL;

	if ( (m_vNewElementCollectors.size()>0) ||
	     (m_pNewBlocker != NULL))
	{
		/*
		 * When the current BufferNode is right pointing to the current
		 * working element in the XMLDocumentWrapper component, then
		 * no new BufferNode is needed to create.
		 * This situation can only happen in the "Forwarding" mode.
		 */
		if ( (m_pCurrentBufferNode != NULL) &&
		     (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
		{
			pBufferNode = m_pCurrentBufferNode;
		}
		else
		{
			pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
		}

		if (m_pNewBlocker != NULL)
		{
			pBufferNode->setBlocker(m_pNewBlocker);

			/*
			 * If no blocking before, then notify the status change listener that
			 * the SAXEventKeeper has entered "blocking" status, during which, no
			 * SAX events will be forwarded to the next document handler.
			 */
			if (m_pCurrentBlockingBufferNode == NULL)
			{
				m_pCurrentBlockingBufferNode = pBufferNode;

				if (m_xSAXEventKeeperStatusChangeListener.is())
				{
					m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_True);
				}
			}

			m_pNewBlocker = NULL;
		}

		if (m_vNewElementCollectors.size()>0)
		{
			std::vector< const ElementCollector* >::const_iterator ii = m_vNewElementCollectors.begin();

			for( ; ii != m_vNewElementCollectors.end(); ++ii )
			{
				pBufferNode->addElementCollector(*ii);
			}

			m_vNewElementCollectors.clear();
		}
	}

	return pBufferNode;
}

ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
/****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
 *
 *   NAME
 *	findElementMarkBuffer -- finds an ElementMark.
 *
 *   SYNOPSIS
 *	pElementMark = findElementMarkBuffer( nId );
 *
 *   FUNCTION
 *	searches an ElementMark with the particular Id in the ElementMark
 *	list.
 *
 *   INPUTS
 *	nId - the Id of the ElementMark to be searched.
 *
 *   RESULT
 *	pElementMark - the ElementMark with the particular Id, or NULL when
 *	               no such Id exists.
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	ElementMark* pElementMark = NULL;

	std::vector< const ElementMark* >::const_iterator ii = m_vElementMarkBuffers.begin();

	for( ; ii != m_vElementMarkBuffers.end(); ++ii )
	{
		if ( nId == (*ii)->getBufferId())
		{
			pElementMark = (ElementMark*)*ii;
			break;
		}
	}

	return pElementMark;
}

void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
/****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
 *
 *   NAME
 *	removeElementMarkBuffer -- removes an ElementMark
 *
 *   SYNOPSIS
 *	removeElementMarkBuffer( nId );
 *
 *   FUNCTION
 *	removes an ElementMark with the particular Id in the ElementMark list.
 *
 *   INPUTS
 *	nId - the Id of the ElementMark to be removed.
 *
 *   RESULT
 *	empty
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	std::vector< const ElementMark* >::iterator ii = m_vElementMarkBuffers.begin();

	for( ; ii != m_vElementMarkBuffers.end(); ++ii )
	{
		if ( nId == (*ii)->getBufferId())
		{
			/*
			 * checks whether this ElementMark still in the new ElementCollect array
			 */
			std::vector< const ElementCollector* >::iterator jj = m_vNewElementCollectors.begin();
			for( ; jj != m_vNewElementCollectors.end(); ++jj )
			{
				if ((*ii) == (*jj))
				{
					m_vNewElementCollectors.erase(jj);
					break;
				}
			}

			/*
			 * checks whether this ElementMark is the new Blocker
			 */
			if ((*ii) == m_pNewBlocker)
			{
				m_pNewBlocker = NULL;
			}

			/*
			 * destory the ElementMark
			 */
			delete (*ii);

			m_vElementMarkBuffers.erase( ii );
			break;
		}
	}
}

rtl::OUString SAXEventKeeperImpl::printBufferNode(
	BufferNode* pBufferNode, sal_Int32 nIndent) const
/****** SAXEventKeeperImpl/printBufferNode ***********************************
 *
 *   NAME
 *	printBufferNode -- retrieves the information of a BufferNode and its
 *	branch.
 *
 *   SYNOPSIS
 *	info = printBufferNode( pBufferNode, nIndent );
 *
 *   FUNCTION
 *	all retrieved information includes:
 *	1. whether it is the current BufferNode;
 *	2. whether it is the current blocking BufferNode;
 *	3. the name of the parent element;
 *	4. the name of this element;
 *	5. all ElementCollectors working on this BufferNode;
 *	6. the Blocker working on this BufferNode;
 *	7. all child BufferNodes' information.
 *
 *   INPUTS
 *	pBufferNode - 	the BufferNode from where information will be retrieved.
 *	nIndent - 	how many space characters prefixed before the output
 *	          	message.
 *
 *   RESULT
 *	info - the information string
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	rtl::OUString rc;

	for ( int i=0; i<nIndent; ++i )
	{
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
	}

	if (pBufferNode == m_pCurrentBufferNode)
	{
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[%]" ));
	}

	if (pBufferNode == m_pCurrentBlockingBufferNode)
	{
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[B]" ));
	}

	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
	rc += m_xXMLDocument->getNodeName(pBufferNode->getXMLElement());

	BufferNode* pParent = (BufferNode*)pBufferNode->getParent();
	if (pParent != NULL)
	{
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[" ));
		rc += m_xXMLDocument->getNodeName(pParent->getXMLElement());
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "]" ));
	}

	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ":EC=" ));
	rc += pBufferNode->printChildren();
	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " BR=" ));

	ElementMark * pBlocker = pBufferNode->getBlocker();
	if (pBlocker != NULL)
	{
		rc += rtl::OUString::valueOf( pBlocker->getBufferId() );
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "(SecId=" ));
		rc += rtl::OUString::valueOf( pBlocker->getSecurityId() );
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ));
		rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
	}
	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));

	std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
	std::vector< const BufferNode* >::const_iterator jj = vChildren->begin();
	for( ; jj != vChildren->end(); ++jj )
	{
		rc += printBufferNode((BufferNode *)*jj, nIndent+4);
	}

	delete vChildren;

	return rc;
}

cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
	SAXEventKeeperImpl::collectChildWorkingElement(BufferNode* pBufferNode) const
/****** SAXEventKeeperImpl/collectChildWorkingElement ************************
 *
 *   NAME
 *	collectChildWorkingElement -- collects a BufferNode's all child
 *	Elements.
 *
 *   SYNOPSIS
 *	list = collectChildWorkingElement( pBufferNode );
 *
 *   FUNCTION
 *	see NAME.
 *
 *   INPUTS
 *	pBufferNode - the BufferNode whose child Elements will be collected.
 *
 *   RESULT
 *	list - the child Elements list.
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();

	cssu::Sequence < cssu::Reference<
		cssxw::XXMLElementWrapper > > aChildrenCollection ( vChildren->size());

	std::vector< const BufferNode* >::const_iterator ii = vChildren->begin();

	sal_Int32 nIndex = 0;
	for( ; ii != vChildren->end(); ++ii )
	{
		aChildrenCollection[nIndex] = (*ii)->getXMLElement();
		nIndex++;
	}

	delete vChildren;

	return aChildrenCollection;
}

void SAXEventKeeperImpl::smashBufferNode(
	BufferNode* pBufferNode, bool bClearRoot) const
/****** SAXEventKeeperImpl/smashBufferNode ***********************************
 *
 *   NAME
 *	smashBufferNode -- removes a BufferNode along with its working
 *	element.
 *
 *   SYNOPSIS
 *	smashBufferNode( pBufferNode, bClearRoot );
 *
 *   FUNCTION
 *	removes the BufferNode's working element from the DOM document, while
 *	reserves all ancestor paths for its child BufferNodes.
 *	when any of the BufferNode's ancestor element is useless, removes it
 *	too.
 *	removes the BufferNode from the BufferNode tree.
 *
 *   INPUTS
 *	pBufferNode - 	the BufferNode to be removed
 *	bClearRoot - 	whether the root element also needs to be cleared up.
 *
 *   RESULT
 *	empty
 *
 *   NOTES
 *	when removeing a Blocker's BufferNode, the bClearRoot flag should be
 *	true. Because a Blocker can buffer many SAX events which are not used
 *	by any other ElementCollector or Blocker.
 *	When the bClearRoot is set to true, the root BufferNode will be first
 *	cleared, with a stop flag seting at the next Blocking BufferNode. This
 *	operation can delete all useless bufferred SAX events which are only
 *	needed by the Blocker to be deleted.
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	if (!pBufferNode->hasAnything())
	{
		BufferNode* pParent = (BufferNode*)pBufferNode->getParent();

	        /*
	         * delete the XML data
	         */
		if (pParent == m_pRootBufferNode)
		{
			bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == NULL);
			bool bIsBlockInside = false;
			bool bIsBlockingAfterward = false;

		        /*
		         * If this is a blocker, then remove any out-element data
		         * which caused by blocking. The removal process will stop
		         * at the next blocker to avoid removing any useful data.
		         */
			if (bClearRoot)
			{
				cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
					aChildElements = collectChildWorkingElement(m_pRootBufferNode);

			        /*
			         * the clearUselessData only clearup the content in the
			         * node, not the node itself.
			         */
				m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
					aChildElements,
					bIsNotBlocking?(NULL):
					               (m_pCurrentBlockingBufferNode->getXMLElement()));

			        /*
			         * remove the node if it is empty, then if its parent is also
			         * empty, remove it, then if the next parent is also empty,
			         * remove it,..., until parent become null.
			         */
				m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
			}

			/*
			 * if blocking, check the relationship between this BufferNode and
			 * the current blocking BufferNode.
			 */
			if ( !bIsNotBlocking )
			{
				/*
				 * the current blocking BufferNode is a descendant of this BufferNode.
				 */
				bIsBlockInside = (NULL != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));

				/*
				 * the current blocking BufferNode locates behind this BufferNode in tree
				 * order.
				 */
				bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
			}

			/*
			 * this BufferNode's working element needs to be deleted only when
			 * 1. there is no blocking, or
			 * 2. the current blocking BufferNode is a descendant of this BufferNode,
			 *    (then in the BufferNode's working element, the useless data before the blocking
			 *     element should be deleted.) or
			 * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
			 *    (then the useless data between the blocking element and the working element
			 *     should be deleted.).
			 * Otherwise, this working element should not be deleted.
			 */
			if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
			{
				cssu::Sequence< cssu::Reference< cssxw::XXMLElementWrapper > >
					aChildElements = collectChildWorkingElement(pBufferNode);

			        /*
			         * the clearUselessData only clearup the content in the
			         * node, not the node itself.
			         */
				m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
					aChildElements,
					bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
						       (NULL));

			        /*
			         * remove the node if it is empty, then if its parent is also
			         * empty, remove it, then if the next parent is also empty,
			         * remove it,..., until parent become null.
			         */
				m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
			}
		}

		sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);

		std::vector< const BufferNode* >* vChildren = pBufferNode->getChildren();
		pParent->removeChild(pBufferNode);
		pBufferNode->setParent(NULL);

		std::vector< const BufferNode * >::const_iterator ii = vChildren->begin();
		for( ; ii != vChildren->end(); ++ii )
		{
			((BufferNode *)(*ii))->setParent(pParent);
			pParent->addChild(*ii, nIndex);
			nIndex++;
		}

		delete vChildren;

		/*
		 * delete the BufferNode
		 */
		delete pBufferNode;
	}
}

BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
	BufferNode* pStartBufferNode) const
/****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
 *
 *   NAME
 *	findNextBlockingBufferNode -- finds the next blocking BufferNode
 *	behind the particular BufferNode.
 *
 *   SYNOPSIS
 *	pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
 *
 *   FUNCTION
 *	see NAME.
 *
 *   INPUTS
 *	pStartBufferNode - the BufferNode from where to search the next
 *	                   blocking BufferNode.
 *
 *   RESULT
 *	pBufferNode - the next blocking BufferNode, or NULL if no such
 *	              BufferNode exists.
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	BufferNode* pNext = NULL;

	if (pStartBufferNode != NULL)
	{
		pNext = pStartBufferNode;

		while (NULL != (pNext = (BufferNode*)pNext->getNextNodeByTreeOrder()))
		{
			if (pNext->getBlocker() != NULL)
			{
				break;
			}
		}
	}

	return pNext;
}

void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) const
/****** SAXEventKeeperImpl/diffuse *******************************************
 *
 *   NAME
 *	diffuse -- diffuse the notification.
 *
 *   SYNOPSIS
 *	diffuse( pBufferNode );
 *
 *   FUNCTION
 *	diffuse the collecting completion notification from the specific
 *	BufferNode along its parent link, until an ancestor which is not
 *	completely received is met.
 *
 *   INPUTS
 *	pBufferNode - the BufferNode from which the notification will be
 *	              diffused.
 *
 *   RESULT
 *	empty
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	BufferNode* pParent = pBufferNode;

	while(pParent->isAllReceived())
	{
		pParent->elementCollectorNotify();
		pParent = (BufferNode*)pParent->getParent();
	}
}

void SAXEventKeeperImpl::releaseElementMarkBuffer()
/****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
 *
 *   NAME
 *	releaseElementMarkBuffer -- releases useless ElementMarks
 *
 *   SYNOPSIS
 *	releaseElementMarkBuffer( );
 *
 *   FUNCTION
 *	releases each ElementMark in the releasing list
 *	m_vReleasedElementMarkBuffers.
 *	The operation differs between an ElementCollector and a Blocker.
 *
 *   INPUTS
 *	empty
 *
 *   RESULT
 *	empty
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	m_bIsReleasing = true;
	while (m_vReleasedElementMarkBuffers.size()>0)
	{
		std::vector< sal_Int32 >::iterator pId = m_vReleasedElementMarkBuffers.begin();
		sal_Int32 nId = *pId;
		m_vReleasedElementMarkBuffers.erase( pId );

		ElementMark* pElementMark = findElementMarkBuffer(nId);

		if (pElementMark != NULL)
		{
			if (cssxc::sax::ElementMarkType_ELEMENTCOLLECTOR
				== pElementMark->getType())
			/*
			 * it is a EC
			 */
			{
				ElementCollector* pElementCollector = (ElementCollector*)pElementMark;

				cssxc::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
				bool bToModify = pElementCollector->getModify();

				/*
			         * Delete the EC from the buffer node.
			         */
				BufferNode* pBufferNode = pElementCollector->getBufferNode();
				pBufferNode->removeElementCollector(pElementCollector);

				if ( nPriority == cssxc::sax::ElementMarkPriority_BEFOREMODIFY)
				{
					pBufferNode->notifyBranch();
				}

				if (bToModify)
				{
					pBufferNode->notifyAncestor();
				}

				/*
				 * delete the ElementMark
				 */
				pElementCollector = NULL;
				pElementMark = NULL;
				removeElementMarkBuffer(nId);

				/*
				 * delete the BufferNode
				 */
				diffuse(pBufferNode);
				smashBufferNode(pBufferNode, false);
			}
			else
			/*
			 * it is a Blocker
			 */
			{
			        /*
			         * Delete the TH from the buffer node.
			         */
				BufferNode *pBufferNode = pElementMark->getBufferNode();
				pBufferNode->setBlocker(NULL);

			        /*
			         * If there is a following handler and no blocking now, then
			         * forward this event
			         */
				if (m_pCurrentBlockingBufferNode == pBufferNode)
				{
				        /*
				         * Before forwarding, the next blocking point needs to be
				         * found.
				         */
					m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);

				        /*
				         * Forward the blocked events between these two STHs.
				         */
	       				if (m_xNextHandler.is())
	       				{
       						BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
       						BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;

       						m_pCurrentBufferNode = pBufferNode;
       						m_pCurrentBlockingBufferNode = NULL;

						m_bIsForwarding = true;

						m_xXMLDocument->generateSAXEvents(
							m_xNextHandler,
							this,
							pBufferNode->getXMLElement(),
							(pTempCurrentBlockingBufferNode == NULL)?NULL:(pTempCurrentBlockingBufferNode->getXMLElement()));

						m_bIsForwarding = false;

						m_pCurrentBufferNode = pTempCurrentBufferNode;
						if (m_pCurrentBlockingBufferNode == NULL)
						{
							m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
						}
					}

					if (m_pCurrentBlockingBufferNode == NULL &&
					    m_xSAXEventKeeperStatusChangeListener.is())
					{
						m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(sal_False);
					}
				}

				/*
				 * delete the ElementMark
				 */
				pElementMark = NULL;
				removeElementMarkBuffer(nId);

				/*
				 * delete the BufferNode
				 */
				diffuse(pBufferNode);
				smashBufferNode(pBufferNode, true);
			}
		}
	}

	m_bIsReleasing = false;

	if (!m_pRootBufferNode->hasAnything() &&
		!m_pRootBufferNode->hasChildren() &&
		m_xSAXEventKeeperStatusChangeListener.is())
	{
		m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(sal_True);
	}
}

void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
/****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
 *
 *   NAME
 *	markElementMarkBuffer -- marks an ElementMark to be released
 *
 *   SYNOPSIS
 *	markElementMarkBuffer( nId );
 *
 *   FUNCTION
 *	puts the ElementMark with the particular Id into the releasing list,
 *	checks whether the releasing process is running, if not then launch
 *	this process.
 *
 *   INPUTS
 *	nId - the Id of the ElementMark which will be released
 *
 *   RESULT
 *	empty
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	m_vReleasedElementMarkBuffers.push_back( nId );
	if ( !m_bIsReleasing )
	{
		releaseElementMarkBuffer();
	}
}

sal_Int32 SAXEventKeeperImpl::createElementCollector(
	sal_Int32 nSecurityId,
	cssxc::sax::ElementMarkPriority nPriority,
	bool bModifyElement,
	const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
/****** SAXEventKeeperImpl/createElementCollector ****************************
 *
 *   NAME
 *	createElementCollector -- creates a new ElementCollector on the
 *	incoming element.
 *
 *   SYNOPSIS
 *	nId = createElementCollector( nSecurityId, nPriority,
 *	                             bModifyElement,
 *	                             xReferenceResolvedListener );
 *
 *   FUNCTION
 *	allocs a new Id, then create an ElementCollector with this Id value.
 *	Add the new created ElementCollector to the new ElementCollecotor list.
 *
 *   INPUTS
 *	nSecurityId - 	the security Id of the new ElementCollector
 *	nPriority - 	the prirority of the new ElementCollector
 *	bModifyElement -whether this BufferNode will modify the content of
 *	                the corresponding element it works on
 *	xReferenceResolvedListener - the listener for the new ElementCollector.
 *
 *   RESULT
 *	nId - the Id of the new ElementCollector
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	sal_Int32 nId = m_nNextElementMarkId;
	m_nNextElementMarkId ++;

	ElementCollector* pElementCollector
		= new ElementCollector(
			nSecurityId,
			nId,
			nPriority,
			bModifyElement,
			xReferenceResolvedListener);

	m_vElementMarkBuffers.push_back( pElementCollector );

        /*
         * All the new EC to initial EC array.
         */
	m_vNewElementCollectors.push_back( pElementCollector );

	return nId;
}


sal_Int32 SAXEventKeeperImpl::createBlocker(sal_Int32 nSecurityId)
/****** SAXEventKeeperImpl/createBlocker *************************************
 *
 *   NAME
 *	createBlocker -- creates a new Blocker on the incoming element.
 *
 *   SYNOPSIS
 *	nId = createBlocker( nSecurityId );
 *
 *   FUNCTION
 *	see NAME.
 *
 *   INPUTS
 *	nSecurityId - 	the security Id of the new Blocker
 *
 *   RESULT
 *	nId - the Id of the new Blocker
 *
 *   HISTORY
 *	05.01.2004 -	implemented
 *
 *   AUTHOR
 *	Michael Mi
 *	Email: michael.mi@sun.com
 ******************************************************************************/
{
	sal_Int32 nId = m_nNextElementMarkId;
	m_nNextElementMarkId ++;

	OSL_ASSERT(m_pNewBlocker == NULL);

	m_pNewBlocker = new ElementMark(nSecurityId, nId);
	m_vElementMarkBuffers.push_back( m_pNewBlocker );

	return nId;
}

/* XSAXEventKeeper */
sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector(  )
	throw (cssu::RuntimeException)
{
	return createElementCollector(
		cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
		cssxc::sax::ElementMarkPriority_AFTERMODIFY,
		false,
		NULL);
}

void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
	throw (cssu::RuntimeException)
{
	markElementMarkBuffer(id);
}

sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker(  )
	throw (cssu::RuntimeException)
{
	return createBlocker(cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID);
}

void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
	throw (cssu::RuntimeException)
{
	markElementMarkBuffer(id);
}

sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking(  )
	throw (cssu::RuntimeException)
{
	return (m_pCurrentBlockingBufferNode != NULL);
}

cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL
	SAXEventKeeperImpl::getElement( sal_Int32 id )
	throw (cssu::RuntimeException)
{
	cssu::Reference< cssxw::XXMLElementWrapper > rc;

	ElementMark* pElementMark = findElementMarkBuffer(id);
	if (pElementMark != NULL)
	{
		rc = pElementMark->getBufferNode()->getXMLElement();
	}

	return rc;
}

void SAL_CALL SAXEventKeeperImpl::setElement(
	sal_Int32 id,
	const cssu::Reference< cssxw::XXMLElementWrapper >& aElement )
	throw (cssu::RuntimeException)
{
	if (aElement.is())
	{
		m_xXMLDocument->rebuildIDLink(aElement);

		ElementMark* pElementMark = findElementMarkBuffer(id);

		if (pElementMark != NULL)
		{
			BufferNode* pBufferNode = pElementMark->getBufferNode();
			if (pBufferNode != NULL)
			{
			        bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
				pBufferNode->setXMLElement(aElement);

				if (bIsCurrent)
				{
					m_xXMLDocument->setCurrentElement(aElement);
				}
			}
		}
	}
	else
	{
		removeElementCollector( id );
	}
}

cssu::Reference< cssxs::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
	const cssu::Reference< cssxs::XDocumentHandler >& xNewHandler )
	throw (cssu::RuntimeException)
{
	cssu::Reference< cssxs::XDocumentHandler > xOldHandler = m_xNextHandler;

	m_xNextHandler = xNewHandler;
	return xOldHandler;
}

rtl::OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
	throw (cssu::RuntimeException)
{
	rtl::OUString rc;

	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ElementMarkBuffers: size = " ));
	rc += rtl::OUString::valueOf((sal_Int32)m_vElementMarkBuffers.size());
	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\nCurrentBufferNode: " ));
	rc += m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement());
	rc += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\n" ));
	rc += printBufferNode(m_pRootBufferNode, 0);

	return rc;
}

cssu::Reference< cssxw::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
	throw (cssu::RuntimeException)
{
	cssu::Reference< cssxw::XXMLElementWrapper > rc;

	if (m_pCurrentBlockingBufferNode != NULL)
	{
		rc = m_pCurrentBlockingBufferNode->getXMLElement();
	}

	return rc;
}

/* XSecuritySAXEventKeeper */
sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
	cssxc::sax::ElementMarkPriority priority,
	sal_Bool modifyElement )
	throw (cssu::RuntimeException)
{
	return createElementCollector(
		cssxc::sax::ConstOfSecurityId::UNDEFINEDSECURITYID,
		priority,
		modifyElement,
		NULL);
}

sal_Int32 SAL_CALL SAXEventKeeperImpl::cloneElementCollector(
	sal_Int32 referenceId,
	cssxc::sax::ElementMarkPriority priority )
	throw (cssu::RuntimeException)
{
	sal_Int32 nId = -1;

	ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
	if (pElementCollector != NULL)
	{
		nId = m_nNextElementMarkId;
		m_nNextElementMarkId ++;

		ElementCollector* pClonedOne
			= pElementCollector->clone(nId, priority);

	        /*
	         * add this EC into the security data buffer array.
	         */
		m_vElementMarkBuffers.push_back(pClonedOne);

	        /*
	         * If the reference EC is still in initial EC array, add
	         * this cloned one into the initial EC array too.
	         */
	        if (pElementCollector->getBufferNode() == NULL)
		{
			m_vNewElementCollectors.push_back(pClonedOne);
		}
	}

	return nId;
}

void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
	throw (cssu::RuntimeException)
{
	ElementMark* pElementMark = findElementMarkBuffer(id);
	if (pElementMark != NULL)
	{
		pElementMark->setSecurityId(securityId);
	}
}


/* XReferenceResolvedBroadcaster */
void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
	sal_Int32 referenceId,
	const cssu::Reference< cssxc::sax::XReferenceResolvedListener >& listener )
	throw (cssu::RuntimeException)
{
	ElementCollector* pElementCollector = (ElementCollector*)findElementMarkBuffer(referenceId);
	if (pElementCollector != NULL)
	{
		pElementCollector->setReferenceResolvedListener(listener);
	}
}

void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
	sal_Int32 /*referenceId*/,
	const cssu::Reference< cssxc::sax::XReferenceResolvedListener >&)
	throw (cssu::RuntimeException)
{
}

/* XSAXEventKeeperStatusChangeBroadcaster */
void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
	const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >& listener )
	throw (cssu::RuntimeException)
{
	m_xSAXEventKeeperStatusChangeListener = listener;
}

void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
	const cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener >&)
	throw (cssu::RuntimeException)
{
}

/* XDocumentHandler */
void SAL_CALL SAXEventKeeperImpl::startDocument(  )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
	if ( m_xNextHandler.is())
	{
		m_xNextHandler->startDocument();
	}
}

void SAL_CALL SAXEventKeeperImpl::endDocument(  )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
	if ( m_xNextHandler.is())
	{
		m_xNextHandler->endDocument();
	}
}

void SAL_CALL SAXEventKeeperImpl::startElement(
	const rtl::OUString& aName,
	const cssu::Reference< cssxs::XAttributeList >& xAttribs )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
        /*
         * If there is a following handler and no blocking now, then
         * forward this event
         */
	if ((m_pCurrentBlockingBufferNode == NULL) &&
	    (m_xNextHandler.is()) &&
	    (!m_bIsForwarding) &&
	    (m_pNewBlocker == NULL))
	{
		m_xNextHandler->startElement(aName, xAttribs);
	}

        /*
         * If not forwarding, buffer this startElement.
         */
       	if (!m_bIsForwarding)
       	{
	#ifndef _USECOMPRESSEDDOCUMENTHANDLER
		m_xDocumentHandler->startElement(aName, xAttribs);
	#else
		sal_Int32 nLength = xAttribs->getLength();
		cssu::Sequence< cssxcsax::XMLAttribute > aAttributes (nLength);

		for ( int i = 0; i<nLength; ++i )
		{
			aAttributes[i].sName = xAttribs->getNameByIndex((short)i);
			aAttributes[i].sValue =xAttribs->getValueByIndex((short)i);
		}

		m_xCompressedDocumentHandler->_startElement(aName, aAttributes);
	#endif

	}

	BufferNode* pBufferNode = addNewElementMarkBuffers();
        if (pBufferNode != NULL)
        {
		setCurrentBufferNode(pBufferNode);
	}
}

void SAL_CALL SAXEventKeeperImpl::endElement( const rtl::OUString& aName )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
        sal_Bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());

        /*
         * If there is a following handler and no blocking now, then
         * forward this event
         */
	if ((m_pCurrentBlockingBufferNode == NULL) &&
	    (m_xNextHandler.is()) &&
	    (!m_bIsForwarding))
	{
		m_xNextHandler->endElement(aName);
	}

	if ((m_pCurrentBlockingBufferNode != NULL) ||
	    (m_pCurrentBufferNode != m_pRootBufferNode) ||
	    (!m_xXMLDocument->isCurrentElementEmpty()))
	{
        	if (!m_bIsForwarding)
        	{
		#ifndef _USECOMPRESSEDDOCUMENTHANDLER
			m_xDocumentHandler->endElement(aName);
		#else
			m_xCompressedDocumentHandler->_endElement(aName);
		#endif
		}

        /*
        * If the current buffer node has not notified yet, and
        * the current buffer node is waiting for the current element,
        * then let it notify.
        */
       	if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode))
		{
			BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
			m_pCurrentBufferNode = (BufferNode*)m_pCurrentBufferNode->getParent();

			pOldCurrentBufferNode->setReceivedAll();

			if ((m_pCurrentBufferNode == m_pRootBufferNode) &&
			    m_xSAXEventKeeperStatusChangeListener.is())
			{
				m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(sal_False);
			}
		}
    }
    else
    {
        if (!m_bIsForwarding)
        {
            m_xXMLDocument->removeCurrentElement();
        }
    }
}

void SAL_CALL SAXEventKeeperImpl::characters( const rtl::OUString& aChars )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
	if (!m_bIsForwarding)
	{
		if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
		{
			m_xNextHandler->characters(aChars);
		}

		if ((m_pCurrentBlockingBufferNode != NULL) ||
		    (m_pCurrentBufferNode != m_pRootBufferNode))
		{
		#ifndef _USECOMPRESSEDDOCUMENTHANDLER
        		m_xDocumentHandler->characters(aChars);
		#else
			m_xCompressedDocumentHandler->_characters(aChars);
		#endif
        	}
        }
}

void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const rtl::OUString& aWhitespaces )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
	characters( aWhitespaces );
}

void SAL_CALL SAXEventKeeperImpl::processingInstruction(
	const rtl::OUString& aTarget, const rtl::OUString& aData )
	throw (cssxs::SAXException, cssu::RuntimeException)
{
	if (!m_bIsForwarding)
	{
		if ((m_pCurrentBlockingBufferNode == NULL) && m_xNextHandler.is())
		{
			m_xNextHandler->processingInstruction(aTarget, aData);
		}

		if ((m_pCurrentBlockingBufferNode != NULL) ||
		    (m_pCurrentBufferNode != m_pRootBufferNode))
		{
		#ifndef _USECOMPRESSEDDOCUMENTHANDLER
			m_xDocumentHandler->processingInstruction(aTarget, aData);
		#else
			m_xCompressedDocumentHandler->_processingInstruction(aTarget, aData);
		#endif
        	}
        }
}

void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const cssu::Reference< cssxs::XLocator >&)
	throw (cssxs::SAXException, cssu::RuntimeException)
{
}

/* XInitialization */
void SAL_CALL SAXEventKeeperImpl::initialize( const cssu::Sequence< cssu::Any >& aArguments )
	throw (cssu::Exception, cssu::RuntimeException)
{
	OSL_ASSERT(aArguments.getLength() == 1);

	aArguments[0] >>= m_xXMLDocument;
	m_xDocumentHandler = cssu::Reference< cssxs::XDocumentHandler >(
		m_xXMLDocument, cssu::UNO_QUERY );
	m_xCompressedDocumentHandler = cssu::Reference< cssxcsax::XCompressedDocumentHandler >(
		m_xXMLDocument, cssu::UNO_QUERY );

	m_pRootBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
	m_pCurrentBufferNode = m_pRootBufferNode;
}

rtl::OUString SAXEventKeeperImpl_getImplementationName ()
	throw (cssu::RuntimeException)
{
	return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
}

sal_Bool SAL_CALL SAXEventKeeperImpl_supportsService( const rtl::OUString& ServiceName )
	throw (cssu::RuntimeException)
{
	return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ));
}

cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl_getSupportedServiceNames(  )
	throw (cssu::RuntimeException)
{
	cssu::Sequence < rtl::OUString > aRet(1);
	rtl::OUString* pArray = aRet.getArray();
	pArray[0] =  rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
	return aRet;
}
#undef SERVICE_NAME

cssu::Reference< cssu::XInterface > SAL_CALL SAXEventKeeperImpl_createInstance(
	const cssu::Reference< cssl::XMultiServiceFactory > &)
	throw( cssu::Exception )
{
	return (cppu::OWeakObject*) new SAXEventKeeperImpl();
}

/* XServiceInfo */
rtl::OUString SAL_CALL SAXEventKeeperImpl::getImplementationName(  )
	throw (cssu::RuntimeException)
{
	return SAXEventKeeperImpl_getImplementationName();
}
sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const rtl::OUString& rServiceName )
	throw (cssu::RuntimeException)
{
	return SAXEventKeeperImpl_supportsService( rServiceName );
}
cssu::Sequence< rtl::OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames(  )
	throw (cssu::RuntimeException)
{
	return SAXEventKeeperImpl_getSupportedServiceNames();
}
