/*
 * 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.
 */

/**
  * $Id$
  */



// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/XSDDOMParser.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/internal/XMLScanner.hpp>
#include <xercesc/internal/ElemStack.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/impl/DOMElementImpl.hpp>
#include <xercesc/dom/impl/DOMAttrImpl.hpp>
#include <xercesc/dom/impl/DOMTextImpl.hpp>
#include <xercesc/framework/XMLValidityCodes.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XSDDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
XSDDOMParser::XSDDOMParser( XMLValidator* const   valToAdopt
                          , MemoryManager* const  manager
                          , XMLGrammarPool* const gramPool):
    XercesDOMParser(valToAdopt, manager, gramPool)
    , fSawFatal(false)
    , fAnnotationDepth(-1)
    , fInnerAnnotationDepth(-1)
    , fDepth(-1)
    , fUserErrorReporter(0)
    , fUserEntityHandler(0)    
    , fURIs(0)
    , fAnnotationBuf(1023, manager)

{
    fURIs = new (manager) ValueVectorOf<unsigned int>(16, manager);
    fXSDErrorReporter.setErrorReporter(this);    
    setValidationScheme(XercesDOMParser::Val_Never);
    setDoNamespaces(true);
}


XSDDOMParser::~XSDDOMParser()
{
    delete fURIs;
}


// ---------------------------------------------------------------------------
//  XSDDOMParser: Helper methods
// ---------------------------------------------------------------------------
DOMElement* XSDDOMParser::createElementNSNode(const XMLCh *namespaceURI,
                                              const XMLCh *qualifiedName)
{
    ReaderMgr::LastExtEntityInfo lastInfo;
    ((ReaderMgr*) fScanner->getLocator())->getLastExtEntityInfo(lastInfo);

    return getDocument()->createElementNS(namespaceURI, qualifiedName,
                                          lastInfo.lineNumber, lastInfo.colNumber);
}


void XSDDOMParser::startAnnotation( const XMLElementDecl&       elemDecl
                                  , const RefVectorOf<XMLAttr>& attrList
                                  , const unsigned int          attrCount)
{
    fAnnotationBuf.append(chOpenAngle);
	fAnnotationBuf.append(elemDecl.getFullName());
    fAnnotationBuf.append(chSpace);

    // attributes are a bit of a pain.  To get this right, we have to keep track
    // of the namespaces we've seen declared, then examine the namespace context
    // for other namespaces so that we can also include them.
    // optimized for simplicity and the case that not many
    // namespaces are declared on this annotation...
    fURIs->removeAllElements();
    for (unsigned int i=0; i < attrCount; i++) {

        const XMLAttr* oneAttrib = attrList.elementAt(i);
        const XMLCh* attrValue = oneAttrib->getValue();        

        if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString))
            fURIs->addElement(fScanner->getPrefixId(XMLUni::fgZeroLenString));
        else  if (!XMLString::compareNString(oneAttrib->getQName(), XMLUni::fgXMLNSColonString, 6))
            fURIs->addElement(fScanner->getPrefixId(oneAttrib->getName()));

        fAnnotationBuf.append(oneAttrib->getQName());
        fAnnotationBuf.append(chEqual);
        fAnnotationBuf.append(chDoubleQuote);
        fAnnotationBuf.append(attrValue);
        fAnnotationBuf.append(chDoubleQuote);
        fAnnotationBuf.append(chSpace);
    }

    // now we have to look through currently in-scope namespaces to see what
    // wasn't declared here
    ValueVectorOf<PrefMapElem*>* namespaceContext = fScanner->getNamespaceContext();
    for (unsigned int j=0; j < namespaceContext->size(); j++)
    {
        unsigned int prefId = namespaceContext->elementAt(j)->fPrefId;

        if (!fURIs->containsElement(prefId)) {

            const XMLCh* prefix = fScanner->getPrefixForId(prefId);

            if (XMLString::equals(prefix, XMLUni::fgZeroLenString)) {
                fAnnotationBuf.append(XMLUni::fgXMLNSString);
            }
            else  {
                fAnnotationBuf.append(XMLUni::fgXMLNSColonString);
                fAnnotationBuf.append(prefix);
            }

            fAnnotationBuf.append(chEqual);
            fAnnotationBuf.append(chDoubleQuote);
            fAnnotationBuf.append(fScanner->getURIText(namespaceContext->elementAt(j)->fURIId));
            fAnnotationBuf.append(chDoubleQuote);
            fAnnotationBuf.append(chSpace);
        }
    }

    fAnnotationBuf.append(chCloseAngle);
    fAnnotationBuf.append(chLF);
}

