/*
 * 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.
 */
// Class header file...
#include "XalanQName.hpp"



#include <xalanc/Include/STLHelper.hpp>



#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



XALAN_CPP_NAMESPACE_BEGIN




const XalanDOMString    XalanQName::s_emptyString(XalanMemMgrs::getDummyMemMgr());



XalanQName::PrefixResolverProxy::PrefixResolverProxy(
            const NamespacesStackType&  theStack,
            const XalanDOMString&       theURI) :
    m_stack(theStack),
    m_uri(theURI)
{
}



XalanQName::PrefixResolverProxy::~PrefixResolverProxy()
{
}



const XalanDOMString*
XalanQName::PrefixResolverProxy::getNamespaceForPrefix(const XalanDOMString&    prefix) const
{
    return XalanQName::getNamespaceForPrefix(m_stack, prefix);
}



const XalanDOMString&
XalanQName::PrefixResolverProxy::getURI() const
{
    return m_uri;
}



const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            const NamespaceVectorType&  namespaces,
            const XalanDOMChar*         prefix)
{
    assert( prefix != 0 );

    const XalanDOMString*   nsURI = 0;

    if(prefix == DOMServices::s_XMLString)
    {
        nsURI = &DOMServices::s_XMLNamespaceURI;
    }
    else if (prefix == DOMServices::s_XMLNamespace)
    {
        nsURI = &DOMServices::s_XMLNamespacePrefixURI;
    }
    else
    {
        const NamespaceVectorType::size_type    theSize = namespaces.size();

        for(NamespaceVectorType::size_type j = theSize; j > 0; --j)
        {
            const NameSpace&    ns = namespaces[j - 1];

            const XalanDOMString&   thisPrefix = ns.getPrefix();

            if(prefix == thisPrefix)
            {
                nsURI = &ns.getURI();

                break;
            }
        }
    }

    return nsURI;
}


const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            const NamespaceVectorType&  namespaces,
            const XalanDOMString&       prefix)
{
    const XalanDOMString*   nsURI = 0;

    if(prefix == DOMServices::s_XMLString)
    {
        nsURI = &DOMServices::s_XMLNamespaceURI;
    }
    else if (prefix == DOMServices::s_XMLNamespace)
    {
        nsURI = &DOMServices::s_XMLNamespacePrefixURI;
    }
    else
    {
        const NamespaceVectorType::size_type    theSize = namespaces.size();

        for(NamespaceVectorType::size_type j = theSize; j > 0; --j)
        {
            const NameSpace&    ns = namespaces[j - 1];

            const XalanDOMString&   thisPrefix = ns.getPrefix();

            if(prefix == thisPrefix)
            {
                nsURI = &ns.getURI();

                break;
            }
        }
    }

    return nsURI;
}

const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            const NamespacesStackType&  nsStack,
            const XalanDOMString&       prefix)
{
    return getNamespaceForPrefix(nsStack.begin(), nsStack.end(), prefix);
}

const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            const NamespacesStackType&  nsStack,
            const XalanDOMChar*         prefix)
{
    return getNamespaceForPrefix(nsStack.begin(), nsStack.end(), prefix);
}

const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            NamespacesStackType::const_iterator     theBegin,
            NamespacesStackType::const_iterator     theEnd,
            const XalanDOMChar*                     prefix)
{
    const XalanDOMString*   nsURI = 0;

    if (theBegin != theEnd)
    {
        do
        {   
            --theEnd;

            nsURI = getNamespaceForPrefix((*theEnd), prefix);

            if (nsURI != 0)
            {
                break;
            }
        } while(theBegin != theEnd);
    }

    return nsURI;
}

const XalanDOMString*
XalanQName::getNamespaceForPrefix(
            NamespacesStackType::const_iterator     theBegin,
            NamespacesStackType::const_iterator     theEnd,
            const XalanDOMString&                   prefix)
{
    const XalanDOMString*   nsURI = 0;

    if (theBegin != theEnd)
    {
        do
        {
            nsURI = getNamespaceForPrefix(*(--theEnd), prefix);

            if (nsURI != 0)
            {
                break;
            }
        } while(theBegin != theEnd);
    }

    return nsURI;
}



const XalanDOMString*
XalanQName::getPrefixForNamespace(
            const NamespaceVectorType&  namespaces,
            const XalanDOMString&       uri)
{
    const XalanDOMString*   thePrefix = 0;

    const NamespaceVectorType::size_type    theSize = namespaces.size();

    for(NamespaceVectorType::size_type j = theSize; j > 0; --j)
    {
        const NameSpace&        ns = namespaces[j - 1];
        const XalanDOMString&   thisURI = ns.getURI();

        if(uri == thisURI)
        {
            thePrefix = &ns.getPrefix();

            break;
        }
    }

    return thePrefix;
}       



const XalanDOMString*
XalanQName::getPrefixForNamespace(
            const NamespacesStackType&  nsStack,
            const XalanDOMString&       uri)
{
    return getPrefixForNamespace(nsStack.begin(), nsStack.end(), uri);
}



const XalanDOMString*
XalanQName::getPrefixForNamespace(
            NamespacesStackType::const_iterator     theBegin,
            NamespacesStackType::const_iterator     theEnd,
            const XalanDOMString&                   uri)
{
    const XalanDOMString*   thePrefix = 0;

    if (theBegin != theEnd)
    {
        do
        {
            thePrefix = getPrefixForNamespace(*(--theEnd), uri);

            if (thePrefix != 0)
            {
                break;
            }
        } while(theBegin != theEnd);
    }

    return thePrefix;
}



