/*
 * 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.
 */
// Base header file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>



#include <cstdio>

#if defined(XALAN_CLASSIC_IOSTREAMS)
#include <iostream.h>
#include <strstream.h>
#else
#include <iostream>
#include <strstream>
#endif



// This is here for memory leak testing. 
#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif



#include <xercesc/util/PlatformUtils.hpp>



// EXTENSION HEADERS...
#include <xalanc/XalanExtensions/FunctionDifference.hpp>
#include <xalanc/XalanExtensions/FunctionDistinct.hpp>
#include <xalanc/XalanExtensions/FunctionEvaluate.hpp>
#include <xalanc/XalanExtensions/FunctionHasSameNodes.hpp>
#include <xalanc/XalanExtensions/FunctionIntersection.hpp>
#include <xalanc/XalanExtensions/FunctionNodeSet.hpp>



#include <xalanc/XalanTransformer/XalanTransformer.hpp>



// HARNESS HEADERS...
#include <xalanc/Harness/XalanXMLFileReporter.hpp>
#include <xalanc/Harness/XalanFileUtility.hpp>



XALAN_USING_STD(cerr)
XALAN_USING_STD(cout)
XALAN_USING_STD(endl)



// GLOBAL VARIABLES...
const char* const   resultString = "The specified function is not available: http://xml.apache.org/xalan:nodeset";


using xalanc::XalanFileUtility;
using xalanc::XalanDOMString;
using xalanc::XalanTransformer;
using xalanc::XalanXMLFileReporter;
using xalanc::XSLTInputSource;
using xalanc::XSLTResultTarget;



void
setHelp(XalanFileUtility&   h)
{
    h.args.getHelpStream() << endl
         << "extensions dirname [-out]"
         << endl
         << endl
         << "dirname        (base directory for xml-xalan\\test\\tests\\extensions)"
         << endl
         << "-out dirname   (base directory for output)"
         << endl;
}


// Generate the various filenames needed for testing.
void
generateFiles(
            const XalanDOMString&   fileName,
            const XalanDOMString&   currentDir,
            XalanDOMString&         xml, 
            XalanDOMString&         xsl,
            XalanDOMString&         out,
            XalanDOMString&         gold,
            const char*             test,
            XalanFileUtility&       h)
{
    // Set up the input/output files.
    const XalanDOMString testName(h.generateFileName(fileName,"out"));

    xsl = h.args.base + currentDir + XalanFileUtility::s_pathSep + fileName;
    xml = h.generateFileName(xsl,"xml");
    h.data.xmlFileURL = xml;
    h.data.xslFileURL = xsl;

    out =  h.args.output + currentDir + XalanFileUtility::s_pathSep + XalanDOMString(test) + testName; 

    gold = h.args.gold + currentDir + XalanFileUtility::s_pathSep + testName;

}

//  TestCase1
//  API Call: 
//      None. Verfies default behavior of XalanTransformer.
//  Comments:
//      This testcase is called once for each function that XalanC implements. It verfies that the function 
//      was properly installed and working correctly within the transformer.  All functions are preinstalled
//      globally. Currently XalanC supports the following extensions; difference, distinct, evaluate, 
//      hasSameNodes, intersection and nodeset. 
//       
void
TestCase1(
            XalanTransformer&       xalan,
            const XalanDOMString&   fileName,
            const XalanDOMString&   currentDir,
            XalanXMLFileReporter&   logFile,
            XalanFileUtility&       h)
{
    
    XalanDOMString  xml, xsl, theOutputFile, theGoldFile;
        
    generateFiles(fileName, currentDir, xml, xsl, theOutputFile, theGoldFile, "tc1-", h);

    h.data.testOrFile = XalanDOMString("TestCase1: ") + fileName;
    h.data.xmlFileURL = xml;
    h.data.xslFileURL = xsl;

    // Create the InputSources and ResultTraget.
    const XSLTInputSource   xmlInputSource(xml);
    const XSLTInputSource   xslInputSource(xsl);
    const XSLTResultTarget  theResultTarget(theOutputFile);

    // Perform the transform and check the results.
    xalan.transform(xmlInputSource, xslInputSource, theResultTarget);   
    h.checkResults(theOutputFile, theGoldFile, logFile);

}

