blob: d1164925d40cbe9a2cf1796d504e1913a16629ab [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "XercesDocumentBridge.hpp"
#include <algorithm>
#include <cassert>
#include <dom/DOM_Node.hpp>
#include <dom/DOM_DOMException.hpp>
#include <Include/STLHelper.hpp>
#include <DOMSupport/DOMServices.hpp>
#include <XalanDOM/XalanDocumentType.hpp>
#include <XalanDOM/XalanElement.hpp>
#include "XercesAttrBridge.hpp"
#include "XercesBridgeHelper.hpp"
#include "XercesCommentBridge.hpp"
#include "XercesCDATASectionBridge.hpp"
#include "XercesDOM_NodeHack.hpp"
#include "XercesDOMException.hpp"
#include "XercesDOMImplementationBridge.hpp"
#include "XercesDocumentFragmentBridge.hpp"
#include "XercesDocumentTypeBridge.hpp"
#include "XercesElementBridge.hpp"
#include "XercesEntityBridge.hpp"
#include "XercesEntityReferenceBridge.hpp"
#include "XercesLiaisonXalanDOMStringPool.hpp"
#include "XercesNodeListBridge.hpp"
#include "XercesNotationBridge.hpp"
#include "XercesProcessingInstructionBridge.hpp"
#include "XercesTextBridge.hpp"
XercesDocumentBridge::XercesDocumentBridge(
const DOM_Document& theXercesDocument,
unsigned long theNumber,
bool threadSafe,
bool buildBridge) :
XalanDocument(),
m_number(theNumber),
m_xercesDocument(theXercesDocument),
m_documentElement(0),
m_nodeMap(),
m_domImplementation(new XercesDOMImplementationBridge(theXercesDocument.getImplementation())),
m_navigators(1, XercesBridgeNavigator(this, threadSafe == true ? false : !buildBridge)),
m_navigator(&m_navigators.front()),
m_children(theXercesDocument.getChildNodes(),
*m_navigator),
m_nodes(),
m_doctype(0),
m_mappingMode(threadSafe == true ? false : !buildBridge),
m_indexValid(false),
m_elementAllocator(25),
m_textAllocator(25),
m_attributeAllocator(25),
m_stringPool(threadSafe == true ? new XercesLiaisonXalanDOMStringPool : new XalanDOMStringPool)
{
#if !defined(XALAN_NO_NAMESPACES)
using std::make_pair;
#endif
if (m_mappingMode == false)
{
// The document index is always 1...
m_navigator->setIndex(1);
// OK, let's build the nodes. This makes things
// thread-safe, so the document can be shared...
buildBridgeNodes();
}
else
{
m_nodeMap.addAssociation(m_xercesDocument, this);
}
}
XercesDocumentBridge::~XercesDocumentBridge()
{
destroyBridge();
}
XalanNode*
XercesDocumentBridge::mapNode(const DOM_Node& theXercesNode) const
{
return mapNode(XercesDOM_NodeHack::getImpl(theXercesNode));
}
XalanNode*
XercesDocumentBridge::mapNode(NodeImpl* theXercesNodeImpl) const
{
XalanNode* theXalanNode = 0;
if (theXercesNodeImpl != 0)
{
theXalanNode = m_nodeMap.getNode(theXercesNodeImpl);
if (theXalanNode == 0)
{
XercesDOM_NodeHack theHack(theXercesNodeImpl);
if (theHack != m_xercesDocument &&
theHack.getOwnerDocument() != m_xercesDocument &&
theHack.getParentNode() != m_xercesDocument)
{
throw XalanDOMException(XalanDOMException::WRONG_DOCUMENT_ERR);
}
else if (m_mappingMode == true)
{
// OK, we haven't yet created a bridge not, so go ahead and
// create one.
theXalanNode = createBridgeNode(theHack, 0, true);
assert(theXalanNode != 0);
}
}
}
return theXalanNode;
}
DOM_Node
XercesDocumentBridge::mapNode(const XalanNode* theXalanNode) const
{
DOM_Node theXercesNode;
if (theXalanNode != 0)
{
theXercesNode = m_nodeMap.getNode(theXalanNode);
if (theXercesNode.isNull() == true)
{
throw XalanDOMException(XalanDOMException::WRONG_DOCUMENT_ERR);
}
}
return theXercesNode;
}
DOM_Attr
XercesDocumentBridge::mapNode(const XalanAttr* theXalanNode) const
{
NodeImpl* const theXercesNodeImpl =
mapNodeToImpl(theXalanNode);
#if defined(XALAN_OLD_STYLE_CASTS)
return XercesDOM_AttrHack((AttrImpl*)theXercesNodeImpl);
#else
return XercesDOM_AttrHack(reinterpret_cast<AttrImpl*>(theXercesNodeImpl));
#endif
}
NodeImpl*
XercesDocumentBridge::mapNodeToImpl(const XalanNode* theXalanNode) const
{
NodeImpl* theXercesNodeImpl = 0;
if (theXalanNode != 0)
{
theXercesNodeImpl = m_nodeMap.getNodeImpl(theXalanNode);
if (theXercesNodeImpl == 0)
{
throw XalanDOMException(XalanDOMException::WRONG_DOCUMENT_ERR);
}
}
return theXercesNodeImpl;
}
XalanAttr*
XercesDocumentBridge::mapNode(const DOM_Attr& theXercesNode) const
{
#if defined(XALAN_OLD_STYLE_CASTS)
return (XercesAttrBridge*)mapNode(XercesDOM_NodeHack::getImpl(theXercesNode));
#else
return static_cast<XercesAttrBridge*>(mapNode(XercesDOM_NodeHack::getImpl(theXercesNode)));
#endif
}
XalanElement*
XercesDocumentBridge::mapNode(const DOM_Element& theXercesNode) const
{
#if defined(XALAN_OLD_STYLE_CASTS)
return (XercesElementBridge*)mapNode(XercesDOM_NodeHack::getImpl(theXercesNode));
#else
return static_cast<XercesElementBridge*>(mapNode(XercesDOM_NodeHack::getImpl(theXercesNode)));
#endif
}
void
XercesDocumentBridge::destroyBridge()
{
#if !defined(XALAN_NO_NAMESPACES)
using std::for_each;
#endif
// Set this to null, since it will be deleted
// by the next for_each...
m_doctype = 0;
// m_bridgeMap contains all of the nodes that
// are still alive...
for_each(m_nodes.begin(),
m_nodes.end(),
DeleteFunctor<XalanNode>());
// Clear everything out, since we just delete everything...
m_nodes.clear();
// Clear out all of the navigators, except ours...
m_navigators.erase(m_navigators.begin() + 1, m_navigators.end());
m_navigator = &m_navigators.front();
// Clear the node map...
m_nodeMap.clear();
m_indexValid = false;
m_mappingMode = true;
m_stringPool->clear();
}
void
XercesDocumentBridge::rebuildBridge()
{
destroyBridge();
buildBridgeNodes();
}
XercesBridgeNavigator&
XercesDocumentBridge::pushNavigator(bool mappingMode) const
{
XercesDocumentBridge* const This =
#if defined(XALAN_OLD_STYLE_CASTS)
(XercesDocumentBridge*)this;
#else
const_cast<XercesDocumentBridge*>(this);
#endif
This->m_navigators.push_back(XercesBridgeNavigator(This, mappingMode));
return This->m_navigators.back();
}
XercesDocumentTypeBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_DocumentType& theDoctype,
unsigned long theIndex,
bool mapNode) const
{
// This is a special case, since there is only one
// doctype node allowed...
assert(m_doctype == 0);
assert(m_xercesDocument.getDoctype().isNull() == false &&
m_xercesDocument.getDoctype() == theDoctype);
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
// Update the member variable for the new instance.
This->m_doctype = new XercesDocumentTypeBridge(theDoctype, theNavigator);
if (mapNode == true)
{
This->m_nodeMap.addAssociation(theDoctype, m_doctype);
}
This->m_nodes.push_back(m_doctype);
return m_doctype;
}
XercesElementBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Element& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
XercesElementBridge* const theBridge =
This->m_elementAllocator.create(theXercesNode,
theNavigator);
if (m_doctype != 0 || mapNode == true)
{
// Add it to the node map, since we my need it for getting
// elements by ID, or we're in mapping mode.
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesDocumentFragmentBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_DocumentFragment& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesDocumentFragmentBridge* const theBridge =
new XercesDocumentFragmentBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesTextBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Text& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
XercesTextBridge* const theBridge =
This->m_textAllocator.create(theXercesNode,
theNavigator);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesCommentBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Comment& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesCommentBridge* const theBridge =
new XercesCommentBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesCDATASectionBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_CDATASection& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesCDATASectionBridge* const theBridge =
new XercesCDATASectionBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesProcessingInstructionBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_ProcessingInstruction& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesProcessingInstructionBridge* const theBridge =
new XercesProcessingInstructionBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesAttrBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Attr& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
XercesAttrBridge* const theBridge =
This->m_attributeAllocator.create(theXercesNode,
theNavigator);
// Add it to the node map -- attributes ALWAYS go in the map
// for now...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
return theBridge;
}
XercesEntityBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Entity& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesEntityBridge* const theBridge =
new XercesEntityBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
// Add it to the node map -- entities ALWAYS go in the map
// for now...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
return theBridge;
}
XercesEntityReferenceBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_EntityReference& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesEntityReferenceBridge* const theBridge =
new XercesEntityReferenceBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
if (mapNode == true)
{
// Add it to the node map...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
}
return theBridge;
}
XercesNotationBridge*
XercesDocumentBridge::createBridgeNode(
const DOM_Notation& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
// Create a navigator...
XercesBridgeNavigator& theNavigator = pushNavigator(mapNode);
theNavigator.setIndex(theIndex);
XercesNotationBridge* const theBridge =
new XercesNotationBridge(theXercesNode,
theNavigator);
#if defined(XALAN_NO_MUTABLE)
XercesDocumentBridge* const This =
(XercesDocumentBridge*)this;
#else
const XercesDocumentBridge* const This =
this;
#endif
This->m_nodes.push_back(theBridge);
// Add it to the node map -- notations ALWAYS go in the map
// for now...
This->m_nodeMap.addAssociation(theXercesNode, theBridge);
return theBridge;
}
XalanNode*
XercesDocumentBridge::createBridgeNode(
const DOM_Node& theXercesNode,
unsigned long theIndex,
bool mapNode) const
{
XalanNode* theNewNode = 0;
switch(theXercesNode.getNodeType())
{
case DOM_Node::ATTRIBUTE_NODE:
{
const DOM_Attr& theAttrNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Attr&)theXercesNode;
#else
static_cast<const DOM_Attr&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theAttrNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::CDATA_SECTION_NODE:
{
const DOM_CDATASection& theCDATASectionNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_CDATASection&)theXercesNode;
#else
static_cast<const DOM_CDATASection&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theCDATASectionNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::COMMENT_NODE:
{
const DOM_Comment& theCommentNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Comment&)theXercesNode;
#else
static_cast<const DOM_Comment&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theCommentNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::DOCUMENT_FRAGMENT_NODE:
{
const DOM_DocumentFragment& theDocumentFragmentNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_DocumentFragment&)theXercesNode;
#else
static_cast<const DOM_DocumentFragment&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theDocumentFragmentNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::ELEMENT_NODE:
{
const DOM_Element& theElementNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Element&)theXercesNode;
#else
static_cast<const DOM_Element&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theElementNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::ENTITY_NODE:
{
const DOM_Entity& theEntityNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Entity&)theXercesNode;
#else
static_cast<const DOM_Entity&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theEntityNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::ENTITY_REFERENCE_NODE:
{
const DOM_EntityReference& theEntityReferenceNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_EntityReference&)theXercesNode;
#else
static_cast<const DOM_EntityReference&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theEntityReferenceNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::NOTATION_NODE:
{
const DOM_Notation& theNotationNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Notation&)theXercesNode;
#else
static_cast<const DOM_Notation&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theNotationNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::PROCESSING_INSTRUCTION_NODE:
{
const DOM_ProcessingInstruction& thePINode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_ProcessingInstruction&)theXercesNode;
#else
static_cast<const DOM_ProcessingInstruction&>(theXercesNode);
#endif
theNewNode = createBridgeNode(thePINode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::TEXT_NODE:
{
const DOM_Text& theTextNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Text&)theXercesNode;
#else
static_cast<const DOM_Text&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theTextNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
case DOM_Node::DOCUMENT_TYPE_NODE:
{
const DOM_DocumentType& theDoctypeNode =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_DocumentType&)theXercesNode;
#else
static_cast<const DOM_DocumentType&>(theXercesNode);
#endif
theNewNode = createBridgeNode(theDoctypeNode, theIndex, mapNode);
assert(theNewNode != 0);
}
break;
default:
assert(false);
break;
}
return theNewNode;
}
void
XercesDocumentBridge::destroyNode(XalanNode* theNode)
{
#if !defined(XALAN_NO_NAMESPACES)
using std::find;
#endif
const NodeVectorType::iterator i =
find(m_nodes.begin(), m_nodes.end(), theNode);
if (i == m_nodes.end())
{
// Doesn't belong to this doc, so throw...
throw XercesDOMException(XercesDOMException::WRONG_DOCUMENT_ERR);
}
else
{
// Delete the node...
delete *i;
// Erase it from the map...
m_nodes.erase(i);
}
}
XalanNode*
XercesDocumentBridge::internalCloneNode(
const XalanNode* theXalanNode,
const DOM_Node& theXercesNode,
bool deep)
{
XalanNode* theNewNode = 0;
if (theXalanNode->getOwnerDocument() != this)
{
throw XercesDOMException(XercesDOMException::WRONG_DOCUMENT_ERR);
}
try
{
const DOM_Node theNewXercesNode =
theXercesNode.cloneNode(deep);
theNewNode = createBridgeNode(theNewXercesNode, 0, true);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theNewNode;
}
const XalanDOMString&
XercesDocumentBridge::getNodeName() const
{
assert(m_navigator != 0);
return m_navigator->getPooledString(m_xercesDocument.getNodeName());
}
const XalanDOMString&
XercesDocumentBridge::getNodeValue() const
{
assert(m_navigator != 0);
return m_navigator->getPooledString(m_xercesDocument.getNodeValue());
}
XercesDocumentBridge::NodeType
XercesDocumentBridge::getNodeType() const
{
return DOCUMENT_NODE;
}
XalanNode*
XercesDocumentBridge::getParentNode() const
{
return 0;
}
const XalanNodeList*
XercesDocumentBridge::getChildNodes() const
{
return &m_children;
}
XalanNode*
XercesDocumentBridge::getFirstChild() const
{
assert(m_navigator != 0);
return m_navigator->getFirstChild(m_xercesDocument);
}
XalanNode*
XercesDocumentBridge::getLastChild() const
{
assert(m_navigator != 0);
return m_navigator->getLastChild(m_xercesDocument);
}
XalanNode*
XercesDocumentBridge::getPreviousSibling() const
{
return 0;
}
XalanNode*
XercesDocumentBridge::getNextSibling() const
{
return 0;
}
const XalanNamedNodeMap*
XercesDocumentBridge::getAttributes() const
{
return 0;
}
XalanDocument*
XercesDocumentBridge::getOwnerDocument() const
{
return 0;
}
#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
XalanNode*
#else
XercesDocumentBridge*
#endif
XercesDocumentBridge::cloneNode(bool deep) const
{
XercesDocumentBridge* theBridge = 0;
try
{
const DOM_Node theNewDocument = m_xercesDocument.cloneNode(deep);
theBridge =
#if defined(XALAN_OLD_STYLE_CASTS)
new XercesDocumentBridge((const DOM_Document&)theNewDocument);
#else
new XercesDocumentBridge(static_cast<const DOM_Document&>(theNewDocument));
#endif
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridge;
}
XalanNode*
XercesDocumentBridge::insertBefore(
XalanNode* newChild,
XalanNode* refChild)
{
assert(m_navigator != 0);
return m_navigator->insertBefore(m_xercesDocument, newChild, refChild);
}
XalanNode*
XercesDocumentBridge::replaceChild(
XalanNode* newChild,
XalanNode* oldChild)
{
assert(m_navigator != 0);
return m_navigator->replaceChild(m_xercesDocument, newChild, oldChild);
}
XalanNode*
XercesDocumentBridge::removeChild(XalanNode* oldChild)
{
assert(m_navigator != 0);
return m_navigator->removeChild(m_xercesDocument, oldChild);
}
XalanNode*
XercesDocumentBridge::appendChild(XalanNode* newChild)
{
assert(m_navigator != 0);
return m_navigator->appendChild(m_xercesDocument, newChild);
}
bool
XercesDocumentBridge::hasChildNodes() const
{
return m_xercesDocument.hasChildNodes();
}
void
XercesDocumentBridge::setNodeValue(const XalanDOMString& nodeValue)
{
XercesBridgeHelper::setNodeValue(m_xercesDocument, nodeValue);
}
void
XercesDocumentBridge::normalize()
{
XercesBridgeHelper::normalize(m_xercesDocument);
}
bool
XercesDocumentBridge::supports(
const XalanDOMString& feature,
const XalanDOMString& version) const
{
return m_xercesDocument.supports(
XercesBridgeHelper::XalanDOMStringToXercesDOMString(feature),
XercesBridgeHelper::XalanDOMStringToXercesDOMString(version));
}
const XalanDOMString&
XercesDocumentBridge::getNamespaceURI() const
{
assert(m_navigator != 0);
return m_navigator->getPooledString(m_xercesDocument.getNamespaceURI());
}
const XalanDOMString&
XercesDocumentBridge::getPrefix() const
{
assert(m_navigator != 0);
return m_navigator->getPooledString(m_xercesDocument.getPrefix());
}
const XalanDOMString&
XercesDocumentBridge::getLocalName() const
{
assert(m_navigator != 0);
return m_navigator->getPooledString(m_xercesDocument.getLocalName());
}
void
XercesDocumentBridge::setPrefix(const XalanDOMString& prefix)
{
XercesBridgeHelper::setPrefix(m_xercesDocument, prefix);
}
bool
XercesDocumentBridge::isIndexed() const
{
return m_indexValid;
}
unsigned long
XercesDocumentBridge::getIndex() const
{
assert(m_navigator != 0);
assert(m_navigator->getIndex() == 1);
return m_navigator->getIndex();
}
XalanElement*
XercesDocumentBridge::createElement(const XalanDOMString& tagName)
{
XalanElement* theBridgeNode = 0;
try
{
const DOM_Element theXercesNode =
m_xercesDocument.createElement(c_wstr(tagName));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanDocumentFragment*
XercesDocumentBridge::createDocumentFragment()
{
XalanDocumentFragment* theBridgeNode = 0;
try
{
const DOM_DocumentFragment theXercesNode =
m_xercesDocument.createDocumentFragment();
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanText*
XercesDocumentBridge::createTextNode(const XalanDOMString& data)
{
XalanText* theBridgeNode = 0;
try
{
const DOM_Text theXercesNode =
m_xercesDocument.createTextNode(c_wstr(data));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanComment*
XercesDocumentBridge::createComment(const XalanDOMString& data)
{
XalanComment* theBridgeNode = 0;
try
{
const DOM_Comment theXercesNode =
m_xercesDocument.createComment(c_wstr(data));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanCDATASection*
XercesDocumentBridge::createCDATASection(const XalanDOMString& data)
{
XalanCDATASection* theBridgeNode = 0;
try
{
const DOM_CDATASection theXercesNode =
m_xercesDocument.createCDATASection(c_wstr(data));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanProcessingInstruction*
XercesDocumentBridge::createProcessingInstruction(
const XalanDOMString& target,
const XalanDOMString& data)
{
XalanProcessingInstruction* theBridgeNode = 0;
try
{
const DOM_ProcessingInstruction theXercesNode =
m_xercesDocument.createProcessingInstruction(c_wstr(target), c_wstr(data));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanAttr*
XercesDocumentBridge::createAttribute(const XalanDOMString& name)
{
XalanAttr* theBridgeNode = 0;
try
{
const DOM_Attr theXercesNode =
m_xercesDocument.createAttribute(c_wstr(name));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanEntityReference*
XercesDocumentBridge::createEntityReference(const XalanDOMString& name)
{
XalanEntityReference* theBridgeNode = 0;
try
{
const DOM_EntityReference theXercesNode =
m_xercesDocument.createEntityReference(c_wstr(name));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanDocumentType*
XercesDocumentBridge::getDoctype() const
{
return m_doctype;
}
XalanDOMImplementation*
XercesDocumentBridge::getImplementation() const
{
return m_domImplementation.get();
}
XalanElement*
XercesDocumentBridge::getDocumentElement() const
{
// If we're working in mapping mode, m_documentElement will
// be null, so we'll have to map the node...
return m_documentElement != 0 ? m_documentElement : mapNode(m_xercesDocument.getDocumentElement());
}
XalanNodeList*
XercesDocumentBridge::getElementsByTagName(const XalanDOMString& /* tagname */) const
{
// Not supported
return 0;
}
XalanNode*
XercesDocumentBridge::importNode(
XalanNode* importedNode,
bool deep)
{
// $$$ToDo: Fix this...
// The problem is that we must get the Xerces node that corresponds to the
// importedNode parameter. We could assume that it is indeed a node from
// another XercesDocumentBridge, but I'm not sure that we should do that.
throw XercesDOMException(XercesDOMException::NOT_SUPPORTED_ERR);
return 0;
}
XalanElement*
XercesDocumentBridge::createElementNS(
const XalanDOMString& namespaceURI,
const XalanDOMString& qualifiedName)
{
XalanElement* theBridgeNode = 0;
try
{
const DOM_Element theXercesNode =
m_xercesDocument.createElementNS(c_wstr(namespaceURI), c_wstr(qualifiedName));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanAttr*
XercesDocumentBridge::createAttributeNS(
const XalanDOMString& namespaceURI,
const XalanDOMString& qualifiedName)
{
XalanAttr* theBridgeNode = 0;
try
{
const DOM_Attr theXercesNode =
m_xercesDocument.createAttributeNS(c_wstr(namespaceURI), c_wstr(qualifiedName));
assert(theXercesNode.isNull() == false);
theBridgeNode = createBridgeNode(theXercesNode, 0, true);
assert(mapNode(theXercesNode) == theBridgeNode);
}
catch(const DOM_DOMException& theException)
{
throw XercesDOMException(theException);
}
return theBridgeNode;
}
XalanNodeList*
XercesDocumentBridge::getElementsByTagNameNS(
const XalanDOMString& /* namespaceURI */,
const XalanDOMString& /* localName */) const
{
// Not supported
return 0;
}
XalanElement*
XercesDocumentBridge::getElementById(const XalanDOMString& elementId) const
{
// $$$ ToDo: This is because DOM_Document::getElementById() is not
// const...
#if defined(XALAN_NO_MUTABLE)
const DOM_Node theXercesNode(((DOM_Document&)m_xercesDocument).getElementById(c_wstr(elementId)));
#else
const DOM_Node theXercesNode(m_xercesDocument.getElementById(c_wstr(elementId)));
#endif
return theXercesNode.isNull() == true ? 0 :
#if defined(XALAN_OLD_STYLE_CASTS)
(XalanElement*)mapNode(theXercesNode);
#else
static_cast<XalanElement*>(mapNode(theXercesNode));
#endif
}
unsigned long
XercesDocumentBridge::getNumber() const
{
return m_number;
}
void
XercesDocumentBridge::buildBridgeNodes()
{
const DOM_Node theStartChild = m_xercesDocument.getFirstChild();
if (theStartChild.isNull() == false)
{
assert(m_navigator != 0);
assert(m_navigators.size() == 1);
m_navigator->setIndex(1);
m_navigator->setFirstChild(0);
BuildBridgeTreeWalker theTreeWalker(
this,
&m_navigators.back(),
m_navigators,
2);
theTreeWalker.traverse(theStartChild, m_xercesDocument);
}
// OK, now set m_documentElement...
XalanNode* theChild = m_navigator->getFirstChild();
while(theChild != 0 && theChild->getNodeType() != XalanNode::ELEMENT_NODE)
{
theChild = theChild->getNextSibling();
}
#if defined(XALAN_OLD_STYLE_CASTS)
m_documentElement = (XalanElement*)theChild;
#else
m_documentElement = static_cast<XalanElement*>(theChild);
#endif
m_indexValid = true;
m_mappingMode = false;
}
XercesDocumentBridge::BuildBridgeTreeWalker::BuildBridgeTreeWalker(
XercesDocumentBridge* theDocument,
XercesBridgeNavigator* theDocumentNavigator,
NavigatorBridgeVectorType& theNavigators,
unsigned long theStartIndex) :
m_document(theDocument),
m_navigators(theNavigators),
m_currentIndex(theStartIndex),
m_parentNavigatorStack(),
m_siblingNavigatorStack()
{
assert(theDocument != 0 && theDocumentNavigator != 0);
// Reserve some space...
m_parentNavigatorStack.reserve(100);
m_parentNavigatorStack.reserve(100);
// The document navigator is the last navigator on the stack...
m_parentNavigatorStack.push_back(NavigatorStackEntryType(theDocumentNavigator, theDocument));
// There is no previous sibling...
m_siblingNavigatorStack.push_back(NavigatorStackEntryType(0, 0));
}
XercesDocumentBridge::BuildBridgeTreeWalker::~BuildBridgeTreeWalker()
{
}
void
XercesDocumentBridge::BuildBridgeTreeWalker::startNode(const DOM_Node& node)
{
XalanNode* const theBridgeNode = m_document->createBridgeNode(node, m_currentIndex, false);
XercesBridgeNavigator& theCurrentNodeNavigator = m_navigators.back();
assert(m_parentNavigatorStack.empty() == false);
assert(m_siblingNavigatorStack.empty() == false);
// Get the two navigators...
NavigatorStackEntryType& theParentEntry = m_parentNavigatorStack.back();
NavigatorStackEntryType& theSiblingEntry = m_siblingNavigatorStack.back();
theCurrentNodeNavigator.setParentNode(theParentEntry.m_node);
// If the first child has not been set, then set it
// now...
if (theParentEntry.m_navigator->getFirstChild() == 0)
{
assert(theSiblingEntry.m_node == 0);
theParentEntry.m_navigator->setFirstChild(theBridgeNode);
}
// Always set the last child...
theParentEntry.m_navigator->setLastChild(theBridgeNode);
theCurrentNodeNavigator.setPreviousSibling(theSiblingEntry.m_node);
if (theSiblingEntry.m_navigator != 0)
{
theSiblingEntry.m_navigator->setNextSibling(theBridgeNode);
}
// Build an entry for the stacks...
const NavigatorStackEntryType theCurrentEntry(&theCurrentNodeNavigator, theBridgeNode);
// My child nodes will now be visited, so push the current
// context on the parent stack...
m_parentNavigatorStack.push_back(theCurrentEntry);
// My siblings will also need to know about me as well...
m_siblingNavigatorStack.push_back(theCurrentEntry);
// This will serve to mark the sibling context for my first child,
// since it has no previous sibling. This will be popped off
// when endNode() is called.
m_siblingNavigatorStack.push_back(NavigatorStackEntryType(0, 0));
// Finally, increment the index counter...
++m_currentIndex;
const short theType = node.getNodeType();
if (theType == DOM_Node::DOCUMENT_TYPE_NODE)
{
// Special case for doctype -- we have to build its entities...
const DOM_DocumentType& theDoctype =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_DocumentType&)node;
#else
static_cast<const DOM_DocumentType&>(node);
#endif
const DOM_NamedNodeMap theEntities =
theDoctype.getEntities();
const unsigned int theLength =
theEntities.getLength();
for (unsigned int i = 0; i < theLength; ++i)
{
// Build it, but don't index it...
m_document->createBridgeNode(theEntities.item(i), m_currentIndex++, true);
}
}
else if (theType == DOM_Node::ELEMENT_NODE)
{
// Special case for element nodes -- we have to build the attributes...
const DOM_Element& theElement =
#if defined(XALAN_OLD_STYLE_CASTS)
(const DOM_Element&)node;
#else
static_cast<const DOM_Element&>(node);
#endif
const DOM_NamedNodeMap theAttributes =
theElement.getAttributes();
const unsigned int theLength =
theAttributes.getLength();
XercesBridgeNavigator* thePreviousAttrNavigator = 0;
XalanNode* thePreviousAttr = 0;
for (unsigned int i = 0; i < theLength; ++i)
{
// Get the attribute from the node map...
const DOM_Node theAttr = theAttributes.item(i);
assert(theAttr.isNull() == false);
// Create a bridge node.
XalanNode* const theCurrentAttr =
m_document->createBridgeNode(theAttr, m_currentIndex, false);
assert(theCurrentAttr != 0);
// Get the attribute node's navigator...
XercesBridgeNavigator& theCurrentAttrNavigator =
m_navigators.back();
// Set the parent node...
theCurrentAttrNavigator.setParentNode(theBridgeNode);
if (thePreviousAttr != 0)
{
assert(thePreviousAttrNavigator != 0);
// Link in the previous attribute...
theCurrentAttrNavigator.setPreviousSibling(thePreviousAttr);
thePreviousAttrNavigator->setNextSibling(theCurrentAttr);
}
// Update the pointers so they point to this attribute...
thePreviousAttr = theCurrentAttr;
thePreviousAttrNavigator = &theCurrentAttrNavigator;
// Finally, increment the index...
++m_currentIndex;
}
}
}
void
XercesDocumentBridge::BuildBridgeTreeWalker::endNode(const DOM_Node& /* node */)
{
assert(m_parentNavigatorStack.empty() == false);
assert(m_siblingNavigatorStack.empty() == false);
// I have to pop my entry, since my children are finished...
m_parentNavigatorStack.pop_back();
// Pop any sibling navigators my child pushed...
while(m_siblingNavigatorStack.back().m_navigator != 0)
{
assert(m_siblingNavigatorStack.back().m_node != 0);
m_siblingNavigatorStack.pop_back();
}
// There must be a context marker...
assert(m_siblingNavigatorStack.back().m_navigator == 0 &&
m_siblingNavigatorStack.back().m_node == 0);
// Pop the context marker...
m_siblingNavigatorStack.pop_back();
}
const XalanDOMString&
XercesDocumentBridge::getPooledString(const XalanDOMString& theString) const
{
return m_stringPool->get(theString);
}
const XalanDOMString&
XercesDocumentBridge::getPooledString(
const XalanDOMChar* theString,
XalanDOMString::size_type theLength) const
{
return m_stringPool->get(theString, theLength);
}