/*
 * 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$
*/
#if HAVE_CONFIG_H
#	include <config.h>
#endif
// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/internal/MemoryManagerImpl.hpp>
#include <xercesc/internal/XSerializationException.hpp>
#include <xercesc/internal/BinMemOutputStream.hpp>
#include <xercesc/util/BinMemInputStream.hpp>

#include "XSerializerTest.hpp"

#include <fstream>

// ---------------------------------------------------------------------------
//  command line option variables
// ---------------------------------------------------------------------------
static const char*                  xmlFile            = 0;
static SAX2XMLReader::ValSchemes    valScheme          = SAX2XMLReader::Val_Auto;
static bool                         doNamespaces       = true;
static bool                         doSchema           = true;
static bool                         schemaFullChecking = false;
static bool                         doList             = false;
static bool                         namespacePrefixes  = false;
static bool                         errorOccurred      = false;
static bool                         recognizeNEL       = false;

static char                         localeStr[64];

// ---------------------------------------------------------------------------
//  parsing components
// ---------------------------------------------------------------------------
static XSerializerHandlers*     handler     = 0;

/***
*
*   This program is a variation of SAX2Count.
*
*   Whenever a file is served, it does the following:
*
*   . parses the file
*   . caches the grammar without issuing any error message with regards to the parsing
*   . serializes(store) the grammar cached to a BinOutputStream
*   . deserialize(load) the grammar from the BinInputStream
*   . parses the instance document a second time
*   . validates the instance against the deserialized grammar if validation is on.
*
***/

#include <cstdio>

static
void parseCase(const char* const xmlFile);

static
bool parseOne(BinOutputStream*    outStream
            , const char* const  xmlFile);

static
void parseTwo(BinInputStream*     inStream
            , const char* const  xmlFile);

static
void parseFile(SAX2XMLReader* const parser
             , const char* const xmlFile);

static
SAX2XMLReader* getParser(XMLGrammarPool* const theGramPool
                       , bool                  setHandler);

// ---------------------------------------------------------------------------
//  Local helper methods
// ---------------------------------------------------------------------------
void usage()
{
    std::cout << "\nUsage:\n"
            "    XSerializerTest [options] <XML file | List file>\n\n"
            "This program invokes the SAX2XMLReader, and then prints the\n"
            "number of elements, attributes, spaces and characters found\n"
            "in each XML file, using SAX2 API.\n\n"
            "Options:\n"
            "    -l          Indicate the input file is a List File that has a list of xml files.\n"
            "                Default to off (Input file is an XML file).\n"
            "    -v=xxx      Validation scheme [always | never | auto*].\n"
            "    -f          Enable full schema constraint checking processing. Defaults to off.\n"
            "    -p          Enable namespace-prefixes feature. Defaults to off.\n"
            "    -n          Disable namespace processing. Defaults to on.\n"
            "                NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.\n"
            "    -s          Disable schema processing. Defaults to on.\n"
            "                NOTE: THIS IS OPPOSITE FROM OTHER SAMPLES.\n"
            "    -locale=ll_CC specify the locale, default: en_US.\n"
            "    -?          Show this help.\n\n"
            "  * = Default if not provided explicitly.\n"
         << std::endl;
}

