protected static StringBuilder collectException(String methodName, String fileName, Throwable e) {

    StringBuilder message = new StringBuilder(ServiceHelper.convertExceptionToString(e));
    message
        .append("' in '")
        .append(methodName)
        .append("' converting the sample file ")
        .append(fileName)
        .append(".")
        .append(System.getProperty("line.separator"));

    return message;
  }
  public void doTest() throws FileNotFoundException, ToolkitException {

    String sampleFilesDirectory =
        System.getProperty(
            BaseTestJAXBTranslator.class.getName() + ".sampleFilesDir",
            "src/test/data/sampleMessages");
    if (sampleFilesDirectory == null) {
      Assert.fail(
          "Test failed because system property "
              + BaseTestJAXBTranslator.class.getName()
              + ".sampleFilesDir was not set. It must be set to a directory containing sample NCIP messages.");
    }

    String fileNamesPattern =
        System.getProperty(
            BaseTestJAXBTranslator.class.getName() + ".fileNamesPattern",
            DEFAULT_FILENAMES_PATTERN);

    String fileNamesToOmitPattern =
        System.getProperty(
            BaseTestJAXBTranslator.class.getName() + ".fileNamesToOmitPattern",
            DEFAULT_FILENAMES_TO_OMIT_PATTERN);

    int iterations = 1;

    String iterationsString =
        System.getProperty(BaseTestJAXBTranslator.class.getName() + ".iterations");
    if (iterationsString != null) {

      iterations = Integer.parseInt(iterationsString);
    }

    File dir = new File(sampleFilesDirectory);

    FileFilter fileFilter =
        new FileFilter() {
          public boolean accept(File file) {
            return file.isFile();
          }
        };

    StringBuilder failuresList = new StringBuilder();
    File[] files = dir.listFiles(fileFilter);
    long initTranslateStreamToSvcElapsedTime = 0;
    long respTranslateStreamToSvcElapsedTime = 0;
    long initTranslateSvcToStreamElapsedTime = 0;
    long respTranslateSvcToStreamElapsedTime = 0;
    long initMsgStreamToSvcCount = 0;
    long respMsgStreamToSvcCount = 0;
    long initMsgSvcToStreamCount = 0;
    long respMsgSvcToStreamCount = 0;

    if (files != null) {

      long startTime = 0;
      long endTime = 0;

      for (int iteration = 0; iteration < iterations; ++iteration) {

        for (File file : files) {

          String fileName = file.getName();

          if ((fileNamesPattern == null
                  || fileNamesPattern.length() == 0
                  || fileName.matches(fileNamesPattern))
              && (fileNamesToOmitPattern == null
                  || fileNamesToOmitPattern.length() == 0
                  || !fileName.matches(fileNamesToOmitPattern))) {

            InputStream inStream = new FileInputStream(file);

            LOG.info("Testing " + fileName);

            ServiceContext serviceContext = serviceValidator.getInitialServiceContext();

            if (fileName.contains("Response")) {

              try {

                startTime = System.currentTimeMillis();

                NCIPResponseData responseData =
                    translator.createResponseData(serviceContext, inStream);

                endTime = System.currentTimeMillis();
                respTranslateStreamToSvcElapsedTime += (endTime - startTime);
                respMsgStreamToSvcCount++;

                Assert.assertNotNull(
                    "createResponseData returned null for " + fileName + ".", responseData);

                if (responseData != null) {

                  try {

                    startTime = System.currentTimeMillis();

                    InputStream responseStream =
                        translator.createResponseMessageStream(serviceContext, responseData);

                    endTime = System.currentTimeMillis();
                    respTranslateSvcToStreamElapsedTime += (endTime - startTime);
                    respMsgSvcToStreamCount++;

                    Assert.assertNotNull(responseStream);

                    if (performXMLDiff) {

                      performXMLDiff(responseStream, failuresList, file);
                    }

                  } catch (ServiceException e) {

                    LOG.debug(
                        "Exception in createResponseMessageStream for '" + fileName + "'.", e);
                    failuresList.append(
                        collectException("createResponseMessageStream", fileName, e));

                  } catch (ValidationException e) {

                    LOG.debug(
                        "Exception in createResponseMessageStream for '" + fileName + "'.", e);
                    failuresList.append(
                        collectException("createResponseMessageStream", fileName, e));
                  }
                }

              } catch (ServiceException e) {

                LOG.debug("Exception in createResponseData for '" + fileName + "'.", e);
                failuresList.append(collectException("createResponseData", fileName, e));

              } catch (ValidationException e) {

                LOG.debug("Exception in createResponseData for '" + fileName + "'.", e);
                failuresList.append(collectException("createResponseData", fileName, e));
              }

            } else {

              try {

                startTime = System.currentTimeMillis();

                NCIPInitiationData initiationData =
                    translator.createInitiationData(serviceContext, inStream);

                endTime = System.currentTimeMillis();
                initTranslateStreamToSvcElapsedTime += (endTime - startTime);
                initMsgStreamToSvcCount++;

                Assert.assertNotNull(
                    "createInitiationData returned null for " + fileName + ".", initiationData);

                if (initiationData != null) {

                  try {

                    startTime = System.currentTimeMillis();

                    InputStream initiationStream =
                        translator.createInitiationMessageStream(serviceContext, initiationData);

                    Assert.assertNotNull(initiationStream);

                    endTime = System.currentTimeMillis();
                    initTranslateSvcToStreamElapsedTime += (endTime - startTime);
                    initMsgSvcToStreamCount++;

                    if (performXMLDiff) {

                      performXMLDiff(initiationStream, failuresList, file);
                    }

                  } catch (ServiceException e) {

                    LOG.debug(
                        "Exception in createInitiationMessageStream for '" + fileName + "'.", e);
                    failuresList.append(
                        collectException("createInitiationMessageStream", fileName, e));

                  } catch (ValidationException e) {

                    LOG.debug(
                        "Exception in createInitiationMessageStream for '" + fileName + "'.", e);
                    failuresList.append(
                        collectException("createInitiationMessageStream", fileName, e));
                  }
                }

              } catch (ServiceException e) {

                LOG.debug("Exception in createInitiationData for '" + fileName + "'.", e);
                failuresList.append(collectException("createInitiationData", fileName, e));

              } catch (ValidationException e) {

                LOG.debug("Exception in createInitiationData for '" + fileName + "'.", e);
                failuresList.append(collectException("createInitiationData", fileName, e));
              }
            }
          }
        }
      }

      Assert.assertTrue(
          "One or more messages failed:" + System.getProperty("line.separator") + failuresList,
          failuresList.length() == 0);

    } else {
      Assert.fail(
          "No files were found in "
              + sampleFilesDirectory
              + ". Note: do not include a trailing slash in the path."
              + "Working directory: "
              + System.getProperty("user.dir"));
    }

    LOG.info(
        "Elapsed time for translating stream-to-service for initiation messages: "
            + initTranslateStreamToSvcElapsedTime
            + " for "
            + initMsgStreamToSvcCount
            + " messages; average "
            + computeAverage(initTranslateStreamToSvcElapsedTime, initMsgStreamToSvcCount));
    LOG.info(
        "Elapsed time for translating stream-to-service for response messages: "
            + respTranslateStreamToSvcElapsedTime
            + " for "
            + respMsgStreamToSvcCount
            + " messages; average "
            + computeAverage(respTranslateStreamToSvcElapsedTime, respMsgStreamToSvcCount));
    LOG.info(
        "Elapsed time for translating service-to-stream for initiation messages: "
            + initTranslateSvcToStreamElapsedTime
            + " for "
            + initMsgSvcToStreamCount
            + " messages; average "
            + computeAverage(initTranslateSvcToStreamElapsedTime, initMsgSvcToStreamCount));
    LOG.info(
        "Elapsed time for translating service-to-stream for response messages: "
            + respTranslateSvcToStreamElapsedTime
            + " for "
            + respMsgSvcToStreamCount
            + " messages; average "
            + computeAverage(respTranslateSvcToStreamElapsedTime, respMsgSvcToStreamCount));

    String statsReport = statisticsBean.createCSVReport();
    System.out.println(statsReport);
  }
  protected void performXMLDiff(InputStream msgStream, StringBuilder failuresList, File file)
      throws ServiceException {

    String fileName = file.getName();

    try {

      File prettyPrintedXMLFile = File.createTempFile("BaseTestJAXBTranslator", ".xml");
      prettyPrintedXMLFile.deleteOnExit();

      Writer outWriter = null;
      try {

        outWriter = new FileWriter(prettyPrintedXMLFile);

      } catch (IOException e) {

        throw new ServiceException(ServiceError.RUNTIME_ERROR, e);
      }

      ToolkitHelper.prettyPrintXML(msgStream, outWriter);

      // Compare the two XML files
      // Because the org.diffxml.diffxml uses a GNU License, not an MIT license,
      // it is not provided as part of the Toolkit, we use reflection to invoke
      // it here so we can avoid problems compiling this class in the absence of that
      // package. Note that, if the package is absent this "diff" will be silently
      // skipped.
      try {
        // The following 3 lines or code are equivalent to this:
        // Diff diffInstance = DiffFactory.createDiff();
        Class<?> diffFactoryClass = Class.forName(DIFFXML_CLASS_NAME);

        try {

          Method createDiffMethod = diffFactoryClass.getMethod("createDiff");
          Object diffInstance = createDiffMethod.invoke(null);

          // The following 2 lines of code are equivalent to this:
          // Document delta = diffInstance.diff(file, temp);
          Method diffMethod = diffInstance.getClass().getMethod("diff", File.class, File.class);
          Document deltaDocument =
              (Document) diffMethod.invoke(diffInstance, file, prettyPrintedXMLFile);

          if (deltaDocument.getDocumentElement().hasChildNodes()) {

            if (reportDiffAsXMLIndented) {

              OutputStream byteStream = new ByteArrayOutputStream();
              // DOMOps.outputXMLIndented(deltaDocument, byteStream);
              Class<?> DOMOpsClass = Class.forName("org.diffxml.diffxml.DOMOps");
              Method outputXMLIndentedMethod =
                  DOMOpsClass.getMethod("outputXMLIndented", Document.class, OutputStream.class);
              outputXMLIndentedMethod.invoke(null, deltaDocument, byteStream);

              failuresList
                  .append(
                      new StringBuilder()
                          .append("performXMLDiff detected differences for ")
                          .append(fileName)
                          .append(":\n")
                          .append('\t')
                          .append("Result XML file does not match input:\n")
                          .append(byteStream.toString()))
                  .append('\n');

            } else {

              try {
                String[] parms = {file.getAbsolutePath(), prettyPrintedXMLFile.getAbsolutePath()};
                String diffOutput = runCmd(diffCommand, parms);
                if (diffOutput != null && diffOutput.length() > 0) {

                  failuresList.append(
                      new StringBuilder()
                          .append("performXMLDiff detected differences for ")
                          .append(fileName)
                          .append(":\n")
                          .append('\t')
                          .append("Input XML file (on the left) is not matched ")
                          .append("by result XML file (on the right):\n")
                          .append(diffOutput));
                }

              } catch (ServiceException e) {

                failuresList.append(collectException("performXMLDiff", fileName, e));
              }
            }
          }

        } catch (ClassNotFoundException e) {

          failuresList.append(collectException("performXMLDiff", fileName, e));

        } catch (InvocationTargetException e) {

          failuresList.append(collectException("performXMLDiff", fileName, e));

        } catch (NoSuchMethodException e) {

          failuresList.append(collectException("performXMLDiff", fileName, e));

        } catch (IllegalAccessException e) {

          failuresList.append(collectException("performXMLDiff", fileName, e));

        } catch (Exception e) {

          failuresList.append(collectException("performXMLDiff", fileName, e));
        }
      } catch (ClassNotFoundException e) {

        LOG.warn(
            "ClassNotFoundException trying to load "
                + DIFFXML_CLASS_NAME
                + ". Skipping diffXML comparison. Exception was:",
            e);

      } finally {

        prettyPrintedXMLFile.delete();
      }

    } catch (IOException e) {

      failuresList.append(collectException("performXMLDiff", fileName, e));
    }
  }