//  TestCase2
//  API Call:
//      XalanTransformer::uninstallExternalFunctionGlobal
//  Comments:
//      This test verifies that the 'nodeset' function is properly uninstalled via the api.
//      Output file should NOT contain data. 
//
void
TestCase2(
            XalanTransformer&       xalan,
            const XalanDOMString&   fileName,
            const XalanDOMString&   currentDir,
            const XalanDOMString&   theNamespace,
            XalanXMLFileReporter&   logFile,
            XalanFileUtility&       h)
{   

    XalanDOMString  xml, xsl, theOutputFile, theGoldFile;
    
    generateFiles(fileName, currentDir, xml, xsl, theOutputFile, theGoldFile, "tc2-", h);
    h.data.testOrFile = XalanDOMString("TestCase2");
    h.data.xmlFileURL = xml;
    h.data.xslFileURL = xsl;

    // Create the InputSources and ResultTraget.
    const XSLTInputSource   xmlInputSource(xml);
    const XSLTInputSource   xslInputSource(xsl);
    const XSLTResultTarget  theResultTarget(theOutputFile);

    // UnInstall the external Global function "nodeset"
    xalan.uninstallExternalFunctionGlobal(
                    theNamespace,
                    XalanDOMString("nodeset"));

    //Perform the transform and check the results.
    xalan.transform(xmlInputSource, xslInputSource, theResultTarget);

    h.checkAPIResults(xalan.getLastError(), 
                          resultString,
                          "transformer.uninstallExternalFunctionGlobal()",
                          logFile,
                          theOutputFile,
                          theGoldFile,
                          true);
}
//  TestCase3:
//  API Call:   
//      XalanTransformer::installExternalFunction
//      XalanTransformer::uninstallExternalFunction
//  Comments:
//      This tests the installExternalFunction method of XalanTransformer using the nodeset function.
//      Output file should NOT contain data.
//
void TestCase3(
            XalanTransformer&       xalan,
            const XalanDOMString&   fileName,
            const XalanDOMString&   currentDir,
            const XalanDOMString&   theNamespace,
            XalanXMLFileReporter&   logFile,
            XalanFileUtility&       h)
{
    using xalanc::FunctionNodeSet;

    XalanDOMString  xml, xsl, theOutputFile, theGoldFile;
    
    generateFiles(fileName, currentDir, xml, xsl, theOutputFile, theGoldFile, "tc3-", h);

    h.data.testOrFile = XalanDOMString("TestCase3a");
    h.data.xmlFileURL = xml;
    h.data.xslFileURL = xsl;

    // Create the InputSources and ResultTraget.
    const XSLTInputSource   xmlInputSource(xml);
    const XSLTInputSource   xslInputSource(xsl);
    const XSLTResultTarget  theResultTarget(theOutputFile);

    // Install the external function "nodeset"
    xalan.installExternalFunction(theNamespace,
                                  XalanDOMString("nodeset"),
                                  FunctionNodeSet());

    // Perform the transform and check the results.
    xalan.transform(xmlInputSource, xslInputSource, theResultTarget);

    h.checkResults(theOutputFile, theGoldFile, logFile);

    // Because we install the function locally, this second instance of the transformer 
    // should _NOT_ run the test successfully.
    XalanTransformer newEngine;
    h.data.testOrFile = XalanDOMString("TestCase3b");

    //Perform the transform and check the results.
    newEngine.transform(xmlInputSource, xslInputSource, theResultTarget);
    h.checkAPIResults(newEngine.getLastError(), 
                               resultString,
                               "transformer.installExternalFunction()",
                               logFile,
                               theOutputFile,
                               theGoldFile,
                               true);

    // Now unInstall the external function "nodeset". Once again the transform should
    // _NOT_ run the test successfully
    h.data.testOrFile = XalanDOMString("TestCase3c");
    xalan.uninstallExternalFunction(theNamespace, XalanDOMString("nodeset"));

    // Perform the transform and check the results.
    xalan.transform(xmlInputSource, xslInputSource, theResultTarget);
    h.checkAPIResults(xalan.getLastError(), 
                               resultString,
                               "transformer.uninstallExternalFunction()",
                               logFile,
                               theOutputFile,
                               theGoldFile,
                               true);

}

//  TestCase4:
//  API Call: 
//      XalanTransformer::installExternalFunctionGlobal
//  Comments:
//      This tests uses transformer method installExternalFunctionGlobal to add the nodeset function. 
//      The output file should contain data.
//
void TestCase4(
            XalanTransformer&       xalan,
            const XalanDOMString&   fileName,
            const XalanDOMString&   currentDir,
            const XalanDOMString&   theNamespace,
            XalanXMLFileReporter&   logFile,
            XalanFileUtility&       h)
{
    using xalanc::FunctionNodeSet;
    
    XalanDOMString  xml, xsl, theOutputFile, theGoldFile;

    generateFiles(fileName, currentDir, xml, xsl, theOutputFile, theGoldFile, "tc4-", h);
    h.data.testOrFile = XalanDOMString("TestCase4a");
    h.data.xmlFileURL = xml;
    h.data.xslFileURL = xsl;

    // Create the InputSources and ResultTraget.
    const XSLTInputSource   xmlInputSource(xml);
    const XSLTInputSource   xslInputSource(xsl);
    const XSLTResultTarget  theResultTarget(theOutputFile);

    // Install the external function "nodeset" Globally
    xalan.installExternalFunctionGlobal(theNamespace,
                                        XalanDOMString("nodeset"),
                                        FunctionNodeSet());

    // Perform the transform and check the results.
    xalan.transform(xmlInputSource, xslInputSource, theResultTarget);
    h.checkResults(theOutputFile, theGoldFile, logFile);

    // Create a second transformer and verify that it can 'see' the extension as well...
    XalanTransformer newEngine;
    h.data.testOrFile = XalanDOMString("TestCase4b");

    newEngine.transform(xmlInputSource, xslInputSource, theResultTarget);
    h.checkResults(theOutputFile, theGoldFile, logFile);

}



