/**
   * Executes the workflow against the files of all representations.
   *
   * @param workflowFile the workflow File
   * @param mapOfRepresentationsAndFiles a {@link Map} of representation and their respective files
   * @param report the execution {@link Report}.
   */
  private void executeWorkflowInAllRepresentations(
      final File workflowFile,
      final Map<String, List<String>> mapOfRepresentationsAndFiles,
      final Report report) {

    for (String representation : mapOfRepresentationsAndFiles.keySet()) {

      final List<String> files = mapOfRepresentationsAndFiles.get(representation);

      ReportItem reportItem = executeWorkflowInRepresentation(workflowFile, representation, files);
      report.addItem(reportItem);
    }
  }
  /** @see Plugin#execute() */
  public Report execute() throws PluginException {

    Report executionReport = new Report();
    executionReport.setType(Report.TYPE_PLUGIN_REPORT);
    executionReport.setTitle(
        "Plugin " + getName() + " (version " + getVersion() + ") execution report.");
    executionReport.addAttribute(
        new Attribute("Start datetime", DateParser.getIsoDate(new Date())));

    // Creates RODAClient, Uploader Browser and Ingest
    initClientServices();

    boolean terminated = false;
    String representationPID;
    try {

      representationPID = getNextRepresentationPID();
      terminated = representationPID == null;

      logger.info("next representation is " + representationPID + ". terminated=" + terminated);

    } catch (RODAException e) {
      logger.debug("Error getting next representation PID - " + e.getMessage(), e);

      executionReport.addAttribute(new Attribute("Error", e.getMessage()));
      executionReport.addAttribute(
          new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

      throw new PluginException(
          "Error getting next representation PID - " + e.getMessage(), e, executionReport);
    }

    while (!terminated) {

      try {

        ReportItem reportItem = executeOn(representationPID);

        logger.info("adding ReportItem for representation " + representationPID + " " + reportItem);

        executionReport.addItem(reportItem);

      } catch (PluginException e) {

        logger.debug(
            "Error converting representation " + representationPID + " - " + e.getMessage(), e);

        if (e.getReportItem() != null) {

          ReportItem reportItem = e.getReportItem();

          reportItem.addAttribute(new Attribute("Error", e.getMessage()));

          reportItem.addAttribute(
              new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

          executionReport.addItem(e.getReportItem());
        }

        if (getParameterFailAtFirstError()) {

          throw new MigratorPluginException(
              "Error executing migration - " + e.getMessage(), e, executionReport);
        }
      }

      addConvertedRepresentationPID(representationPID);

      try {

        representationPID = getNextRepresentationPID();
        terminated = representationPID == null;

        logger.info("next representation is " + representationPID + ". terminated=" + terminated);

      } catch (RODAException e) {
        logger.debug("Error getting next representation PID - " + e.getMessage(), e);

        executionReport.addAttribute(new Attribute("Error", e.getMessage()));
        executionReport.addAttribute(
            new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

        throw new PluginException(
            "Error getting next representation PID - " + e.getMessage(), e, executionReport);
      }
    }

    executionReport.addAttribute(
        new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

    return executionReport;
  }
  /**
   * Executes the plugin.
   *
   * @return The execution {@link Report}
   * @throws PluginException if an error occurred during execution.
   * @see Plugin#execute()
   */
  public Report execute() throws PluginException {

    initClientServices();

    final Report report = new Report();
    report.setType(Report.TYPE_PLUGIN_REPORT);
    report.setTitle("Report of plugin " + getName());
    report.setAttributes(
        new Attribute[] {
          new Attribute("Agent name", getName()),
          new Attribute("Agent version", Float.toString(getVersion())),
          new Attribute("Start datetime", DateParser.getIsoDate(new Date()))
        });

    try {

      final Document plan = getPlanDocument(planFile);

      final List<String> fileURLs = getFileURLsFromPlan(plan);
      logger.debug("File URLs from plan: " + fileURLs);

      report.addAttribute(
          new Attribute("Number of files", new Integer(fileURLs.size()).toString()));

      final Map<String, List<String>> representationFiles = groupFileIDsByRepresentation(fileURLs);
      logger.debug("representationFiles: " + representationFiles);

      report.addAttribute(
          new Attribute(
              "Number of representations", new Integer(representationFiles.size()).toString()));

      final File workflowFile = getWorkflowFile(plan);
      logger.debug("Workflow file: " + workflowFile);

      executeWorkflowInAllRepresentations(workflowFile, representationFiles, report);

      report.addAttribute(new Attribute("Successful", "yes"));
      report.addAttribute(new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

      // Report for the execution of this Plugin
      return report;

    } catch (PluginException e) {
      logger.error("Error executing plugin - " + e.getMessage(), e);
      logger.info("Setting report in exception and re-throwing");

      report.addAttribute(new Attribute("Successful", "no"));
      report.addAttribute(new Attribute("Error", e.getMessage()));
      report.addAttribute(new Attribute("Finish datetime", DateParser.getIsoDate(new Date())));

      e.setReport(report);

      throw e;
    }
  }