@Override
  public void add(IUndoableOperation operation) {
    Assert.isNotNull(operation);

    /*
     * If we are in the middle of executing an open batching operation, and
     * this is not that operation, then we need only add the context of the
     * new operation to the batch. The operation itself is disposed since we
     * will never undo or redo it. We consider it to be triggered by the
     * batching operation and assume that its undo will be triggered by the
     * batching operation undo.
     */
    synchronized (openCompositeLock) {
      if (openComposite != null && openComposite != operation) {
        openComposite.add(operation);
        return;
      }
    }

    if (checkUndoLimit(operation)) {
      synchronized (undoRedoHistoryLock) {
        undoList.add(operation);
      }
      notifyAdd(operation);

      // flush redo stack for related contexts
      IUndoContext[] contexts = operation.getContexts();
      for (int i = 0; i < contexts.length; i++) {
        flushRedo(contexts[i]);
      }
    } else {
      // Dispose the operation since we will not have a reference to it.
      operation.dispose();
    }
  }
 @Override
 public void dispose(
     IUndoContext context, boolean flushUndo, boolean flushRedo, boolean flushContext) {
   // dispose of any limit that was set for the context if it is not to be
   // used again.
   if (flushContext) {
     if (DEBUG_OPERATION_HISTORY_DISPOSE) {
       Tracing.printTrace(
           "OPERATIONHISTORY", "Flushing context " + context); // $NON-NLS-1$//$NON-NLS-2$
     }
     flushUndo(context);
     flushRedo(context);
     limits.remove(context);
     return;
   }
   if (flushUndo) {
     flushUndo(context);
   }
   if (flushRedo) {
     flushRedo(context);
   }
 }