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



#include <xalanc/DOMSupport/DOMServices.hpp>



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



namespace XALAN_CPP_NAMESPACE {



XercesNotationBridge::XercesNotationBridge(
            const DOM_NotationType&         theXercesDOMNotation,
            const XercesBridgeNavigator&    theNavigator) :
    XalanNotation(),
    m_xercesNode(theXercesDOMNotation),
    m_navigator(theNavigator)
{
}



XercesNotationBridge::~XercesNotationBridge()
{
}



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



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



XercesNotationBridge::NodeType
XercesNotationBridge::getNodeType() const
{
    return NOTATION_NODE;
}



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



const XalanNodeList*
XercesNotationBridge::getChildNodes() const
{
    return 0;
}



XalanNode*
XercesNotationBridge::getFirstChild() const
{
    return 0;
}



XalanNode*
XercesNotationBridge::getLastChild() const
{
    return 0;
}



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



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



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



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



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

    return theBridge;
}



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



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



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



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



bool
XercesNotationBridge::hasChildNodes() const
{
    return false;
}



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



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


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



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



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



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



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



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



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



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



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



}


#endif //XALAN_BUILD_DEPRECATED_DOM_BRIDGE 