// ---------------------------------------------------------------------------
//  Program entry point
// ---------------------------------------------------------------------------
int main(int argC, char* argV[])
{

    // Check command line and extract arguments.
    if (argC < 2)
    {
        usage();
        return 1;
    }

    memset(localeStr, 0, sizeof localeStr);

    int argInd;
    for (argInd = 1; argInd < argC; argInd++)
    {
        // Break out on first parm not starting with a dash
        if (argV[argInd][0] != '-')
            break;

        // Watch for special case help request
        if (!strcmp(argV[argInd], "-?"))
        {
            usage();
            return 2;
        }
         else if (!strncmp(argV[argInd], "-v=", 3)
              ||  !strncmp(argV[argInd], "-V=", 3))
        {
            const char* const parm = &argV[argInd][3];

            if (!strcmp(parm, "never"))
                valScheme = SAX2XMLReader::Val_Never;
            else if (!strcmp(parm, "auto"))
                valScheme = SAX2XMLReader::Val_Auto;
            else if (!strcmp(parm, "always"))
                valScheme = SAX2XMLReader::Val_Always;
            else
            {
                std::cerr << "Unknown -v= value: " << parm << std::endl;
                return 2;
            }
        }
         else if (!strcmp(argV[argInd], "-n")
              ||  !strcmp(argV[argInd], "-N"))
        {
            doNamespaces = false;
        }
         else if (!strcmp(argV[argInd], "-s")
              ||  !strcmp(argV[argInd], "-S"))
        {
            doSchema = false;
        }
         else if (!strcmp(argV[argInd], "-f")
              ||  !strcmp(argV[argInd], "-F"))
        {
            schemaFullChecking = true;
        }
         else if (!strcmp(argV[argInd], "-l")
              ||  !strcmp(argV[argInd], "-L"))
        {
            doList = true;
        }
         else if (!strcmp(argV[argInd], "-p")
              ||  !strcmp(argV[argInd], "-P"))
        {
            namespacePrefixes = true;
        }
         else if (!strcmp(argV[argInd], "-special:nel"))
        {
            // turning this on will lead to non-standard compliance behaviour
            // it will recognize the unicode character 0x85 as new line character
            // instead of regular character as specified in XML 1.0
            // do not turn this on unless really necessary
             recognizeNEL = true;
        }
         else if (!strncmp(argV[argInd], "-locale=", 8))
        {
             // Get out the end of line
             strcpy(localeStr, &(argV[argInd][8]));
        }
        else
        {
            std::cerr << "Unknown option '" << argV[argInd]
                << "', ignoring it\n" << std::endl;
        }
    }

    //
    //  There should at least one parameter left, and that
    //  should be the file name(s).
    //
    if (argInd == argC)
    {
        usage();
        return 1;
    }

    // Initialize the XML4C2 system
    try
    {
        if (strlen(localeStr))
        {
            XMLPlatformUtils::Initialize(localeStr);
        }
        else
        {
            XMLPlatformUtils::Initialize();
        }

        if (recognizeNEL)
        {
            XMLPlatformUtils::recognizeNEL(recognizeNEL);
        }

    }

    catch (const XMLException& toCatch)
    {
        std::cerr << "Error during initialization! Message:\n"
            << StrX(toCatch.getMessage()) << std::endl;
        return 1;
    }

    std::ifstream fin;

    // the input is a list file
    if (doList)
        fin.open(argV[argInd]);

    if (fin.fail()) {
        std::cerr <<"Cannot open the list file: " << argV[argInd] << std::endl;
        return 2;
    }

    while (true)
    {
        char fURI[1000];
        //initialize the array to zeros
        memset(fURI,0,sizeof(fURI));

        if (doList) {
            if (! fin.eof() ) {
                fin.getline (fURI, sizeof(fURI));
                if (!*fURI)
                    continue;
                else {
                    xmlFile = fURI;
                    std::cerr << "==Parsing== " << xmlFile << std::endl;
                }
            }
            else
                break;
        }
        else {
            if (argInd < argC)
            {
                 xmlFile = argV[argInd];
                 argInd++;
            }
            else
                break;
        }

        parseCase(xmlFile);
    }

    if (doList)
        fin.close();

    // And call the termination method
    XMLPlatformUtils::Terminate();

    if (errorOccurred)
        return 4;
    else
        return 0;

}

// ---------------------------------------------------------------------------
//  Serialization/Deserialization
// ---------------------------------------------------------------------------
static const int BufSize = 1024;

static void parseCase(const char* const xmlFile)
{
    //
    //  Create our SAX handler object and install it on the parser, as the
    //  document and error handler.
    //
    if (!handler)
        handler = new XSerializerHandlers();

    BinOutputStream* myOut = new BinMemOutputStream(BufSize);
    Janitor<BinOutputStream> janOut(myOut);

    if (!parseOne(myOut, xmlFile))
        return;

    BinInputStream*  myIn  = new BinMemInputStream(
                                                   ((BinMemOutputStream*)myOut)->getRawBuffer()
                                                 , (XMLSize_t)((BinMemOutputStream*)myOut)->getSize()
                                                 , BinMemInputStream::BufOpt_Reference
                                                  );
    Janitor<BinInputStream> janIn(myIn);

    parseTwo(myIn, xmlFile);

}

