@Override
  public <
          A extends FlexoUndoableAction<A, T1, T2>,
          T1 extends FlexoModelObject,
          T2 extends FlexoModelObject>
      A performRedoAction(A action, EventObject event) {
    boolean confirmRedoAction = true;
    ActionInitializer<A, T1, T2> actionInitializer = getActionInitializer(action.getActionType());
    FlexoActionRedoInitializer<A> initializer = null;
    if (actionInitializer != null) {
      initializer = actionInitializer.getDefaultRedoInitializer();
      if (initializer != null) {
        confirmRedoAction = initializer.run(event, action);
      }
    }

    if (confirmRedoAction) {
      actionWillBeRedone(action);
      try {
        if (getProject() != null) {
          getProject().clearRecentlyCreatedObjects();
        }
        action.redoActionInContext();
        if (getProject() != null) {
          getProject().notifyRecentlyCreatedObjects();
        }
        actionHasBeenRedone(action, true); // Action succeeded
      } catch (FlexoException exception) {
        actionHasBeenUndone(action, false); // Action failed
        ProgressWindow.hideProgressWindow();
        FlexoExceptionHandler<A> exceptionHandler = null;
        if (actionInitializer != null) {
          exceptionHandler = actionInitializer.getDefaultExceptionHandler();
        }
        if (exceptionHandler != null) {
          if (exceptionHandler.handleException(exception, action)) {
            // The exception has been handled, we may still have to execute finalizer, if any
          } else {
            return action;
          }
        } else {
          return action;
        }
      }

      FlexoActionRedoFinalizer<A> finalizer = null;
      if (actionInitializer != null) {
        finalizer = actionInitializer.getDefaultRedoFinalizer();
        if (finalizer != null) {
          confirmRedoAction = finalizer.run(event, action);
        }
      }
    }
    ProgressWindow.hideProgressWindow();
    return action;
  }
  private <
          A extends FlexoAction<A, T1, T2>,
          T1 extends FlexoModelObject,
          T2 extends FlexoModelObject>
      boolean runExceptionHandler(FlexoException exception, final A action) {
    actionHasBeenPerformed(action, false); // Action failed
    ProgressWindow.hideProgressWindow();
    FlexoExceptionHandler<A> exceptionHandler = null;
    ActionInitializer<A, T1, T2> actionInitializer = getActionInitializer(action.getActionType());
    if (actionInitializer != null) {
      exceptionHandler = actionInitializer.getDefaultExceptionHandler();
    }
    if (exceptionHandler != null) {
      if (exceptionHandler.handleException(exception, action)) {
        // The exception has been handled, we may still have to execute finalizer, if any
        return true;
      } else {
        return false;
      }

    } else {
      return false;
    }
  }
  private <
          A extends org.openflexo.foundation.action.FlexoAction<A, T1, T2>,
          T1 extends FlexoModelObject,
          T2 extends FlexoModelObject>
      A executeAction(final A action, final EventObject event) {
    final boolean progressIsShowing = ProgressWindow.hasInstance();
    boolean confirmDoAction = runInitializer(action, event);
    if (confirmDoAction) {
      actionWillBePerformed(action);
      if (action.isLongRunningAction() && SwingUtilities.isEventDispatchThread()) {
        ProgressWindow.showProgressWindow(action.getLocalizedName(), 100);
        SwingWorker<Void, Void> worker =
            new SwingWorker<Void, Void>() {
              @Override
              protected Void doInBackground() throws Exception {
                runAction(action);
                return null;
              }

              @Override
              protected void done() {
                super.done();
                try {
                  get();
                } catch (InterruptedException e) {
                  e.printStackTrace();
                } catch (ExecutionException e) {
                  e.printStackTrace();
                  if (e.getCause() instanceof FlexoException) {
                    if (!runExceptionHandler((FlexoException) e.getCause(), action)) {
                      if (!progressIsShowing) {
                        ProgressWindow.hideProgressWindow();
                      }
                      return;
                    }
                  } else {
                    throw new RuntimeException(
                        FlexoLocalization.localizedForKey("action_failed")
                            + " "
                            + action.getLocalizedName(),
                        e.getCause());
                  }
                }
                runFinalizer(action, event);
                if (!progressIsShowing) {
                  ProgressWindow.hideProgressWindow();
                }
              }
            };
        worker.execute();
        return action;
      } else {
        try {
          runAction(action);
        } catch (FlexoException exception) {
          if (!runExceptionHandler(exception, action)) {
            return null;
          }
        }
        runFinalizer(action, event);
        if (!progressIsShowing) {
          ProgressWindow.hideProgressWindow();
        }
      }
    }

    return action;
  }