/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



#include <node.hxx>

#include <stdio.h>
#include <string.h>

#include <libxml/xmlstring.h>

#include <algorithm>

#include <boost/bind.hpp>

#include <rtl/uuid.h>
#include <rtl/instance.hxx>
#include <osl/mutex.hxx>

#include <com/sun/star/xml/sax/FastToken.hpp>

#include <document.hxx>
#include <attr.hxx>
#include <childlist.hxx>

#include "../events/eventdispatcher.hxx"
#include "../events/mutationevent.hxx"



using namespace ::com::sun::star;


namespace {
    struct UnoTunnelId
        : public ::rtl::StaticWithInit< Sequence<sal_Int8>, UnoTunnelId >
    {
        Sequence<sal_Int8> operator() ()
        {
            Sequence<sal_Int8> ret(16);
            rtl_createUuid(
                reinterpret_cast<sal_uInt8*>(ret.getArray()), 0, sal_True);
            return ret;
        }
    };
}

namespace DOM
{
    void pushContext(Context& io_rContext)
    {
        io_rContext.maNamespaces.push_back(
            io_rContext.maNamespaces.back());
    }

    void popContext(Context& io_rContext)
    {
        io_rContext.maNamespaces.pop_back();
    }

    void addNamespaces(Context& io_rContext, xmlNodePtr pNode)
    {
        // add node's namespaces to current context
        for (xmlNsPtr pNs = pNode->nsDef; pNs != 0; pNs = pNs->next) {
            const xmlChar *pPrefix = pNs->prefix;
            OString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
                           strlen(reinterpret_cast<const char*>(pPrefix)));
            const xmlChar *pHref = pNs->href;
            OUString val(reinterpret_cast<const sal_Char*>(pHref),
                strlen(reinterpret_cast<const char*>(pHref)),
                RTL_TEXTENCODING_UTF8);

            OSL_TRACE("Trying to add namespace %s (prefix %s)",
                      (const char*)pHref, (const char*)pPrefix);

            Context::NamespaceMapType::iterator aIter=
                io_rContext.maNamespaceMap.find(val);
            if( aIter != io_rContext.maNamespaceMap.end() )
            {
                Context::Namespace aNS;
                aNS.maPrefix = prefix;
                aNS.mnToken = aIter->second;
                aNS.maNamespaceURL = val;

                io_rContext.maNamespaces.back().push_back(aNS);

                OSL_TRACE("Added with token 0x%x", aIter->second);
            }
        }
    }

    sal_Int32 getToken( const Context& rContext, const sal_Char* pToken )
    {
        const Sequence<sal_Int8> aSeq( (sal_Int8*)pToken, strlen( pToken ) );
        return rContext.mxTokenHandler->getTokenFromUTF8( aSeq );
    }

    sal_Int32 getTokenWithPrefix( const Context& rContext, const sal_Char* pPrefix, const sal_Char* pName )
    {
        sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
        OString prefix(pPrefix,
                       strlen(reinterpret_cast<const char*>(pPrefix)));

        OSL_TRACE("getTokenWithPrefix(): prefix %s, name %s",
                  (const char*)pPrefix, (const char*)pName);

        Context::NamespaceVectorType::value_type::const_iterator aIter;
        if( (aIter=std::find_if(rContext.maNamespaces.back().begin(),
                                rContext.maNamespaces.back().end(),
                                boost::bind(std::equal_to<OString>(),
                                            boost::bind(&Context::Namespace::getPrefix,
                                                        _1),
                                            boost::cref(prefix)))) != rContext.maNamespaces.back().end() )
        {
            nNamespaceToken = aIter->mnToken;
            sal_Int32 nNameToken = getToken( rContext, pName );
            if( nNameToken != FastToken::DONTKNOW )
                nNamespaceToken |= nNameToken;
        }

        return nNamespaceToken;
    }


    CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex,
                NodeType const& reNodeType, xmlNodePtr const& rpNode)
        :   m_bUnlinked(false)
        ,   m_aNodeType(reNodeType)
        ,   m_aNodePtr(rpNode)
        // keep containing document alive
        // (but not if this is a document; that would create a leak!)
        ,   m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE)
                ? &const_cast<CDocument&>(rDocument) : 0 )
        ,   m_rMutex(const_cast< ::osl::Mutex & >(rMutex))
    {
        OSL_ASSERT(m_aNodePtr);
    }

    void CNode::invalidate()
    {
        //remove from list if this wrapper goes away
        if (m_aNodePtr != 0 && m_xDocument.is()) {
            m_xDocument->RemoveCNode(m_aNodePtr, this);
        }
        // #i113663#: unlinked nodes will not be freed by xmlFreeDoc
        if (m_bUnlinked) {
            xmlFreeNode(m_aNodePtr);
        }
        m_aNodePtr = 0;
    }

    CNode::~CNode()
    {
        // if this is the document itself, the mutex is already freed!
        if (NodeType_DOCUMENT_NODE == m_aNodeType) {
            invalidate();
        } else {
            ::osl::MutexGuard const g(m_rMutex);
            invalidate(); // other nodes are still alive so must lock mutex
        }
    }

    CNode *
    CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode)
    {
        uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY);
        if (!xUnoTunnel.is()) { return 0; }
        CNode *const pCNode( reinterpret_cast< CNode* >(
                        ::sal::static_int_cast< sal_IntPtr >(
                            xUnoTunnel->getSomething(UnoTunnelId::get()))));
        return pCNode;
    }

    CDocument & CNode::GetOwnerDocument()
    {
        OSL_ASSERT(m_xDocument.is());
        return *m_xDocument; // needs overriding in CDocument!
    }


    static void lcl_nsexchange(
            xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs)
    {
        // recursively exchange any references to oldNs with references to newNs
        xmlNodePtr cur = aNode;
        while (cur != 0)
        {
            if (cur->ns == oldNs)
                cur->ns = newNs;
            if (cur->type == XML_ELEMENT_NODE)
            {
                xmlAttrPtr curAttr = cur->properties;
                while(curAttr != 0)
                {
                    if (curAttr->ns == oldNs)
                        curAttr->ns = newNs;
                    curAttr = curAttr->next;
                }
                lcl_nsexchange(cur->children, oldNs, newNs);
            }
            cur = cur->next;
        }
    }

    /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent)
    {
        xmlNodePtr cur = aNode;

        //handle attributes
        if (cur != NULL && cur->type == XML_ELEMENT_NODE)
        {
            xmlAttrPtr curAttr = cur->properties;
            while(curAttr != 0)
            {
                if (curAttr->ns != NULL)
                {
                    xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, curAttr->ns->prefix);
                    if (ns != NULL)
                        curAttr->ns = ns;
                }
                curAttr = curAttr->next;
            }
        }

        while (cur != NULL)
        {
            nscleanup(cur->children, cur);
            if (cur->ns != NULL)
            {
                xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix);
                if (ns != NULL && ns != cur->ns && strcmp((char*)ns->href, (char*)cur->ns->href)==0)
                {
                    xmlNsPtr curDef = cur->nsDef;
                    xmlNsPtr *refp = &(cur->nsDef); // insert point
                    while (curDef != NULL)
                    {
                        ns = xmlSearchNs(cur->doc, aParent, curDef->prefix);
                        if (ns != NULL && ns != curDef && strcmp((char*)ns->href, (char*)curDef->href)==0)
                        {
                            // reconnect ns pointers in sub-tree to newly found ns before
                            // removing redundant nsdecl to prevent dangling pointers.
                            lcl_nsexchange(cur, curDef, ns);
                            *refp = curDef->next;
                            xmlFreeNs(curDef);
                            curDef = *refp;
                        } else {
                            refp = &(curDef->next);
                            curDef = curDef->next;
                        }
                    }
                }
            }
            cur = cur->next;
        }
    }

    void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler)
    {
        if (!i_xHandler.is()) throw RuntimeException();
        // default: do nothing
    }

    void CNode::fastSaxify(Context& io_rContext)
    {
        if (!io_rContext.mxDocHandler.is()) throw RuntimeException();
        // default: do nothing
    }

    bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/)
    {
        // default: no children allowed
        return false;
    }

    /**
    Adds the node newChild to the end of the list of children of this node.
    */
    Reference< XNode > SAL_CALL CNode::appendChild(
            Reference< XNode > const& xNewChild)
        throw (RuntimeException, DOMException)
    {
        ::osl::ClearableMutexGuard guard(m_rMutex);

        if (0 == m_aNodePtr) { return 0; }

        CNode *const pNewChild(CNode::GetImplementation(xNewChild));
        if (!pNewChild) { throw RuntimeException(); }
        xmlNodePtr const cur = pNewChild->GetNodePtr();
        if (!cur) { throw RuntimeException(); }

        // error checks:
        // from other document
        if (cur->doc != m_aNodePtr->doc) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }
        // same node
        if (cur == m_aNodePtr) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (cur->parent != NULL) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        // check whether this is an attribute node; it needs special handling
        xmlNodePtr res = NULL;
        if (cur->type == XML_ATTRIBUTE_NODE)
        {
            xmlChar const*const pChildren((cur->children)
                    ? cur->children->content
                    : reinterpret_cast<xmlChar const*>(""));
            CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild));
            if (!pCAttr) { throw RuntimeException(); }
            xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
            if (pNs) {
                res = reinterpret_cast<xmlNodePtr>(
                        xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren));
            } else {
                res = reinterpret_cast<xmlNodePtr>(
                        xmlNewProp(m_aNodePtr, cur->name, pChildren));
            }
        }
        else
        {
            res = xmlAddChild(m_aNodePtr, cur);

            // libxml can do optimization when appending nodes.
            // if res != cur, something was optimized and the newchild-wrapper
            // should be updated
            if (res && (cur != res)) {
                pNewChild->invalidate(); // cur has been freed
            }
        }

        if (!res) { return 0; }

        // use custom ns cleanup instead of
        // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr);
        // because that will not remove unneeded ns decls
        nscleanup(res, m_aNodePtr);

        ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res);

        if (!pNode.is()) { return 0; }

        // dispatch DOMNodeInserted event, target is the new node
        // this node is the related node
        // does bubble
        pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY);
        event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted")
            , sal_True, sal_False,
            this,
            OUString(), OUString(), OUString(), (AttrChangeType)0 );

        // the following dispatch functions use only UNO interfaces
        // and call event listeners, so release mutex to prevent deadlocks.
        guard.clear();

        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
        // dispatch subtree modified for this node
        dispatchSubtreeModified();

        return pNode.get();
    }

    /**
    Returns a duplicate of this node, i.e., serves as a generic copy
    constructor for nodes.
    */
    Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
            xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0));
        if (!pNode.is()) { return 0; }
        pNode->m_bUnlinked = true; // not linked yet
        return pNode.get();
    }

    /**
    A NamedNodeMap containing the attributes of this node (if it is an Element)
    or null otherwise.
    */
    Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes()
        throw (RuntimeException)
    {
        // return empty reference; only element node may override this impl
        return Reference< XNamedNodeMap>();
    }

    /**
    A NodeList that contains all children of this node.
    */
    Reference< XNodeList > SAL_CALL CNode::getChildNodes()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex));
        return xNodeList;
    }

    /**
    The first child of this node.
    */
    Reference< XNode > SAL_CALL CNode::getFirstChild()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNode > const xNode(
                GetOwnerDocument().GetCNode(m_aNodePtr->children).get());
        return xNode;
    }

    /**
    The last child of this node.
    */
    Reference< XNode > SAL_CALL CNode::getLastChild()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNode > const xNode(
            GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get());
        return xNode;
    }

    /**
    Returns the local part of the qualified name of this node.
    */
    OUString SAL_CALL CNode::getLocalName()
        throw (RuntimeException)
    {
        // see CElement/CAttr
        return ::rtl::OUString();
    }


    /**
    The namespace URI of this node, or null if it is unspecified.
    */
    OUString SAL_CALL CNode::getNamespaceURI()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OUString aURI;
        if (m_aNodePtr != NULL &&
            (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
            m_aNodePtr->ns != NULL)
        {
            const xmlChar* xHref = m_aNodePtr->ns->href;
            aURI = OUString((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8);
        }
        return aURI;
    }

    /**
    The node immediately following this node.
    */
    Reference< XNode > SAL_CALL CNode::getNextSibling()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNode > const xNode(
                GetOwnerDocument().GetCNode(m_aNodePtr->next).get());
        return xNode;
    }

    /**
    The name of this node, depending on its type; see the table above.
    */
    OUString SAL_CALL CNode::getNodeName()
        throw (RuntimeException)
    {
        /*
        Interface  	     nodeName  	            nodeValue  	                    attributes
        --------------------------------------------------------------------------------------
        Attr 	         name of attribute 	    value of attribute 	            null
        CDATASection 	 "#cdata-section" 	    content of the CDATA Section 	null
        Comment 	     "#comment" 	        content of the comment 	        null
        Document 	     "#document" 	        null 	                        null
        DocumentFragment "#document-fragment" 	null 	                        null
        DocumentType 	 document type name 	null 	                        null
        Element 	     tag name 	            null 	                        NamedNodeMap
        Entity 	         entity name 	        null 	                        null
        EntityReference  name of entity         null 	                        null
                         referenced
        Notation 	     notation name 	        null 	                        null
        Processing\   	 target                 entire content excluding        null
        Instruction 	                        the target
        Text 	         "#text" 	            content of the text node     	null
        */
        OUString aName;
        return aName;
    }

    /**
    A code representing the type of the underlying object, as defined above.
    */
    NodeType SAL_CALL CNode::getNodeType()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        return m_aNodeType;
    }

    /**
    The value of this node, depending on its type; see the table above.
    */
    OUString SAL_CALL CNode::getNodeValue()
        throw (RuntimeException)
    {
        OUString aValue;
        return aValue;
    }

    /**
    The Document object associated with this node.
    */
    Reference< XDocument > SAL_CALL CNode::getOwnerDocument()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XDocument > const xDoc(& GetOwnerDocument());
        return xDoc;
    }

    /**
    The parent of this node.
    */
    Reference< XNode > SAL_CALL CNode::getParentNode()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNode > const xNode(
                GetOwnerDocument().GetCNode(m_aNodePtr->parent).get());
        return xNode;
    }

    /**
    The namespace prefix of this node, or null if it is unspecified.
    */
    OUString SAL_CALL CNode::getPrefix()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OUString aPrefix;
        if (m_aNodePtr != NULL &&
            (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) &&
            m_aNodePtr->ns != NULL)
        {
            const xmlChar* xPrefix = m_aNodePtr->ns->prefix;
            if( xPrefix != NULL )
                aPrefix = OUString((sal_Char*)xPrefix, strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8);
        }
        return aPrefix;

    }

    /**
    The node immediately preceding this node.
    */
    Reference< XNode > SAL_CALL CNode::getPreviousSibling()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        Reference< XNode > const xNode(
                GetOwnerDocument().GetCNode(m_aNodePtr->prev).get());
        return xNode;
    }

    /**
    Returns whether this node (if it is an element) has any attributes.
    */
    sal_Bool SAL_CALL CNode::hasAttributes()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL);
    }

    /**
    Returns whether this node has any children.
    */
    sal_Bool SAL_CALL CNode::hasChildNodes()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        return (m_aNodePtr != NULL && m_aNodePtr->children != NULL);
    }

    /**
    Inserts the node newChild before the existing child node refChild.
    */
    Reference< XNode > SAL_CALL CNode::insertBefore(
            const Reference< XNode >& newChild, const Reference< XNode >& refChild)
        throw (RuntimeException, DOMException)
    {
        if (!newChild.is() || !refChild.is()) { throw RuntimeException(); }

        if (newChild->getOwnerDocument() != getOwnerDocument()) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }
        if (refChild->getParentNode() != Reference< XNode >(this)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        ::osl::ClearableMutexGuard guard(m_rMutex);

        CNode *const pNewNode(CNode::GetImplementation(newChild));
        CNode *const pRefNode(CNode::GetImplementation(refChild));
        if (!pNewNode || !pRefNode) { throw RuntimeException(); }
        xmlNodePtr const pNewChild(pNewNode->GetNodePtr());
        xmlNodePtr const pRefChild(pRefNode->GetNodePtr());
        if (!pNewChild || !pRefChild) { throw RuntimeException(); }

        if (pNewChild == m_aNodePtr) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        // already has parent
        if (pNewChild->parent != NULL)
        {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        // attributes are unordered anyway, so just do appendChild
        if (XML_ATTRIBUTE_NODE == pNewChild->type) {
            guard.clear();
            return appendChild(newChild);
        }

        xmlNodePtr cur = m_aNodePtr->children;

        //search child before which to insert
        while (cur != NULL)
        {
            if (cur == pRefChild) {
                // insert before
                pNewChild->next = cur;
                pNewChild->prev = cur->prev;
                cur->prev = pNewChild;
                if (pNewChild->prev != NULL) {
                    pNewChild->prev->next = pNewChild;
                }
                pNewChild->parent = cur->parent;
                if (pNewChild->parent->children == cur) {
                    pNewChild->parent->children = pNewChild;
                }
                // do not update parent->last here!
                pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
                break;
            }
            cur = cur->next;
        }
        return refChild;
    }

    /**
    Tests whether the DOM implementation implements a specific feature and
    that feature is supported by this node.
    */
  sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/)
        throw (RuntimeException)
    {
        OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)");
        return sal_False;
    }

    /**
    Puts all Text nodes in the full depth of the sub-tree underneath this
    Node, including attribute nodes, into a "normal" form where only structure
    (e.g., elements, comments, processing instructions, CDATA sections, and
    entity references) separates Text nodes, i.e., there are neither adjacent
    Text nodes nor empty Text nodes.
    */
    void SAL_CALL CNode::normalize()
        throw (RuntimeException)
    {
        //XXX combine adjacent text nodes and remove empty ones
        OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)");
    }

    /**
    Removes the child node indicated by oldChild from the list of children,
    and returns it.
    */
    Reference< XNode > SAL_CALL
    CNode::removeChild(const Reference< XNode >& xOldChild)
        throw (RuntimeException, DOMException)
    {
        if (!xOldChild.is()) {
            throw RuntimeException();
        }

        if (xOldChild->getOwnerDocument() != getOwnerDocument()) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }
        if (xOldChild->getParentNode() != Reference< XNode >(this)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        ::osl::ClearableMutexGuard guard(m_rMutex);

        if (!m_aNodePtr) { throw RuntimeException(); }

        Reference<XNode> xReturn( xOldChild );

        ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild));
        if (!pOld.is()) { throw RuntimeException(); }
        xmlNodePtr const old = pOld->GetNodePtr();
        if (!old) { throw RuntimeException(); }

        if( old->type == XML_ATTRIBUTE_NODE )
        {
            xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old);
            xmlRemoveProp( pAttr );
            pOld->invalidate(); // freed by xmlRemoveProp
            xReturn.clear();
        }
        else
        {
            xmlUnlinkNode(old);
            pOld->m_bUnlinked = true;
        }

        /*DOMNodeRemoved
         * Fired when a node is being removed from its parent node.
         * This event is dispatched before the node is removed from the tree.
         * The target of this event is the node being removed.
         *   Bubbles: Yes
         *   Cancelable: No
         *   Context Info: relatedNode holds the parent node
         */
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY);
        event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"),
            sal_True,
            sal_False,
            this,
            OUString(), OUString(), OUString(), (AttrChangeType)0 );

        // the following dispatch functions use only UNO interfaces
        // and call event listeners, so release mutex to prevent deadlocks.
        guard.clear();

        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
        // subtree modified for this node
        dispatchSubtreeModified();

        return xReturn;
    }

    /**
    Replaces the child node oldChild with newChild in the list of children,
    and returns the oldChild node.
    */
    Reference< XNode > SAL_CALL CNode::replaceChild(
            Reference< XNode > const& xNewChild,
            Reference< XNode > const& xOldChild)
        throw (RuntimeException, DOMException)
    {
        if (!xOldChild.is() || !xNewChild.is()) {
            throw RuntimeException();
        }

        if (xNewChild->getOwnerDocument() != getOwnerDocument()) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }
        if (xOldChild->getParentNode() != Reference< XNode >(this)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        ::osl::ClearableMutexGuard guard(m_rMutex);

/*
        Reference< XNode > aNode = removeChild(oldChild);
        appendChild(newChild);
*/
        ::rtl::Reference<CNode> const pOldNode(
                CNode::GetImplementation(xOldChild));
        ::rtl::Reference<CNode> const pNewNode(
                CNode::GetImplementation(xNewChild));
        if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); }
        xmlNodePtr const pOld = pOldNode->GetNodePtr();
        xmlNodePtr const pNew = pNewNode->GetNodePtr();
        if (!pOld || !pNew) { throw RuntimeException(); }

        if (pNew == m_aNodePtr) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        // already has parent
        if (pNew->parent != NULL) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }

        if( pOld->type == XML_ATTRIBUTE_NODE )
        {
            // can only replace attribute with attribute
            if ( pOld->type != pNew->type )
            {
                DOMException e;
                e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
                throw e;
            }

            xmlAttrPtr pAttr = (xmlAttrPtr)pOld;
            xmlRemoveProp( pAttr );
            pOldNode->invalidate(); // freed by xmlRemoveProp
            appendChild(xNewChild);
        }
        else
        {

        xmlNodePtr cur = m_aNodePtr->children;
        //find old node in child list
        while (cur != NULL)
        {
            if(cur == pOld)
            {
                // exchange nodes
                pNew->prev = pOld->prev;
                if (pNew->prev != NULL)
                    pNew->prev->next = pNew;
                pNew->next = pOld->next;
                if (pNew->next != NULL)
                    pNew->next->prev = pNew;
                pNew->parent = pOld->parent;
                if(pNew->parent->children == pOld)
                    pNew->parent->children = pNew;
                if(pNew->parent->last == pOld)
                    pNew->parent->last = pNew;
                pOld->next = NULL;
                pOld->prev = NULL;
                pOld->parent = NULL;
                pOldNode->m_bUnlinked = true;
                pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc
            }
            cur = cur->next;
        }
        }

        guard.clear(); // release for calling event handlers
        dispatchSubtreeModified();

        return xOldChild;
    }

    void CNode::dispatchSubtreeModified()
    {
        // only uses UNO interfaces => needs no mutex

        // dispatch DOMSubtreeModified
        // target is _this_ node
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY);
        event->initMutationEvent(
            OUString::createFromAscii("DOMSubtreeModified"), sal_True,
            sal_False, Reference< XNode >(),
            OUString(), OUString(), OUString(), (AttrChangeType)0 );
        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
    }

    /**
    The value of this node, depending on its type; see the table above.
    */
    void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/)
        throw (RuntimeException, DOMException)
    {
        // use specific node implememntation
        // if we end up down here, something went wrong
        DOMException e;
        e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
        throw e;
    }

    /**
    The namespace prefix of this node, or null if it is unspecified.
    */
    void SAL_CALL CNode::setPrefix(const OUString& prefix)
        throw (RuntimeException, DOMException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if ((0 == m_aNodePtr) ||
            ((m_aNodePtr->type != XML_ELEMENT_NODE) &&
             (m_aNodePtr->type != XML_ATTRIBUTE_NODE)))
        {
            DOMException e;
            e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR;
            throw e;
        }
        OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8);
        xmlChar *pBuf = (xmlChar*)o1.getStr();
        if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL)
        {
            xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix));
            m_aNodePtr->ns->prefix = xmlStrdup(pBuf);
        }

    }

        // --- XEventTarget
    void SAL_CALL CNode::addEventListener(const OUString& eventType,
        const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
        sal_Bool useCapture)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        CDocument & rDocument(GetOwnerDocument());
        events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
        rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture);
    }

    void SAL_CALL CNode::removeEventListener(const OUString& eventType,
        const Reference< com::sun::star::xml::dom::events::XEventListener >& listener,
        sal_Bool useCapture)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        CDocument & rDocument(GetOwnerDocument());
        events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher());
        rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture);
    }

    sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt)
        throw(RuntimeException, EventException)
    {
        CDocument * pDocument;
        events::CEventDispatcher * pDispatcher;
        xmlNodePtr pNode;
        {
            ::osl::MutexGuard const g(m_rMutex);

            pDocument = & GetOwnerDocument();
            pDispatcher = & pDocument->GetEventDispatcher();
            pNode = m_aNodePtr;
        }
        // this calls event listeners, do not call with locked mutex
        pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt);
        return sal_True;
    }

    ::sal_Int64 SAL_CALL
    CNode::getSomething(Sequence< ::sal_Int8 > const& rId)
        throw (RuntimeException)
    {
        if ((rId.getLength() == 16) &&
            (0 == rtl_compareMemory(UnoTunnelId::get().getConstArray(),
                                    rId.getConstArray(), 16)))
        {
            return ::sal::static_int_cast< sal_Int64 >(
                    reinterpret_cast< sal_IntPtr >(this) );
        }
        return 0;
    }
}

