@Override
 public Void call() throws Exception {
   Stopwatch reportingStopwatch = Stopwatch.started();
   reportingTask.generateReports();
   LOGGER.debug("{} generated in {} ms", reportingTask.toString(), reportingStopwatch.stop());
   return null;
 }
  public TestOutcomes generateReportsForTestResultsFrom(final File sourceDirectory)
      throws IOException {

    Stopwatch stopwatch = Stopwatch.started();
    copyScreenshotsFrom(sourceDirectory);

    LOGGER.debug("Copied screenshots after {} ms", stopwatch.lapTime());

    TestOutcomes allTestOutcomes = loadTestOutcomesFrom(sourceDirectory);

    LOGGER.debug("Loaded test outcomes after {} ms", stopwatch.lapTime());

    generateReportsForTestResultsIn(allTestOutcomes);

    LOGGER.debug("Generated reports after {} ms", stopwatch.lapTime());

    return allTestOutcomes;
  }
  public void generateReportsForTestResultsIn(TestOutcomes testOutcomes) throws IOException {

    Stopwatch stopwatch = Stopwatch.started();
    LOGGER.info("Generating test results for {} tests", testOutcomes.getTestCount());

    FreemarkerContext context =
        new FreemarkerContext(
            environmentVariables,
            requirements.getRequirementsService(),
            issueTracking,
            relativeLink);

    RequirementsOutcomes requirementsOutcomes =
        requirements.getRequirementsOutcomeFactory().buildRequirementsOutcomesFrom(testOutcomes);

    LOGGER.info(
        "{} requirements loaded after {} ms",
        requirementsOutcomes.getFlattenedRequirementCount(),
        stopwatch.lapTime());

    requirementsOutcomes = requirementsOutcomes.withoutUnrelatedRequirements();

    LOGGER.info(
        "{} related requirements found after {} ms",
        requirementsOutcomes.getFlattenedRequirementCount(),
        stopwatch.lapTime());

    List<String> knownRequirementReportNames =
        requirementReportNamesFrom(requirementsOutcomes, reportNameProvider);

    Set<ReportingTask> reportingTasks = new HashSet<>();

    reportingTasks.add(new CopyResourcesTask());
    reportingTasks.add(new CopyTestResultsTask());
    reportingTasks.add(
        new AggregateReportingTask(
            context,
            environmentVariables,
            requirements.getRequirementsService(),
            getOutputDirectory(),
            testOutcomes));
    reportingTasks.add(
        new TagTypeReportingTask(
            context, environmentVariables, getOutputDirectory(), reportNameProvider, testOutcomes));
    reportingTasks.addAll(
        tagReportsFor(testOutcomes)
            .using(
                context,
                environmentVariables,
                getOutputDirectory(),
                reportNameProvider,
                testOutcomes.getTags(),
                knownRequirementReportNames));

    reportingTasks.addAll(
        ResultReports.resultReportsFor(
            testOutcomes, context, environmentVariables, getOutputDirectory(), reportNameProvider));
    reportingTasks.addAll(
        RequirementsReports.requirementsReportsFor(
            context,
            environmentVariables,
            getOutputDirectory(),
            reportNameProvider,
            requirements.getRequirementsOutcomeFactory(),
            requirements.getRequirementsService(),
            relativeLink,
            testOutcomes,
            requirementsOutcomes));

    LOGGER.info("Starting generating reports: {} ms", stopwatch.lapTime());
    generateReportsFor(reportingTasks);

    LOGGER.info(
        "Finished generating test results for {} tests after {} ms",
        testOutcomes.getTestCount(),
        stopwatch.stop());
  }