bool
XalanQName::isValidNCName(const XalanDOMString&     theNCName)
{
    return isValidNCName(c_wstr(theNCName), length(theNCName));
}



bool
XalanQName::isValidNCName(
            const XalanDOMChar*         theNCName,
            XalanDOMString::size_type   theLength)
{
    assert(theNCName != 0);

    if (theLength == XalanDOMString::npos)
    {
        theLength = length(theNCName);
    }

    if (theLength == 0)
    {
        return false;
    }
    else
    {
        XalanDOMChar    c = theNCName[0];

        if(!(XalanXMLChar::isLetter(c) || c == XalanUnicode::charLowLine))
          return false;

        if(theLength > 1)
        {
            for(XalanDOMString::size_type i = 1; i < theLength; i++)
            {
                c = theNCName[i]; 

                if(!(XalanXMLChar::isLetter(c) ||
                     XalanXMLChar::isDigit(c) ||
                     XalanXMLChar::isExtender(c) ||
                     XalanXMLChar::isCombiningChar(c) ||
                     c == XalanUnicode::charLowLine ||
                     c == XalanUnicode::charHyphenMinus ||
                     c == XalanUnicode::charFullStop))
                {
                    return false;
                }
            }
        }

        return true;
    }
}



bool
XalanQName::isValidQName(const XalanDOMString&  theQName)
{
    return isValidQName(c_wstr(theQName), length(theQName));
}



bool
XalanQName::isValidQName(
            const XalanDOMChar*         theQName,
            XalanDOMString::size_type   theLength)
{
    const XalanDOMString::size_type     theIndex =
        indexOf(theQName, XalanUnicode::charColon);

    if (theIndex == theLength)
    {
        return isValidNCName(theQName, theLength);
    }
    else
    {
        const XalanDOMChar* const   thePrefix = c_wstr(theQName);
        const XalanDOMChar* const   theLocalName = thePrefix + theIndex + 1;

        return XalanQName::isValidNCName(thePrefix, theIndex) &&
               XalanQName::isValidNCName(theLocalName, theLength - theIndex - 1);
    }
}


const XalanDOMChar  XalanQName::InvalidQNameException::m_type[] = 
{   
    XalanUnicode::charLetter_I,
    XalanUnicode::charLetter_n,
    XalanUnicode::charLetter_v,
    XalanUnicode::charLetter_a,
    XalanUnicode::charLetter_l,
    XalanUnicode::charLetter_i,
    XalanUnicode::charLetter_d,
    XalanUnicode::charLetter_Q,
    XalanUnicode::charLetter_N,
    XalanUnicode::charLetter_a,
    XalanUnicode::charLetter_m,
    XalanUnicode::charLetter_e,
    XalanUnicode::charLetter_E,
    XalanUnicode::charLetter_x,
    XalanUnicode::charLetter_c,
    XalanUnicode::charLetter_e,
    XalanUnicode::charLetter_p,
    XalanUnicode::charLetter_t,
    XalanUnicode::charLetter_i,
    XalanUnicode::charLetter_o,
    XalanUnicode::charLetter_n,
    0
};



XalanQName::InvalidQNameException::InvalidQNameException(
            const XalanDOMChar*         theQName,
            XalanDOMString::size_type   theQNameLength,
            const XalanDOMString&       theURI,
            int                         theLineNumber,
            int                         theColumnNumber,
            XalanDOMString&             theResult) :
    XSLException(
        format(theQName, theQNameLength, theResult),
        theURI,
        theLineNumber,
        theColumnNumber,
        theResult.getMemoryManager())
{
}



XalanQName::InvalidQNameException::InvalidQNameException(
            const LocatorType&          theLocator,
            const XalanDOMChar*         theQName,
            XalanDOMString::size_type   theQNameLength,
            XalanDOMString&             theResult) :
    XSLException(
        theLocator, 
        format(theQName, theQNameLength, theResult),
        theResult.getMemoryManager())
{
}



XalanQName::InvalidQNameException::InvalidQNameException(
            const XalanDOMChar*         theQName,
            XalanDOMString::size_type   theQNameLength,
            XalanDOMString&             theResult) :
    XSLException(
        format(theQName, theQNameLength, theResult),
        theResult.getMemoryManager())
{
}



XalanQName::InvalidQNameException::InvalidQNameException(
            const XalanDOMString&   theMessage,
            MemoryManager&          theManager) :
    XSLException(
        theMessage,
        theManager)
{
}



XalanQName::InvalidQNameException::InvalidQNameException(
            const Locator&          theLocator,
            const XalanDOMString&   theMessage,
            MemoryManager&          theManager) :
    XSLException(
        theLocator,
        theMessage,
        theManager)
{
}



XalanQName::InvalidQNameException::~InvalidQNameException()
{
}



const XalanDOMString&
XalanQName::InvalidQNameException::format(
            const XalanDOMChar*         theQName,
            XalanDOMString::size_type   theQNameLength,
            XalanDOMString&             theResult )
{
    XalanDOMString  theParameter(theResult.getMemoryManager());

    theParameter.append(theQName, theQNameLength);

    return XalanMessageLoader::getMessage(
                theResult,
                XalanMessages::IsNotValidQName_1Param,
                theParameter);
}



XALAN_CPP_NAMESPACE_END
