private String createDerivedRepresentation(
      final String roPID,
      final Map<String, WorkflowExecutionOutput> outputs,
      final ReportItem reportItem)
      throws ExecutePlanException {

    logger.trace(String.format("createNewRepresentation(%s, %s)", roPID, outputs));

    RepresentationObject roOriginal = null;
    LocalRepresentationObject roLocalDerived = null;
    final StringBuilder sbExecDetails = new StringBuilder();

    try {

      roOriginal = rodaClient.getBrowserService().getRepresentationObject(roPID);

      roLocalDerived = downloadRepresentationToLocalDisk(roOriginal);
      roLocalDerived.setId(DateParser.getIsoDate(new Date()));
      roLocalDerived.setStatuses(new String[] {RepresentationObject.STATUS_NORMALIZED});

      sbExecDetails.append(
          String.format("<planExecutionDetails plan=\"%s\">%n", planFile.getName()));

      // Check if root file was changed
      if (outputs.containsKey(roLocalDerived.getRootFile().getId())) {
        final WorkflowExecutionOutput output = outputs.get(roLocalDerived.getRootFile().getId());
        updateFile(roLocalDerived.getRootFile(), output);
        sbExecDetails.append(
            getPlanExecutionDetailsForFile(roLocalDerived.getRootFile().getId(), output));
      }

      if (roLocalDerived.getPartFiles() != null) {
        for (RepresentationFile rFile : roLocalDerived.getPartFiles()) {
          if (outputs.containsKey(rFile.getId())) {
            final WorkflowExecutionOutput output = outputs.get(rFile.getId());
            updateFile(rFile, output);
            sbExecDetails.append(getPlanExecutionDetailsForFile(rFile.getId(), output));
          }
        }
      }

      sbExecDetails.append(String.format("</planExecutionDetails>%n"));

      roLocalDerived.setType(RepresentationObject.DIGITALIZED_WORK);
      final String subtype = RepresentationBuilder.getRepresentationSubtype(roLocalDerived);
      roLocalDerived.setSubType(subtype);

    } catch (RODAException e) {
      deleteTemporaryLocalRepresentation(roLocalDerived);
      logger.error(e.getMessage(), e);
      throw new ExecutePlanException(e.getMessage(), e);
    } catch (RemoteException e) {
      deleteTemporaryLocalRepresentation(roLocalDerived);
      logger.error(e.getMessage(), e);
      throw new ExecutePlanException(e.getMessage(), e);
    } catch (IOException e) {
      deleteTemporaryLocalRepresentation(roLocalDerived);
      logger.error(e.getMessage(), e);
      throw new ExecutePlanException(e.getMessage(), e);
    }

    String derivedROPID = null;
    try {

      derivedROPID = ingestRepresentation(roLocalDerived);
      reportItem.addAttribute(new Attribute("Derived representation PID", derivedROPID));

    } catch (IngestException e) {

      logger.error("Error ingesting new representation - " + e.getMessage(), e);
      throw new ExecutePlanException("Error ingesting new representation - " + e.getMessage(), e);

    } finally {

      deleteTemporaryLocalRepresentation(roLocalDerived);
    }

    try {

      final String epoPID =
          createPreservationEvent(
              roOriginal.getPid(), derivedROPID, sbExecDetails.toString(), reportItem);
      reportItem.addAttribute(new Attribute("Derivation event PID", epoPID));

    } catch (ExecutePlanException e) {
      logger.debug("Error registering convertion event - " + e.getMessage(), e);

      try {
        logger.warn("Error registering convertion event. Removing created object " + derivedROPID);

        this.rodaClient.getIngestService().removeObjects(new String[] {derivedROPID});

      } catch (RODAClientException e1) {
        logger.warn(
            "Error removing representation " + roPID + " - " + e1.getMessage() + ". IGNORING", e1);
      } catch (RemoteException e1) {
        logger.warn(
            "Error removing representation " + roPID + " - " + e1.getMessage() + ". IGNORING", e1);
      } catch (IngestException e1) {
        logger.warn(
            "Error removing representation " + roPID + " - " + e1.getMessage() + ". IGNORING", e1);
      }

      throw new ExecutePlanException(
          "Error registering convertion event - " + e.getMessage(), e, reportItem);
    }

    return derivedROPID;
  }
  /**
   * @throws ConverterException
   * @see SynchronousConverter#convert(RepresentationObject)
   */
  public ConversionResult convert(RepresentationObject representation)
      throws RepresentationAlreadyConvertedException, InvalidRepresentationException,
          WrongRepresentationTypeException, WrongRepresentationSubtypeException,
          ConverterException {

    UUID uuid = UUID.randomUUID();
    File finalDirectory = new File(getCacheDirectory(), uuid.toString());

    StringBuffer report = new StringBuffer();

    LocalRepresentationObject localRepresentation = null;
    try {

      localRepresentation = downloadRepresentationToLocalDisk(representation);

      logger.trace("Representation downloaded " + localRepresentation);

    } catch (DownloaderException e) {
      logger.debug("Exception downloading representation files - " + e.getMessage(), e);
      throw new ConverterException(
          "Exception downloading representation files - " + e.getMessage(), e);
    } catch (IOException e) {
      logger.debug("Exception downloading representation files - " + e.getMessage(), e);
      throw new ConverterException(
          "Exception downloading representation files - " + e.getMessage(), e);
    }

    File tempDirectory = null;
    try {

      tempDirectory = TempDir.createUniqueDirectory("convertedRep");

      logger.debug("Saving converted representation files to " + tempDirectory);

    } catch (IOException e) {
      logger.debug("Error creating directory for converted representation - " + e.getMessage(), e);
      throw new ConverterException(
          "Error creating directory for converted representation - " + e.getMessage(), e);
    }

    LocalRepresentationObject convertedRepresentation = null;
    try {
      // Create a new RepresentationObject that is a copy of source
      // RepresentationObject
      convertedRepresentation = new LocalRepresentationObject(tempDirectory, localRepresentation);

      // Convert Root File
      RepresentationFile convertedRootFile =
          convertRootFile(localRepresentation.getRootFile(), tempDirectory, report);

      convertedRepresentation.setRootFile(convertedRootFile);

      String subtype = RepresentationBuilder.getRepresentationSubtype(convertedRepresentation);
      convertedRepresentation.setSubType(subtype);

    } catch (IOException e) {
      logger.debug("Error creating directory for converted representation - " + e.getMessage(), e);
      throw new ConverterException(
          "Error creating directory for converted representation - " + e.getMessage(), e);
    } catch (CommandException e) {
      logger.debug("Error converting representation - " + e.getMessage(), e);
      throw new ConverterException("Error converting representation - " + e.getMessage(), e);
    }

    try {

      moveToFinalDirectory(convertedRepresentation, finalDirectory);

    } catch (IOException e) {
      logger.debug("Error moving representation to cache - " + e.getMessage(), e);
      throw new ConverterException("Error moving representation to cache - " + e.getMessage(), e);
    }

    EventPreservationObject eventPO = new EventPreservationObject();
    eventPO.setOutcome("success");
    eventPO.setOutcomeDetailNote("converter outcome details");
    eventPO.setOutcomeDetailExtension(report.toString());

    logger.info("Event is " + eventPO);

    return new ConversionResult(convertedRepresentation, eventPO, getAgent());
  }