blob: 6ca8e3d2a197822a10f4cb0ae52bca895253205f [file] [log] [blame]
/*
* 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(XALANQNAME_HEADER_GUARD_1357924680)
#define XALANQNAME_HEADER_GUARD_1357924680
// Base header file. Must be first.
#include <xalanc/XPath/XPathDefinitions.hpp>
#include <xalanc/Include/XalanMap.hpp>
#include <xalanc/Include/XalanDeque.hpp>
#include <xalanc/Include/STLHelper.hpp>
#include <xalanc/XalanDOM/XalanDOMString.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/PrefixResolver.hpp>
#include <xalanc/XPath/NameSpace.hpp>
#include <xalanc/XPath/XalanXPathException.hpp>
namespace XALAN_CPP_NAMESPACE {
class XalanElement;
class XPathEnvSupport;
/**
* Class to represent a qualified name. The name of an internal XSLT object,
* specifically a named template (see [7 Named Templates]), a mode (see [6.7 Modes]),
* an attribute set (see [8.1.4 Named Attribute Sets]), a key (see [14.2 Keys]),
* a locale (see [14.3 Number Formatting]), a variable or a parameter (see
* [12 Variables and Parameters]) is specified as a QName. If it has a prefix,
* then the prefix is expanded into a URI reference using the namespace declarations
* in effect on the attribute in which the name occurs. The expanded name
* consisting of the local part of the name and the possibly null URI reference
* is used as the name of the object. The default namespace is not used for
* unprefixed names.
*/
class XALAN_XPATH_EXPORT XalanQName
{
public:
typedef XalanDeque<NameSpace, ConstructWithMemoryManagerTraits<NameSpace> >
NamespaceVectorType;
typedef XalanDeque<NamespaceVectorType, ConstructWithMemoryManagerTraits<NamespaceVectorType> >
NamespacesStackType;
/**
* Construct an empty XalanQName.
*
*/
explicit
XalanQName()
{
}
virtual
~XalanQName()
{
}
XalanQName(const XalanQName&)
{
}
/**
* Retrieve the local part of qualified name.
*
* @return local part string
*/
virtual const XalanDOMString&
getLocalPart() const = 0;
/**
* Retrieve the namespace of qualified name.
*
* @return namespace string
*/
virtual const XalanDOMString&
getNamespace() const = 0;
/**
* Determine if the qualified name is valid.
*
* @return true if the instance is a valid QName, false if not.
*/
bool
isValid() const
{
return isValidNCName(getLocalPart());
}
/**
* Whether the qualified name is empty.
*
* @return true if namespace and local part are both empty
*/
bool
isEmpty() const
{
return getNamespace().empty() && getLocalPart().empty();
}
/**
* Override equals and agree that we're equal if the passed object is a
* string and it matches the name of the arg.
*
* @param theRHS namespace to compare
* @return true if namespace and local part are both empty
*/
bool
equals(const XalanQName& theRHS) const
{
// Note that we do not use our member variables here. See
// class QNameReference for details...
return getLocalPart() == theRHS.getLocalPart() &&
getNamespace() == theRHS.getNamespace();
}
/**
* Format the QName using the notation "{namespace-uri}local-part" or
* "local-part" if the namespace URI is empty. The result is appended
* to the provided string.
*
* @param theString The string to format with the
* @return A reference to the parameter.
*/
XalanDOMString&
format(XalanDOMString& theString) const;
size_t
hash() const
{
return getLocalPart().hash() % (getNamespace().hash() + 1);
}
class XALAN_XPATH_EXPORT PrefixResolverProxy : public PrefixResolver
{
public:
/**
* Construct a PrefixResolver from a NamespacesStackType
* instance.
*
* @param theStack The stack to use for prefix resolution
* @param theURI The namespace URI of the resolver, if any. Only a reference is kept, so this cannot be a temporary
* @return pointer to the string value if found, otherwise 0.
*/
PrefixResolverProxy(
const NamespacesStackType& theStack,
const XalanDOMString& theURI);
virtual
~PrefixResolverProxy();
virtual const XalanDOMString*
getNamespaceForPrefix(const XalanDOMString& prefix) const;
virtual const XalanDOMString&
getURI() const;
private:
const NamespacesStackType& m_stack;
const XalanDOMString& m_uri;
};
/**
* Get the namespace for a prefix by searching a vector of namespaces.
*
* @param namespaces vector of namespaces to search
* @param prefix namespace prefix to find
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getNamespaceForPrefix(
const NamespaceVectorType& namespaces,
const XalanDOMString& prefix);
/**
* Get the namespace for a prefix by searching a stack of namespace
* vectors.
*
* @param nsStack stack of namespace vectors to search
* @param prefix namespace prefix to find
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getNamespaceForPrefix(
const NamespacesStackType& nsStack,
const XalanDOMString& prefix);
static const XalanDOMString*
getNamespaceForPrefix(
const NamespacesStackType& nsStack,
const XalanDOMChar* prefix);
/**
* Get the namespace for a prefix by searching a range of iterators.
* The search is done in reverse, from the end of the range to the
* beginning.
*
* @param theBegin The beginning iterator for the range
* @param theBegin The ending iterator for the range
* @param prefix namespace prefix to find
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getNamespaceForPrefix(
NamespacesStackType::const_iterator theBegin,
NamespacesStackType::const_iterator theEnd,
const XalanDOMString& prefix);
/**
* Get the prefix for a namespace by searching a vector of namespaces.
*
* @param namespaces vector of namespaces to search
* @param uri URI string for namespace to find
* @param reverse true to search vector from last to first, default true
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getPrefixForNamespace(
const NamespaceVectorType& namespaces,
const XalanDOMString& uri);
static const XalanDOMString*
getNamespaceForPrefix(
const NamespaceVectorType& namespaces,
const XalanDOMChar* prefix);
/**
* Get the prefix for a namespace by searching a stack of namespace
* vectors.
*
* @param nsStack stack of namespace vectors to search
* @param uri URI string for namespace to find
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getPrefixForNamespace(
const NamespacesStackType& nsStack,
const XalanDOMString& uri);
/**
* Get the prefix for a namespace by searching a range of iterators.
* The search is done in reverse, from the end of the range to the
* beginning.
*
* @param theBegin The beginning iterator for the range to search
* @param theBegin The ending iterator for the range to search
* @param uri URI string for namespace to find
* @return pointer to the string value if found, otherwise null.
*/
static const XalanDOMString*
getPrefixForNamespace(
NamespacesStackType::const_iterator theBegin,
NamespacesStackType::const_iterator theEnd,
const XalanDOMString& uri);
static const XalanDOMString*
getNamespaceForPrefix(
NamespacesStackType::const_iterator theBegin,
NamespacesStackType::const_iterator theEnd,
const XalanDOMChar* prefix);
/**
* Determine if the string supplied satisfies the grammar for
* an XML NCName.
*
* @param theNCName The string to check
* @return bool true if the string is a valid NCName, false if not.
*/
static bool
isValidNCName(const XalanDOMString& theNCName);
/**
* Determine if the string supplied satisfies the grammar for
* an XML NCName.
*
* @param theNCName The string to check
* @param theLength The length of the string
* @return bool true if the string is a valid NCName, false if not
*/
static bool
isValidNCName(
const XalanDOMChar* theNCName,
XalanDOMString::size_type theLength = XalanDOMString::npos);
/**
* Determine if the string supplied satisfies the grammar for
* an XML QName. Note that this function does not determine
* if any supplied prefix is bound to a namespace URI
*
* @param theQName The string to check
* @return bool true if the string is a valid QName, false if not
*/
static bool
isValidQName(const XalanDOMString& theQName);
/**
* Determine if the string supplied satisfies the grammar for
* an XML QName. Note that this function does not determine
* if any supplied prefix is bound to a namespace URI
*
* @param theQName The string to check
* @param theLength The length of the string
* @return bool true if the string is a valid QName, false if not
*/
static bool
isValidQName(
const XalanDOMChar* theQName,
XalanDOMString::size_type theLength = XalanDOMString::npos);
class InvalidQNameException : public XalanXPathException
{
public:
/**
* Constructor
*
* @param theQName The QName string that is not valid.
* @param theQNameLength The length of the string.
* @param theResult A temporary string for loading the error message.
*/
InvalidQNameException(
const XalanDOMChar* theQName,
XalanDOMString::size_type theQNameLength,
XalanDOMString& theResult,
const Locator* theLocator);
/**
* Constructor
*
* @param theMessage The message for the exception
* @param theManager The MemoryManager instance to use when constructing the exception
*/
InvalidQNameException(
const XalanDOMString& theMessage,
MemoryManager& theManager,
const Locator* theLocator);
InvalidQNameException(const InvalidQNameException& other);
virtual
~InvalidQNameException();
virtual const XalanDOMChar*
getType() const;
private:
static const XalanDOMString&
format(
const XalanDOMChar* theQName,
XalanDOMString::size_type theQNameLength,
XalanDOMString& theResult);
};
protected:
static const XalanDOMString s_emptyString;
};
inline bool
operator==(
const XalanQName& theLHS,
const XalanQName& theRHS)
{
return theLHS.equals(theRHS);
}
inline bool
operator!=(
const XalanQName& theLHS,
const XalanQName& theRHS)
{
return !(theLHS == theRHS);
}
inline bool
operator<(
const XalanQName& theLHS,
const XalanQName& theRHS)
{
if (theLHS.getNamespace() < theRHS.getNamespace())
{
return true;
}
else if (equals(theLHS.getNamespace(), theRHS.getNamespace()))
{
return theLHS.getLocalPart() < theRHS.getLocalPart();
}
else
{
return false;
}
}
template<>
struct XalanMapKeyTraits<XalanQName>
{
typedef XalanHashMemberReference<XalanQName> Hasher;
typedef std::equal_to<XalanQName> Comparator;
};
template<>
struct XalanMapKeyTraits<const XalanQName*>
{
typedef XalanHashMemberPointer<XalanQName> Hasher;
typedef pointer_equal<XalanQName> Comparator;
};
}
#endif // XALANQNAME_HEADER_GUARD_1357924680