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

#include <string.h>

#include <boost/shared_ptr.hpp>

#include <rtl/ustrbuf.hxx>

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

#include <comphelper/attributelist.hxx>

#include <node.hxx>
#include <attr.hxx>
#include <elementlist.hxx>
#include <attributesmap.hxx>
#include <document.hxx>

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


namespace DOM
{

    CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex,
            xmlNodePtr const pNode)
        : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode)
    {
    }

    void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler)
    {
        if (!i_xHandler.is()) throw RuntimeException();
        comphelper::AttributeList *pAttrs =
            new comphelper::AttributeList();
        OUString type = OUString::createFromAscii("");
        // add namespace definitions to attributes
        for (xmlNsPtr pNs = m_aNodePtr->nsDef; pNs != 0; pNs = pNs->next) {
            const xmlChar *pPrefix = pNs->prefix;
            OUString prefix(reinterpret_cast<const sal_Char*>(pPrefix),
                strlen(reinterpret_cast<const char*>(pPrefix)),
                RTL_TEXTENCODING_UTF8);
            OUString name = (prefix.equalsAscii(""))
                ? OUString::createFromAscii("xmlns")
                : OUString::createFromAscii("xmlns:") + prefix;
            const xmlChar *pHref = pNs->href;
            OUString val(reinterpret_cast<const sal_Char*>(pHref),
                strlen(reinterpret_cast<const char*>(pHref)),
                RTL_TEXTENCODING_UTF8);
            pAttrs->AddAttribute(name, type, val);
        }
        // add attributes
        for (xmlAttrPtr pAttr = m_aNodePtr->properties;
                        pAttr != 0; pAttr = pAttr->next) {
            ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr));
            OSL_ENSURE(pNode != 0, "CNode::get returned 0");
            OUString prefix = pNode->getPrefix();
            OUString name = (prefix.getLength() == 0)
                ? pNode->getLocalName()
                : prefix + OUString(static_cast<sal_Unicode>(':')) + pNode->getLocalName();
            OUString val  = pNode->getNodeValue();
            pAttrs->AddAttribute(name, type, val);
        }
        OUString prefix = getPrefix();
        OUString name = (prefix.getLength() == 0)
            ? getLocalName()
            : prefix + OUString(static_cast<sal_Unicode>(':')) + getLocalName();
        Reference< XAttributeList > xAttrList(pAttrs);
        i_xHandler->startElement(name, xAttrList);
        // recurse
        for (xmlNodePtr pChild = m_aNodePtr->children;
                        pChild != 0; pChild = pChild->next) {
            ::rtl::Reference<CNode> const pNode(
                    GetOwnerDocument().GetCNode(pChild));
            OSL_ENSURE(pNode != 0, "CNode::get returned 0");
            pNode->saxify(i_xHandler);
        }
        i_xHandler->endElement(name);
    }

    void CElement::fastSaxify( Context& i_rContext )
    {
        if (!i_rContext.mxDocHandler.is()) throw RuntimeException();
        pushContext(i_rContext);
        addNamespaces(i_rContext,m_aNodePtr);

        // add attributes
        i_rContext.mxAttribList->clear();
        for (xmlAttrPtr pAttr = m_aNodePtr->properties;
                        pAttr != 0; pAttr = pAttr->next) {
            ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr));
            OSL_ENSURE(pNode != 0, "CNode::get returned 0");

            const xmlChar* xName = pAttr->name;
            sal_Int32 nAttributeToken=FastToken::DONTKNOW;

            if( pAttr->ns && strlen((char*)pAttr->ns->prefix) )
                nAttributeToken = getTokenWithPrefix( i_rContext,
                                                      (sal_Char*)pAttr->ns->prefix,
                                                      (sal_Char*)xName );
            else
                nAttributeToken = getToken( i_rContext, (sal_Char*)xName );

            if( nAttributeToken != FastToken::DONTKNOW )
                i_rContext.mxAttribList->add( nAttributeToken,
                                              OUStringToOString(pNode->getNodeValue(),
                                                                RTL_TEXTENCODING_UTF8));
        }

        const xmlChar* xPrefix = m_aNodePtr->ns ? m_aNodePtr->ns->prefix : (const xmlChar*)"";
        const xmlChar* xName = m_aNodePtr->name;
        sal_Int32 nElementToken=FastToken::DONTKNOW;
        if( strlen((char*)xPrefix) )
            nElementToken = getTokenWithPrefix( i_rContext, (sal_Char*)xPrefix, (sal_Char*)xName );
        else
            nElementToken = getToken( i_rContext, (sal_Char*)xName );

        Reference<XFastContextHandler> xParentHandler(i_rContext.mxCurrentHandler);
        try
        {
            Reference< XFastAttributeList > xAttr( i_rContext.mxAttribList.get() );
            if( nElementToken == FastToken::DONTKNOW )
            {
                const OUString aNamespace;
                const OUString aElementName( (sal_Char*)xPrefix,
                                             strlen((char*)xPrefix),
                                             RTL_TEXTENCODING_UTF8 );

                if( xParentHandler.is() )
                    i_rContext.mxCurrentHandler = xParentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
                else
                    i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );

                if( i_rContext.mxCurrentHandler.is() )
                    i_rContext.mxCurrentHandler->startUnknownElement( aNamespace, aElementName, xAttr );
            }
            else
            {
                if( xParentHandler.is() )
                    i_rContext.mxCurrentHandler = xParentHandler->createFastChildContext( nElementToken, xAttr );
                else
                    i_rContext.mxCurrentHandler = i_rContext.mxDocHandler->createFastChildContext( nElementToken, xAttr );

                if( i_rContext.mxCurrentHandler.is() )
                    i_rContext.mxCurrentHandler->startFastElement( nElementToken, xAttr );
            }
        }
        catch( Exception& )
        {}

        // recurse
        for (xmlNodePtr pChild = m_aNodePtr->children;
                        pChild != 0; pChild = pChild->next) {
            ::rtl::Reference<CNode> const pNode(
                    GetOwnerDocument().GetCNode(pChild));
            OSL_ENSURE(pNode != 0, "CNode::get returned 0");
            pNode->fastSaxify(i_rContext);
        }

		if( i_rContext.mxCurrentHandler.is() ) try
		{
			if( nElementToken != FastToken::DONTKNOW )
				i_rContext.mxCurrentHandler->endFastElement( nElementToken );
			else
            {
                const OUString aNamespace;
                const OUString aElementName( (sal_Char*)xPrefix,
                                             strlen((char*)xPrefix),
                                             RTL_TEXTENCODING_UTF8 );

				i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName );
            }
		}
		catch( Exception& )
		{}

        // restore after children have been processed
        i_rContext.mxCurrentHandler = xParentHandler;
        popContext(i_rContext);
    }

    bool CElement::IsChildTypeAllowed(NodeType const nodeType)
    {
        switch (nodeType) {
            case NodeType_ELEMENT_NODE:
            case NodeType_TEXT_NODE:
            case NodeType_COMMENT_NODE:
            case NodeType_PROCESSING_INSTRUCTION_NODE:
            case NodeType_CDATA_SECTION_NODE:
            case NodeType_ENTITY_REFERENCE_NODE:
                return true;
            case NodeType_ATTRIBUTE_NODE:
                /* this is not relly allowed by the DOM spec, but this
                   implementation has evidently supported it (by special case
                   handling, so the attribute does not actually become a child)
                   so allow it for backward compatibility */
                return true;
            default:
                return false;
        }
    }


    /**
		Retrieves an attribute value by name.
		return empty string if attribute is not set
    */
    OUString SAL_CALL CElement::getAttribute(OUString const& name)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return ::rtl::OUString();
        }
        // search properties
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        ::boost::shared_ptr<xmlChar const> const pValue(
            xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree);
        OUString const ret( (pValue)
            ?   OUString(reinterpret_cast<sal_Char const*>(pValue.get()),
                        strlen(reinterpret_cast<char const*>(pValue.get())),
                        RTL_TEXTENCODING_UTF8)
            :   OUString() );
        return ret;
    }

    /**
    Retrieves an attribute node by name.
    */
    Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
        if (0 == pAttr) {
            return 0;
        }
        Reference< XAttr > const xRet(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr)).get()),
            UNO_QUERY_THROW);
        return xRet;
    }

    /**
    Retrieves an Attr node by local name and namespace URI.
    */
    Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS(
            const OUString& namespaceURI, const OUString& localName)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return 0;
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pNS =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS);
        if (0 == pAttr) {
            return 0;
        }
        Reference< XAttr > const xRet(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr)).get()),
            UNO_QUERY_THROW);
        return xRet;
    }

    /**
    Retrieves an attribute value by local name and namespace URI.
	return empty string if attribute is not set
    */
    OUString SAL_CALL
    CElement::getAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return ::rtl::OUString();
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pNS =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        ::boost::shared_ptr<xmlChar const> const pValue(
                xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree);
        if (0 == pValue) {
            return ::rtl::OUString();
        }
        OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()),
                        strlen(reinterpret_cast<char const*>(pValue.get())),
                        RTL_TEXTENCODING_UTF8);
        return ret;
    }

    /**
    Returns a NodeList of all descendant Elements with a given tag name,
    in the order in which they are
    encountered in a preorder traversal of this Element tree.
    */
    Reference< XNodeList > SAL_CALL
    CElement::getElementsByTagName(OUString const& rLocalName)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNodeList > const xList(
                new CElementList(this, m_rMutex, rLocalName));
        return xList;
    }

    /**
    Returns a NodeList of all the descendant Elements with a given local
    name and namespace URI in the order in which they are encountered in
    a preorder traversal of this Element tree.
    */
    Reference< XNodeList > SAL_CALL
    CElement::getElementsByTagNameNS(
            OUString const& rNamespaceURI, OUString const& rLocalName)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNodeList > const xList(
            new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI));
        return xList;
    }

    /**
    The name of the element.
    */
    OUString SAL_CALL CElement::getTagName()
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return ::rtl::OUString();
        }
        OUString const ret((sal_Char*)m_aNodePtr->name,
                strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8);
        return ret;
    }


    /**
    Returns true when an attribute with a given name is specified on this
    element or has a default value, false otherwise.
    */
    sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar *xName = (xmlChar*)o1.getStr();
        return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL);
    }

    /**
    Returns true when an attribute with a given local name and namespace
    URI is specified on this element or has a default value, false otherwise.
    */
    sal_Bool SAL_CALL CElement::hasAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
        throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar *xName = (xmlChar*)o1.getStr();
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar *xNs = (xmlChar*)o2.getStr();
        return (m_aNodePtr != NULL && xmlHasNsProp(m_aNodePtr, xName, xNs) != NULL);
    }

    /**
    Removes an attribute by name.
    */
    void SAL_CALL CElement::removeAttribute(OUString const& name)
        throw (RuntimeException, DOMException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return;
        }
        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName);
        if (0 == xmlUnsetProp(m_aNodePtr, pName)) {
            ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr), false));
            if (pCNode.is()) {
                pCNode->invalidate(); // freed by xmlUnsetProp
            }
        }
    }

    /**
    Removes an attribute by local name and namespace URI.
    */
    void SAL_CALL CElement::removeAttributeNS(
            OUString const& namespaceURI, OUString const& localName)
        throw (RuntimeException, DOMException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            return;
        }
        OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pName =
            reinterpret_cast<xmlChar const*>(o1.getStr());
        OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        xmlChar const*const pURI =
            reinterpret_cast<xmlChar const*>(o2.getStr());
        xmlNsPtr const pNs =
            xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI);
        xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI);
        if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) {
            ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(pAttr), false));
            if (pCNode.is()) {
                pCNode->invalidate(); // freed by xmlUnsetNsProp
            }
        }
    }

    /**
    Removes the specified attribute node.
    */
    Reference< XAttr > SAL_CALL
    CElement::removeAttributeNode(Reference< XAttr > const& oldAttr)
        throw (RuntimeException, DOMException)
    {
        ::osl::MutexGuard const g(m_rMutex);

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

        ::rtl::Reference<CNode> const pCNode(
            CNode::GetImplementation(Reference<XNode>(oldAttr.get())));
        if (!pCNode.is()) { throw RuntimeException(); }

        xmlNodePtr const pNode = pCNode->GetNodePtr();
        xmlAttrPtr const pAttr = (xmlAttrPtr) pNode;
        if (!pAttr) { throw RuntimeException(); }

        if (pAttr->parent != m_aNodePtr)
        {
            DOMException e;
            e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR;
            throw e;
        }
        if (pAttr->doc != m_aNodePtr->doc)
        {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }

        Reference< XAttr > aAttr;
        if (oldAttr->getNamespaceURI().getLength() > 0) {
            ::rtl::OUStringBuffer qname(oldAttr->getPrefix());
            if (0 != qname.getLength()) {
                qname.append(sal_Unicode(':'));
            }
            qname.append(oldAttr->getName());
            aAttr = GetOwnerDocument().createAttributeNS(
                oldAttr->getNamespaceURI(), qname.makeStringAndClear());
        } else {
            aAttr = GetOwnerDocument().createAttribute(oldAttr->getName());
        }
        aAttr->setValue(oldAttr->getValue());
        xmlRemoveProp(pAttr);
        pCNode->invalidate(); // freed by xmlRemoveProp

        return aAttr;
    }

    /**
    Adds a new attribute node.
    */
    Reference< XAttr >
    CElement::setAttributeNode_Impl_Lock(
            Reference< XAttr > const& xNewAttr, bool const bNS)
    {
        if (xNewAttr->getOwnerDocument() != getOwnerDocument()) {
            DOMException e;
            e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR;
            throw e;
        }

        ::osl::ClearableMutexGuard guard(m_rMutex);

        if (0 == m_aNodePtr) {
            throw RuntimeException();
        }

        // get the implementation
        CAttr *const pCAttr = dynamic_cast<CAttr*>(
                CNode::GetImplementation(xNewAttr));
        if (!pCAttr) { throw RuntimeException(); }
        xmlAttrPtr const pAttr =
            reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr());
        if (!pAttr) { throw RuntimeException(); }

        // check whether the attribute is not in use by another element
        if (pAttr->parent) {
            DOMException e;
            e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR;
            throw e;
        }

        xmlAttrPtr res = NULL;
        xmlChar const*const pContent(
                (pAttr->children) ? pAttr->children->content : 0);

        if (bNS) {
            xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) );
            res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent);
        } else {
            res = xmlNewProp(m_aNodePtr, pAttr->name, pContent);
        }

        // get the new attr node
        Reference< XAttr > const xAttr(
            static_cast< XNode* >(GetOwnerDocument().GetCNode(
                    reinterpret_cast<xmlNodePtr>(res)).get()),
            UNO_QUERY_THROW);

        // attribute adition event
        // dispatch DOMAttrModified event
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMAttrModified")), UNO_QUERY);
        event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"),
            sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY),
            OUString(), xAttr->getValue(), xAttr->getName(),
            AttrChangeType_ADDITION);

        guard.clear(); // release mutex before calling event handlers

        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
        dispatchSubtreeModified();

        return xAttr;
    }

    Reference< XAttr >
    CElement::setAttributeNode(const Reference< XAttr >& newAttr)
        throw (RuntimeException, DOMException)
    {
        return setAttributeNode_Impl_Lock(newAttr, false);
    }

    /**
    Adds a new attribute.
    */
    Reference< XAttr >
    CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr)
        throw (RuntimeException, DOMException)
    {
        return setAttributeNode_Impl_Lock(newAttr, true);
    }

    /**
    Adds a new attribute.
    */
    void SAL_CALL
    CElement::setAttribute(OUString const& name, OUString const& value)
        throw (RuntimeException, DOMException)
    {
        ::osl::ClearableMutexGuard guard(m_rMutex);

        OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8);
        xmlChar *xName = (xmlChar*)o1.getStr();
        OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
        xmlChar *xValue = (xmlChar*)o2.getStr();

        if (0 == m_aNodePtr) {
            throw RuntimeException();
        }
        OUString oldValue;
        AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
        ::boost::shared_ptr<xmlChar const> const pOld(
            xmlGetProp(m_aNodePtr, xName), xmlFree);
        if( !bool(pOld)) {
            aChangeType = AttrChangeType_ADDITION;
            xmlNewProp(m_aNodePtr, xName, xValue);
        } else {
            oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
                        strlen(reinterpret_cast<char const*>(pOld.get())),
                        RTL_TEXTENCODING_UTF8);
            xmlSetProp(m_aNodePtr, xName, xValue);
        }

        // dispatch DOMAttrModified event
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMAttrModified")), UNO_QUERY);
        event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"),
            sal_True, sal_False,
            Reference< XNode >(getAttributeNode(name), UNO_QUERY),
            oldValue, value, name, aChangeType);

        guard.clear(); // release mutex before calling event handlers
        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
        dispatchSubtreeModified();
    }

    /**
    Adds a new attribute.
    */
    void SAL_CALL
    CElement::setAttributeNS(OUString const& namespaceURI,
            OUString const& qualifiedName, OUString const& value)
        throw (RuntimeException, DOMException)
    {
        if (namespaceURI.getLength() == 0) throw RuntimeException();

        ::osl::ClearableMutexGuard guard(m_rMutex);

        OString o1, o2, o3, o4, o5;
        xmlChar *xPrefix = NULL;
        xmlChar *xLName = NULL;
        o1 = OUStringToOString(qualifiedName, RTL_TEXTENCODING_UTF8);
        xmlChar *xQName = (xmlChar*)o1.getStr();
        sal_Int32 idx = qualifiedName.indexOf(':');
        if (idx != -1)
        {
            o2 = OUStringToOString(
                qualifiedName.copy(0,idx),
                RTL_TEXTENCODING_UTF8);
            xPrefix = (xmlChar*)o2.getStr();
            o3 = OUStringToOString(
                qualifiedName.copy(idx+1),
                RTL_TEXTENCODING_UTF8);
            xLName = (xmlChar*)o3.getStr();
        }  else {
            xPrefix = (xmlChar*)"";
            xLName = xQName;
        }
        o4 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8);
        o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
        xmlChar *xURI= (xmlChar*)o4.getStr();
        xmlChar *xValue = (xmlChar*)o5.getStr();

        if (0 == m_aNodePtr) {
            throw RuntimeException();
        }

        //find the right namespace
        xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix);
        // if no namespace found, create a new one
        if (pNs == NULL) {
            pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix);
        }

        if (strcmp((char*)pNs->href, (char*)xURI) != 0) {
            // ambiguous ns prefix
            throw RuntimeException();
        }

        // found namespace matches

        OUString oldValue;
        AttrChangeType aChangeType = AttrChangeType_MODIFICATION;
        ::boost::shared_ptr<xmlChar const> const pOld(
                xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree);
        if( !bool(pOld)) {
            aChangeType = AttrChangeType_ADDITION;
            xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue);
        } else {
            oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()),
                        strlen(reinterpret_cast<char const*>(pOld.get())),
                        RTL_TEXTENCODING_UTF8);
            xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue);
        }
        // dispatch DOMAttrModified event
        Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
        Reference< XMutationEvent > event(docevent->createEvent(
            OUString::createFromAscii("DOMAttrModified")), UNO_QUERY);
        event->initMutationEvent(
            OUString::createFromAscii("DOMAttrModified"),
            sal_True, sal_False,
            Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY),
            oldValue, value, qualifiedName, aChangeType);

        guard.clear(); // release mutex before calling event handlers
        dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
        dispatchSubtreeModified();
    }

    Reference< XNamedNodeMap > SAL_CALL
    CElement::getAttributes() throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        Reference< XNamedNodeMap > const xMap(
                new CAttributesMap(this, m_rMutex));
        return xMap;
    }

    OUString SAL_CALL CElement::getNodeName()throw (RuntimeException)
    {
        return getLocalName();
    }

    OUString SAL_CALL CElement::getLocalName()throw (RuntimeException)
    {
        ::osl::MutexGuard const g(m_rMutex);

        OUString aName;
        if (m_aNodePtr != NULL)
        {
            const xmlChar* xName = m_aNodePtr->name;
            aName = OUString((const sal_Char*)xName, strlen((const char*)xName), RTL_TEXTENCODING_UTF8);
        }
        return aName;
    }

    OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException)
    {
        return OUString();
    }

    void SAL_CALL CElement::setElementName(const OUString& aName)
        throw (RuntimeException, DOMException)
    {
        if ((aName.getLength() <= 0) ||
            (0 <= aName.indexOf(OUString::createFromAscii(":"))))
        {
            DOMException e;
            e.Code = DOMExceptionType_INVALID_CHARACTER_ERR;
            throw e;
        }

        ::osl::MutexGuard const g(m_rMutex);

        if (0 == m_aNodePtr) {
            throw RuntimeException();
        }
        OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8);
        xmlChar *xName = (xmlChar*)oName.getStr();
        xmlNodeSetName(m_aNodePtr, xName);
    }

}
