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



#include <xalanc/DOMSupport/DOMServices.hpp>



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



namespace XALAN_CPP_NAMESPACE {



XercesCommentBridge::XercesCommentBridge(
            const DOM_CommentType&          theXercesComment,
            const XercesBridgeNavigator&    theNavigator) :
    XalanComment(),
    m_xercesNode(theXercesComment),
    m_navigator(theNavigator)
{
}



XercesCommentBridge::~XercesCommentBridge()
{
}



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



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



XercesCommentBridge::NodeType
XercesCommentBridge::getNodeType() const
{
    return COMMENT_NODE;
}



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



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



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



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



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



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



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



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



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

    return theBridge;
}



XalanNode*
XercesCommentBridge::insertBefore(
            XalanNode*  /* newChild */,
            XalanNode*  /* refChild */)
{
    throw XercesDOMException(XercesDOMException::HIERARCHY_REQUEST_ERR);

    return 0;
}



XalanNode*
XercesCommentBridge::replaceChild(
            XalanNode*  /* newChild */,
            XalanNode*  /* oldChild */)
{
    throw XercesDOMException(XercesDOMException::HIERARCHY_REQUEST_ERR);

    return 0;
}



XalanNode*
XercesCommentBridge::removeChild(XalanNode* /* oldChild */)
{
    throw XercesDOMException(XercesDOMException::HIERARCHY_REQUEST_ERR);

    return 0;
}



XalanNode*
XercesCommentBridge::appendChild(XalanNode*  /* newChild */)
{
    throw XercesDOMException(XercesDOMException::HIERARCHY_REQUEST_ERR);

    return 0;
}



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



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



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


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



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



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



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



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



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



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



const XalanDOMString&
XercesCommentBridge::getData() const
{
    return m_navigator.getPooledString(m_xercesNode.getData());
}



unsigned int
XercesCommentBridge::getLength() const
{
    return m_xercesNode.getLength();
}



XalanDOMString
XercesCommentBridge::substringData(
            unsigned int    offset, 
            unsigned int    count) const
{
    return XercesBridgeHelper::substringData(m_xercesNode, offset, count);
}



void
XercesCommentBridge::appendData(const XalanDOMString&   arg)
{
    XercesBridgeHelper::appendData(m_xercesNode, arg);
}



void
XercesCommentBridge::insertData(
            unsigned int            offset,
            const  XalanDOMString&  arg)
{
    XercesBridgeHelper::insertData(m_xercesNode, offset, arg);
}



void
XercesCommentBridge::deleteData(
            unsigned int    offset, 
            unsigned int    count)
{
    XercesBridgeHelper::deleteData(m_xercesNode, offset, count);
}



void
XercesCommentBridge::replaceData(
            unsigned int            offset, 
            unsigned int            count, 
            const XalanDOMString&   arg)
{
    XercesBridgeHelper::replaceData(m_xercesNode, offset, count, arg);
}



}


#endif //XALAN_BUILD_DEPRECATED_DOM_BRIDGE 