void XSDDOMParser::startAnnotationElement( const XMLElementDecl&       elemDecl
                                         , const RefVectorOf<XMLAttr>& attrList
                                         , const unsigned int          attrCount)
{
    fAnnotationBuf.append(chOpenAngle);
    fAnnotationBuf.append(elemDecl.getFullName());
    //fAnnotationBuf.append(chSpace);

    for(unsigned int i=0; i < attrCount; i++) {

        const XMLAttr* oneAttr = attrList.elementAt(i);
        fAnnotationBuf.append(chSpace);
        fAnnotationBuf.append(oneAttr ->getQName());
        fAnnotationBuf.append(chEqual);
        fAnnotationBuf.append(chDoubleQuote);
        fAnnotationBuf.append(oneAttr->getValue());
        fAnnotationBuf.append(chDoubleQuote);
    }

    fAnnotationBuf.append(chCloseAngle);
}

void XSDDOMParser::endAnnotationElement( const XMLElementDecl& elemDecl
                                       , bool complete)
{
    if (complete)
    {
        fAnnotationBuf.append(chLF);
        fAnnotationBuf.append(chOpenAngle);
        fAnnotationBuf.append(chForwardSlash);
        fAnnotationBuf.append(elemDecl.getFullName());
        fAnnotationBuf.append(chCloseAngle);

        // note that this is always called after endElement on <annotation>'s
        // child and before endElement on annotation.
        // hence, we must make this the child of the current
        // parent's only child.
        DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(fAnnotationBuf.getRawBuffer());
        fCurrentNode->appendChild(node);
        fAnnotationBuf.reset();
    }
    else      //capturing character calls
    {
        fAnnotationBuf.append(chOpenAngle);
        fAnnotationBuf.append(chForwardSlash);
        fAnnotationBuf.append(elemDecl.getFullName());
        fAnnotationBuf.append(chCloseAngle);
    }
}


// ---------------------------------------------------------------------------
//  XSDDOMParser: Setter methods
// ---------------------------------------------------------------------------
void XSDDOMParser::setUserErrorReporter(XMLErrorReporter* const errorReporter)
{
    fUserErrorReporter = errorReporter;
    fScanner->setErrorReporter(this);
}

void XSDDOMParser::setUserEntityHandler(XMLEntityHandler* const entityHandler)
{
    fUserEntityHandler = entityHandler;
    fScanner->setEntityHandler(this);
}


