/*
 * 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: XSDDOMParser.cpp 568078 2007-08-21 11:43:25Z amassari $
  */



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