blob: 30abe3a1146fde70d70e0f79fa890c68da999974 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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.
*/
// Class header file...
#include "XPathExecutionContextDefault.hpp"
#include <xercesc/sax/Locator.hpp>
#include <xalanc/Include/STLHelper.hpp>
#include <xalanc/PlatformSupport/PrefixResolver.hpp>
#include <xalanc/PlatformSupport/XalanLocator.hpp>
#include <xalanc/PlatformSupport/DoubleSupport.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanDecimalFormatSymbols.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/DOMSupport/DOMSupport.hpp>
#include "XObjectFactory.hpp"
#include "XalanQName.hpp"
#include "XPathEnvSupport.hpp"
XALAN_CPP_NAMESPACE_BEGIN
const NodeRefList XPathExecutionContextDefault::s_dummyList;
XPathExecutionContextDefault::XPathExecutionContextDefault(
XPathEnvSupport& theXPathEnvSupport,
DOMSupport& theDOMSupport,
XObjectFactory& theXObjectFactory,
XalanNode* theCurrentNode,
const NodeRefListBase* theContextNodeList,
const PrefixResolver* thePrefixResolver) :
XPathExecutionContext(&theXObjectFactory),
m_xpathEnvSupport(&theXPathEnvSupport),
m_domSupport(&theDOMSupport),
m_currentNodeStack(),
m_contextNodeListStack(),
m_prefixResolver(thePrefixResolver),
m_nodeListCache(eNodeListCacheListSize),
m_stringCache(),
m_cachedPosition(),
m_scratchQName()
{
m_currentNodeStack.push_back(theCurrentNode);
m_contextNodeListStack.push_back(theContextNodeList == 0 ? &s_dummyList : theContextNodeList);
}
XPathExecutionContextDefault::XPathExecutionContextDefault(
XalanNode* theCurrentNode,
const NodeRefListBase* theContextNodeList,
const PrefixResolver* thePrefixResolver) :
XPathExecutionContext(),
m_xpathEnvSupport(0),
m_domSupport(0),
m_currentNodeStack(),
m_contextNodeListStack(),
m_prefixResolver(thePrefixResolver),
m_nodeListCache(eNodeListCacheListSize),
m_stringCache(),
m_cachedPosition(),
m_scratchQName()
{
m_currentNodeStack.push_back(theCurrentNode);
m_contextNodeListStack.push_back(theContextNodeList == 0 ? &s_dummyList : theContextNodeList);
}
XPathExecutionContextDefault::~XPathExecutionContextDefault()
{
reset();
}
void
XPathExecutionContextDefault::reset()
{
if (m_xpathEnvSupport != 0)
{
m_xpathEnvSupport->reset();
}
if (m_domSupport != 0)
{
m_domSupport->reset();
}
if (m_xobjectFactory != 0)
{
m_xobjectFactory->reset();
}
m_currentNodeStack.clear();
m_currentNodeStack.push_back(0);
m_contextNodeListStack.clear();
m_contextNodeListStack.push_back(&s_dummyList);
m_prefixResolver = 0;
m_nodeListCache.reset(),
m_stringCache.reset();
m_cachedPosition.clear();
}
XalanNode*
XPathExecutionContextDefault::getCurrentNode() const
{
assert(m_currentNodeStack.empty() == false);
return m_currentNodeStack.back();
}
void
XPathExecutionContextDefault::pushCurrentNode(XalanNode* theCurrentNode)
{
m_currentNodeStack.push_back(theCurrentNode);
}
void
XPathExecutionContextDefault::popCurrentNode()
{
assert(m_currentNodeStack.empty() == false);
m_currentNodeStack.pop_back();
}
bool
XPathExecutionContextDefault::isNodeAfter(
const XalanNode& node1,
const XalanNode& node2) const
{
return m_domSupport->isNodeAfter(node1, node2);
}
void
XPathExecutionContextDefault::pushContextNodeList(const NodeRefListBase& theList)
{
m_cachedPosition.clear();
m_contextNodeListStack.push_back(&theList);
}
void
XPathExecutionContextDefault::popContextNodeList()
{
m_cachedPosition.clear();
m_contextNodeListStack.pop_back();
}
const NodeRefListBase&
XPathExecutionContextDefault::getContextNodeList() const
{
assert(m_contextNodeListStack.empty() == false);
return *m_contextNodeListStack.back();
}
XPathExecutionContextDefault::size_type
XPathExecutionContextDefault::getContextNodeListLength() const
{
assert(m_contextNodeListStack.empty() == false);
return m_contextNodeListStack.back()->getLength();
}
XPathExecutionContextDefault::size_type
XPathExecutionContextDefault::getContextNodeListPosition(const XalanNode& contextNode) const
{
assert(m_contextNodeListStack.empty() == false);
if (m_cachedPosition.m_node == &contextNode)
{
assert((m_cachedPosition.m_index == 0 && m_contextNodeListStack.back()->indexOf(&contextNode) == NodeRefListBase::npos) ||
(m_contextNodeListStack.back()->indexOf(&contextNode) + 1 == m_cachedPosition.m_index));
}
else
{
// Get the index of the node...
const size_type theIndex = m_contextNodeListStack.back()->indexOf(&contextNode);
// If not found, it's 0. Otherwise, it's the index + 1
#if defined(XALAN_NO_MUTABLE)
((XPathExecutionContextDefault*)this)->m_cachedPosition.m_index = theIndex == NodeRefListBase::npos ? 0 : theIndex + 1;
((XPathExecutionContextDefault*)this)->m_cachedPosition.m_node = &contextNode;
#else
m_cachedPosition.m_index = theIndex == NodeRefListBase::npos ? 0 : theIndex + 1;
m_cachedPosition.m_node = &contextNode;
#endif
}
return m_cachedPosition.m_index;
}
bool
XPathExecutionContextDefault::elementAvailable(const XalanQName& theQName) const
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->elementAvailable(theQName.getNamespace(), theQName.getLocalPart());
}
bool
XPathExecutionContextDefault::elementAvailable(
const XalanDOMString& theName,
const LocatorType* theLocator) const
{
assert(m_xpathEnvSupport != 0);
XalanQNameByValue& theQName = getScratchQName();
theQName.set(theName, m_prefixResolver, theLocator);
return elementAvailable(m_scratchQName);
}
bool
XPathExecutionContextDefault::functionAvailable(const XalanQName& theQName) const
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->functionAvailable(theQName.getNamespace(), theQName.getLocalPart());
}
bool
XPathExecutionContextDefault::functionAvailable(
const XalanDOMString& theName,
const LocatorType* theLocator) const
{
assert(m_xpathEnvSupport != 0);
XalanQNameByValue& theQName = getScratchQName();
theQName.set(theName, m_prefixResolver, theLocator);
return functionAvailable(theQName);
}
const XObjectPtr
XPathExecutionContextDefault::extFunction(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
XalanNode* context,
const XObjectArgVectorType& argVec,
const LocatorType* locator)
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->extFunction(*this, theNamespace, functionName, context, argVec, locator);
}
XalanDocument*
XPathExecutionContextDefault::parseXML(
const XalanDOMString& urlString,
const XalanDOMString& base) const
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->parseXML(urlString, base);
}
MutableNodeRefList*
XPathExecutionContextDefault::borrowMutableNodeRefList()
{
return m_nodeListCache.get();
}
bool
XPathExecutionContextDefault::returnMutableNodeRefList(MutableNodeRefList* theList)
{
return m_nodeListCache.release(theList);
}
MutableNodeRefList*
XPathExecutionContextDefault::createMutableNodeRefList() const
{
return new MutableNodeRefList;
}
XalanDOMString&
XPathExecutionContextDefault::getCachedString()
{
return m_stringCache.get();
}
bool
XPathExecutionContextDefault::releaseCachedString(XalanDOMString& theString)
{
return m_stringCache.release(theString);
}
void
XPathExecutionContextDefault::getNodeSetByKey(
XalanDocument* /* doc */,
const XalanQName& /* qname */,
const XalanDOMString& /* ref */,
MutableNodeRefList& /* nodelist */)
{
}
void
XPathExecutionContextDefault::getNodeSetByKey(
XalanDocument* /* doc */,
const XalanDOMString& /* name */,
const XalanDOMString& /* ref */,
const LocatorType* /* locator */,
MutableNodeRefList& /* nodelist */)
{
}
const XObjectPtr
XPathExecutionContextDefault::getVariable(
const XalanQName& name,
const LocatorType* /* locator */)
{
assert(m_xobjectFactory != 0);
return m_xobjectFactory->createUnknown(name.getLocalPart());
}
const PrefixResolver*
XPathExecutionContextDefault::getPrefixResolver() const
{
return m_prefixResolver;
}
void
XPathExecutionContextDefault::setPrefixResolver(const PrefixResolver* thePrefixResolver)
{
m_prefixResolver = thePrefixResolver;
}
const XalanDOMString*
XPathExecutionContextDefault::getNamespaceForPrefix(const XalanDOMString& prefix) const
{
assert(m_prefixResolver != 0);
return m_prefixResolver->getNamespaceForPrefix(prefix);
}
XalanDOMString
XPathExecutionContextDefault::findURIFromDoc(const XalanDocument* owner) const
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->findURIFromDoc(owner);
}
const XalanDOMString&
XPathExecutionContextDefault::getUnparsedEntityURI(
const XalanDOMString& theName,
const XalanDocument& theDocument) const
{
return m_domSupport->getUnparsedEntityURI(theName, theDocument);
}
bool
XPathExecutionContextDefault::shouldStripSourceNode(const XalanText& /* node */)
{
return false;
}
void
XPathExecutionContextDefault::error(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const LocatorType* locator) const
{
assert(m_xpathEnvSupport != 0);
XalanLocator::size_type lineNumber = XalanLocator::getUnknownValue();
XalanLocator::size_type columnNumber = XalanLocator::getUnknownValue();
XalanDOMString uri;
if (locator != 0)
{
lineNumber = locator->getLineNumber();
columnNumber = locator->getColumnNumber();
const XalanDOMChar* id =
locator->getPublicId();
if (id != 0)
{
uri = id;
}
else
{
id = locator->getSystemId();
if (id != 0)
{
uri = id;
}
}
}
if (m_xpathEnvSupport->problem(
XPathEnvSupport::eXPATHProcessor,
XPathEnvSupport::eError,
m_prefixResolver,
sourceNode,
msg,
c_wstr(uri),
lineNumber,
columnNumber) == true)
{
throw XalanXPathException(msg, uri, lineNumber, columnNumber);
}
}
void
XPathExecutionContextDefault::warn(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const LocatorType* locator) const
{
assert(m_xpathEnvSupport != 0);
XalanLocator::size_type lineNumber = XalanLocator::getUnknownValue();
XalanLocator::size_type columnNumber = XalanLocator::getUnknownValue();
XalanDOMString uri;
if (locator != 0)
{
lineNumber = locator->getLineNumber();
columnNumber = locator->getColumnNumber();
const XalanDOMChar* id =
locator->getPublicId();
if (id != 0)
{
uri = id;
}
else
{
id = locator->getSystemId();
if (id != 0)
{
uri = id;
}
}
}
if (m_xpathEnvSupport->problem(
XPathEnvSupport::eXPATHProcessor,
XPathEnvSupport::eWarning,
m_prefixResolver,
sourceNode,
msg,
c_wstr(uri),
lineNumber,
columnNumber) == true)
{
throw XalanXPathException(msg, uri, lineNumber, columnNumber);
}
}
void
XPathExecutionContextDefault::message(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const LocatorType* locator) const
{
assert(m_xpathEnvSupport != 0);
XalanLocator::size_type lineNumber = XalanLocator::getUnknownValue();
XalanLocator::size_type columnNumber = XalanLocator::getUnknownValue();
XalanDOMString uri;
if (locator != 0)
{
lineNumber = locator->getLineNumber();
columnNumber = locator->getColumnNumber();
const XalanDOMChar* id =
locator->getPublicId();
if (id != 0)
{
uri = id;
}
else
{
id = locator->getSystemId();
if (id != 0)
{
uri = id;
}
}
}
if (m_xpathEnvSupport->problem(
XPathEnvSupport::eXPATHProcessor,
XPathEnvSupport::eMessage,
m_prefixResolver,
sourceNode,
msg,
c_wstr(uri),
lineNumber,
columnNumber) == true)
{
throw XalanXPathException(msg, uri, lineNumber, columnNumber);
}
}
XalanDocument*
XPathExecutionContextDefault::getSourceDocument(const XalanDOMString& theURI) const
{
assert(m_xpathEnvSupport != 0);
return m_xpathEnvSupport->getSourceDocument(theURI);
}
void
XPathExecutionContextDefault::setSourceDocument(
const XalanDOMString& theURI,
XalanDocument* theDocument)
{
assert(m_xpathEnvSupport != 0);
m_xpathEnvSupport->setSourceDocument(theURI, theDocument);
}
void XPathExecutionContextDefault::formatNumber(
double number,
const XalanDOMString& pattern,
XalanDOMString& theResult,
const XalanNode* context,
const LocatorType* locator)
{
doFormatNumber(number, pattern, 0, theResult, context, locator);
}
void XPathExecutionContextDefault::formatNumber(
double number,
const XalanDOMString& pattern,
const XalanDOMString& /* dfsName */,
XalanDOMString& theResult,
const XalanNode* context,
const LocatorType* locator)
{
doFormatNumber(number, pattern, 0, theResult, context, locator);
}
void XPathExecutionContextDefault::doFormatNumber(
double number,
const XalanDOMString& /* pattern */,
const XalanDecimalFormatSymbols* theDFS,
XalanDOMString& theResult,
const XalanNode* context,
const LocatorType* locator)
{
if (DoubleSupport::isNaN(number) == true)
{
if (theDFS != 0)
{
theResult = theDFS->getNaN();
}
else
{
DoubleToDOMString(number, theResult);
}
}
else if (DoubleSupport::isNegativeInfinity(number) == true)
{
if (theDFS != 0)
{
theResult = theDFS->getMinusSign();
theResult += theDFS->getInfinity();
}
else
{
DoubleToDOMString(number, theResult);
}
}
else if (DoubleSupport::isPositiveInfinity(number) == true )
{
if (theDFS != 0)
{
theResult = theDFS->getInfinity();
}
else
{
DoubleToDOMString(number, theResult);
}
}
else
{
warn(
XalanMessageLoader::getMessage(XalanMessages::FunctionIsNotImplemented_1Param,"format-number()"),
context,
locator);
DoubleToDOMString(number,theResult);
}
}
XALAN_CPP_NAMESPACE_END