dbertoni    2004/08/03 08:59:09

  Added:       c/src/xalanc/Harness XalanFileUtility.cpp
                        XalanFileUtility.hpp XalanHarnessDefinitions.hpp
                        XalanXMLFileReporter.cpp XalanXMLFileReporter.hpp
  Log:
  Initial revision.
  
  Revision  Changes    Path
  1.1                  xml-xalan/c/src/xalanc/Harness/XalanFileUtility.cpp
  
  Index: XalanFileUtility.cpp
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed 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.
   */
  
  #include "XalanFileUtility.hpp"
  
  
  
  #include <cstdlib>
  #include <cstdio>
  #include <ctime>
  #include <vector>
  #include <climits>
  #include <cstring>
  
  #if defined(WIN32)
  #include <direct.h>
  #define PATH_MAX _MAX_PATH
  #define chdir _chdir
  #define getcwd _getcwd
  #define mkdir _mkdir
  #else
  #if !defined(PATH_MAX)
  #define PATH_MAX 2000
  #endif
  #define DIR_MODE_BITS 509
  #include <dirent.h>
  #include <unistd.h>
  
  #include <sys/stat.h>
  #endif
  
  
  #if defined(XALAN_CLASSIC_IOSTREAMS)
  #include <iostream.h>
  #include <strstream.h>
  #else
  #include <iostream>
  #include <strstream>
  #endif
  
  #if !defined(NDEBUG) && defined(_MSC_VER)
  #include <crtdbg.h>
  #endif
  
  
  
  #include "xercesc/sax/SAXException.hpp"
  
  
  
  #include "xalanc/PlatformSupport/DirectoryEnumerator.hpp"
  #include "xalanc/PlatformSupport/DOMStringHelper.hpp"
  #include "xalanc/PlatformSupport/XalanOutputStreamPrintWriter.hpp"
  #include "xalanc/PlatformSupport/XalanFileOutputStream.hpp"
  #include "xalanc/PlatformSupport/XalanUnicode.hpp"
  
  
  
  #include "xalanc/XMLSupport/FormatterToXML.hpp"
  #include "xalanc/XMLSupport/FormatterTreeWalker.hpp"
  
  
  
  #include "xalanc/XalanSourceTree/XalanSourceTreeDOMSupport.hpp"
  #include "xalanc/XalanSourceTree/XalanSourceTreeParserLiaison.hpp"
  #include "xalanc/XalanSourceTree/XalanSourceTreeDocument.hpp"
  
  
  
  #include "xalanc/XSLT/StylesheetRoot.hpp"
  
  
  
  #include "xalanc/XalanTransformer/XalanCompiledStylesheet.hpp"
  #include "xalanc/XalanTransformer/XalanTransformer.hpp"
  
  
  
  #include "XalanXMLFileReporter.hpp"
  
  
  
  XALAN_CPP_NAMESPACE_BEGIN
  
  
  
  
  const char* const   xalanNodeTypes[] =
  {
      "UNKNOWN_NODE",
      "ELEMENT_NODE",
      "ATTRIBUTE_NODE",
      "TEXT_NODE",
      "CDATA_SECTION_NODE",
      "ENTITY_REFERENCE_NODE",
      "ENTITY_NODE",
      "PROCESSING_INSTRUCTION_NODE",
      "COMMENT_NODE",
      "DOCUMENT_NODE",
      "DOCUMENT_TYPE_NODE",
      "DOCUMENT_FRAGMENT_NODE",
      "NOTATION_NODE"
  };
  
  
  
  XALAN_USING_STD(cerr)
  XALAN_USING_STD(cout)
  XALAN_USING_STD(endl)
  
  
  const XalanDOMString    XalanFileUtility::s_emptyString;
  
  
  
  XalanFileUtility::reportStruct::reportStruct() :
      theDrive(),
      testOrFile(),
      xmlFileURL(),
      xslFileURL(),
      xmlFormat(),
      msg(0),
      currentNode(),
      actual(),
      expected(),
      pass(0),
      fail(0),
      nogold(0)
  {
  }
  
  
  
  void
  XalanFileUtility::reportStruct::reset()
  {
      clear(testOrFile);
      msg = "";
      clear(currentNode);
      clear(actual);
      clear(expected);
  }
  
  
  
  XalanFileUtility::cmdParams::cmdParams() :
      help(),
      base(),
      output(),
      gold(),
      sub(),
      source(0),
      skip(false),
      iters(0)
  {
  }
  
  
  
  const char*
  XalanFileUtility::cmdParams::getHelpMessage()
  {
      help << '\0';
  
      const char* const   data = help.str();
  
  #if defined(HPUX)
     help.rdbuf() -> freeze(false);
  #else
      help.freeze(false);
  #endif
  
      return data;
  }
  
  
  
  XalanFileUtility::XalanFileUtility() :
      data(),
      args()
  {
      cout << endl
           << "Using Xalan version "
           << XALAN_FULLVERSIONDOT
           << endl
           << "Using Xerces version "
           << XERCES_FULLVERSIONDOT
           << endl
           << endl;
  }
  
  
  
  XalanFileUtility::~XalanFileUtility()
  {
  }
  
  
  
  #if !defined(WIN32)
  XalanDOMString
  XalanFileUtility::getDrive()
  {
      return XalanDOMString();
  }
  #else
  XalanDOMString
  XalanFileUtility::getDrive()
  {
      const char temp[] =
      {
          char(_getdrive() + 'A' - 1),
          ':',
          '\0'
      };
      
      return XalanDOMString(temp, sizeof(temp) - 1);
  }
  #endif
  
  
  bool
  XalanFileUtility::getParams(
              int             argc,
              char*           argv[],
              const char*     outDir,
              bool            fsetGold)
  {
      bool fSuccess = true;   // Used to continue argument loop
      bool fsetOut = true;    // Set default output directory, set to false if 
data is provided
  
      args.skip = true;       // Default values for performance testing 
parameters.
      args.iters = 3;         
  
      // Insure that required "-base" argument is there.
      //
      if (argc == 1 || argv[1][0] == '-')
      {
          cout << args.getHelpMessage();  
          return false;
      }
      else
      {
          if (checkDir(XalanDOMString(argv[1])))
          {
              assign(args.base, XalanDOMString(argv[1]));
          }
          else
          {
              cout << endl << "Given base directory \"" << argv[1] << "\" does 
not exist" << endl;
              cout << args.getHelpMessage();
              return false;
          }
      }
  
      // Get the rest of the arguments.
      //
      for (int i = 2; i < argc && fSuccess == true; ++i)
      {
          if(!stricmp("-out", argv[i]))
          {
              ++i;
              if(i < argc && argv[i][0] != '-')
              {
                  assign(args.output, XalanDOMString(argv[i]));
                  append(args.output, s_pathSep);
                  checkAndCreateDir(args.output);
                  fsetOut = false;
              }
              else
              {
                  cout << args.getHelpMessage();
                  fSuccess = false;
              }
          }
          else if(!stricmp("-gold", argv[i]))
          {
              ++i;
              if(i < argc && argv[i][0] != '-')
              {
                  assign(args.gold, XalanDOMString(argv[i]));
  
                  if ( !checkDir(args.gold) )
                  {   
                      cout << "Given Gold dir - " << 
c_str(TranscodeToLocalCodePage(args.gold)) << " - does not exist" << endl;
                      fSuccess = false;
                  }
  
                  append(args.gold, s_pathSep);
                  fsetGold = false;
              }
              else
              {
                  cout << args.getHelpMessage();
                  fSuccess = false;
              }
          }
          else if(!stricmp("-source", argv[i]))
          {
              ++i;
              if(i < argc && argv[i][0] != '-')
              {
                  if (stricmp(argv[i],"XPL") == 0)
                  {
                      args.source = 1;
                      outDir = "DOM-XALAN";
                  }
                  else if (stricmp(argv[i], "DOM") == 0)
                  {
                      args.source = 2;
                      outDir = "DOM-XERCES";
                  }
                  else
                  {
                      cout << args.getHelpMessage();
                      fSuccess = false;
                  }
              }
              else
              {
                  cout << args.getHelpMessage();
                  fSuccess = false;
              }
          }
          else if(!stricmp("-sub", argv[i]))
          {
              ++i;
              if(i < argc && argv[i][0] != '-')
              {
                  assign(args.sub, XalanDOMString(argv[i]));
              }
              else
              {
                  cout << args.getHelpMessage();
                  fSuccess = false;
              }
          }
          else if(!stricmp("-i", argv[i]))
          {
              args.skip = false;
          }
          else if(!stricmp("-iter", argv[i]))
          {
              ++i;
              
              // Make sure number is there and is greater then zero
              if(i < argc && atol(argv[i]) > 0)
              {
                  args.iters = atol(argv[i]);
              }
              else
              {
                  cout << args.getHelpMessage();
                  fSuccess = false;
              }
          }
          else
          {
              cout << args.getHelpMessage();
              fSuccess = false;
          }
  
      } // End of for-loop
  
      // Do we need to set the default output directory??
      //
      if (fsetOut)
      { 
          unsigned int ii = lastIndexOf(args.base, s_pathSep[0]);
  
          if (ii < length(args.base))
          {
              args.output.assign(args.base, 0, ii + 1);
          }
  
          append(args.output,XalanDOMString(outDir));
          checkAndCreateDir(args.output);
          append(args.output,s_pathSep); 
  
      }
      // Do we need to set the default gold directory??
      //
      if (fsetGold)
      {
          args.gold = args.base;
          append(args.gold,XalanDOMString("-gold"));
          if ( !checkDir(args.gold) )
          {   
              cout << "Assumed Gold dir - " << 
c_str(TranscodeToLocalCodePage(args.gold)) << " - does not exist" << endl;
              fSuccess = false;
          }
          append(args.gold,s_pathSep);
      }
      
      // Add the path seperator to the end of the base directory 
      // here after we've finished using it for all directory creation.
      //
      append(args.base,s_pathSep);
      
      return fSuccess;
  }
  
  
  
  //  This routine retrieves test file names from specified directories.
  //  Inputs: baseDir:    typically "conf" or "perf"
  //          relDir:     sub-directory to search.
  //
  //  Notes:  It builds the searchSpecification by concatenating all the 
  //          necessary components.
  //
  XalanFileUtility::FileNameVectorType
  XalanFileUtility::getTestFileNames(
              const XalanDOMString&   baseDir,
              const XalanDOMString&   relDir,
              bool                    useDirPrefix)
  {
      char buffer3[PATH_MAX];
      getcwd(buffer3, PATH_MAX);
  
      const XalanDOMString    searchSuffix(XALAN_STATIC_UCODE_STRING("*.xsl"));
      XalanDOMString  searchSpecification;
  
      // Allow directory search w/o mandating files start with directory name. 
Required for files
      // garnered from XSLTMARK performance directory exm.
      if (useDirPrefix)
      {
          assign(searchSpecification, baseDir + relDir + s_pathSep + relDir + 
searchSuffix);
      }
      else
      {
          assign(searchSpecification, baseDir + relDir + s_pathSep + 
searchSuffix); 
      }
  
  
      DirectoryEnumeratorFunctor<FileNameVectorType, XalanDOMString>  
theEnumerator;
      FileNameVectorType  theFiles;
      theEnumerator(searchSpecification, theFiles);
  
      chdir(buffer3);
  
      return theFiles;
  }
  
  /*  This routine retrieves all sub-directories from the specified directories.
  //  Inputs: rootDirectory:  typically "conf" or "perf"
  //
  //  Notes:  The searchSpecification in this case is just "*". 
  //                                                                          
*/  
  XalanFileUtility::FileNameVectorType
  XalanFileUtility::getDirectoryNames(const XalanDOMString&        
rootDirectory)
  {
      char buffer2[PATH_MAX];
      getcwd(buffer2, PATH_MAX);
  
      const XalanDOMString    dirSpec(XALAN_STATIC_UCODE_STRING("*"));
  
      DirectoryEnumeratorFunctor<FileNameVectorType, XalanDOMString, 
DirectoryFilterPredicate> theEnumerator;
      FileNameVectorType  theFiles;
      theEnumerator(XalanDOMString(rootDirectory), XalanDOMString(dirSpec), 
theFiles);
      
      chdir(buffer2);
  
      return theFiles;
  }
  
  
  bool XalanFileUtility::checkDir(const XalanDOMString&    directory )
  {
      char buffer[PATH_MAX];
  
      getcwd(buffer, PATH_MAX);
  
      bool    fResult = false;
  
      if ( !chdir(c_str(TranscodeToLocalCodePage(directory))) )
      {
          fResult = true;
      }
  
      chdir(buffer);
  
      return fResult;
  }
  
  
  void XalanFileUtility::checkAndCreateDir(const XalanDOMString&   directory)
  {
      char buffer[PATH_MAX];
  
      getcwd(buffer, PATH_MAX);
  
      if ( (chdir(c_str(TranscodeToLocalCodePage(directory)))) )
      {
          //cout << "Couldn't change to " << directory << ", will create it." 
<< endl;
  #if defined(WIN32)
          if ( !mkdir(c_str(TranscodeToLocalCodePage(directory))))
  #else
          if ( !mkdir(c_str(TranscodeToLocalCodePage(directory)), 
DIR_MODE_BITS))
  #endif
          {
              cout << directory << " created." << endl;
          }
          else
          {
              cout << directory << " NOT created." << endl;
          }
      }
  
      chdir(buffer);
  }
  
  /*  This routine generates file names based on the provide suffix
  //  Inputs: theXMLFileName: typically "conf" or "perf"
  //          suffix:         typically "xsl" or "out".
  //
  //  Notes:  
  */  
  
  XalanDOMString
  XalanFileUtility::generateFileName(
              const XalanDOMString&   theXMLFileName,
              const char*             suffix,
              bool*                   status)
  {
      XalanDOMString  targetFile;
      int             thePeriodIndex = -1;
      const int       theLength = length(theXMLFileName);
  
      for (int i = theLength - 1; i > 0; i--)
      {
          if (charAt(theXMLFileName, i) == XalanUnicode::charFullStop)
          {
              thePeriodIndex = i;        // charFullStop is the dot (x2E)
              break;
          }
      }
  
      if (thePeriodIndex != -1)
      {
          targetFile.assign(theXMLFileName, 0, thePeriodIndex + 1);
  
          targetFile += XalanDOMString(suffix);
      }
  
      // Check the .xml file exists.
      if (!strcmp(suffix,"xml"))
      {
          FILE* fileHandle = fopen(c_str(TranscodeToLocalCodePage(targetFile)), 
"r");
          if (fileHandle == 0)
          {
              cout << "TEST ERROR: File Missing: " << targetFile << endl;
  
              if (status != 0)
              {
                  *status = false;
              }
          }
          else
          {
              fclose(fileHandle);
          }
      }
  
      return targetFile;
  }
  
  
  /*  This routine generates a Unique Runid. 
  //  Inputs: None
  //          
  //  Notes: The format is mmddhhmm. For example
  //         03151046 is "Mar 15 10:46"   
  */
  
  XalanDOMString
  XalanFileUtility::generateUniqRunid()
  {
  #if defined(XALAN_STRICT_ANSI_HEADERS)
      using std::tm;
      using std::time;
      using std::localtime;
      using std::strftime;
  #endif
  
      struct tm *newtime;
      time_t long_time;
      char tmpbuf[10];
  
      time( &long_time );                /* Get time as long integer. */
      newtime = localtime( &long_time ); /* Convert to local time. */
  
      strftime( tmpbuf, 10,"%m%d%H%M",newtime );
  
      return XalanDOMString(tmpbuf);
  }
  
  
  //  This routine gets Xerces Version number. It's used to put the Xerces 
