blob: 7354fcfaa8fdb49c836d07c7a9bc2b66fa346eaf [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/>.
*
* @author <a href="mailto:david_n_bertoni@lotus.com">David N. Bertoni</a>
*/
#if !defined(XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680)
#define XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680
// Base include file. Must be first.
#include <XPath/XPathDefinitions.hpp>
#include <cassert>
#include <vector>
#include <XalanDOM/XalanDOMString.hpp>
// Base class header file...
#include <PlatformSupport/ExecutionContext.hpp>
#include <XPath/MutableNodeRefList.hpp>
#include <XPath/ResultTreeFragBase.hpp>
class XalanDecimalFormatSymbols;
class PrefixResolver;
class XalanQName;
class XLocator;
class XMLURL;
class XObject;
class XObjectPtr;
class XObjectFactory;
class XalanDocument;
class XalanElement;
class XalanNode;
class XalanText;
//
// An abstract class which provides support for executing XPath functions
// and extension functions.
//
class XALAN_XPATH_EXPORT XPathExecutionContext : public ExecutionContext
{
public:
#if defined(XALAN_NO_NAMESPACES)
typedef vector<XObjectPtr> XObjectArgVectorType;
#else
typedef std::vector<XObjectPtr> XObjectArgVectorType;
#endif
typedef NodeRefListBase::size_type size_type;
explicit
XPathExecutionContext(XObjectFactory* theXObjectFactory = 0);
virtual
~XPathExecutionContext();
/**
* Reset the instance. This must be called before another
* execution is attempted.
*/
virtual void
reset() = 0;
/**
* Retrieve the node currently being executed.
*
* @return current node
*/
virtual XalanNode*
getCurrentNode() const = 0;
/**
* Change the node currently being executed.
*
* @param theCurrentNode new current node
*/
virtual void
setCurrentNode(XalanNode* theCurrentNode) = 0;
class CurrentNodeSetAndRestore
{
public:
CurrentNodeSetAndRestore(
XPathExecutionContext& theExecutionContext,
XalanNode* theNode) :
m_executionContext(theExecutionContext),
m_savedNode(theExecutionContext.getCurrentNode())
{
m_executionContext.setCurrentNode(theNode);
}
~CurrentNodeSetAndRestore()
{
m_executionContext.setCurrentNode(m_savedNode);
}
private:
XPathExecutionContext& m_executionContext;
XalanNode* const m_savedNode;
};
/**
* Retrieve the factory object for creating XObjects.
*
* @return factory object instance
*/
XObjectFactory&
getXObjectFactory() const
{
assert(m_xobjectFactory != 0);
return *m_xobjectFactory;
}
/**
* Convenience function for creating a node set with
* the supplied node as the only member.
*
* @param node The node queried
* @return a pointer to the XObject instance.
*/
virtual XObjectPtr
createNodeSet(XalanNode& theNode) = 0;
/**
* Determine if a node is after another node, in document order.
*
* @param node1 The first node
* @param node2 The second node
* @return true if node1 one is after node2, or false if it is not.
*/
virtual bool
isNodeAfter(
const XalanNode& node1,
const XalanNode& node2) const = 0;
/**
* Retrieve node list for current context.
*
* @return node list
*/
virtual const NodeRefListBase&
getContextNodeList() const = 0;
/**
* Set node list for current context.
*
* @param theList new node list
*/
virtual void
setContextNodeList(const NodeRefListBase& theList) = 0;
class ContextNodeListSetAndRestore
{
public:
ContextNodeListSetAndRestore(
XPathExecutionContext& theExecutionContext,
const NodeRefListBase& theNodeList) :
m_executionContext(theExecutionContext),
m_savedNodeList(theExecutionContext.getContextNodeList())
{
m_executionContext.setContextNodeList(theNodeList);
}
~ContextNodeListSetAndRestore()
{
m_executionContext.setContextNodeList(m_savedNodeList);
}
private:
XPathExecutionContext& m_executionContext;
const NodeRefListBase& m_savedNodeList;
};
/*
* Get the count of nodes in the current context node list.
*
* @return length of list
*/
virtual size_type
getContextNodeListLength() const = 0;
/*
* Get the position of the node in the current context node list.
* Note that this is 1-based indexing (XPath/XSLT-style), not 0-based.
* Thus, 0 will be returned if the node was not found.
*
* @return position in list
*/
virtual size_type
getContextNodeListPosition(const XalanNode& contextNode) const = 0;
/**
* Determine if an external element is available.
*
* @param theNamespace namespace for the element
* @param elementName name of extension element
* @return whether the given element is available or not
*/
virtual bool
elementAvailable(
const XalanDOMString& theNamespace,
const XalanDOMString& elementName) const = 0;
/**
* Determine if a function is available. For standard
* function availability, theNamespace should be an
* empty string.
*
* @param theNamespace namespace for the function
* @param functionName name of the function
* @return whether the function is available or not
*/
virtual bool
functionAvailable(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName) const = 0;
/**
* Handle an extension function.
*
* @param theNamespace namespace of function
* @param functionName extension function name
* @param context The context node
* @param argVec vector of arguments to function
* @param locator A Locator instance for error reporting
* @return pointer to XObject result
*/
virtual const XObjectPtr
extFunction(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
XalanNode* context,
const XObjectArgVectorType& argVec,
const Locator* locator) = 0;
/**
* Provides support for XML parsing service.
*
* @param urlString location of the XML
* @param base base location for URI
* @return parsed document
*/
virtual XalanDocument*
parseXML(
const XalanDOMString& urlString,
const XalanDOMString& base) const = 0;
/**
* Borrow a cached MutableNodeRefList instance.
*
* @return A pointer to the instance.
*/
virtual MutableNodeRefList*
borrowMutableNodeRefList() = 0;
/**
* Return a previously borrowed MutableNodeRefList instance.
*
* @param theList A pointer the to previously borrowed instance.
* @return true if the list was borrowed (at therefore, destroyed), false if not.
*/
virtual bool
returnMutableNodeRefList(MutableNodeRefList* theList) = 0;
class BorrowReturnMutableNodeRefList
{
public:
BorrowReturnMutableNodeRefList(XPathExecutionContext& executionContext) :
m_xpathExecutionContext(&executionContext),
m_mutableNodeRefList(executionContext.borrowMutableNodeRefList())
{
assert(m_mutableNodeRefList != 0);
}
// N.B. Non-const copy constructor semantics (like std::auto_ptr)
BorrowReturnMutableNodeRefList(const BorrowReturnMutableNodeRefList& theSource) :
m_xpathExecutionContext(theSource.m_xpathExecutionContext),
m_mutableNodeRefList(theSource.m_mutableNodeRefList)
{
assert(m_mutableNodeRefList != 0);
((BorrowReturnMutableNodeRefList&)theSource).m_mutableNodeRefList = 0;
}
~BorrowReturnMutableNodeRefList()
{
release();
}
MutableNodeRefList&
operator*() const
{
assert(m_mutableNodeRefList != 0);
return *m_mutableNodeRefList;
}
MutableNodeRefList*
get() const
{
return m_mutableNodeRefList;
}
MutableNodeRefList*
operator->() const
{
return get();
}
void
release()
{
assert(m_xpathExecutionContext != 0);
if (m_mutableNodeRefList != 0)
{
m_xpathExecutionContext->returnMutableNodeRefList(m_mutableNodeRefList);
m_mutableNodeRefList = 0;
}
}
BorrowReturnMutableNodeRefList
clone() const
{
assert(m_xpathExecutionContext != 0);
BorrowReturnMutableNodeRefList theResult(*m_xpathExecutionContext);
*theResult = *m_mutableNodeRefList;
return theResult;
}
// N.B. Non-const assignment operator semantics.
BorrowReturnMutableNodeRefList&
operator=(BorrowReturnMutableNodeRefList& theRHS)
{
release();
m_xpathExecutionContext = theRHS.m_xpathExecutionContext;
m_mutableNodeRefList = theRHS.m_mutableNodeRefList;
theRHS.m_mutableNodeRefList = 0;
return *this;
}
private:
XPathExecutionContext* m_xpathExecutionContext;
MutableNodeRefList* m_mutableNodeRefList;
};
virtual XalanDOMString&
getCachedString() = 0;
virtual bool
releaseCachedString(XalanDOMString& theString) = 0;
class GetAndReleaseCachedString
{
public:
GetAndReleaseCachedString(XPathExecutionContext& theExecutionContext) :
m_executionContext(&theExecutionContext),
m_string(&theExecutionContext.getCachedString())
{
}
// Note non-const copy semantics...
GetAndReleaseCachedString(GetAndReleaseCachedString& theSource) :
m_executionContext(theSource.m_executionContext),
m_string(theSource.m_string)
{
theSource.m_string = 0;
}
~GetAndReleaseCachedString()
{
if (m_string != 0)
{
m_executionContext->releaseCachedString(*m_string);
}
}
XalanDOMString&
get() const
{
assert(m_string != 0);
return *m_string;
}
XPathExecutionContext&
getExecutionContext() const
{
return *m_executionContext;
}
private:
// Not implemented...
GetAndReleaseCachedString&
operator=(const GetAndReleaseCachedString&);
// Data members...
XPathExecutionContext* m_executionContext;
XalanDOMString* m_string;
};
/**
* Create a MutableNodeRefList with the appropriate context.
*
* @return pointer to node list created
*/
virtual MutableNodeRefList*
createMutableNodeRefList() const = 0;
/**
* Given a valid element key, return the corresponding node list.
*
* @param doc source document
* @param name name of the key, which must match the 'name'
* attribute on xsl:key
* @param ref value that must match the value found by the
* 'match' attribute on xsl:key
* @param resolver resolver for namespace resolution
* @param nodelist A node list to contain the nodes found
*/
virtual void
getNodeSetByKey(
XalanNode* doc,
const XalanDOMString& name,
const XalanDOMString& ref,
const PrefixResolver& resolver,
MutableNodeRefList& nodelist) = 0;
/**
* Given a name, locate a variable in the current context, and return
* a pointer to the object.
*
* @param theName name of variable
* @return pointer to an XObject if the variable was found, 0 if it was not
*/
virtual const XObjectPtr
getVariable(
const XalanQName& name,
const Locator* locator = 0) = 0;
/**
* Retrieve the resolver for namespaces.
*
* @return object for namespace resolution
*/
virtual const PrefixResolver*
getPrefixResolver() const = 0;
/**
* Change the resolver for namespaces.
*
* @param thePrefixResolver new object for namespace resolution
*/
virtual void
setPrefixResolver(const PrefixResolver* thePrefixResolver) = 0;
class PrefixResolverSetAndRestore
{
public:
PrefixResolverSetAndRestore(
XPathExecutionContext& theExecutionContext,
const PrefixResolver* theResolver) :
m_executionContext(theExecutionContext),
m_savedResolver(theExecutionContext.getPrefixResolver())
{
m_executionContext.setPrefixResolver(theResolver);
}
PrefixResolverSetAndRestore(
XPathExecutionContext& theExecutionContext,
const PrefixResolver* theOldResolver,
const PrefixResolver* theNewResolver) :
m_executionContext(theExecutionContext),
m_savedResolver(theOldResolver)
{
m_executionContext.setPrefixResolver(theNewResolver);
}
~PrefixResolverSetAndRestore()
{
m_executionContext.setPrefixResolver(m_savedResolver);
}
private:
XPathExecutionContext& m_executionContext;
const PrefixResolver* const m_savedResolver;
};
/**
* Retrieve the URI corresponding to a namespace prefix
*
* @param prefix prefix for a namespace
* @return URI corresponding to namespace
*/
virtual const XalanDOMString*
getNamespaceForPrefix(const XalanDOMString& prefix) const = 0;
/**
* Given a DOM Document, tell what URI was used to parse it. Needed for
* relative resolution.
*
* @param owner source document
* @return document URI
*/
virtual XalanDOMString
findURIFromDoc(const XalanDocument* owner) const = 0;
/**
* The getUnparsedEntityURI function returns the URI of the unparsed
* entity with the specified name in the same document as the context
* node (see [3.3 Unparsed Entities]). It returns the empty string if
* there is no such entity.
*
* @param theName name of entity
* @param theDocument document containing entity
* @return URI for the entity
*/
virtual const XalanDOMString&
getUnparsedEntityURI(
const XalanDOMString& theName,
const XalanDocument& theDocument) const = 0;
/**
* Tells, through the combination of the default-space attribute
* on xsl:stylesheet, xsl:strip-space, xsl:preserve-space, and the
* xml:space attribute, whether or not extra whitespace should be stripped
* from the node. Literal elements from template elements should
* <em>not</em> be tested with this function.
*
* @param textNode text node from the source tree
* @return true if the text node should be stripped of extra whitespace
*/
virtual bool
shouldStripSourceNode(const XalanNode& node) = 0;
/**
* Tells if FoundIndex should be thrown if index is found. This is an
* optimization for match patterns, and is used internally by the XPath
* engine.
*
* @return true to throw FoundIndex
*/
virtual bool
getThrowFoundIndex() const = 0;
/**
* Changes whether FoundIndex should be thrown if index is found. This is an
* optimization for match patterns, and is used internally by the XPath
* engine.
*
* @param fThrow true to throw FoundIndex
*/
virtual void
setThrowFoundIndex(bool fThrow) = 0;
virtual XalanDocument*
getSourceDocument(const XalanDOMString& theURI) const = 0;
/**
* Associate a document with a given URI.
*
* @param theURI document URI
* @param theDocument source document
*/
virtual void
setSourceDocument(
const XalanDOMString& theURI,
XalanDocument* theDocument) = 0;
/**
* Retrieve the XalanDecimalFormatSymbols instance associated with
* the name.
*
* @param qname the QName for the lookup
* @return a pointer to the matching instance, or 0 if none was found
*/
virtual const XalanDecimalFormatSymbols*
getDecimalFormatSymbols(const XalanQName& qname) = 0;
// These interfaces are inherited from ExecutionContext...
virtual void
error(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
error(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
virtual void
error(
const char* msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
error(
const char* msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
virtual void
warn(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
warn(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
virtual void
warn(
const char* msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
warn(
const char* msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
virtual void
message(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
message(
const XalanDOMString& msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
virtual void
message(
const char* msg,
const XalanNode* sourceNode = 0,
const XalanNode* styleNode = 0) const = 0;
virtual void
message(
const char* msg,
const XalanNode* sourceNode,
const Locator* locator) const = 0;
protected:
XObjectFactory* m_xobjectFactory;
};
#endif // XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680