/*
 * 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 "XercesEntityBridge.hpp"



#include <xalanc/DOMSupport/DOMServices.hpp>



#include "XercesBridgeHelper.hpp"
#include "XercesBridgeNavigator.hpp"
#include "XercesDocumentBridge.hpp"



namespace XALAN_CPP_NAMESPACE {



XercesEntityBridge::XercesEntityBridge(
            const DOM_EntityType&           theXercesDOMEntity,
            const XercesBridgeNavigator&    theNavigator) :
    XalanEntity(),
    m_xercesNode(theXercesDOMEntity),
    m_navigator(theNavigator),
    m_children(m_xercesNode.getChildNodes(),
               theNavigator)
{
}



XercesEntityBridge::~XercesEntityBridge()
{
}



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



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



XercesEntityBridge::NodeType
XercesEntityBridge::getNodeType() const
{
    return ENTITY_NODE;
}



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



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



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



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



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



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



const XalanNamedNodeMap*
XercesEntityBridge::getAttributes() const
{
    return 0;
}



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



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

    return theBridge;
}



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



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



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



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



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



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



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


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



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



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



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



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



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



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



const XalanDOMString&
XercesEntityBridge::getPublicId() const
{
    return m_navigator.getPooledString(m_xercesNode.getPublicId());
}



const XalanDOMString&
XercesEntityBridge::getSystemId() const
{
    return m_navigator.getPooledString(m_xercesNode.getSystemId());
}



const XalanDOMString&
XercesEntityBridge::getNotationName() const
{
    return m_navigator.getPooledString(m_xercesNode.getNotationName());
}



}


#endif //XALAN_BUILD_DEPRECATED_DOM_BRIDGE 


