blob: 6634e01426ee3f449436dd4c508eae43d287e0c0 [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.
*/
#if !defined(XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680)
#define XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680
// Base include file. Must be first.
#include <xalanc/XPath/XPathDefinitions.hpp>
#include <cassert>
#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/XalanDOM/XalanDOMString.hpp>
/**
* @author <a href="mailto:david_n_bertoni@lotus.com">David N. Bertoni</a>
*/
// Base class header file...
#include <xalanc/PlatformSupport/ExecutionContext.hpp>
#include <xalanc/XPath/MutableNodeRefList.hpp>
XALAN_CPP_NAMESPACE_BEGIN
class XalanDecimalFormatSymbols;
class PrefixResolver;
class XalanQName;
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:
typedef XalanVector<XObjectPtr> XObjectArgVectorType;
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
pushCurrentNode(XalanNode* theCurrentNode) = 0;
/**
* Reset the node currently being executed.
*/
virtual void
popCurrentNode() = 0;
class CurrentNodePushAndPop
{
public:
CurrentNodePushAndPop(
XPathExecutionContext& theExecutionContext,
XalanNode* theNewNode) :
m_executionContext(theExecutionContext)
{
theExecutionContext.pushCurrentNode(theNewNode);
}
~CurrentNodePushAndPop()
{
m_executionContext.popCurrentNode();
}
private:
XPathExecutionContext& m_executionContext;
};
/**
* Retrieve the factory object for creating XObjects.
*
* @return factory object instance
*/
XObjectFactory&
getXObjectFactory() const
{
assert(m_xobjectFactory != 0);
return *m_xobjectFactory;
}
/**
* 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;
/**
* Push the node list for current context.
*
* @param theList new node list
*/
virtual void
pushContextNodeList(const NodeRefListBase& theList) = 0;
/**
* Pop the node list for current context.
*/
virtual void
popContextNodeList() = 0;
class ContextNodeListPushAndPop
{
public:
ContextNodeListPushAndPop(
XPathExecutionContext& theExecutionContext,
const NodeRefListBase& theNodeList) :
m_executionContext(theExecutionContext)
{
m_executionContext.pushContextNodeList(theNodeList);
}
~ContextNodeListPushAndPop()
{
m_executionContext.popContextNodeList();
}
private:
XPathExecutionContext& m_executionContext;
};
/**
* Get the node list for current context.
*
* @return node list
*/
virtual const NodeRefListBase&
getContextNodeList() const = 0;
/*
* 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 theQName The QName of the element
*
* @return whether the given element is available or not
*/
virtual bool
elementAvailable(const XalanQName& theQName) const = 0;
/**
* Determine if an external element is available by resolving
* a string to a QName.
*
* @param theName The name of the element
* @param locator A LocatorType instance for error reporting
*
* @return whether the given element is available or not
*/
virtual bool
elementAvailable(
const XalanDOMString& theName,
const LocatorType* locator) const = 0;
/**
* Determine if a function is available.
*
* @param theQName The QName of the function
*
* @return whether the function is available or not
*/
virtual bool
functionAvailable(const XalanQName& theQName) const = 0;
/**
* Determine if a function is available.
*
* @param theName The name of the function
* @param locator A LocatorType instance for error reporting
*
* @return whether the function is available or not
*/
virtual bool
functionAvailable(
const XalanDOMString& theName,
const LocatorType* locator) 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 LocatorType 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 LocatorType* 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;
};
/**
* Get a cached string for temporary use.
*
* @return A reference to the string
*/
virtual XalanDOMString&
getCachedString() = 0;
/**
* Return a cached string.
*
* @param theString The string to release.
*
* @return true if the string was released successfully.
*/
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 qname 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 nodelist A node list to contain the nodes found
*/
virtual void
getNodeSetByKey(
XalanDocument* doc,
const XalanQName& qname,
const XalanDOMString& ref,
MutableNodeRefList& nodelist) = 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. Will be resolved to a
* qname using the provided resolver.
* @param ref value that must match the value found by the
* 'match' attribute on xsl:key
* @param locator The LocatorType to use for error reporting. Can be 0.
* @param nodelist A node list to contain the nodes found
*/
virtual void
getNodeSetByKey(
XalanDocument* doc,
const XalanDOMString& name,
const XalanDOMString& ref,
const LocatorType* locator,
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 An XObjectPtr instance. If the variable is not found, an exception
* is thrown, or the routine returns an instance of XUnknown.
*/
virtual const XObjectPtr
getVariable(
const XalanQName& name,
const LocatorType* 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 XalanText& node) = 0;
/**
* Get the document associated with the given URI.
*
* @param theURI document URI
* @return a pointer to the document instance, if any.
*/
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;
/**
* Formats a number according to the specified pattern.
*
* @param number the number to be formatted
* @param pattern the format pattern
* @param theResult the formatted number
* @param context the source node
* @param locator the locator
*/
virtual void formatNumber(
double number,
const XalanDOMString& pattern,
XalanDOMString& theResult,
const XalanNode* context = 0,
const LocatorType* locator = 0) = 0;
/**
* Formats a number according to the specified pattern.
*
* @param number the number to be formatted
* @param pattern the format pattern
* @param dfsName the name of decimal format to use
* @param theResult the formatted number
* @param context the source node
* @param locator the locator
* @return a pointer to the functor, 0 if none was found
*/
virtual void formatNumber(
double number,
const XalanDOMString& pattern,
const XalanDOMString& dfsName,
XalanDOMString& theResult,
const XalanNode* context = 0,
const LocatorType* locator = 0) = 0;
// These interfaces are inherited from ExecutionContext...
virtual void
error(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const LocatorType* locator = 0) const = 0;
virtual void
warn(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const LocatorType* locator = 0) const = 0;
virtual void
message(
const XalanDOMString& msg,
const XalanNode* sourceNode = 0,
const LocatorType* locator = 0) const = 0;
protected:
XObjectFactory* m_xobjectFactory;
};
XALAN_CPP_NAMESPACE_END
#endif // XPATHEXECUTIONCONTEXT_HEADER_GUARD_1357924680