/*
 * 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 "XMLHarnessHandlers.hpp"
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/SAXException.hpp>
#include <xercesc/validators/common/Grammar.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/BinInputStream.hpp>

// ---------------------------------------------------------------------------
//  XMLHarnessHandlers: Constructors and Destructor
// ---------------------------------------------------------------------------
XMLHarnessHandlers::XMLHarnessHandlers(const XMLCh* baseURL, const XMLCh* scanner) : BaseHarnessHandlers(baseURL)
, fTestBaseURL(5)
{
    fParser = XMLReaderFactory::createXMLReader();
    fParser->setProperty(XMLUni::fgXercesScannerName, (void*)scanner);
    fParser->setFeature(XMLUni::fgSAX2CoreValidation, true);
    fParser->setFeature(XMLUni::fgXercesDynamic, false);
    fParser->setErrorHandler(&fErrorHandler);
    
    fTestBaseURL.push(new XMLURL(fBaseURL));
}

XMLHarnessHandlers::~XMLHarnessHandlers()
{
    delete fParser;
}

static XMLCh szTest[]={ chLatin_T, chLatin_E, chLatin_S, chLatin_T, chNull };
static XMLCh szTestCases[]={ chLatin_T, chLatin_E, chLatin_S, chLatin_T, chLatin_C, chLatin_A, chLatin_S, chLatin_E, chLatin_S, chNull };
static XMLCh szID[]={ chLatin_I, chLatin_D, chNull };
static XMLCh szURI[]={ chLatin_U, chLatin_R, chLatin_I, chNull };
static XMLCh szType[]={ chLatin_T, chLatin_Y, chLatin_P, chLatin_E, chNull };
static XMLCh szValid[]={ chLatin_v, chLatin_a, chLatin_l, chLatin_i, chLatin_d, chNull };
static XMLCh szInvalid[]={ chLatin_i, chLatin_n, chLatin_v, chLatin_a, chLatin_l, chLatin_i, chLatin_d, chNull };
static XMLCh szNotWellFormed[]={ chLatin_n, chLatin_o, chLatin_t, chDash, chLatin_w, chLatin_f, chNull };
static XMLCh szError[]={ chLatin_e, chLatin_r, chLatin_r, chLatin_o, chLatin_r, chNull };
static XMLCh szBase[]={ chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull };
static XMLCh szNamespace[]={ chLatin_N, chLatin_A, chLatin_M, chLatin_E, chLatin_S, chLatin_P, chLatin_A, chLatin_C, chLatin_E, chNull };
static XMLCh szNO[]={ chLatin_n, chLatin_o, chNull };
static XMLCh szVersion[] = { chLatin_V, chLatin_E, chLatin_R, chLatin_S, chLatin_I, chLatin_O, chLatin_N, chNull };
static XMLCh szEdition[] = { chLatin_E, chLatin_D, chLatin_I, chLatin_T, chLatin_I, chLatin_O, chLatin_N, chNull };
static XMLCh szFive[]={ chDigit_5, chNull };

// ---------------------------------------------------------------------------
//  XMLHarnessHandlers: Implementation of the SAX DocumentHandler interface
// ---------------------------------------------------------------------------
void XMLHarnessHandlers::startElement(const XMLCh* const /* uri */
                                   , const XMLCh* const localname
                                   , const XMLCh* const /* qname */
                                   , const Attributes& attrs)
{
    if(XMLString::equals(localname, szTestCases))
    {
        const XMLCh* baseUrl=attrs.getValue(szBase);
        XMLURL newBase;
        XMLURL prevBase=*fTestBaseURL.peek();
        if(baseUrl!=NULL)
            newBase.setURL(prevBase, baseUrl);
        else
            newBase=prevBase;
        fTestBaseURL.push(new XMLURL(newBase));
    }
    else if(XMLString::equals(localname, szTest))
    {
        const XMLCh* useNS=attrs.getValue(szNamespace);
        const XMLCh* testName=attrs.getValue(szID);
        const XMLCh* version=attrs.getValue(szVersion);
        if(version == NULL || XMLString::equals(version, XMLUni::fgVersion1_0))
        {
            const XMLCh* editions=attrs.getValue(szEdition);
            // skip tests that don't apply to v.1.0 5th Edition
            if(editions)
            {
                BaseRefVectorOf<XMLCh>* tokens = XMLString::tokenizeString(editions);
                bool appliesTo5 = false;
                for (XMLSize_t i = 0; i < tokens->size(); i++) {
                    if (XMLString::equals(tokens->elementAt(i), szFive)) {
                        appliesTo5 = true;
                        break;
                    }
                }
                delete tokens;
                if(!appliesTo5)
                    return;
            }
        }

        XMLURL testSet;
        testSet.setURL(*fTestBaseURL.peek(), attrs.getValue(szURI));
        bool success=true, fatalFailure=false;
        try
        {
            if(useNS!=NULL && XMLString::equals(useNS, szNO))
            {
                fParser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
                fParser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, false);
            }
            else
            {
                fParser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
                fParser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true);
            }
            fErrorHandler.resetErrors();
            fParser->parse(testSet.getURLText());
        }
        catch (const OutOfMemoryException&)
        {
            fatalFailure=true;
            std::cout << "Test " << StrX(testName) << " ran out of memory" << std::endl;
            success=false;
        }
        catch(const XMLException& exc)
        {
            std::cout << "Test " << StrX(testName) << " threw " << StrX(exc.getMessage()) << std::endl;
            success=false;
        }
        catch (...)
        {
            fatalFailure=true;
            std::cout << "Test " << StrX(testName) << " crashed" << std::endl;
            success=false;
            exit(1);
        }
        fTests++;
        if(fatalFailure)
        {
            fFailures++;
            printFile(testSet);
        }
        else
        {
            ValidityOutcome expResult=unknown;
            const XMLCh* validity=attrs.getValue(szType);
            if(XMLString::equals(validity, szValid))
                expResult=valid;
            else if(XMLString::equals(validity, szInvalid) || XMLString::equals(validity, szNotWellFormed) || XMLString::equals(validity, szError) )
                expResult=invalid;
            else
                std::cerr << "Unknown result type " << StrX(validity) << std::endl;
            if(success && !fErrorHandler.getSawErrors())
            {
                if(expResult!=valid)
                {
                    fFailures++;
                    std::cout << "Test " << StrX(testName) << " succeeded but was expected to fail" << std::endl;
                    printFile(testSet);
                }
            }
            else
            {
                if(expResult!=invalid)
                {
                    fFailures++;
                    std::cout << "Test " << StrX(testName) << " failed but was expected to pass" << std::endl;
                    std::cout << "Reported error: " << StrX(fErrorHandler.getErrorText()) << std::endl;
                    printFile(testSet);
                }
            }
        }
    }
}

void XMLHarnessHandlers::endElement(const XMLCh* const /* uri */, const XMLCh* const localname, const XMLCh* const /* qname */)
{
    if(XMLString::equals(localname, szTestCases))
    {
        fTestBaseURL.pop();
    }
}