int
runTests(
            int     argc,
            char*   argv[])
{
    int             theResult = 0;

    XalanFileUtility    h;

    // Set the program help string,  then get the command line parameters.
    //
    setHelp(h); 

    if (h.getParams(argc, argv, "EXTENSION-RESULTS") == true)
    {
        const XalanDOMString    currentDir("library");
        const XalanDOMString    extDir(h.args.base + currentDir);

        // Check that the base directory is correct.
        if ( !h.checkDir(extDir) )
        {
            cout << "Invalid base directory - " << extDir << endl;
            cout << h.args.getHelpMessage();

            theResult = -1;
        }
        else
        {
            try
            {
                // Generate Unique Run id. (Only used to name the result logfile.)
                const XalanDOMString    UniqRunid = h.generateUniqRunid();

                // Defined basic constants for file manipulation 
                const XalanDOMString    drive(h.getDrive());
                const XalanDOMString    resultsFile(drive + h.args.output + currentDir + UniqRunid + XalanFileUtility::s_xmlSuffix);
                
                XalanXMLFileReporter    logFile(resultsFile);
                logFile.logTestFileInit("C++ Extension Testing. ");
                logFile.logTestCaseInit(currentDir);

                cout << "Performing Extension testing ..." << endl;

                XalanTransformer    xalan;              
                        
                // Check that output directory is there.
                XalanDOMString      fileName;
                        
                const XalanDOMString    theOutputDir(h.args.output + currentDir);

                h.checkAndCreateDir(theOutputDir);

                typedef XalanFileUtility::FileNameVectorType        FileNameVectorType;

                // Get the files found in the "cextension" directory
                const FileNameVectorType    files = h.getTestFileNames(h.args.base, currentDir, true);

                // TestCase1 is used to verify correct functioning of the default extension functions
                TestCase1(xalan, files[0], currentDir, logFile, h); // Difference function
                TestCase1(xalan, files[1], currentDir, logFile, h); // Distinct 
                TestCase1(xalan, files[2], currentDir, logFile, h); // Evaluate 
                TestCase1(xalan, files[3], currentDir, logFile, h); // HasSameNodes 
                TestCase1(xalan, files[4], currentDir, logFile, h); // Intersection 
                TestCase1(xalan, files[5], currentDir, logFile, h); // NodeSet01 - basic testing
                TestCase1(xalan, files[6], currentDir, logFile, h); // NodeSet02 - extensive RTF testing. 

                const XalanDOMString    theNamespace("http://xml.apache.org/xalan");

                // These testcases are used to test the Install/Uninstall Function API's of the transformer.
                TestCase2(xalan, files[5], currentDir, theNamespace, logFile, h);
                TestCase3(xalan, files[5], currentDir, theNamespace, logFile, h);
                TestCase4(xalan, files[5], currentDir, theNamespace, logFile, h);

                logFile.logTestCaseClose("Done", "Pass");
                h.reportPassFail(logFile, UniqRunid);
                    
                logFile.logTestFileClose("C++ Extension Testing: ", "Done");
                logFile.close();

                h.analyzeResults(xalan, resultsFile);
            }
            catch(...)
            {
                cerr << "Exception caught!!!" << endl << endl;

                theResult = -1;
            }
        }
    }

    return theResult;

}



int
main(
            int     argc,
            char*   argv[])
{
#if !defined(NDEBUG) && defined(_MSC_VER)
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

    int theResult = 0;

    try
    {
        using xercesc::XMLPlatformUtils;

        // Call the static initializers for xerces and xalan, and create a transformer
        //
        XMLPlatformUtils::Initialize();

        XalanTransformer::initialize();

        theResult = runTests(argc, argv);

        XalanTransformer::terminate();

        XMLPlatformUtils::Terminate();

        XalanTransformer::ICUCleanUp();
    }
    catch(...)
    {
        cerr << "Initialization failed!" << endl << endl;

        theResult = -1;
    }

    return theResult;
}
