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


#if defined(XALAN_BUILD_DEPRECATED_DOM_BRIDGE)


#include "XercesElementBridge.hpp"



#include <xalanc/XalanDOM/XalanAttr.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XercesParserLiaison/Deprecated/XercesBridgeHelper.hpp>
#include <xalanc/XercesParserLiaison/Deprecated/XercesBridgeNavigator.hpp>
#include <xalanc/XercesParserLiaison/XercesDOMException.hpp>
#include <xalanc/XercesParserLiaison/Deprecated/XercesDocumentBridge.hpp>



namespace XALAN_CPP_NAMESPACE {



XercesElementBridge::XercesElementBridge(
            const DOM_ElementType&          theXercesElement,
            const XercesBridgeNavigator&    theNavigator) :
    XalanElement(),
    m_xercesNode(theXercesElement),
    m_navigator(theNavigator),
    m_children(theXercesElement.getChildNodes(),
               theNavigator),
    m_attributes(theXercesElement.getAttributes(),
                 theNavigator)
{
}



XercesElementBridge::~XercesElementBridge()
{
}



const XalanDOMString&
XercesElementBridge::getNodeName() const
{
    return m_navigator.getPooledString(m_xercesNode.getNodeNameImpl());
}



const XalanDOMString&
XercesElementBridge::getNodeValue() const
{
    return m_navigator.getPooledString(m_xercesNode.getNodeValueImpl());
}



XercesElementBridge::NodeType
XercesElementBridge::getNodeType() const
{
    return ELEMENT_NODE;
}



XalanNode*
XercesElementBridge::getParentNode() const
{
    return m_navigator.getParentNode(m_xercesNode);
}



const XalanNodeList*
XercesElementBridge::getChildNodes() const
{
    return &m_children;
}



XalanNode*
XercesElementBridge::getFirstChild() const
{
    return m_navigator.getFirstChild(m_xercesNode);
}



XalanNode*
XercesElementBridge::getLastChild() const
{
    return m_navigator.getLastChild(m_xercesNode);
}



XalanNode*
XercesElementBridge::getPreviousSibling() const
{
    return m_navigator.getPreviousSibling(m_xercesNode);
}



XalanNode*
XercesElementBridge::getNextSibling() const
{
    return m_navigator.getNextSibling(m_xercesNode);
}



const XalanNamedNodeMap*
XercesElementBridge::getAttributes() const
{
    return &m_attributes;
}



XalanDocument*
XercesElementBridge::getOwnerDocument() const
{
    return m_navigator.getOwnerDocument();
}



XercesElementBridge*
XercesElementBridge::cloneNode(bool deep) const
{
    XercesElementBridge* const  theBridge =
        static_cast<XercesElementBridge*>(m_navigator.cloneNode(this, m_xercesNode, deep));

    return theBridge;
}



XalanNode*
XercesElementBridge::insertBefore(
            XalanNode*  newChild,
            XalanNode*  refChild)
{
    return m_navigator.insertBefore(m_xercesNode, newChild, refChild);
}



XalanNode*
XercesElementBridge::replaceChild(
            XalanNode*  newChild,
            XalanNode*  oldChild)
{
    return m_navigator.replaceChild(m_xercesNode, newChild, oldChild);
}



XalanNode*
XercesElementBridge::removeChild(XalanNode* oldChild)
{
    return m_navigator.removeChild(m_xercesNode, oldChild);
}



XalanNode*
XercesElementBridge::appendChild(XalanNode* newChild)
{
    return m_navigator.appendChild(m_xercesNode, newChild);
}



bool
XercesElementBridge::hasChildNodes() const
{
    return m_xercesNode.hasChildNodes();
}



void
XercesElementBridge::setNodeValue(const XalanDOMString&     nodeValue)
{
    XercesBridgeHelper::setNodeValue(m_xercesNode, nodeValue);
}



void
XercesElementBridge::normalize()
{
    XercesBridgeHelper::normalize(m_xercesNode);
}


bool
XercesElementBridge::isSupported(
            const XalanDOMString&   feature,
            const XalanDOMString&   version) const
{
    return m_xercesNode.isSupported(
                XercesBridgeHelper::XalanDOMStringToXercesDOMString(feature),
                XercesBridgeHelper::XalanDOMStringToXercesDOMString(version));
}



const XalanDOMString&
XercesElementBridge::getNamespaceURI() const
{
    return m_navigator.getPooledString(m_xercesNode.getNamespaceURIImpl());
}



const XalanDOMString&
XercesElementBridge::getPrefix() const
{
    return m_navigator.getPooledString(m_xercesNode.getPrefixImpl());
}



const XalanDOMString&
XercesElementBridge::getLocalName() const
{
    return m_navigator.getPooledString(m_xercesNode.getLocalNameImpl());
}



void
XercesElementBridge::setPrefix(const XalanDOMString&    prefix)
{
    XercesBridgeHelper::setPrefix(m_xercesNode, prefix);
}



bool
XercesElementBridge::isIndexed() const
{
    return m_navigator.getOwnerDocument()->isIndexed();
}



XercesElementBridge::IndexType
XercesElementBridge::getIndex() const
{
    return m_navigator.getIndex();
}



const XalanDOMString&
XercesElementBridge::getTagName() const
{
    return m_navigator.getPooledString(m_xercesNode.getTagNameImpl());
}



const XalanDOMString&
XercesElementBridge::getAttribute(const XalanDOMString&     name) const
{
    return m_navigator.getPooledString(m_xercesNode.getAttributeImpl(name.c_str()));
}



XalanAttr*
XercesElementBridge::getAttributeNode(const XalanDOMString&     name) const
{
    return static_cast<XalanAttr*>(m_attributes.getNamedItem(name));
}



XalanNodeList*
XercesElementBridge::getElementsByTagName(const XalanDOMString&     /* name */) const
{
    // Not supported...
    return 0;
}



void
XercesElementBridge::setAttribute(
            const XalanDOMString&   name, 
            const XalanDOMString&   value)
{
    try
    {
        m_xercesNode.setAttribute(name.c_str(), value.c_str());
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }
}



XalanAttr*
XercesElementBridge::setAttributeNode(XalanAttr*    newAttr)
{
    assert(newAttr != 0);

    const DOM_AttrType  theXercesAttrNode =
            m_navigator.mapNode(newAttr);
    assert(theXercesAttrNode.isNull() == false);

    XalanAttr*  theXalanAttrResult = 0;

    try
    {
        const DOM_AttrType  theXercesAttrResult =
            m_xercesNode.setAttributeNode(theXercesAttrNode);

        theXalanAttrResult = m_navigator.mapNode(theXercesAttrResult);
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }

    return theXalanAttrResult;
}



XalanAttr*
XercesElementBridge::removeAttributeNode(XalanAttr*     oldAttr)
{
    assert(oldAttr != 0);

    const DOM_AttrType  theXercesAttrNode =
            m_navigator.mapNode(oldAttr);
    assert(theXercesAttrNode.isNull() == false);

    XalanAttr*  theXalanAttrResult = 0;

    try
    {
        const DOM_AttrType  theXercesAttrResult =
            m_xercesNode.removeAttributeNode(theXercesAttrNode);

        theXalanAttrResult = m_navigator.mapNode(theXercesAttrResult);
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }

    return theXalanAttrResult;
}



void
XercesElementBridge::removeAttribute(const XalanDOMString&  name)
{
    try
    {
        m_xercesNode.removeAttribute(name.c_str());
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }
}



const XalanDOMString&
XercesElementBridge::getAttributeNS(
            const XalanDOMString&   namespaceURI,
            const XalanDOMString&   localName) const
{
    return m_navigator.getPooledString(m_xercesNode.getAttributeNSImpl(namespaceURI.c_str(), localName.c_str()));
}



void
XercesElementBridge::setAttributeNS(
            const XalanDOMString&   namespaceURI,
            const XalanDOMString&   qualifiedName,
            const XalanDOMString&   value)
{
    try
    {
        m_xercesNode.setAttributeNS(namespaceURI.c_str(), qualifiedName.c_str(), value.c_str());
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }
}



void
XercesElementBridge::removeAttributeNS(
            const XalanDOMString&   namespaceURI,
            const XalanDOMString&   localName)
{
    try
    {
        m_xercesNode.removeAttributeNS(namespaceURI.c_str(), localName.c_str());
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }
}



XalanAttr*
XercesElementBridge::getAttributeNodeNS(
            const XalanDOMString&   namespaceURI,
            const XalanDOMString&   localName) const
{
    const DOM_AttrType  theAttrNode =
        m_xercesNode.getAttributeNodeNS(namespaceURI.c_str(), localName.c_str());

    if (theAttrNode.isNull() == true)
    {
        return 0;
    }
    else
    {
        return m_navigator.mapNode(theAttrNode);
    }
}



XalanAttr*
XercesElementBridge::setAttributeNodeNS(XalanAttr*  newAttr)
{
    assert(newAttr != 0);


    const DOM_AttrType  theXercesAttrNode =
            m_navigator.mapNode(newAttr);
    assert(theXercesAttrNode.isNull() == false);

    XalanAttr*  theXalanAttrResult = 0;

    try
    {
        const DOM_AttrType  theXercesAttrResult =
            m_xercesNode.setAttributeNodeNS(theXercesAttrNode);

        theXalanAttrResult = m_navigator.mapNode(theXercesAttrResult);
    }
    catch(const DOM_DOMExceptionType&   theException)
    {
        throw XercesDOMException(theException);
    }

    return theXalanAttrResult;
}



XalanNodeList*
XercesElementBridge::getElementsByTagNameNS(
            const XalanDOMString&   /* namespaceURI */,
            const XalanDOMString&   /* localName */) const
{
    // Not supported...
    return 0;
}



}


#endif //XALAN_BUILD_DEPRECATED_DOM_BRIDGE 