// ---------------------------------------------------------------------------
//  XSDDOMParser: Implementation of the XMLDocumentHandler interface
// ---------------------------------------------------------------------------
void XSDDOMParser::startElement( const XMLElementDecl&       elemDecl
                               , const unsigned int          urlId
                               , const XMLCh* const          elemPrefix
                               , const RefVectorOf<XMLAttr>& attrList
                               , const unsigned int          attrCount
                               , const bool                  isEmpty
                               , const bool                  isRoot)
{
    fDepth++;

    // while it is true that non-whitespace character data
    // may only occur in appInfo or documentation
    // elements, it's certainly legal for comments and PI's to
    // occur as children of annotation; we need
    // to account for these here.
    if (fAnnotationDepth == -1)
    {
        if (XMLString::equals(elemDecl.getBaseName(), SchemaSymbols::fgELT_ANNOTATION) &&
            XMLString::equals(getURIText(urlId), SchemaSymbols::fgURI_SCHEMAFORSCHEMA))
        {

            fAnnotationDepth = fDepth;
            startAnnotation(elemDecl, attrList, attrCount);
        } 
    }
    else if (fDepth == fAnnotationDepth+1)
    {
        fInnerAnnotationDepth = fDepth;
        startAnnotationElement(elemDecl, attrList, attrCount);
    }
    else
    {
        startAnnotationElement(elemDecl, attrList, attrCount);
        if(isEmpty)
            endElement(elemDecl, urlId, isRoot, elemPrefix);
        // avoid falling through; don't call startElement in this case
        return;
    }

    DOMElement *elem;
    if (urlId != fScanner->getEmptyNamespaceId())  //TagName has a prefix
    {
        if (elemPrefix && *elemPrefix)
        {
            XMLBufBid elemQName(&fBufMgr);
            elemQName.set(elemPrefix);
            elemQName.append(chColon);
            elemQName.append(elemDecl.getBaseName());
            elem = createElementNSNode(
                fScanner->getURIText(urlId), elemQName.getRawBuffer());
        }
        else {
            elem = createElementNSNode(
                fScanner->getURIText(urlId), elemDecl.getBaseName());
        }
    }
    else {
        elem = createElementNSNode(0, elemDecl.getBaseName());
    }

    DOMElementImpl *elemImpl = (DOMElementImpl *) elem;
    for (unsigned int index = 0; index < attrCount; ++index)
    {
        const XMLAttr* oneAttrib = attrList.elementAt(index);
        unsigned int attrURIId = oneAttrib->getURIId();
        const XMLCh* namespaceURI = 0;

        //for xmlns=...
        if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString))
            attrURIId = fScanner->getXMLNSNamespaceId();

        //TagName has a prefix
        if (attrURIId != fScanner->getEmptyNamespaceId())
            namespaceURI = fScanner->getURIText(attrURIId); //get namespaceURI

        //  revisit.  Optimize to init the named node map to the
        //            right size up front.
        DOMAttrImpl *attr = (DOMAttrImpl *)
            fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName());
        attr->setValue(oneAttrib -> getValue());
        DOMNode* remAttr = elemImpl->setAttributeNodeNS(attr);
        if (remAttr)
            remAttr->release();

        // Attributes of type ID.  If this is one, add it to the hashtable of IDs
        //   that is constructed for use by GetElementByID().
        if (oneAttrib->getType()==XMLAttDef::ID)
        {
            if (fDocument->fNodeIDMap == 0)
                fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument);
            fDocument->fNodeIDMap->add(attr);
            attr->fNode.isIdAttr(true);
        }

        attr->setSpecified(oneAttrib->getSpecified());
    }

    // set up the default attributes
    if (elemDecl.hasAttDefs())
	{
        XMLAttDefList* defAttrs = &elemDecl.getAttDefList();
        XMLAttDef* attr = 0;
        DOMAttrImpl * insertAttr = 0;

        for (unsigned int i=0; i<defAttrs->getAttDefCount(); i++)
        {
            attr = &defAttrs->getAttDef(i);

            const XMLAttDef::DefAttTypes defType = attr->getDefaultType();
            if ((defType == XMLAttDef::Default)
            ||  (defType == XMLAttDef::Fixed))
            {
                // DOM Level 2 wants all namespace declaration attributes
                // to be bound to "http://www.w3.org/2000/xmlns/"
                // So as long as the XML parser doesn't do it, it needs to
                // done here.
                const XMLCh* qualifiedName = attr->getFullName();
                XMLBufBid bbPrefixQName(&fBufMgr);
                XMLBuffer& prefixBuf = bbPrefixQName.getBuffer();
                int colonPos = -1;
                unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos);

                const XMLCh* namespaceURI = 0;
                if (XMLString::equals(qualifiedName, XMLUni::fgXMLNSString))
                    uriId = fScanner->getXMLNSNamespaceId();

                //TagName has a prefix
                if (uriId != fScanner->getEmptyNamespaceId())
                    namespaceURI = fScanner->getURIText(uriId);

                insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS(
                    namespaceURI, qualifiedName);

                DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr);
                if (remAttr)
                    remAttr->release();

                if (attr->getValue() != 0)
                {
                    insertAttr->setValue(attr->getValue());
                    insertAttr->setSpecified(false);
                }
            }

            insertAttr = 0;
            attr->reset();
        }
    }

    fCurrentParent->appendChild(elem);
    fNodeStack->push(fCurrentParent);
    fCurrentParent = elem;
    fCurrentNode = elem;
    fWithinElement = true;

    // If an empty element, do end right now (no endElement() will be called)
    if (isEmpty)
        endElement(elemDecl, urlId, isRoot, elemPrefix);
}



void XSDDOMParser::endElement( const XMLElementDecl& elemDecl
                             , const unsigned int
                             , const bool
                             , const XMLCh* const)
{
    if(fAnnotationDepth > -1)
    {
        if (fInnerAnnotationDepth == fDepth)
        {
            fInnerAnnotationDepth = -1;
            endAnnotationElement(elemDecl, false);
	    }
        else if (fAnnotationDepth == fDepth) 
        {
            fAnnotationDepth = -1;
            endAnnotationElement(elemDecl, true);
        }
        else 
        {   // inside a child of annotation
            endAnnotationElement(elemDecl, false);
            fDepth--;
            return;
        }
    }

	fDepth--;
    fCurrentNode   = fCurrentParent;
    fCurrentParent = fNodeStack->pop();

    // If we've hit the end of content, clear the flag
    if (fNodeStack->empty())
        fWithinElement = false;
}