Version
  //  into the output xml results file as an attribute of 'PerfData' element.
  //  Inputs: None
  //              
  
  XalanDOMString
  XalanFileUtility::getXercesVersion()
  {
  
      return XalanDOMString(gXercesFullVersionStr);
  }
  
  /*  This routine creates a FormatterToXML FormatterListener. This is used to 
format
  //  the output DOM so a comparision can be done with the expected GOLD file. 
  //  Inputs: None
  //              
  */
  
  
  FormatterListener* 
  XalanFileUtility::getXMLFormatter(
              PrintWriter&            resultWriter,
              int                     indentAmount,
              const XalanDOMString&   mimeEncoding,
              const StylesheetRoot*   stylesheet)
  {
      XalanDOMString  version;
      bool            outputIndent= 0;
      XalanDOMString  mediatype;
      XalanDOMString  doctypeSystem;
      XalanDOMString  doctypePublic;
      XalanDOMString  standalone;
  
      if (stylesheet != 0)
      {
          version = stylesheet->getOutputVersion();
  
          mediatype = stylesheet->getOutputMediaType();
          doctypeSystem = stylesheet->getOutputDoctypeSystem();
          doctypePublic = stylesheet->getOutputDoctypePublic();
          standalone = stylesheet->getOutputStandalone();
          outputIndent = stylesheet->getOutputIndent();
      }
  
      return new FormatterToXML(
                      resultWriter,
                      version,
                      outputIndent,
                      indentAmount,
                      mimeEncoding,
                      mediatype,
                      doctypeSystem,
                      doctypePublic,
                      true,   // xmlDecl
                      standalone);
  }
  
  
  /*  This routine is used to compares the results of a transform and report 
the results.
  //  When a failure is detected the 'data' structure used to report detailed 
info about 
  //  a failure is filled in.
  //  Inputs: 
  //      goldFile    - Name of gold file
  //      outputFile  - Name of result file.
  //      logfile     - Name of log file reporter.
  //      
  //  Returns: 
  //      Void
  */
  void
  XalanFileUtility::checkResults(
              const XalanDOMString&   outputFile, 
              const XalanDOMString&   goldFile, 
              XalanXMLFileReporter&   logfile)
  {
      int ambgFlag = data.nogold; // get the current number of tests w/o gold 
files.
  
      // Compare the results, report success if compareSerializedResults 
returns true.
      if(compareSerializedResults(outputFile, goldFile))
      {
          cout << "Passed: " << data.testOrFile << endl;
          logfile.logCheckPass(data.testOrFile);
          data.pass += 1;
      }
      else
      {
          typedef XalanXMLFileReporter::Hashtable  Hashtable;
  
          // if the compairson fails gather up the failure data and determine 
if it failed 
          // due to bad output or missing Gold file. Lastly, log the failure.
          Hashtable   attrs;
          Hashtable   actexp;
  
          reportError();
  
          attrs.insert(Hashtable::value_type(XalanDOMString("reason"), 
XalanDOMString(data.msg)));
          attrs.insert(Hashtable::value_type(XalanDOMString("atNode"), 
data.currentNode));
          actexp.insert(Hashtable::value_type(XalanDOMString("exp"), 
data.expected));
          actexp.insert(Hashtable::value_type(XalanDOMString("act"), 
data.actual));
  
          actexp.insert(Hashtable::value_type(XalanDOMString("xsl"), 
data.xslFileURL));
          actexp.insert(Hashtable::value_type(XalanDOMString("xml"), 
data.xmlFileURL));
          actexp.insert(Hashtable::value_type(XalanDOMString("result"), 
outputFile));
          actexp.insert(Hashtable::value_type(XalanDOMString("gold"), 
goldFile));
  
          if (ambgFlag < data.nogold)
          {
              logfile.logCheckAmbiguous(data.testOrFile);
          }
          else
          {
              logfile.logCheckFail(data.testOrFile, attrs, actexp);
          }
      }
  }
  
  void
  XalanFileUtility::checkAPIResults(
              const XalanDOMString&   actual, 
              const XalanDOMString&   expected, 
              const char*             msg,
              XalanXMLFileReporter&        logfile,
              const XalanDOMString&   outputFile, 
              const XalanDOMString&   goldFile,
              bool                    containsOnly)
  {
      if(actual == expected ||
         (containsOnly == true && indexOf(actual, expected) != 
XalanDOMString::npos))
      {
          data.pass += 1;
          cout << "Passed: " << data.testOrFile << endl;
          logfile.logCheckPass(data.testOrFile);
      }
      else
      {   data.actual = actual;
          data.expected = expected;
          data.currentNode = "API Test";
          data.msg = msg;
          data.fail += 1;
  
          reportError();
  
          typedef XalanXMLFileReporter::Hashtable  Hashtable;
  
          Hashtable   actexp;
  
          actexp.insert(Hashtable::value_type(XalanDOMString("exp"), expected));
          actexp.insert(Hashtable::value_type(XalanDOMString("act"), actual));
          actexp.insert(Hashtable::value_type(XalanDOMString("xsl"), 
data.xslFileURL));
          actexp.insert(Hashtable::value_type(XalanDOMString("xml"), 
data.xmlFileURL));
          actexp.insert(Hashtable::value_type(XalanDOMString("result"), 
outputFile));
          actexp.insert(Hashtable::value_type(XalanDOMString("gold"), 
goldFile));
  
          // Todo: Need to determine if I should check for missing gold in 
these cases.
          logfile.logCheckFail(data.testOrFile, actexp);
      }
  }
  
  
  
  /*  This routine compares the results of a transform with the gold file.
  //  It in turn call the domCompare routine to do the actual comparision. 
  //  Inputs: 
  //      gold - Dom tree for the expected results
  //      doc  - Dom tree created during transformation
  //      filename - Current filename
  //      
  //  Returns: 
  //      Void
  //      
  */
  void
  XalanFileUtility::checkDOMResults(
              const XalanDOMString&           theOutputFile, 
              const XalanCompiledStylesheet*  compiledSS, 
              const XalanSourceTreeDocument*  dom,
              const XSLTInputSource&          goldInputSource,
              XalanXMLFileReporter&                logfile)
  {
      const int   ambgFlag = data.nogold;
  
      const XalanDOMString    mimeEncoding("");
  
      XalanFileOutputStream           myOutput(theOutputFile);
      XalanOutputStreamPrintWriter    myResultWriter(myOutput);
  
      FormatterListener* const    theFormatter =
          getXMLFormatter(
              myResultWriter,
              0,
              mimeEncoding,
              compiledSS->getStylesheetRoot());
  
      FormatterTreeWalker     theTreeWalker(*theFormatter);
  
      theTreeWalker.traverse(dom);
  
      delete theFormatter;
  
      XalanSourceTreeDOMSupport       domSupport;
      XalanSourceTreeParserLiaison    parserLiaison(domSupport);
      
      domSupport.setParserLiaison(&parserLiaison);
  
      const XalanDocument* const  goldDom =
          parserLiaison.parseXMLStream(goldInputSource);
  
      if(domCompare(*goldDom, *dom))
      {
          cout << "Passed: " << data.testOrFile << endl;
          logfile.logCheckPass(data.testOrFile);
          data.pass += 1;
      }
      else
      {
          typedef XalanXMLFileReporter::Hashtable  Hashtable;
  
          // if the compairson fails gather up the failure data and determine 
if it failed 
          // due to bad output or missing Gold file. Lastly, log the failure.
          Hashtable attrs;
          Hashtable actexp;
  
          reportError();
  
          attrs.insert(Hashtable::value_type(XalanDOMString("reason"), 
XalanDOMString(data.msg)));
          attrs.insert(Hashtable::value_type(XalanDOMString("atNode"), 
data.currentNode));
          actexp.insert(Hashtable::value_type(XalanDOMString("exp"), 
data.expected));
          actexp.insert(Hashtable::value_type(XalanDOMString("act"), 
data.actual));
  
          if (ambgFlag < data.nogold)
          {
              logfile.logCheckAmbiguous(data.testOrFile);
          }
          else
          {
              logfile.logCheckFail(data.testOrFile, attrs, actexp);
          }
      }
  }
  
  /*  This routine takes the result file and gold file and parses them.
  //  If either of the files fails to parse and a SAXException is throw,
  //  then the files are compared using a char by char file compare,
  //  otherwise the domCompare routine is used.
  //  Inputs: 
  //      outputFile:  Name of result file
  //      goldFile:    Name of gold file
  //      
  //  Returns: 
  //      True or False
  //      
  */
  bool
  XalanFileUtility::compareSerializedResults(
              const XalanDOMString&   outputFile,
              const XalanDOMString&   goldFile)
  {
  
      const XSLTInputSource resultInputSource(outputFile);
      const XSLTInputSource goldInputSource(goldFile);
  
      XalanSourceTreeDOMSupport       domSupport;
      XalanSourceTreeParserLiaison    parserLiaison(domSupport);
  
      domSupport.setParserLiaison(&parserLiaison);
  
      try
      {
          const XalanDocument* const  transformDom =
              parserLiaison.parseXMLStream(resultInputSource);
          assert(transformDom != 0);
  
          const XalanDocument* const  goldDom =
              parserLiaison.parseXMLStream(goldInputSource);
          assert(goldDom != 0);
  
          return domCompare(*goldDom, *transformDom);
      }
      // This exception is being reported prior to this Catch, however, 
however, I clarify that it's a SAX exception.
      // It's a good indication that the Gold file is not a valid XML.  When 
this happens the transform result needs
      // to be compared with the Gold,  with a character by character basis,  
not via the DOM compair. 
      catch (const XERCES_CPP_NAMESPACE_QUALIFIER SAXException&)
      {
          cout << "SAXException: Using fileCompare to check output.\n";
  
          return fileCompare(c_str(TranscodeToLocalCodePage(goldFile)), 
c_str(TranscodeToLocalCodePage(outputFile)));
      }
   
  }
  
  
  
  static void
  replaceNonAsciiCharacters(
              char*   theBuffer,
              char    theReplacementChar)
  {
      while(*theBuffer)
      {
          if (unsigned(*theBuffer) > 127)
          {
              *theBuffer = theReplacementChar;
          }
  
          ++theBuffer;
      }
  }
  
  
  
  /*  This routine is used to compare the results against the gold when one or 
both of 
  //  fails to parse without throwing a SAXException. When a failure is 
detected the 'data' 
  //  structure used to report detailed info about a failure is filled in.
  //  Inputs: 
  //      outputFile:  Name of result file
  //      goldFile:    Name of gold file
  //      
  //  Returns: 
  //      True or False
  //      
  */
  bool
  XalanFileUtility::fileCompare(
              const char*     goldFile,
              const char*     outputFile)
  {
      const unsigned long     maxBuffer = 132;
  
      char rline[maxBuffer] = {'0'};  // declare buffers to hold single line 
from file
      char gline[maxBuffer] = {'0'};  
      char temp[10];              // buffer to hold line number
      char lineNum = 1;
  
      // Set fail data incase there are i/o problems with the files to compare.
      data.expected = XalanDOMString(" ");
      data.actual = XalanDOMString(" ");
      data.currentNode = XalanDOMString("Line: 0");
  
      // Attempt to open the files. 
      FILE* const     result = fopen(outputFile, "r");
      FILE* const     gold = fopen(goldFile, "r");
  
      // If the result file fails to open report this as a failure.
      if (!result)
      {
          data.msg = "No Result (Transform failed)";
          data.fail += 1;
          return false;
      }
  
      // If the gold file fails to open report this as ambiguous.
      if (!gold)
      {
          data.msg = "No Gold file";
          data.nogold += 1;
          return false;
      }
  
      // Start file comparison,  line by line..
      while(!feof(result) && !feof(gold))
      {
          fgets(gline, sizeof(gline), gold );
          fgets(rline, sizeof(rline), result );
          sprintf(temp,"%d",lineNum);
  
          if (ferror(gold) || ferror(result))
          {
              data.msg = "Read Error - Gold/Result file";
              data.currentNode = XalanDOMString("Line: ") + 
XalanDOMString(temp);
              return false;
          }
  
          // Compare the lines character by charcter ....
          unsigned int i = 0;
          while(i < strlen(gline)) 
          {
              if (gline[i] == rline[i]) 
              {
                  i++;
              }
              else
              {   // If there is a mismatch collect up the fail data and return 
false.  To ensure that 
                  // the results can be seen in the browser enclose the 
actual/expected in CDATA Sections.
  
                  // Replace any non-ASCII characters.  Otherwise, we would 
have to encode them
                  // in UTF-8, which is a huge pain.
                  replaceNonAsciiCharacters(gline, '?');
                  replaceNonAsciiCharacters(rline, '?');
  
                  data.msg = "Text based comparison failure";
                  data.expected = XalanDOMString("<![CDATA[") + 
XalanDOMString(gline) + XalanDOMString("]]>");
                  data.actual = XalanDOMString("<![CDATA[") + 
XalanDOMString(rline) + XalanDOMString("]]>");
                  data.currentNode = XalanDOMString("Line: ") + 
XalanDOMString(temp);
                  data.fail += 1;
              fclose(result);     fclose(gold);
                  return false;
              }
          }
  
          lineNum += 1;
      }
              fclose(result);     fclose(gold);
      return true;
  }
  
  
  
  /*  This routine performs a DOM Comparision. 
  //  Inputs: 
  //      gold - Dom tree for the expected results
  //      doc  - Dom tree created during transformation
  //      filename - Current filename
  //      
  //  Returns: 
  //      True or False
  //      
  */
  bool 
  XalanFileUtility::domCompare(
              const XalanNode&    gold,
              const XalanNode&    doc)
  {
      const XalanNode::NodeType   docNodeType  = doc.getNodeType();
      const XalanNode::NodeType   goldNodeType = gold.getNodeType();
  
      const XalanDOMString&  docNodeName  = doc.getNodeName();    
  
      if (goldNodeType != docNodeType)
      {
          collectData("NodeType mismatch.",
                      docNodeName,
                      XalanDOMString(xalanNodeTypes[docNodeType]),
                      XalanDOMString(xalanNodeTypes[goldNodeType]));
  
          return false;
      }
  
      switch (goldNodeType)
      {
      case XalanNode::ELEMENT_NODE:   // ATTRIBUTE_NODEs are processed with 
diffElement().
          { 
              if (diffElement(gold, doc) == false) 
              {
                  return false;
              }
          }
          break;
  
      case XalanNode::CDATA_SECTION_NODE:
      case XalanNode::TEXT_NODE:  
          {
              const XalanDOMString&   docNodeValue  = doc.getNodeValue();
              const XalanDOMString&   goldNodeValue = gold.getNodeValue();
              
              //debugNodeData(docNodeName, docNodeValue);
              
              if(goldNodeValue != docNodeValue)
              {
                  collectData("Text node mismatch. ", 
                               docNodeName,
                               goldNodeValue,
                               docNodeValue);
                  return false;
              }
          }
          break;
  
      case XalanNode::PROCESSING_INSTRUCTION_NODE:
          {
              const XalanDOMString&  goldNodeName  = gold.getNodeName();
  
              if (goldNodeName != docNodeName)
              {
                  collectData("processing-instruction target mismatch. ", 
                               docNodeName,
                               goldNodeName,
                               docNodeName);
  
                  return false;
              }
              else
              {
                  const XalanDOMString&   docNodeValue  = doc.getNodeValue();
                  const XalanDOMString&   goldNodeValue = gold.getNodeValue();
  
                  if (goldNodeValue != docNodeValue)
                  {
                      collectData("processing-instruction data mismatch. ", 
                                   docNodeName,
                                   goldNodeValue,
                                   docNodeValue);
  
                      return false;
                  }
              }
          }
          break;
  
      case XalanNode::COMMENT_NODE:
          {
              const XalanDOMString&   docNodeValue  = doc.getNodeValue();
              const XalanDOMString&   goldNodeValue = gold.getNodeValue();
  
              if (goldNodeValue != docNodeValue)
              {
                  collectData("comment data mismatch. ", 
                               docNodeName,
                               goldNodeValue,
                               docNodeValue);
  
                  return false;
              }
          }
          break;
  
      case XalanNode::DOCUMENT_NODE:
          {
              //debugNodeData(docNodeName);
  
              const XalanNode *goldNextNode;
              const XalanNode *domNextNode;
  
              goldNextNode = gold.getFirstChild();
              domNextNode = doc.getFirstChild();
  
              if (0 != goldNextNode)
              {
                  if(domCompare(*goldNextNode,*domNextNode) == false)
                  {
                      return false;
                  }
              }
          }
          break;
  
      case XalanNode::ENTITY_REFERENCE_NODE:
      case XalanNode::ENTITY_NODE:
      case XalanNode::DOCUMENT_TYPE_NODE:
      case XalanNode::DOCUMENT_FRAGMENT_NODE:
      case XalanNode::NOTATION_NODE:
      default:
          cerr << "Unexpected node type: " << goldNodeType << endl;
  
          return false;
      }
  
      // Need to process siblings.  Children are processed in diffElement, since
      // only they can have children in the XPath data model.
      const XalanNode* const  goldNextNode = gold.getNextSibling();
      const XalanNode* const  domNextNode = doc.getNextSibling();
  
      if (0 != goldNextNode)
      {
          if (0 != domNextNode)
          {
              if (domCompare(*goldNextNode, *domNextNode) == false)
              {
                  return false;
              }
          }
          else
          {
              collectData("Missing sibling node. ", 
                       docNodeName,
                       goldNextNode->getNodeName(),
                       goldNextNode->getNodeName());
  
              return false;
          }
      }
      else if (0 != domNextNode)
      {
          collectData("Extra sibling node. ", 
              docNodeName,
              domNextNode->getNodeName(),
              domNextNode->getNodeName());
  
          return false;
      }
  
      return true;
  }
  
  
  
  bool 
  XalanFileUtility::domCompare(
              const XalanDocument&    gold,
              const XalanDocument&    doc)
  {
      const XalanNode*    theGoldPos = &gold;
      const XalanNode*    theDocPos = &doc;
  
      bool    fEqual = true;
  
      do
      {
          fEqual = diffNode(theGoldPos, theDocPos);
  
          if (fEqual == true)
          {
              assert(theGoldPos != 0 && theDocPos != 0);
  
              const XalanNode*    nextGoldNode = theGoldPos->getFirstChild();
              const XalanNode*    nextDocNode = theDocPos->getFirstChild();
  
              bool    fBreak = false;
  
              while(
                  nextGoldNode == 0 &&
                  nextDocNode == 0 &&
                  fBreak == false)
              {
                  // Move to the next sibling of each node,
                  // since we would get here only if both have
                  // no children.
                  nextGoldNode = theGoldPos->getNextSibling();
                  nextDocNode = theDocPos->getNextSibling();
  
                  // If there is no next sibling, move up to the
                  // parent.  If one, but not both, has a sibling,
                  // we'll end up back at the top of the do/while
                  // loop and the difference will be reported.
                  if(0 == nextGoldNode && 0 == nextDocNode)
                  {
                      theGoldPos = theGoldPos->getParentNode();
                      theDocPos = theDocPos->getParentNode();
  
                      // If the parent is null, then we've reached
                      // the end of the document.  Note that if we
                      // got here, then there must also be a parent
                      // node in the document we're verifying, so we
                      // could simply assert that theDocPos is either
                      // null if theGoldPos is null, or it is not-null
                      // if theGoldPos is not-null.
                      if(0 == theGoldPos)
                      {
                          nextGoldNode = theGoldPos;
  
                          fBreak = true;
                      }
  
                      if(0 == theDocPos)
                      {
                          nextDocNode = theDocPos;
  
                          fBreak = true;
                      }
                  }
              }
  
              theGoldPos = nextGoldNode;
              theDocPos = nextDocNode;
          }
      } while((theGoldPos != 0 || theDocPos != 0) && fEqual == true);
  
  
      return fEqual;
  }
  
  
  
  bool
  XalanFileUtility::diffNode(
              const XalanNode&    gold,
              const XalanNode&    doc)
  {
      const XalanNode::NodeType   docNodeType  = doc.getNodeType();
      const XalanNode::NodeType   goldNodeType = gold.getNodeType();
  
      const XalanDOMString&  docNodeName  = doc.getNodeName();    
  
      if (goldNodeType != docNodeType)
      {
          collectData("NodeType mismatch.",
                      docNodeName,
                      XalanDOMString(xalanNodeTypes[docNodeType]),
                      XalanDOMString(xalanNodeTypes[goldNodeType]));
  
          return false;
      }
  
      switch (goldNodeType)
      {
      case XalanNode::ELEMENT_NODE:   // ATTRIBUTE_NODEs are processed with 
diffElement().
          return diffElement2(gold, doc);
          break;
  
      case XalanNode::CDATA_SECTION_NODE:
      case XalanNode::TEXT_NODE:  
          {
              const XalanDOMString&   docNodeValue  = doc.getNodeValue();
              const XalanDOMString&   goldNodeValue = gold.getNodeValue();
              
              //debugNodeData(docNodeName, docNodeValue);
              
              if(goldNodeValue != docNodeValue)
              {
                  collectData("Text node mismatch. ", 
                               docNodeName,
                               goldNodeValue,
                               docNodeValue);
                  return false;
              }
          }
          break;
  
      case XalanNode::PROCESSING_INSTRUCTION_NODE:
          {
              const XalanDOMString&  goldNodeName  = gold.getNodeName();
  
              if (goldNodeName != docNodeName)
              {
                  collectData("processing-instruction target mismatch. ", 
                               docNodeName,
                               goldNodeName,
                               docNodeName);
  
                  return false;
              }
              else
              {
                  const XalanDOMString&   docNodeValue  = doc.getNodeValue();
                  const XalanDOMString&   goldNodeValue = gold.getNodeValue();
  
                  if (goldNodeValue != docNodeValue)
                  {
                      collectData("processing-instruction data mismatch. ", 
                                   docNodeName,
                                   goldNodeValue,
                                   docNodeValue);
  
                      return false;
                  }
              }
          }
          break;
  
      case XalanNode::COMMENT_NODE:
          {
              const XalanDOMString&   docNodeValue  = doc.getNodeValue();
              const XalanDOMString&   goldNodeValue = gold.getNodeValue();
  
              if (goldNodeValue != docNodeValue)
              {
                  collectData("comment data mismatch. ", 
                               docNodeName,
                               goldNodeValue,
                               docNodeValue);
  
                  return false;
              }
          }
          break;
  
      case XalanNode::DOCUMENT_NODE:
          break;
  
      case XalanNode::ENTITY_REFERENCE_NODE:
      case XalanNode::ENTITY_NODE:
      case XalanNode::DOCUMENT_TYPE_NODE:
      case XalanNode::DOCUMENT_FRAGMENT_NODE:
      case XalanNode::NOTATION_NODE:
      default:
          cerr << "Unexpected node type: " << goldNodeType << endl;
  
          return false;
      }
  
      return true;
  }
  
  
  
  bool
  XalanFileUtility::diffNode(
              const XalanNode*    gold,
              const XalanNode*    doc)
  {
      if (gold != 0 && doc != 0)
      {
          return diffNode(*gold, *doc);
      }
      else if (gold != 0)
      {
          const XalanNode* const  parent =
              gold->getParentNode();
  
          collectData(
              "Missing sibling node. ",
              parent == 0 ? s_emptyString : parent->getNodeName(),
              s_emptyString,
              gold->getNodeName());
  
          return false;
      }
      else
      {
          assert(doc != 0 && gold == 0);
  
          const XalanNode* const  parent =
              doc->getParentNode();
  
          collectData(
              "Extra sibling node. ", 
              parent == 0 ? s_emptyString : parent->getNodeName(),
              doc->getNodeName(),
              s_emptyString);
  
          return false;
      }
  }
  
  
  
  /*  This routine compares two element nodes. 
  //  Inputs: 
  //      gold - Dom tree for the expected results
  //      doc  - Dom tree created during transformation
  //      filename - Current filenam
  //      
  //  Returns: 
  //      True or False
  //                      
  */
  
  bool
  XalanFileUtility::diffElement(
              const XalanNode&    gold,
              const XalanNode&    doc)
  {
      assert(gold.getNodeType() == XalanNode::ELEMENT_NODE);
      assert(gold.getNodeType() == XalanNode::ELEMENT_NODE);
  
      const XalanDOMString&  docNodeName  = doc.getNodeName();    
      const XalanDOMString&  goldNodeName = gold.getNodeName();
  
      const XalanDOMString&  docNsUri  = doc.getNamespaceURI();
      const XalanDOMString&  goldNsUri = gold.getNamespaceURI();
  
      //debugNodeData(docNodeName);
  
      // This essentially checks 2 things, that the prefix and localname are the
      // same.  So specific checks of these items are not necessary.
      if (goldNodeName != docNodeName)
      {
          collectData("Element mismatch. ", 
                           docNodeName,
                           goldNodeName,
                           docNodeName);
          return false;
      }
  
      if ( goldNsUri != docNsUri)
      {
          collectData("Element NamespaceURI mismatch. ",
                           docNodeName,
                           goldNsUri,
                           docNsUri);
          return false;
      }
  
      // Get Attributes for each Element Node. 
      const XalanNamedNodeMap* const  goldAttrs = gold.getAttributes();
      const XalanNamedNodeMap* const  docAttrs  = doc.getAttributes();
  
      // Get number of Attributes
      const unsigned int  numGoldAttr = goldAttrs->getLength();
      const unsigned int  numDomAttr  = docAttrs ->getLength();
  
      /*
      // This needs to be uncommented if 'compare.exe' is to work. 
      // If this is the 'root' element strip off the xmlns:xml namespace 
attribute,
      // that is lurking around on the gold file, but not the dom.  This is 
necessary
      // only for the 'compare' test, that uses a pure DOM, that has not been 
serialized.
      //if (goldNodeName == XalanDOMString("root"))
      {
          numGoldAttr -= 1;
          XalanNode *gXMLAttr = goldAttrs->item(1);
      }
      */
      // Check that each Element has same number of Attributes. If they don't 
report error  
      if ( numGoldAttr == numDomAttr )
      {
          // Compare Attributes one at a time.
          //for (int i=1; i < numGoldAttr; i++)  // To be used with 'compare'
          for (unsigned int i = 0; i < numGoldAttr; ++i)
          {
              // Attribute order is irrelvant, so comparision is base on 
Attribute name.
              const XalanNode* const  gAttr = goldAttrs->item(i);
              const XalanDOMString&   goldAttrName = gAttr->getNodeName();
  
              const XalanNode* const  dAttr = 
docAttrs->getNamedItem(goldAttrName);
  
              if (dAttr != 0)
              {
                  if( ! (diffAttr(gAttr, dAttr)) )
                      return false;
              }
              else
              {
                  collectData("Element missing named Attribute. ",
                           docNodeName,
                           goldAttrName,
                           XalanDOMString("NOTHING"));
  
                  return false;
              }
          }
      }
      else
      {
          char  buf1[2], buf2[2];
          sprintf(buf1, "%u", numGoldAttr);
          sprintf(buf2, "%u", numDomAttr);
          collectData("Wrong number of attributes. ",
                           docNodeName,
                           XalanDOMString(buf1),
                           XalanDOMString(buf2));
          return false;
      }
  
      const XalanNode*    goldNextNode = gold.getFirstChild();
      const XalanNode*    domNextNode = doc.getFirstChild();
  
      if (0 != goldNextNode)
      {
          if (0 != domNextNode)
          {
              if ( ! domCompare(*goldNextNode, *domNextNode) )
                  return false;
          }
          else
          {
              collectData("Element missing ChildNode. ", 
                           docNodeName,
                           XalanDOMString(goldNextNode->getNodeName()),
                           XalanDOMString("NOTHING"));
              return false;
          }
      }
      else if (domNextNode != 0)
      {
          // The result doc has additional Children. If the additional node is 
a text node
          // then gather up the text and print it out.
          if ( domNextNode->getNodeType() == XalanNode::TEXT_NODE)
          {
              collectData("Result has additional Child node: ", 
                      docNodeName,
                      XalanDOMString("NOTHING"),       
                      XalanDOMString(domNextNode->getNodeName()) + 
XalanDOMString("  \"") +
                      XalanDOMString(domNextNode->getNodeValue()) + 
XalanDOMString("\""));
          }
          // Additional node is NOT text, so just print it's Name.
          else
          {
              collectData("Result has additional Child node: ", 
                          docNodeName,
                          XalanDOMString("NOTHING"),       
                          XalanDOMString(domNextNode->getNodeName()));
  
          }
          return false;
  
      }
  
      return true;
  }
  
  
  bool
  XalanFileUtility::diffElement2(
              const XalanNode&    gold,
              const XalanNode&    doc)
  {
      assert(gold.getNodeType() == XalanNode::ELEMENT_NODE);
      assert(gold.getNodeType() == XalanNode::ELEMENT_NODE);
  
      const XalanDOMString&  docNodeName  = doc.getNodeName();    
      const XalanDOMString&  goldNodeName = gold.getNodeName();
  
      const XalanDOMString&  docNsUri  = doc.getNamespaceURI();
      const XalanDOMString&  goldNsUri = gold.getNamespaceURI();
  
      //debugNodeData(docNodeName);
  
      // This essentially checks 2 things, that the prefix and localname are the
      // same.  So specific checks of these items are not necessary.
      if (goldNodeName != docNodeName)
      {
          collectData("Element mismatch. ", 
                           docNodeName,
                           goldNodeName,
                           docNodeName);
          return false;
      }
  
      if ( goldNsUri != docNsUri)
      {
          collectData("Element NamespaceURI mismatch. ",
                           docNodeName,
                           goldNsUri,
                           docNsUri);
          return false;
      }
  
      // Get Attributes for each Element Node. 
      const XalanNamedNodeMap* const  goldAttrs = gold.getAttributes();
      assert(goldAttrs != 0);
  
      const XalanNamedNodeMap* const  docAttrs  = doc.getAttributes();
      assert(docAttrs != 0);
  
      // Get number of Attributes
      const unsigned int  numGoldAttr = goldAttrs->getLength();
      const unsigned int  numDomAttr  = docAttrs ->getLength();
  
      // Check that each Element has same number of Attributes. If they don't 
report error  
      if ( numGoldAttr == numDomAttr )
      {
          // Compare Attributes one at a time.
          //for (int i=1; i < numGoldAttr; i++)  // To be used with 'compare'
          for (unsigned int i = 0; i < numGoldAttr; ++i)
          {
              // Attribute order is irrelvant, so comparision is base on 
Attribute name.
              const XalanNode* const  gAttr = goldAttrs->item(i);
              const XalanDOMString&   goldAttrName = gAttr->getNodeName();
  
              const XalanNode* const  dAttr = 
docAttrs->getNamedItem(goldAttrName);
  
              if (dAttr != 0)
              {
                  if( ! (diffAttr(gAttr, dAttr)) )
                      return false;
              }
              else
              {
                  collectData("Element missing named Attribute. ",
                           docNodeName,
                           goldAttrName,
                           XalanDOMString("NOTHING"));
  
                  return false;
              }
          }
      }
      else
      {
          char  buf1[2], buf2[2];
          sprintf(buf1, "%u", numGoldAttr);
          sprintf(buf2, "%u", numDomAttr);
          collectData("Wrong number of attributes. ",
                           docNodeName,
                           XalanDOMString(buf1),
                           XalanDOMString(buf2));
          return false;
      }
  
      return true;
  }
  
  
  /*  This routine compares two attribute nodes. 
  //  Inputs: 
  //      gAttr - attribute from Gold dom tree 
  //      dAttr - attribute from Dom tree created during transformation
  //      fileName - Current filenam
  //      
  //  Returns: 
  //      True or False
  //              
  */
  
  bool XalanFileUtility::diffAttr(const XalanNode* gAttr, const XalanNode* 
dAttr)
  {
  
      const XalanDOMString&   docAttrName  = dAttr->getNodeName();
  
      //debugAttributeData(goldAttrName);
  
      const XalanDOMString&   goldAttrValue = gAttr->getNodeValue();
      const XalanDOMString&   docAttrValue    = dAttr->getNodeValue();
  
      if (goldAttrValue != docAttrValue)
      {
          collectData(
              "Attribute Value mismatch. ",
              docAttrName,
              goldAttrValue,
              docAttrValue);
  
          return false;
      }
  
      const XalanDOMString&   goldAttrNsUri = gAttr->getNamespaceURI();
      const XalanDOMString&   docAttrNsUri    = dAttr->getNamespaceURI();
  
      if (goldAttrNsUri != docAttrNsUri)
      {
          collectData(
              "Attribute NamespaceURI mismatch. ", 
              docAttrName,
              goldAttrNsUri,
              docAttrNsUri);
  
          return false;
      }
  
      return true;
  }
  
  /*  This routine reports DOM comparison errors. 
  //  Inputs: 
  //      file    -   Name of current file
  //      node    -   Current node that fails
  //      msg     -   Failure message
  //
  */
  void
  XalanFileUtility::reportError()
  {
  
      cout << endl
           << "* Failed "
           << data.testOrFile
           << "  Error: "
           << data.msg
           << endl
           << "   "
           << "Processing Node: "
           << data.currentNode
           << endl
           << "   Expected:   "
           << data.expected
           << endl
           << "   Actual:     "
           << data.actual
           << endl
           << endl;
  }
  
  
  #if !defined(NDEBUG)
  void
  XalanFileUtility::debugNodeData(const XalanDOMString&    value) const
  {
      cout << "Node is: " << c_str(TranscodeToLocalCodePage(value)) << endl;
  }
  
  
  
  void
  XalanFileUtility::debugNodeData(
              const XalanDOMString&   node,
              const XalanDOMString&   value) const
  {
      cout << "Node is: " << c_str(TranscodeToLocalCodePage(node)) << "   "
           << "Value is: \"" << c_str(TranscodeToLocalCodePage(value)) << 
"\"\n";
  }
  
  
  
  void
  XalanFileUtility::debugAttributeData(const XalanDOMString&   value) const
  {
      cout << "Attribute is: " << c_str(TranscodeToLocalCodePage(value)) << 
endl;
  }
  
  #endif
  
  
  
  /*  This routine collects up data pertinent to a dom comparison failure. 
  //  Inputs: 
  //      errmsg:         Reason for the failure.
  //      currentnode:    Node in the dom tree where the mismatch occured
  //      expdata:        Expected data based on the Gold file.
  //      actdata:        Actual data returned in the result file.
  //  Returns: Void                       
  */
  void 
  XalanFileUtility::collectData(
              const char*             errmsg,
              const XalanDOMString&   currentnode,
              const XalanDOMString&   expdata,
              const XalanDOMString&   actdata)
  {
      data.msg = errmsg;
      data.currentNode = currentnode;
      data.expected = expdata;
      data.actual = actdata;
      data.fail += 1;
  }
  
  
  /*  Routine prints the result to the console, as well as adds summary info 
into the logfile. 
  //  Inputs: 
  //      logfile:    Current log file
  //      runid:      Unique runid
  //  Returns: Void                       
  */
  void
  XalanFileUtility::reportPassFail(
              XalanXMLFileReporter&        logfile,
              const XalanDOMString&   runid)
  {
      typedef XalanXMLFileReporter::Hashtable  Hashtable;
  
      Hashtable   runResults;
  
      char temp[5];
  
      // Create entrys that contain runid, xerces version, and numbers for 
Pass, Fail and No Gold.
  
      runResults.insert(Hashtable::value_type(XalanDOMString("UniqRunid"), 
runid));
      runResults.insert(Hashtable::value_type(XalanDOMString("Xerces-Version 
"), getXercesVersion()));
      runResults.insert(Hashtable::value_type(XalanDOMString("BaseDrive "), 
XalanDOMString(getDrive())));
      runResults.insert(Hashtable::value_type(XalanDOMString("TestBase "), 
XalanDOMString(args.base)));
      runResults.insert(Hashtable::value_type(XalanDOMString("xmlFormat "), 
data.xmlFormat));
      sprintf(temp, "%ld", args.iters);
      runResults.insert(Hashtable::value_type(XalanDOMString("Iters "), 
XalanDOMString(temp)));
  
      sprintf(temp, "%d", data.pass);
      runResults.insert(Hashtable::value_type(XalanDOMString("Passed"), 
XalanDOMString(temp)));
      
      sprintf(temp, "%d", data.fail);
      runResults.insert(Hashtable::value_type(XalanDOMString("Failed"), 
XalanDOMString(temp)));
  
      sprintf(temp, "%d", data.nogold);
      runResults.insert(Hashtable::value_type(XalanDOMString("No_Gold_Files"), 
XalanDOMString(temp)));
  
      logfile.logElementWAttrs(10, "RunResults", runResults, "xxx");  
  
      cout << "\nPassed " << data.pass;
      cout << "\nFailed " << data.fail;
      cout << "\nMissing Gold " << data.nogold << endl;
  
  }
  
  /*  Routine runs a stylesheet on the log file and displays the results in 
HTML. 
  //  Inputs: 
  //      xalan:          An instance of the transformer
  //      resultsFile:    logfile 
  //  Returns: Void                       
  */
  void
  XalanFileUtility::analyzeResults(XalanTransformer& xalan, const 
XalanDOMString& resultsFile)
  {
      XalanDOMString paramValue;
      bool    fileStatus;
  
  #if defined(AIX) || defined(SOLARIS) || defined(LINUX) || defined(HPUX)
  
      bool    pathStatus;
      CharVectorType     withPath;
      TranscodeToLocalCodePage(resultsFile, withPath, false);
      if (withPath[0] == '/')
          pathStatus=true;
      else
          pathStatus=false;
      
      char buffer5[PATH_MAX];
      XalanDOMString resultPath= XalanDOMString(getcwd(buffer5, PATH_MAX));
      append(resultPath, s_pathSep);
  #endif
      
  
      // Pass the results .xml file as a parameter to the stylesheet.  It must 
be wrapped in single
      // quotes so that it is not considered an expression.
      //
    #if defined (AIX) || defined(SOLARIS) || defined(LINUX) || defined(HPUX)
      assign(paramValue, XalanDOMString("\'"));
      if ( !pathStatus )
          append(paramValue, resultPath);
      append(paramValue, resultsFile);
      append(paramValue, XalanDOMString("\'"));
    #else 
      assign(paramValue, XalanDOMString("'"));
          append(paramValue, resultsFile);
          append(paramValue, XalanDOMString("'"));
    #endif
  
      // Set the parameter
      //
      xalan.setStylesheetParam(XalanDOMString("testfile"), paramValue);
  
      // Generate the input and output file names.
      //
      const XalanDOMString  theHTMLFile = generateFileName(resultsFile,"html", 
&fileStatus);
      const XalanDOMString  theStylesheet = args.base + 
XalanDOMString("cconf.xsl");
      const XalanDOMString  theXMLSource = args.base + 
XalanDOMString("cconf.xml");
  
      // Check that we can find the stylesheet to analyze the results.
      //
      FILE* fileHandle = fopen(c_str(TranscodeToLocalCodePage(theStylesheet)), 
"r");
      if (fileHandle == 0)
      {
          cout << "ANALYSIS ERROR: File Missing: " << 
c_str(TranscodeToLocalCodePage(theStylesheet)) << endl;
          return;
      }
      else
      {
          fclose(fileHandle);
      }
  
      // Create the InputSources and ResultTarget.
      const XSLTInputSource   xslInputSource(theStylesheet);
      const XSLTInputSource   xmlInputSource(theXMLSource);
      const XSLTResultTarget  resultFile(theHTMLFile);
  
      // Do the transform, display the output HTML, or report any failure.
      const int   result = xalan.transform(xmlInputSource, xslInputSource, 
resultFile);
  
      if (result == 0)
      {
      #if defined(_MSC_VER)
          system(c_str(TranscodeToLocalCodePage(theHTMLFile)));
      #else
          cout << "The HTML output: " << theHTMLFile << " was created" << endl;
      #endif
      }
      else 
      {
          cout << "Analysis failed due to following error: "
               << xalan.getLastError()
               << endl;
      }   
  }
  
  
  
  const XalanDOMChar    XalanFileUtility::s_xmlSuffix[] =
  {
      XalanUnicode::charFullStop,
      XalanUnicode::charLetter_x,
      XalanUnicode::charLetter_m,
      XalanUnicode::charLetter_l,
        0
  };
  
  const XalanDOMChar    XalanFileUtility::s_pathSep[] =
  {
  #if defined(WIN32)
      XalanUnicode::charReverseSolidus,
  #else
      XalanUnicode::charSolidus,
  #endif
        0
  };
  
  
  
  XALAN_CPP_NAMESPACE_END
  
  
  
  1.1                  xml-xalan/c/src/xalanc/Harness/XalanFileUtility.hpp
  
  Index: XalanFileUtility.hpp
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed 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.
   */
  #if !defined(XALAN_FILEUTILITY_HEADER_GUARD_1357924680)
  #define XALAN_FILEUTILITY_HEADER_GUARD_1357924680
  
  
  
  #include "xalanc/Harness/XalanHarnessDefinitions.hpp"
  
  
  
  #include <vector>
  
  
  #if defined(XALAN_CLASSIC_IOSTREAMS)
  #include <strstream.h>
  #else
  #include <strstream>
  #endif
  
  
  
  #include "xalanc/XalanDOM/XalanDOMString.hpp"
  
  
  
  XALAN_CPP_NAMESPACE_BEGIN
  
  
  
  class FormatterListener;
  class PrintWriter;
  class StylesheetRoot;
  class XalanCompiledStylesheet;
  class XalanDocument;
  class XalanNode;
  class XalanSourceTreeDocument;
  class XalanTransformer;
  class XalanXMLFileReporter;
  class XSLTInputSource;
  
  
  
  // This class is exported from the Harness.dll
  class XALAN_HARNESS_EXPORT XalanFileUtility 
  {
  public:
  
  // A vector to hold directory names and file names.
  #if defined(XALAN_NO_STD_NAMESPACE)
      typedef vector<XalanDOMString>          FileNameVectorType;
  #else
      typedef std::vector<XalanDOMString>     FileNameVectorType;
  #endif
  
      struct XALAN_HARNESS_EXPORT reportStruct
      {
          XalanDOMString  theDrive;
          XalanDOMString  testOrFile;
          XalanDOMString  xmlFileURL;
          XalanDOMString  xslFileURL;
          XalanDOMString  xmlFormat;
          const char*     msg;
          XalanDOMString  currentNode;
          XalanDOMString  actual;
          XalanDOMString  expected;
          int             pass;
          int             fail;
          int             nogold;
  
          reportStruct();
  
          void
          reset();
  
      } data;
  
      struct XALAN_HARNESS_EXPORT cmdParams
      {
      private:
  
  #if defined(XALAN_NO_STD_NAMESPACE)
          typedef ostrstream          StreamType;
  #else
          typedef std::ostrstream     StreamType;
  #endif
  
          StreamType  help;
  
      public:
  
          XalanDOMString  base;
          XalanDOMString  output;
          XalanDOMString  gold;
          XalanDOMString  sub;
          int             source;
          bool            skip;
          long            iters;
  
  
          cmdParams();
  
          ~cmdParams()
          {
          }
  
          const char*
          getHelpMessage();
  
          StreamType&
          getHelpStream()
          {
              return help;
          }
  
      } args;
  
      /** Simple constructor, does not perform initialization.  */
      XalanFileUtility();
  
      ~XalanFileUtility();
  
      /** 
      * Utility method used to get test files from a specific directory.
      * @returns a vector containing test files.
      */
  
      XalanDOMString
      getDrive();
  
      bool
      getParams(
              int             argc,
              char*           argv[],
              const char*     outDir,
              bool            fsetGold = true);
  
  
      FileNameVectorType
      getTestFileNames(
              const XalanDOMString&   baseDir,
              const XalanDOMString&   relDir,
              bool                    useDirPrefix);
  
      /** 
      * Utility method used to get subdirectories from a specific directory.
      * @returns a vector containing directory files.
      */  
      FileNameVectorType
      getDirectoryNames(const XalanDOMString&     rootDirectory);
  
      /** 
      * Utility method used to create default directories when neccessary
      */
      void
      checkAndCreateDir(const XalanDOMString&     directory);
  
      /** 
      * Utility method determines if directory exists.
      */
      bool
      checkDir(const XalanDOMString&  directory);
  
      /** 
      * Utility method used to get XSL file based on XML file.
      * @returns a XalanDOMString.
      */
      XalanDOMString
      getXSLFileName(const XalanDOMString&    theXMLFileName);
  
      /** 
      * Utility method used to get OUT file based on XML file.
      * @returns a XalanDOMString.
      */
      XalanDOMString
      generateFileName(
              const XalanDOMString&  theXMLFileName,
              const char*             suffix,
              bool*                   status = 0);
  
      /** 
      * Utility method used to generate UniqRunid.
      * @returns a XalanDOMString.
      */
      XalanDOMString
      generateUniqRunid();
  
      /** 
      * Utility methods used to get Xerces Version number.
      * @returns a XalanDOMString.
      */
      XalanDOMString
      getXercesVersion();
  
  
      void
      checkResults(
              const XalanDOMString&   outputFile, 
              const XalanDOMString&   goldFile, 
              XalanXMLFileReporter&   logfile);
  
      void
      checkAPIResults(
              const XalanDOMString&   actual, 
              const XalanDOMString&   expected,
              const char*             msg,
              XalanXMLFileReporter&   logfile,
              const XalanDOMString&   outputFile,
              const XalanDOMString&   goldFile,
              bool                    containsOnly = false);
  
      void
      checkAPIResults(
              const char*             actual,
              const char*             expected,
              const char*             msg,
              XalanXMLFileReporter&        logfile,
              const XalanDOMString&   outputFile,
              const XalanDOMString&   goldFile,
              bool                    containsOnly = false)
      {
          checkAPIResults(
              XalanDOMString(actual), 
              XalanDOMString(expected),
              msg,
              logfile,
              outputFile,
              goldFile,
              containsOnly);
      }
  
      /**
      * Utility method used to compare the results. It inturn
      * call domCompare.  
      * @returns Void.
      */
      void
      checkDOMResults(
              const XalanDOMString&           theOutputFile, 
              const XalanCompiledStylesheet*  compiledSS,
              const XalanSourceTreeDocument*  dom,
              const XSLTInputSource&          goldInputSource,
              XalanXMLFileReporter&                logfile);
  
      bool
      compareSerializedResults(
              const XalanDOMString&   transformResult,
              const XalanDOMString&   goldInputSource);
      /**
      * Utility method used to create a FormatterToXML FormatterListener.
      * This is required to DOM comparisions. 
      * @returns a pointer to a FormatterListener.
      */
      FormatterListener* 
      getXMLFormatter(
              PrintWriter&            resultWriter,
              int                     indentAmount,
              const XalanDOMString&   mimeEncoding,
              const StylesheetRoot*   stylesheet);
  
  
      bool
      fileCompare(
              const char*     goldFile,
              const char*     outputFile);
  
      /** 
      * Utility methods used to perform a DOM Compare
      * @returns boolean
      */
      bool 
      domCompare(const XalanNode& gold, const XalanNode& doc);
  
      /** 
      * Utility methods used to perform a DOM Compare
      * @returns boolean
      */
      bool 
      domCompare(
              const XalanDocument&    gold,
              const XalanDocument&    doc);
  
      /** 
      * Utility methods used to diff two Element nodes.
      * @returns boolean.
      */
      bool 
      diffElement(const XalanNode& gold, const XalanNode& doc);
  
      /** 
      * Utility methods used to diff two nodes.
      * @returns true if the nodes are equal, and false if not.
      */
      bool
      diffNode(
              const XalanNode&    gold,
              const XalanNode&    doc);
  
      /** 
      * Utility methods used to diff two nodes.
      * @returns true if the nodes are equal, and false if not.
      */
      bool
      diffNode(
              const XalanNode*    gold,
              const XalanNode*    doc);
  
      /** 
      * Utility methods used to diff two Element nodes.
      * @returns boolean.
      */
      bool 
      diffElement2(
              const XalanNode&    gold,
              const XalanNode&    doc);
  
      /** 
      * Utility methods used to diff two attribute nodes.
      * @returns boolean.
      */
      bool 
      diffAttr(const XalanNode* gAttr, const XalanNode* dAttr);
  
      /** 
      * Utility methods used to report Pass/Fail numbers.
      * @returns void.
      */
      void
      reportPassFail(XalanXMLFileReporter& logfile);
  
      void
      reportPassFail(XalanXMLFileReporter& logfile, const XalanDOMString& 
runid);
  
      void
      analyzeResults(XalanTransformer& xalan, const XalanDOMString& 
resultsFile);
  
      static const XalanDOMChar   s_xmlSuffix[];
  
      static const XalanDOMChar   s_pathSep[];
  
  private:
  
      static const XalanDOMString     s_emptyString;
  
      XalanDOMString
      getProgramName(const char* fullName);
  
      /** 
      * Utility methods used to collect information about compare failures.
      * @returns void.
      */
      void 
      collectData(
              const char*             errmsg,
              const XalanDOMString&   currentnode,
              const XalanDOMString&   actdata,
              const XalanDOMString&   expdata);
  
      /** 
      * Utility methods used to report DOM compare errors.
      * @returns void.
      */
      void
      reportError();
  
  #if defined(NDEBUG)
      void
      debugNodeData(const XalanDOMString&     /* value */) const
      {
      }
  
      void
      debugNodeData(
              const XalanDOMString&   /* node */,
              const XalanDOMString&   /* value */) const
      {
      }
  
      void
      debugAttributeData(const XalanDOMString&    /* value */) const
      {
      }
  
  #else
  
      void
      debugNodeData(const XalanDOMString&     value) const;
  
      void
      debugNodeData(
              const XalanDOMString&   node,
              const XalanDOMString&   value) const;
  
      void
      debugAttributeData(const XalanDOMString&    value) const;
  
  #endif
  
  };        // end of class FileUtility
  
  
  
  XALAN_CPP_NAMESPACE_END
  
  
  
  #endif  // XALAN_FILEUTILITY_HEADER_GUARD_1357924680
  
  
  
  1.1                  
xml-xalan/c/src/xalanc/Harness/XalanHarnessDefinitions.hpp
  
  Index: XalanHarnessDefinitions.hpp
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed 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.
   */
  #if !defined(XALAN_HARNESSDEFINITIONS_HEADER_GUARD_1357924680)
  #define XALAN_HARNESSDEFINITIONS_HEADER_GUARD_1357924680
  
  #include "xalanc/Include/PlatformDefinitions.hpp"
  
  #if defined(XALAN_HARNESS_BUILD_DLL)
  #   define XALAN_HARNESS_EXPORT XALAN_PLATFORM_EXPORT
  #   define XALAN_HARNESS_EXPORT_FUNCTION(T) XALAN_PLATFORM_EXPORT_FUNCTION(T)
  #else
  #   define XALAN_HARNESS_EXPORT XALAN_PLATFORM_IMPORT
  #   define XALAN_HARNESS_EXPORT_FUNCTION(T) XALAN_PLATFORM_IMPORT_FUNCTION(T)
  #endif
  
  
  #endif  // XALAN_HARNESSDEFINITIONS_HEADER_GUARD_1357924680
  
  
  
  1.1                  xml-xalan/c/src/xalanc/Harness/XalanXMLFileReporter.cpp
  
  Index: XalanXMLFileReporter.cpp
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed 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.
   */
  
  #include "XalanXMLFileReporter.hpp" 
  
  
  
  #include <cstdlib>
  #include <ctime>
  
  
  
  #include "xalanc/PlatformSupport/DOMStringHelper.hpp"
  #include "xalanc/PlatformSupport/XalanUnicode.hpp"
  
  
  
  XALAN_CPP_NAMESPACE_BEGIN
  
  
  
  XalanXMLFileReporter::XalanXMLFileReporter(const XalanDOMString&  fileName) :
      OPT_FILENAME(),
      ELEM_RESULTSFILE(),
      ELEM_TESTFILE(),
      ELEM_FILERESULT(),
      ELEM_TESTCASE(),
      ELEM_CASERESULT(),
      ELEM_CHECKRESULT(),
      ELEM_STATISTIC(),
      ELEM_LONGVAL(),
      ELEM_DOUBLEVAL(),
      ELEM_MESSAGE(),
      ELEM_ARBITRARY(),
      ELEM_HASHTABLE(),
      ELEM_HASHITEM(),
      ATTR_LEVEL(),
      ATTR_DESC(),
      ATTR_TIME(),
      ATTR_RESULT(),
      ATTR_KEY(),
      ATTR_FILENAME(),
      LESS_THAN(),
      GREATER_THAN(),
      EQUALS_QUOTE(),
      SPACE(),
      QUOTE(),
      QUOTE_SPACE(),
      QUOTE_GREATER_THAN(),
      QUOTE_SOLIDUS_GREATER_THAN(),
      PASS(),
      AMBG(),
      ERRR(),
      FAIL(),
      LESS_THAN_SOLIDUS(),
      XML_HEADER(),
      REASON_EQUALS_QUOTE(),
      TESTCASEINIT_HDR(),
      TESTCASECLOSE_HDR(),
      MESSAGE_HDR(),
      STATISTIC_HDR(),
      ARBITRARY_HDR(),
      HASHTABLE_HDR(),
      HASHITEM_HDR(),
      CHECKPASS_HDR(),
      CHECKAMBG_HDR(),
      CHECKERRR_HDR(),
      CHECKFAIL_HDR(),
      CHECKFAIL_FTR(),
      m_anyOutput(false),
      m_fileName(fileName),
      m_fileHandle(0),
      m_ready(false),
      m_error(false),
      m_flushOnCaseClose(true)
  {
      if (m_fileName.empty() == false)
      {
          m_ready = initialize();
      }
  }
  
  bool
  XalanXMLFileReporter::initialize()
  {       
      if (m_fileName.empty() == true)
      {
          // We don't have a valid file, so bail
          m_error = true;
          m_ready = false;
          fprintf(stderr, "XalanXMLFileReporter.initialize() ERROR: No file 
name specified");
      }
      else
      {
          // Transcode down the file name...
          CharVectorType  theTranscodedFileName;
          
          TranscodeToLocalCodePage(m_fileName, theTranscodedFileName, true);
  
          const char* const       theTranscodedFileNamePointer = 
&theTranscodedFileName.front();
  
          // Create a file and ensure it has a place to live
          m_fileHandle = fopen(theTranscodedFileNamePointer, "w");
          if (m_fileHandle == 0)
          {
              // Couldn't create or find the directory for the file to live in, 
so bail
              m_error = true;
              m_ready = false;
              fprintf(stderr, "XalanXMLFileReporter.initialize() ERROR: unble 
to open file, %s", theTranscodedFileNamePointer);
              return(false);
          }
          else
          {
              m_ready = true;
  
              initStrings();
  
              startResultsFile();
  
              // fprintf(stderr, "DEBUG:XalanXMLFileReporter.initialize() 
complete with " + fileName);
          }
      }
  
      return m_ready;
  }
  
  
  
  bool
  XalanXMLFileReporter::getFlushOnCaseClose()
  {
      return(m_flushOnCaseClose);
  }
  
  
  
  const XalanDOMString& 
  XalanXMLFileReporter::getFileName() const
  {
      return(m_fileName);
  }
  
  
  
  void 
  XalanXMLFileReporter::setFileName(const XalanDOMString& fileName)
  {
      m_fileName = fileName;
  }
  
  
  
  bool 
  XalanXMLFileReporter::checkError()
  {
      // Ensure our underlying reporter, if one, is still OK
      if (m_fileHandle == 0)            
      {            
          m_error = true;        
      }
      return(m_error);
  }
  
  
  
  bool 
  XalanXMLFileReporter::isReady() 
  {
      // Ensure our underlying reporter, if one, is still OK
      if (m_fileHandle == 0) 
      {
          // NEEDSWORK: should we set m_ready = false in this case?
          //            errors in the PrintStream are not necessarily fatal
          m_error = true;
          m_ready = false;
      }
      return(m_ready);
  }
  
  
  
  void 
  XalanXMLFileReporter::flush()
  {
      if (isReady())
      {
          fflush(m_fileHandle);
      }
  }
  
  
  
  void 
  XalanXMLFileReporter::close()
  {
      fflush(m_fileHandle);
      if (isReady()) 
      {
          if (m_fileHandle != 0)
          {
              closeResultsFile();
              fclose(m_fileHandle);
          }
      }
      m_ready = false;
  }
  
  
  
  void 
  XalanXMLFileReporter::logTestFileInit(const XalanDOMString& msg)
  {
      if (isReady())
      {
          printToFile(LESS_THAN + ELEM_TESTFILE 
                                + SPACE + ATTR_DESC + EQUALS_QUOTE + 
escapestring(msg) + QUOTE_SPACE + ATTR_TIME + EQUALS_QUOTE + 
getDateTimeString() + QUOTE_GREATER_THAN);
      }
  }
  
  
  
  void 
  XalanXMLFileReporter::logTestFileClose(const XalanDOMString& /* msg */, const 
XalanDOMString& /* result */)
  {
      if (isReady())
      {
  //        printToFile(LESS_THAN + ELEM_FILERESULT 
  //                             + SPACE + ATTR_DESC + EQUALS_QUOTE + 
escapestring(msg) + QUOTE_SPACE + ATTR_RESULT + EQUALS_QUOTE + result + 
QUOTE_SPACE + ATTR_TIME + EQUALS_QUOTE + getDateTimeString() + 
QUOTE_SOLIDUS_GREATER_THAN);
          printToFile(LESS_THAN_SOLIDUS + ELEM_TESTFILE + GREATER_THAN);
      }
      flush();
  }
  
  
  
  void 
  XalanXMLFileReporter::logTestCaseInit(const XalanDOMString& msg)
  {
      if (isReady())
      {
          printToFile(TESTCASEINIT_HDR + escapestring(msg) + 
QUOTE_GREATER_THAN);
      }
  }
  
  
  
  void 
  XalanXMLFileReporter::logTestCaseClose(const XalanDOMString& /* msg */, const 
XalanDOMString& /* result */)
  {
      if (isReady())
      {
          //printToFile(TESTCASECLOSE_HDR + escapestring(msg) + QUOTE_SPACE + 
ATTR_RESULT + EQUALS_QUOTE + result + QUOTE_SOLIDUS_GREATER_THAN);
          printToFile(LESS_THAN_SOLIDUS + ELEM_TESTCASE + GREATER_THAN);
      }
      if (getFlushOnCaseClose())
      {
          flush();
      }
  }
  
  
  
  void 
  XalanXMLFileReporter::logMessage(int level, const XalanDOMString& msg)
  {
      char tmp[20];
      sprintf(tmp, "%d", level);
  
      if (isReady())
      {
          printToFile(MESSAGE_HDR + tmp + QUOTE_GREATER_THAN);
          printToFile(escapestring(msg));
          printToFile(LESS_THAN_SOLIDUS + ELEM_MESSAGE + GREATER_THAN);
      }
  }
  
  void XalanXMLFileReporter::addMetricToAttrs(char* desc, double theMetric, 
Hashtable& attrs)
  {
      XalanDOMString  temp;
  
      DoubleToDOMString(theMetric, temp);
      attrs.insert(Hashtable::value_type(XalanDOMString(desc), temp));
  
      return;
  }
  
  void 
  XalanXMLFileReporter::logElementWAttrs(int /* level */, const XalanDOMString& 
element, Hashtable attrs, const XalanDOMString& msg)
  {
      if (isReady() && !element.empty()&& !attrs.empty())
      {
  //      char tmp[20];
  //      sprintf(tmp, "%d", level);
  //
  //      Took out this level attribute cuz we don't use it.
  //      printToFile(LESS_THAN + element + SPACE + ATTR_LEVEL + EQUALS_QUOTE
  //                      + tmp + QUOTE);
          printToFile(LESS_THAN + element + SPACE);
      
          Hashtable::iterator theEnd = attrs.end();   
      
          for(Hashtable::iterator i = attrs.begin(); i != theEnd; ++i)
          {            
              
              printToFile((*i).first + EQUALS_QUOTE
                                    + (*i).second + QUOTE);
          }
  
          printToFile(GREATER_THAN);
          if (msg.empty() != 0)
              printToFile(escapestring(msg));
          printToFile(LESS_THAN_SOLIDUS + element + GREATER_THAN);
      }
  }
  
  void 
  XalanXMLFileReporter::logElement(const XalanDOMString& element, const 
XalanDOMString& msg)
  {
      if (isReady() && !element.empty() && !msg.empty())
      {
          printToFile(LESS_THAN + element + GREATER_THAN + escapestring(msg) + 
LESS_THAN_SOLIDUS + element + GREATER_THAN);
      }
  }
  
  void 
  XalanXMLFileReporter::logStatistic (int level, long lVal, double dVal, const 
XalanDOMString& msg)
  {
      if (isReady())
      {
          char tmp[40];
  
          sprintf(tmp, "%d", level);
          printToFile(STATISTIC_HDR + tmp + QUOTE_SPACE + ATTR_DESC + 
EQUALS_QUOTE + escapestring(msg) + QUOTE_GREATER_THAN);
          
          sprintf(tmp, "%ld", lVal);
          printToFile(LESS_THAN + ELEM_LONGVAL + GREATER_THAN + tmp + 
LESS_THAN_SOLIDUS + ELEM_LONGVAL + GREATER_THAN);
          
          sprintf(tmp, "%f", dVal);
          printToFile(LESS_THAN + ELEM_DOUBLEVAL + GREATER_THAN + tmp + 
LESS_THAN_SOLIDUS + ELEM_DOUBLEVAL + GREATER_THAN);
          
          printToFile(LESS_THAN_SOLIDUS + ELEM_STATISTIC + GREATER_THAN);
          
      }
  }
  
  
  
  void 
  XalanXMLFileReporter::logArbitraryMessage (int level, const XalanDOMString& 
msg)
  {
      char tmp[20];
      sprintf(tmp, "%d", level);
  
      if (isReady())
      {            
          printToFile(ARBITRARY_HDR + tmp + QUOTE_GREATER_THAN);
          printToFile(escapestring(msg));
          printToFile(LESS_THAN_SOLIDUS + ELEM_ARBITRARY + GREATER_THAN);
      }
  }
  
  /*
  void logHashtable (int level, Hashtable hash, XalanDOMString msg)
  {
      if (isReady())
      {
          printToFile(HASHTABLE_HDR + level + QUOTE_SPACE + ATTR_DESC + 
EQUALS_QUOTE + msg + QUOTE_GREATER_THAN);
          if (hash == null)
          {
              printToFile(LESS_THAN + ELEM_HASHITEM + SPACE + ATTR_KEY + 
"=\"null\">");
              printToFile(LESS_THAN_SOLIDUS + ELEM_HASHITEM + GREATER_THAN);
          }
          try
          {
              for (Enumeration enum = hash.keys(); enum.hasMoreElements();)
              {
                  Object key = enum.nextElement();
                  // Ensure we'll have clean output by pre-fetching value 
before outputting anything
                  XalanDOMString value = hash.get(key).tostring();
                  printToFile(HASHITEM_HDR + key.tostring() + 
QUOTE_GREATER_THAN);
                  printToFile(value);
                  printToFile(LESS_THAN_SOLIDUS + ELEM_HASHITEM + GREATER_THAN);
              }
          } 
          catch (Exception e)
          {
              // No-op: should ensure we have clean output
          }
          printToFile(LESS_THAN_SOLIDUS + ELEM_HASHTABLE + GREATER_THAN);
      }
  }
  */
  
  
  
  void 
  XalanXMLFileReporter::logCheckPass(const XalanDOMString& comment)
  {
      if (isReady())
      {
          printToFile(CHECKPASS_HDR + escapestring(comment) + 
QUOTE_SOLIDUS_GREATER_THAN);
      }
  }
  
  
  void 
  XalanXMLFileReporter::logCheckFail(const XalanDOMString& comment)
  {
      if (isReady())
      {
          printToFile(CHECKFAIL_HDR + escapestring(comment) + 
QUOTE_SOLIDUS_GREATER_THAN);
  
      }
  }
  
  
  void 
  XalanXMLFileReporter::logCheckFail(const XalanDOMString& test, Hashtable 
actexp)
  {
      if (isReady())
      {
          printToFile(CHECKFAIL_HDR + escapestring(test) + QUOTE);
  
          printToFile(GREATER_THAN);
          
          Hashtable::iterator aeEnd = actexp.end();
          for(Hashtable::iterator ii = actexp.begin(); ii != aeEnd; ++ii)
          {            
              logElement((*ii).first, (*ii).second);
          }
  
          printToFile(CHECKFAIL_FTR);
      }
  }
  
  void 
  XalanXMLFileReporter::logCheckFail(const XalanDOMString& test, Hashtable 
attrs, Hashtable actexp)
  {
      if (isReady())
      {
          printToFile(CHECKFAIL_HDR + escapestring(test) + QUOTE);
  
          Hashtable::iterator fdEnd = attrs.end();    
          for(Hashtable::iterator i = attrs.begin(); i != fdEnd; ++i)
          {            
              printToFile((*i).first + EQUALS_QUOTE
                                    + (*i).second + QUOTE);
          }
  
          printToFile(GREATER_THAN);
          
          Hashtable::iterator aeEnd = actexp.end();
          for(Hashtable::iterator ii = actexp.begin(); ii != aeEnd; ++ii)
          {            
              logElement((*ii).first, (*ii).second);
          }
  
          printToFile(CHECKFAIL_FTR);
      }
  }
  
  void 
  XalanXMLFileReporter::logCheckAmbiguous(const XalanDOMString& comment)
  {
      if (isReady())
      {
          printToFile(CHECKAMBG_HDR + escapestring(comment) + 
QUOTE_SOLIDUS_GREATER_THAN);
      }
  }
  
  
  void 
  XalanXMLFileReporter::logErrorResult(const XalanDOMString& test, const 
XalanDOMString& reason)
  {
      if (isReady())
      {
          printToFile(CHECKFAIL_HDR + escapestring(test) + QUOTE_SPACE + 
XalanDOMString(REASON_EQUALS_QUOTE) + escapestring(reason)  + 
QUOTE_SOLIDUS_GREATER_THAN);
  
      }
  }
  
  
  void 
  XalanXMLFileReporter::logCheckErr(const XalanDOMString& comment)
  {
      if (isReady())
      {
          printToFile(CHECKERRR_HDR + escapestring(comment) + 
QUOTE_SOLIDUS_GREATER_THAN);
      }
  }
  
  
  
  static const XalanDOMChar   theAmpersandString[] =
  {
      XalanUnicode::charAmpersand,
      XalanUnicode::charLetter_a,
      XalanUnicode::charLetter_m,
      XalanUnicode::charLetter_p,
      XalanUnicode::charSemicolon,
      0
  };
  
  
  
  static const XalanDOMChar   theApostropheString[] =
  {
      XalanUnicode::charAmpersand,
      XalanUnicode::charLetter_a,
      XalanUnicode::charLetter_p,
      XalanUnicode::charLetter_o,
      XalanUnicode::charLetter_s,
      XalanUnicode::charSemicolon,
      0
  };
  
  
  
  static const XalanDOMChar   theLessThanString[] =
  {
      XalanUnicode::charAmpersand,
      XalanUnicode::charLetter_l,
      XalanUnicode::charLetter_t,
      XalanUnicode::charSemicolon,
      0
  };
  
  
  
  static const XalanDOMChar   theGreaterThanString[] =
  {
      XalanUnicode::charAmpersand,
      XalanUnicode::charLetter_g,
      XalanUnicode::charLetter_t,
      XalanUnicode::charSemicolon,
      0
  };
  
  
  
  static const XalanDOMChar   theQuoteString[] =
  {
      XalanUnicode::charAmpersand,
      XalanUnicode::charLetter_q,
      XalanUnicode::charLetter_u,
      XalanUnicode::charLetter_o,
      XalanUnicode::charLetter_t,
      XalanUnicode::charSemicolon,
      0
  };
  
  
  
  XalanDOMString
  XalanXMLFileReporter::escapestring(const XalanDOMString&  s)
  {
      XalanDOMString      sb;
  
      const XalanDOMString::size_type     length = s.length();
  
      sb.reserve(length);
  
      for (XalanDOMString::size_type i = 0; i < length; i++)
      {
          const XalanDOMChar  ch = charAt(s, i);
  
          if (XalanUnicode::charLessThanSign == ch)
          {
              append(sb, theLessThanString);
          }
          else if (XalanUnicode::charGreaterThanSign == ch)
          {
              append(sb, theGreaterThanString);
          }
          else if (XalanUnicode::charAmpersand == ch) 
          {
              append(sb, theAmpersandString);
          }
          else if (XalanUnicode::charQuoteMark == ch) 
          {
              append(sb, theQuoteString);
          }
          else if (XalanUnicode::charApostrophe == ch) 
          {
              append(sb, theApostropheString);
          }
          else
          {
              append(sb, ch);
          }
      }
  
      return sb;
  }
  
  
  
  bool 
  XalanXMLFileReporter::startResultsFile()
  {
      if (isReady())
      {
          // Write out XML header and root test result element
          printToFile(XML_HEADER);
  
          // Note: this tag is closed in our .close() method, which the caller 
had better call!
          printToFile(LESS_THAN + ELEM_RESULTSFILE + SPACE + ATTR_FILENAME + 
EQUALS_QUOTE + m_fileName + QUOTE_GREATER_THAN);
  
          return true;
      }
      else
      {
          return false;
      }
  }
  
  
  
  bool 
  XalanXMLFileReporter::closeResultsFile()
  {
      if (isReady() == false)
      {
          return false;
      }
      else
      {            
          printToFile(LESS_THAN_SOLIDUS + ELEM_RESULTSFILE + GREATER_THAN);
          return true;
      }
  }
  
  
  bool 
  XalanXMLFileReporter::printToFile(const XalanDOMString&  output) 
  {
      if (isReady() == false)
      {
          return false;
      }
      else
      {
          const CharVectorType    theResult(TranscodeToLocalCodePage(output));
  
          if(!theResult.size())
          {
              fputs("Error transcoding text to local codepage", m_fileHandle);
          }
          else 
          {
              fputs(c_str(theResult), m_fileHandle);
          }
  
          fputs("\n", m_fileHandle);
  
          return true;
      }
  }
  
  
  
  XalanDOMString 
  XalanXMLFileReporter::getDateTimeString() 
  {
  #if defined(XALAN_STRICT_ANSI_HEADERS)
      using std::tm;
      using std::time;
      using std::localtime;
      using std::asctime;
      using std::strlen;
  #endif
  
      struct tm *tmNow;
      time_t time_tNow;
  
      time(&time_tNow);     
      tmNow = localtime(&time_tNow);
      
      const char* const   theTime = asctime(tmNow);
  
      return XalanDOMString(theTime, XalanDOMString::length(theTime) - 1);
  }
  
  
  
  void
  XalanXMLFileReporter::initStrings()
  {
      OPT_FILENAME = XALAN_STATIC_UCODE_STRING("filename");
      ELEM_RESULTSFILE = XALAN_STATIC_UCODE_STRING("resultsfile");
      ELEM_TESTFILE = XALAN_STATIC_UCODE_STRING("testfile");
      ELEM_FILERESULT = XALAN_STATIC_UCODE_STRING("fileresult");
      ELEM_TESTCASE = XALAN_STATIC_UCODE_STRING("Test_Dir");
      ELEM_CASERESULT = XALAN_STATIC_UCODE_STRING("Dir-result");
      ELEM_CHECKRESULT = XALAN_STATIC_UCODE_STRING("Testcase");
      ELEM_STATISTIC = XALAN_STATIC_UCODE_STRING("statistic");
      ELEM_LONGVAL = XALAN_STATIC_UCODE_STRING("longval");
      ELEM_DOUBLEVAL = XALAN_STATIC_UCODE_STRING("doubleval");
      ELEM_MESSAGE = XALAN_STATIC_UCODE_STRING("message");
      ELEM_ARBITRARY = XALAN_STATIC_UCODE_STRING("arbitrary");
      ELEM_HASHTABLE = XALAN_STATIC_UCODE_STRING("hashtable");
      ELEM_HASHITEM = XALAN_STATIC_UCODE_STRING("hashitem");
      ATTR_LEVEL = XALAN_STATIC_UCODE_STRING("level");
      ATTR_DESC = XALAN_STATIC_UCODE_STRING("desc");
      ATTR_TIME = XALAN_STATIC_UCODE_STRING("time");
      ATTR_RESULT = XALAN_STATIC_UCODE_STRING("result");
      ATTR_KEY = XALAN_STATIC_UCODE_STRING("key");
      ATTR_FILENAME = OPT_FILENAME;
      LESS_THAN = XALAN_STATIC_UCODE_STRING("<");
      GREATER_THAN = XALAN_STATIC_UCODE_STRING(">");
      EQUALS_QUOTE = XALAN_STATIC_UCODE_STRING("=\"");
      SPACE = XALAN_STATIC_UCODE_STRING(" ");
      QUOTE = XALAN_STATIC_UCODE_STRING("\"");
      QUOTE_SPACE = XALAN_STATIC_UCODE_STRING("\" ");
      QUOTE_GREATER_THAN = XALAN_STATIC_UCODE_STRING("\">");
      QUOTE_SOLIDUS_GREATER_THAN = XALAN_STATIC_UCODE_STRING("\"/>");
      PASS = XALAN_STATIC_UCODE_STRING("PASS");
      AMBG = XALAN_STATIC_UCODE_STRING("AMBG");
      ERRR = XALAN_STATIC_UCODE_STRING("ERRR");
      FAIL = XALAN_STATIC_UCODE_STRING("FAIL");
      LESS_THAN_SOLIDUS = XALAN_STATIC_UCODE_STRING("</");
      XML_HEADER = XALAN_STATIC_UCODE_STRING("<?xml version=\"1.0\"?>");
      REASON_EQUALS_QUOTE = XALAN_STATIC_UCODE_STRING("reason=\"");
  
      TESTCASEINIT_HDR = LESS_THAN + ELEM_TESTCASE + SPACE + ATTR_DESC + 
EQUALS_QUOTE;
      TESTCASECLOSE_HDR = LESS_THAN + ELEM_CASERESULT + SPACE + ATTR_DESC + 
EQUALS_QUOTE;
      MESSAGE_HDR = LESS_THAN + ELEM_MESSAGE + SPACE + ATTR_LEVEL + 
EQUALS_QUOTE;
      STATISTIC_HDR = LESS_THAN + ELEM_STATISTIC + SPACE + ATTR_LEVEL + 
EQUALS_QUOTE;
      ARBITRARY_HDR = LESS_THAN + ELEM_ARBITRARY + SPACE + ATTR_LEVEL + 
EQUALS_QUOTE;
      HASHTABLE_HDR = LESS_THAN + ELEM_HASHTABLE + SPACE + ATTR_LEVEL + 
EQUALS_QUOTE;
      HASHITEM_HDR = LESS_THAN + ELEM_HASHITEM + SPACE + ATTR_KEY + 
EQUALS_QUOTE;
      CHECKPASS_HDR = LESS_THAN + ELEM_CHECKRESULT + SPACE + ATTR_RESULT + 
EQUALS_QUOTE + PASS + QUOTE_SPACE + ATTR_DESC + EQUALS_QUOTE;
      CHECKAMBG_HDR = LESS_THAN + ELEM_CHECKRESULT + SPACE + ATTR_RESULT + 
EQUALS_QUOTE + AMBG + QUOTE_SPACE + ATTR_DESC + EQUALS_QUOTE;
      CHECKERRR_HDR = LESS_THAN + ELEM_CHECKRESULT + SPACE + ATTR_RESULT + 
EQUALS_QUOTE + ERRR + QUOTE_SPACE + ATTR_DESC + EQUALS_QUOTE;
      CHECKFAIL_HDR = LESS_THAN + ELEM_CHECKRESULT + SPACE + ATTR_RESULT + 
EQUALS_QUOTE + FAIL + QUOTE_SPACE + ATTR_DESC + EQUALS_QUOTE;
      CHECKFAIL_FTR = LESS_THAN_SOLIDUS + ELEM_CHECKRESULT + GREATER_THAN;
  }
  
  
  
  XALAN_CPP_NAMESPACE_END
  
  
  
  1.1                  xml-xalan/c/src/xalanc/Harness/XalanXMLFileReporter.hpp
  
  Index: XalanXMLFileReporter.hpp
  ===================================================================
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed 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.
   */
  #if !defined(HARNESS_HEADER_GUARD_1357924680)
  #define HARNESS_HEADER_GUARD_1357924680
  
  
  
  #include "xalanc/Harness/XalanHarnessDefinitions.hpp"
  
  
  
  #include <cstdio>
  #include <map>
  
  
  
  #include "xalanc/XalanDOM/XalanDOMString.hpp"
  
  
  
  XALAN_CPP_NAMESPACE_BEGIN
  
  
  
  // This class is exported from the Harness.dll
  class XALAN_HARNESS_EXPORT XalanXMLFileReporter
  {
  public:
  
  #if defined(XALAN_NO_STD_NAMESPACE)
      typedef map<XalanDOMString, XalanDOMString, less<XalanDOMString> >  
Hashtable;
  #else
      typedef std::map<XalanDOMString, XalanDOMString>    Hashtable;
  #endif
  
  #if defined(XALAN_STRICT_ANSI_HEADERS)
      typedef std::FILE   FileHandleType;
  #else
      typedef FILE        FileHandleType;
  #endif
  
  public:
  
  
      // Construct and initialize this reporter with specified filename, if
      // the filename is not empty.
      XalanXMLFileReporter(const XalanDOMString& fileName = XalanDOMString());
  
      // Initialize this XalanXMLFileReporter.  Must be called before 
attempting to log anything.
      bool initialize();
  
      // Accessor for flushing; is set from properties.
      bool getFlushOnCaseClose();
  
      // Accessor methods for our properties block.
      const XalanDOMString& getFileName() const;
  
      // Accessor methods for our properties block.
      void setFileName(const XalanDOMString& fileName);
  
      // Accessor methods for our properties block.
      void setFileName(const char* fileName)
      {
          setFileName(XalanDOMString(fileName));
      }
  
      //
      // Is this Reporter still running OK?  
      // @returns status - true if an error has occoured, false if it's still 
working fine
      bool checkError();
  
        
      //
      // Is this Reporter ready to log results?  
      // @returns status - true if it's ready to report, false otherwise
      bool isReady();
  
      // Flush this reporter - ensure our File is flushed.
      void flush();
  
  
      // Close this reporter - ensure our File, etc. are closed.
      void close();
  
      //-----------------------------------------------------
      //-------- Testfile / Testcase start and stop routines --------
      //-----------------------------------------------------
  
      /**
      * Report that a testfile has started.  
      * @param msg message to log out
      */
      void logTestFileInit(const XalanDOMString& msg);
  
      void logTestFileInit(const char*    msg)
      {
          logTestFileInit(XalanDOMString(msg));
      }
  
      /**
      * Report that a testfile has finished, and report it's result.  
      * @param msg message to log out
      * @param result result of testfile
      */
      void logTestFileClose(const XalanDOMString& msg, const XalanDOMString& 
result);
  
      void logTestFileClose(const char* msg, const char* result)
      {
          logTestFileClose(XalanDOMString(msg), XalanDOMString(result));  
      }
  
      void logTestCaseInit(const XalanDOMString& msg);
  
      void logTestCaseInit(const char*    msg)
      {
          logTestCaseInit(XalanDOMString(msg));
      }
  
      /**
      * Report that a testcase has finished, and report it's result.  
      * @param msg message to log out
      * @param result result of testfile
      */
      void logTestCaseClose(const XalanDOMString& msg, const XalanDOMString& 
result);
  
      void logTestCaseClose(const char* msg, const char* result)
      {
          logTestCaseClose(XalanDOMString(msg), XalanDOMString(result));
      }
      //-----------------------------------------------------
      //-------- Test results reporting and logging routines --------
      //-----------------------------------------------------
  
  
      /**
      * Report a comment to result file with specified severity.  
      * <P>Record format: &lt;message level="##"&gt;msg&lt;/message&gt;</P>
      * @param level severity or class of message.
      * @param msg comment to log out.
      */
      void logMessage(int level, const XalanDOMString& msg);
  
      /**
      * Logs out statistics to result file with specified severity.  
      * <P>Record format: &lt;statistic level="##" 
desc="msg"&gt;&lt;longval&gt;1234&lt;/longval&gt;&lt;doubleval&gt;1.234&lt;/doubleval&gt;&lt;/statistic&gt;</P>
      * @param level severity of message.
      * @param lVal statistic in long format.
      * @param dVal statistic in double format.
      * @param msg comment to log out.
      */
      void logStatistic (int level, long lVal, double dVal, const 
XalanDOMString& msg);
  
      void logStatistic (int level, long lVal, double dVal, const char*   msg)
      {
          logStatistic(level, lVal, dVal, XalanDOMString(msg));
      }
  
      // This routine will add an attribute to the attribute list.
      void addMetricToAttrs(char* desc, double theMetric, Hashtable& attrs);
  
      /**
      * Logs out a element to results with specified severity.
      * Uses user-supplied element name and attribute list.  Currently
      * attribute values and msg are forced .toString().  Also,
      * 'level' is forced to be the first attribute of the element.
      * @param level severity of message.
      * @param element name of enclosing element
      * @param attrs hash of name=value attributes; note that the
      * caller must ensure they're legal XML
      * @param msg comment to log out.
      */
      void logElementWAttrs(int level, const XalanDOMString& element, Hashtable 
attrs, const XalanDOMString& msg);
  
      void logElementWAttrs(int level,  const char* element, Hashtable attrs, 
const char* msg)
      {
          logElementWAttrs(level, XalanDOMString(element), attrs, 
XalanDOMString(msg));
      }
  
      void logElement(int level, const XalanDOMString& element, const 
XalanDOMString& msg);
  
      void logElement(const XalanDOMString& element, const XalanDOMString& msg);
      /**
      * Report an arbitrary XalanDOMString to result file with specified 
severity.  
      * <P>Appends and prepends \\n newline characters at the start and 
      * end of the message to separate it from the tags.</P>
      * <P>Record format: &lt;arbitrary level="##"&gt;<BR/>
      * msg<BR/>
      * &lt;/arbitrary&gt;
      * </P>
      * @param level severity or class of message.
      * @param msg arbitrary XalanDOMString to log out.
      */
      void logArbitraryMessage (int level, const XalanDOMString& msg);
  
      /**
      * Report a complete Hashtable to result file with specified severity.  
      * <P>Indents each hashitem within the table.</P>
      * <P>Record format: &lt;hashtable level="##" desc="msg"/&gt;<BR/>
      * &nbsp;&nbsp;&lt;hashitem key="key1"&gt;value1&lt;/hashitem&gt;<BR/>
      * &nbsp;&nbsp;&lt;hashitem key="key2"&gt;value2&lt;/hashitem&gt;<BR/>
      * &lt;/hashtable&gt;
      * </P>
      * @param level severity or class of message.
      * @param hash Hashtable to log the contents of. 
      * @param msg decription of the Hashtable.
      */
      /*
      void logHashtable (int level, Hashtable hash, const XalanDOMString& msg);
      */
  
      /**
      * Writes out a Pass record with comment.  
      * <P>Record format: &lt;checkresult result="PASS" desc="comment"/&gt;</P>
      * @param comment comment to log with the pass record.
      */
      void logCheckPass(const XalanDOMString& comment);
  
      /**
      * Writes out an ambiguous record with comment.  
      * <P>Record format: &lt;checkresult result="AMBG" desc="comment"/&gt;</P>
      * @param comment comment to log with the ambg record.
      */
      void logCheckAmbiguous(const XalanDOMString& comment);
  
      /**
      * Writes out a Fail record with comment.  
      * <P>Record format: &lt;checkresult result="FAIL" desc="comment"/&gt;</P>
      * @param comment comment to log with the fail record.
      */
      void logCheckFail(const XalanDOMString& comment);
  
      void logCheckFail(const XalanDOMString& test, Hashtable faildata, 
Hashtable actexp);
  
      void logCheckFail(const XalanDOMString& test, Hashtable actexp);
  
      void logErrorResult(const XalanDOMString& test, const XalanDOMString& 
reason);
  
      /**
      * Writes out a Error record with comment.  
      * <P>Record format: &lt;checkresult result="ERRR" desc="comment"/&gt;</P>
      * @param comment comment to log with the error record.
      */
      void logCheckErr(const XalanDOMString& comment);
  
      /**
      * Escapes a XalanDOMString to remove <, >, ', &, and " so it's valid XML. 
 
      * <P>Stolen mostly from Xalan applet sample.</P>
      * @param s XalanDOMString to escape.
      * @return XalanDOMString that has been escaped.
      */
      XalanDOMString escapestring(const XalanDOMString& s);
  
  
  private:
  
      /**
      * worker method to dump the xml header and open the resultsfile element.  
      */
      bool startResultsFile();
  
      /**
      * worker method to close the resultsfile element.  
      */
      bool closeResultsFile();
  
      /**
      * worker method to prints to the resultsfile.  
      */
      bool printToFile(const XalanDOMString& output);
  
      void
      initStrings();
  
      /**
      * worker method to prints to the resultsfile.  
      */
      XalanDOMString getDateTimeString();
      
      /** Key for Properties block that denotes our output filename.  */
      XalanDOMString  OPT_FILENAME;
  
      /** XML tagnames for results file structure.  */
      XalanDOMString  ELEM_RESULTSFILE;
      XalanDOMString  ELEM_TESTFILE;
      XalanDOMString  ELEM_FILERESULT;
      XalanDOMString  ELEM_TESTCASE;
      XalanDOMString  ELEM_CASERESULT;
      XalanDOMString  ELEM_CHECKRESULT;
      XalanDOMString  ELEM_STATISTIC;
      XalanDOMString  ELEM_LONGVAL;
      XalanDOMString  ELEM_DOUBLEVAL;
      XalanDOMString  ELEM_MESSAGE;
      XalanDOMString  ELEM_ARBITRARY;
      XalanDOMString  ELEM_HASHTABLE;
      XalanDOMString  ELEM_HASHITEM;
  
      /** XML attribute names for results file structure.  */
      XalanDOMString  ATTR_LEVEL;
      XalanDOMString  ATTR_DESC;
      XalanDOMString  ATTR_TIME;
      XalanDOMString  ATTR_RESULT;
      XalanDOMString  ATTR_KEY;
      XalanDOMString  ATTR_FILENAME;
      XalanDOMString  LESS_THAN;
      XalanDOMString  GREATER_THAN;
      XalanDOMString  EQUALS_QUOTE;
      XalanDOMString  SPACE;
      XalanDOMString  QUOTE;
      XalanDOMString  QUOTE_SPACE;
      XalanDOMString  QUOTE_GREATER_THAN;
      XalanDOMString  QUOTE_SOLIDUS_GREATER_THAN;
      XalanDOMString  PASS;
      XalanDOMString  AMBG;
      XalanDOMString  ERRR;
      XalanDOMString  FAIL;
      XalanDOMString  LESS_THAN_SOLIDUS;
      XalanDOMString  XML_HEADER;
      XalanDOMString  REASON_EQUALS_QUOTE;
  
      /** 
      * Optimization: for heavy use methods, form pre-defined constants to save 
on XalanDOMString concatenation.  
      * <P>Note the indent; must be updated if we ever switch to another 
indenting method.</P>
      */
      XalanDOMString  TESTCASEINIT_HDR;
      XalanDOMString  TESTCASECLOSE_HDR;
      XalanDOMString  MESSAGE_HDR;
      XalanDOMString  STATISTIC_HDR;
      XalanDOMString  ARBITRARY_HDR;
      XalanDOMString  HASHTABLE_HDR;
      XalanDOMString  HASHITEM_HDR;
      XalanDOMString  CHECKPASS_HDR;
      XalanDOMString  CHECKAMBG_HDR;
      XalanDOMString  CHECKERRR_HDR;
      XalanDOMString  CHECKFAIL_HDR;
      XalanDOMString  CHECKFAIL_FTR;
  
      /** If we have output anything yet.  */
      bool m_anyOutput;
  
      /** Name of the file we're outputing to.  */
      XalanDOMString m_fileName;
  
      /** File reference and other internal convenience variables.  */
      FileHandleType* m_fileHandle;
  
      /** If we're ready to start outputting yet.  */
      bool m_ready;
  
      /** If an error has occoured in this Reporter.  */
      bool m_error;
  
      /** If we should flush after every logTestCaseClose.  */
      bool m_flushOnCaseClose;
  
  };        // end of class XalanXMLFileReporter
  
  
  
  XALAN_CPP_NAMESPACE_END
  
  
  
  #endif
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to