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



#include <cassert>



#include <xalanc/DOMSupport/DOMServices.hpp>



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



namespace XALAN_CPP_NAMESPACE {



XercesAttrBridge::XercesAttrBridge(
            const DOM_AttrType&             theXercesAttr,
            const XercesBridgeNavigator&    theNavigator) :
    XalanAttr(),
    m_xercesNode(theXercesAttr),
    m_children(theXercesAttr.getChildNodes(),
               theNavigator),
    m_navigator(theNavigator)
{
}



XercesAttrBridge::~XercesAttrBridge()
{
}



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



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



XercesAttrBridge::NodeType
XercesAttrBridge::getNodeType() const
{
    return ATTRIBUTE_NODE;
}



XalanNode*
XercesAttrBridge::getParentNode() const
{
    return 0;
}



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



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



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



XalanNode*
XercesAttrBridge::getPreviousSibling() const
{
    return 0;
}



XalanNode*
XercesAttrBridge::getNextSibling() const
{
    return 0;
}



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



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



XercesAttrBridge*
XercesAttrBridge::cloneNode(bool    deep) const
{
    assert(m_navigator.getOwnerDocument() != 0);

    XercesAttrBridge* const     theBridge =
        static_cast<XercesAttrBridge*>(m_navigator.cloneNode(this, m_xercesNode, deep));

    return theBridge;
}



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



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



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



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



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



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



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



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



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



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



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



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



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



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



const XalanDOMString&
XercesAttrBridge::getName() const
{
    return m_navigator.getPooledString(m_xercesNode.getName());
}



bool
XercesAttrBridge::getSpecified() const
{
    return m_xercesNode.getSpecified();
}



const XalanDOMString&
XercesAttrBridge::getValue() const
{
    return m_navigator.getPooledString(m_xercesNode.getValue());
}



void
XercesAttrBridge::setValue(const XalanDOMString&    value)
{
    XercesBridgeHelper::setNodeValue(m_xercesNode, value);
}



XalanElement*
XercesAttrBridge::getOwnerElement() const
{
    return m_navigator.getOwnerElement(m_xercesNode);
}



}


#endif //XALAN_BUILD_DEPRECATED_DOM_BRIDGE 