static
bool parseOne(BinOutputStream*    outStream
            , const char* const   xmlFile)
{
    //we don't use janitor here
    MemoryManager*  theMemMgr   = new MemoryManagerImpl();
    XMLGrammarPool* theGramPool = new XMLGrammarPoolImpl(theMemMgr);
    SAX2XMLReader*  theParser   = getParser(theGramPool, false);  //don't emit error
    bool            retVal      = true;

    theParser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);

    //scan instance document and cache grammar
    try
    {
        theParser->parse(xmlFile);
    }
    catch (...)
    {
        //do nothing, it could be an invalid instance document, but the grammar is fine
    }

    //serialize the grammar pool
    try
    {
        theGramPool->serializeGrammars(outStream);
    }
    catch (const XSerializationException& e)
    {
        //do emit error here so that we know serialization failure
        std::cerr << "An error occurred during serialization\n   Message: "
            << StrX(e.getMessage()) << std::endl;

        retVal = false;
    }

    catch (...)
    {
        //do emit error here so that we know serialization failure
        std::cerr << "An error occurred during serialization\n" << std::endl;

        retVal = false;
    }

    //the order is important
    delete theParser;
    delete theGramPool;
    delete theMemMgr;

    return retVal;
}

static
void parseTwo(BinInputStream*     inStream
            , const char* const   xmlFile)
{
    //we don't use janitor here
    MemoryManager*  theMemMgr   = new MemoryManagerImpl();
    XMLGrammarPool* theGramPool = new XMLGrammarPoolImpl(theMemMgr);
    bool            errorSeen   = false;

    //de-serialize grammar pool
    try
    {
        theGramPool->deserializeGrammars(inStream);
    }

    catch(const XSerializationException& e)
    {
        std::cerr << "An error occurred during de-serialization\n   Message: "
            << StrX(e.getMessage()) << std::endl;

        errorSeen = true;
    }

    catch (...)
    {
        //do emit error here so that we know serialization failure
        std::cerr << "An error occurred during de-serialization\n" << std::endl;

        errorSeen = true;
    }

    if (!errorSeen)
    {
        SAX2XMLReader*  theParser   = getParser(theGramPool, true); //set the handler

        theParser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
        parseFile(theParser, xmlFile);
        delete theParser;
    }

    //the order is important
    delete theGramPool;
    delete theMemMgr;

    return;
}

static SAX2XMLReader* getParser(XMLGrammarPool* const theGramPool
                              , bool                  setHandler)
{
    SAX2XMLReader* parser = XMLReaderFactory::createXMLReader(theGramPool->getMemoryManager(), theGramPool);

    parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, doNamespaces);
    parser->setFeature(XMLUni::fgXercesSchema, doSchema);
    parser->setFeature(XMLUni::fgXercesHandleMultipleImports, true);
    parser->setFeature(XMLUni::fgXercesSchemaFullChecking, schemaFullChecking);
    parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, namespacePrefixes);

    if (valScheme == SAX2XMLReader::Val_Auto)
    {
        parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
        parser->setFeature(XMLUni::fgXercesDynamic, true);
    }
    if (valScheme == SAX2XMLReader::Val_Never)
    {
        parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
    }
    if (valScheme == SAX2XMLReader::Val_Always)
    {
        parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
        parser->setFeature(XMLUni::fgXercesDynamic, false);
    }

    if (setHandler)
    {
        parser->setContentHandler(handler);
        parser->setErrorHandler(handler);
    }
    else
    {
        parser->setContentHandler(0);
        parser->setErrorHandler(0);
    }

    return parser;
}

static void parseFile(SAX2XMLReader* const parser
                    , const char* const xmlFile)
{
    //
    //  Get the starting time and kick off the parse of the indicated
    //  file. Catch any exceptions that might propogate out of it.
    //
    unsigned long duration;

    //reset error count first
    handler->resetErrors();

    try
    {
        const unsigned long startMillis = XMLPlatformUtils::getCurrentMillis();
        parser->parse(xmlFile);
        const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis();
        duration = endMillis - startMillis;
    }
    catch (const XMLException& e)
    {
        std::cerr << "\nError during parsing: '" << xmlFile << "'\n"
            << "Exception message is:  \n"
            << StrX(e.getMessage()) << "\n" << std::endl;
        errorOccurred = true;
    }
    catch (...)
    {
        std::cerr << "\nUnexpected exception during parsing: '" << xmlFile << "'\n";
        errorOccurred = true;
    }

    // Print out the stats that we collected and time taken
    if (!handler->getSawErrors())
    {
        std::cout << xmlFile << ": " << duration << " ms ("
            << handler->getElementCount() << " elems, "
            << handler->getAttrCount() << " attrs, "
            << handler->getSpaceCount() << " spaces, "
            << handler->getCharacterCount() << " chars)" << std::endl;
    }
    else
        errorOccurred = true;

}