void XSDDOMParser::docCharacters(  const   XMLCh* const    chars
                              , const unsigned int    length
                              , const bool            cdataSection)
{
    // Ignore chars outside of content
    if (!fWithinElement)
        return;

    if (fInnerAnnotationDepth == -1)
    {
        if (!((ReaderMgr*) fScanner->getReaderMgr())->getCurrentReader()->isAllSpaces(chars, length))
        {
            ReaderMgr::LastExtEntityInfo lastInfo;
            fScanner->getReaderMgr()->getLastExtEntityInfo(lastInfo);
            fXSLocator.setValues(lastInfo.systemId, lastInfo.publicId, lastInfo.lineNumber, lastInfo.colNumber);
            fXSDErrorReporter.emitError(XMLValid::NonWSContent, XMLUni::fgValidityDomain, &fXSLocator);
        }
    }
    // when it's within either of the 2 annotation subelements, characters are
    // allowed and we need to store them.
    else if (cdataSection == true)
    {
        fAnnotationBuf.append(XMLUni::fgCDataStart);
        fAnnotationBuf.append(chars, length);
        fAnnotationBuf.append(XMLUni::fgCDataEnd);
    }
    else
    {
        for(unsigned int i = 0; i < length; i++ )
        {
            if(chars[i] == chAmpersand)
            {
                fAnnotationBuf.append(chAmpersand);
                fAnnotationBuf.append(XMLUni::fgAmp);
                fAnnotationBuf.append(chSemiColon);
            }
            else if (chars[i] == chOpenAngle)
            {
                fAnnotationBuf.append(chAmpersand);
                fAnnotationBuf.append(XMLUni::fgLT);
                fAnnotationBuf.append(chSemiColon);
            }
            else {
                fAnnotationBuf.append(chars[i]);
            }
        }
    }
}

void XSDDOMParser::docComment(const XMLCh* const comment)
{
    if (fAnnotationDepth > -1)
    {
        fAnnotationBuf.append(XMLUni::fgCommentString);
        fAnnotationBuf.append(comment);
        fAnnotationBuf.append(chDash);
        fAnnotationBuf.append(chDash);
        fAnnotationBuf.append(chCloseAngle);
    }
}

void XSDDOMParser::startEntityReference(const XMLEntityDecl&)
{
}

void XSDDOMParser::endEntityReference(const XMLEntityDecl&)
{
}

void XSDDOMParser::ignorableWhitespace( const XMLCh* const chars
                                      , const unsigned int length
                                      , const bool)
{
    // Ignore chars before the root element
    if (!fWithinElement || !fIncludeIgnorableWhitespace)
        return;

    if (fAnnotationDepth > -1)
        fAnnotationBuf.append(chars, length);
}

// ---------------------------------------------------------------------------
//  XSDDOMParser: Implementation of the XMLErrorReporter interface
// ---------------------------------------------------------------------------
void XSDDOMParser::error(const   unsigned int                code
                         , const XMLCh* const                msgDomain
                         , const XMLErrorReporter::ErrTypes  errType
                         , const XMLCh* const                errorText
                         , const XMLCh* const                systemId
                         , const XMLCh* const                publicId
                         , const XMLSSize_t                  lineNum
                         , const XMLSSize_t                  colNum)
{
    if (errType >= XMLErrorReporter::ErrType_Fatal)
        fSawFatal = true;

    if (fUserErrorReporter)
        fUserErrorReporter->error(code, msgDomain, errType, errorText,
                                  systemId, publicId, lineNum, colNum);
}

InputSource* XSDDOMParser::resolveEntity(const XMLCh* const publicId,
                                         const XMLCh* const systemId,
                                         const XMLCh* const baseURI)
{
    if (fUserEntityHandler)
        return fUserEntityHandler->resolveEntity(publicId, systemId, baseURI);

    return 0;
}

InputSource*
XSDDOMParser::resolveEntity(XMLResourceIdentifier* resourceIdentifier)
{
    if (fUserEntityHandler)
        return fUserEntityHandler->resolveEntity(resourceIdentifier);

    return 0;
}

XERCES_CPP_NAMESPACE_END
