@Override
  public ScenarioInstance createInstance(final EvaluatorContext ctx, Operation operation) {
    /** This scenario is triggered by a delete of a file matching the pattern */
    if (operation instanceof DeleteFileOperation) {
      DeleteFileOperation c = (DeleteFileOperation) operation;

      Matcher m = pattern.matcher(c.getName());
      if (m.matches()) {
        if (logger.isDebugEnabled()) {
          logger.debug("New Scenario Delete Restore Shuffle Instance:" + c.getName());
        }

        ScenarioDeleteRestoreInstance instance = new ScenarioDeleteRestoreInstance();
        instance.setTimeout(timeout);
        instance.setRanking(ranking);
        return instance;
      }
    }

    // No not interested.
    return null;
  }
  /**
   * Evaluate the next operation
   *
   * @param operation
   */
  public Command evaluate(Operation operation) {

    /** Anti-pattern : timeout */
    Date now = new Date();
    if (now.getTime() > startTime.getTime() + getTimeout()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Instance timed out");
      }
      isComplete = true;
      return null;
    }

    switch (internalState) {
      case NONE:
        if (operation instanceof RenameFileOperation) {
          RenameFileOperation r = (RenameFileOperation) operation;
          fileMiddle = r.getFrom();
          fileEnd = r.getTo();

          String[] paths = FileName.splitPath(r.getFromPath());
          folderMiddle = paths[0];

          String[] paths2 = FileName.splitPath(r.getToPath());
          folderEnd = paths2[0];

          internalState = InternalState.DELETE;
        } else {
          // anything else bomb out
          if (logger.isDebugEnabled()) {
            logger.debug("State error, expected a RENAME");
          }
          isComplete = true;
        }

      case DELETE:
        if (operation instanceof DeleteFileOperation) {
          internalState = InternalState.MOVE;
          DeleteFileOperation d = (DeleteFileOperation) operation;
          if (d.getName().equalsIgnoreCase(fileEnd)) {
            ArrayList<Command> commands = new ArrayList<Command>();
            ArrayList<Command> postCommitCommands = new ArrayList<Command>();
            ArrayList<Command> postErrorCommands = new ArrayList<Command>();
            // Rename node to remove "hidden". In this case node will be moved to the archive store
            // and can be restored later.
            // This can be replaced with command that removes hidden aspect in future(when
            // ContentDiskDriver2.setFileInformation() method will support hidden attribute)
            RenameFileCommand r1 =
                new RenameFileCommand(
                    fileEnd,
                    "tmp" + fileEnd,
                    d.getRootNodeRef(),
                    folderEnd + "\\" + fileEnd,
                    folderEnd + "\\" + "tmp" + fileEnd);
            fileEnd = "tmp" + fileEnd;
            commands.add(r1);
            commands.add(
                new DeleteFileCommand(fileEnd, d.getRootNodeRef(), folderEnd + "\\" + fileEnd));
            postCommitCommands.add(newDeleteFileCallbackCommand());
            return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
          }
        }
        if (operation instanceof CloseFileOperation) {
          CloseFileOperation c = (CloseFileOperation) operation;
          if (c.getNetworkFile().hasDeleteOnClose() && c.getName().equalsIgnoreCase(fileEnd)) {
            internalState = InternalState.MOVE;
            ArrayList<Command> commands = new ArrayList<Command>();
            ArrayList<Command> postCommitCommands = new ArrayList<Command>();
            ArrayList<Command> postErrorCommands = new ArrayList<Command>();
            // Rename node to remove "hidden". In this case node will be moved to the archive store
            // and can be restored later.
            RenameFileCommand r1 =
                new RenameFileCommand(
                    fileEnd,
                    "tmp" + fileEnd,
                    c.getRootNodeRef(),
                    folderEnd + "\\" + fileEnd,
                    folderEnd + "\\" + "tmp" + fileEnd);
            fileEnd = "tmp" + fileEnd;
            commands.add(r1);
            commands.add(
                new CloseFileCommand(
                    fileEnd, c.getNetworkFile(), c.getRootNodeRef(), folderEnd + "\\" + fileEnd));
            postCommitCommands.add(newDeleteFileCallbackCommand());
            return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
          }
        }

        break;

      case MOVE:
        if (operation instanceof MoveFileOperation && originalNodeRef != null) {
          if (logger.isDebugEnabled()) {
            logger.info("Tracking rename: " + operation);
          }
          MoveFileOperation m = (MoveFileOperation) operation;

          if (fileMiddle.equalsIgnoreCase(m.getTo())) {
            if (logger.isDebugEnabled()) {
              logger.debug("Got second rename");
            }

            fileFrom = m.getFrom();

            String[] paths = FileName.splitPath(m.getFromPath());
            String oldFolder = paths[0];

            ArrayList<Command> commands = new ArrayList<Command>();

            RestoreFileCommand rest1 =
                new RestoreFileCommand(fileEnd, m.getRootNodeRef(), folderEnd, 0, originalNodeRef);
            RenameFileCommand r1 =
                new RenameFileCommand(
                    fileEnd,
                    fileMiddle,
                    m.getRootNodeRef(),
                    folderEnd + "\\" + fileEnd,
                    folderMiddle + "\\" + fileMiddle);
            commands.add(rest1);
            commands.add(r1);
            CopyContentCommand copyContent =
                new CopyContentCommand(
                    fileFrom,
                    fileMiddle,
                    m.getRootNodeRef(),
                    oldFolder + "\\" + fileFrom,
                    folderMiddle + "\\" + fileMiddle);
            commands.add(copyContent);
            DeleteFileCommand d1 =
                new DeleteFileCommand(oldFolder, m.getRootNodeRef(), oldFolder + "\\" + fileFrom);
            commands.add(d1);

            isComplete = true;
            return new CompoundCommand(commands);
          }
        }

        break;
    }

    return null;
  }