public void redoTransformationAction(TransMeta transMeta, TransAction transAction) {
    switch (transAction.getType()) {
      case TransAction.TYPE_ACTION_NEW_STEP:
        // re-delete the step at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          StepMeta stepMeta = (StepMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addStep(idx, stepMeta);

          spoon.refreshTree();
          spoon.refreshGraph();
        }
        break;

      case TransAction.TYPE_ACTION_NEW_CONNECTION:
        // re-insert the connection at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          DatabaseMeta ci = (DatabaseMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addDatabase(idx, ci);
          spoon.refreshTree();
          spoon.refreshGraph();
        }
        break;

      case TransAction.TYPE_ACTION_NEW_NOTE:
        // re-insert the note at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addNote(idx, ni);
          spoon.refreshTree();
          spoon.refreshGraph();
        }
        break;

      case TransAction.TYPE_ACTION_NEW_HOP:
        // re-insert the hop at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addTransHop(idx, hi);
          spoon.refreshTree();
          spoon.refreshGraph();
        }
        break;

        //
        // DELETE
        //
      case TransAction.TYPE_ACTION_DELETE_STEP:
        // re-remove the step at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeStep(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

      case TransAction.TYPE_ACTION_DELETE_CONNECTION:
        // re-remove the connection at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeDatabase(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

      case TransAction.TYPE_ACTION_DELETE_NOTE:
        // re-remove the note at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeNote(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

      case TransAction.TYPE_ACTION_DELETE_HOP:
        // re-remove the hop at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeTransHop(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        //
        // CHANGE
        //

        // We changed a step : undo this...
      case TransAction.TYPE_ACTION_CHANGE_STEP:
        // Delete the current step, insert previous version.
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          StepMeta stepMeta = (StepMeta) ((StepMeta) transAction.getCurrent()[i]).clone();
          transMeta.getStep(transAction.getCurrentIndex()[i]).replaceMeta(stepMeta);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a connection : undo this...
      case TransAction.TYPE_ACTION_CHANGE_CONNECTION:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          DatabaseMeta databaseMeta = (DatabaseMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];

          transMeta.getDatabase(idx).replaceMeta((DatabaseMeta) databaseMeta.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a note : undo this...
      case TransAction.TYPE_ACTION_CHANGE_NOTE:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];

          transMeta.removeNote(idx);
          transMeta.addNote(idx, (NotePadMeta) ni.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a hop : undo this...
      case TransAction.TYPE_ACTION_CHANGE_HOP:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];

          transMeta.removeTransHop(idx);
          transMeta.addTransHop(idx, (TransHopMeta) hi.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        //
        // CHANGE POSITION
        //
      case TransAction.TYPE_ACTION_POSITION_STEP:
        for (int i = 0; i < transAction.getCurrentIndex().length; i++) {
          // Find & change the location of the step:
          StepMeta stepMeta = transMeta.getStep(transAction.getCurrentIndex()[i]);
          stepMeta.setLocation(transAction.getCurrentLocation()[i]);
        }
        spoon.refreshGraph();
        break;
      case TransAction.TYPE_ACTION_POSITION_NOTE:
        for (int i = 0; i < transAction.getCurrentIndex().length; i++) {
          int idx = transAction.getCurrentIndex()[i];
          NotePadMeta npi = transMeta.getNote(idx);
          Point curr = transAction.getCurrentLocation()[i];
          npi.setLocation(curr);
        }
        spoon.refreshGraph();
        break;
      default:
        break;
    }

    // OK, now check if we need to do this again...
    if (transMeta.viewNextUndo() != null) {
      if (transMeta.viewNextUndo().getNextAlso()) spoon.redoAction(transMeta);
    }
  }
  public void undoTransformationAction(TransMeta transMeta, TransAction transAction) {
    switch (transAction.getType()) {
        // We created a new step : undo this...
      case TransAction.TYPE_ACTION_NEW_STEP:
        // Delete the step at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeStep(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We created a new connection : undo this...
      case TransAction.TYPE_ACTION_NEW_CONNECTION:
        // Delete the connection at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeDatabase(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We created a new note : undo this...
      case TransAction.TYPE_ACTION_NEW_NOTE:
        // Delete the note at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeNote(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We created a new hop : undo this...
      case TransAction.TYPE_ACTION_NEW_HOP:
        // Delete the hop at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeTransHop(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We created a new slave : undo this...
      case TransAction.TYPE_ACTION_NEW_SLAVE:
        // Delete the slave at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.getSlaveServers().remove(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We created a new slave : undo this...
      case TransAction.TYPE_ACTION_NEW_CLUSTER:
        // Delete the slave at correct location:
        for (int i = transAction.getCurrent().length - 1; i >= 0; i--) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.getClusterSchemas().remove(idx);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        //
        // DELETE
        //

        // We delete a step : undo this...
      case TransAction.TYPE_ACTION_DELETE_STEP:
        // un-Delete the step at correct location: re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          StepMeta stepMeta = (StepMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addStep(idx, stepMeta);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We deleted a connection : undo this...
      case TransAction.TYPE_ACTION_DELETE_CONNECTION:
        // re-insert the connection at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          DatabaseMeta ci = (DatabaseMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addDatabase(idx, ci);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We delete new note : undo this...
      case TransAction.TYPE_ACTION_DELETE_NOTE:
        // re-insert the note at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          transMeta.addNote(idx, ni);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We deleted a hop : undo this...
      case TransAction.TYPE_ACTION_DELETE_HOP:
        // re-insert the hop at correct location:
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i];
          int idx = transAction.getCurrentIndex()[i];
          // Build a new hop:
          StepMeta from = transMeta.findStep(hi.getFromStep().getName());
          StepMeta to = transMeta.findStep(hi.getToStep().getName());
          TransHopMeta hinew = new TransHopMeta(from, to);
          transMeta.addTransHop(idx, hinew);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        //
        // CHANGE
        //

        // We changed a step : undo this...
      case TransAction.TYPE_ACTION_CHANGE_STEP:
        // Delete the current step, insert previous version.
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          StepMeta prev = (StepMeta) ((StepMeta) transAction.getPrevious()[i]).clone();
          int idx = transAction.getCurrentIndex()[i];

          transMeta.getStep(idx).replaceMeta(prev);
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a connection : undo this...
      case TransAction.TYPE_ACTION_CHANGE_CONNECTION:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          DatabaseMeta prev = (DatabaseMeta) transAction.getPrevious()[i];
          int idx = transAction.getCurrentIndex()[i];

          transMeta.getDatabase(idx).replaceMeta((DatabaseMeta) prev.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a note : undo this...
      case TransAction.TYPE_ACTION_CHANGE_NOTE:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          int idx = transAction.getCurrentIndex()[i];
          transMeta.removeNote(idx);
          NotePadMeta prev = (NotePadMeta) transAction.getPrevious()[i];
          transMeta.addNote(idx, (NotePadMeta) prev.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        // We changed a hop : undo this...
      case TransAction.TYPE_ACTION_CHANGE_HOP:
        // Delete & re-insert
        for (int i = 0; i < transAction.getCurrent().length; i++) {
          TransHopMeta prev = (TransHopMeta) transAction.getPrevious()[i];
          int idx = transAction.getCurrentIndex()[i];

          transMeta.removeTransHop(idx);
          transMeta.addTransHop(idx, (TransHopMeta) prev.clone());
        }
        spoon.refreshTree();
        spoon.refreshGraph();
        break;

        //
        // POSITION
        //

        // The position of a step has changed: undo this...
      case TransAction.TYPE_ACTION_POSITION_STEP:
        // Find the location of the step:
        for (int i = 0; i < transAction.getCurrentIndex().length; i++) {
          StepMeta stepMeta = transMeta.getStep(transAction.getCurrentIndex()[i]);
          stepMeta.setLocation(transAction.getPreviousLocation()[i]);
        }
        spoon.refreshGraph();
        break;

        // The position of a note has changed: undo this...
      case TransAction.TYPE_ACTION_POSITION_NOTE:
        for (int i = 0; i < transAction.getCurrentIndex().length; i++) {
          int idx = transAction.getCurrentIndex()[i];
          NotePadMeta npi = transMeta.getNote(idx);
          Point prev = transAction.getPreviousLocation()[i];
          npi.setLocation(prev);
        }
        spoon.refreshGraph();
        break;
      default:
        break;
    }

    // OK, now check if we need to do this again...
    if (transMeta.viewNextUndo() != null) {
      if (transMeta.viewNextUndo().getNextAlso()) spoon.undoAction(transMeta);
    }
  }