/*******************************************************************************
 * Copyright (c) 2005, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tasktop Technologies -  Bug 323444 - [Undo] [Commands] java.util.ConcurrentModificationException
 *     		when trying to get the undo history from a source viewer
 *******************************************************************************/
package org.eclipse.core.commands.operations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.internal.util.Tracing;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;

/**
 * <p>
 * A base implementation of IOperationHistory that implements a linear undo and
 * redo model . The most recently added operation is available for undo, and the
 * most recently undone operation is available for redo.
 * </p>
 * <p>
 * If the operation eligible for undo is not in a state where it can be undone,
 * then no undo is available. No other operations are considered. Likewise, if
 * the operation available for redo cannot be redone, then no redo is available.
 * </p>
 * <p>
 * Implementations for the direct undo and redo of a specified operation are
 * available. If a strict linear undo is to be enforced, than an
 * IOperationApprover should be installed that prevents undo and redo of any
 * operation that is not the most recently undone or redone operation in all of
 * its undo contexts.
 * </p>
 * <p>
 * The data structures used by the DefaultOperationHistory are synchronized, and
 * entry points that modify the undo and redo history concurrently are also
 * synchronized. This means that the DefaultOperationHistory is relatively
 * "thread-friendly" in its implementation. Outbound notifications or operation
 * approval requests will occur on the thread that initiated the request.
 * Clients may use DefaultOperationHistory API from any thread; however,
 * listeners or operation approvers that receive notifications from the
 * DefaultOperationHistory must be prepared to receive these notifications from
 * a background thread. Any UI access occurring inside these notifications must
 * be properly synchronized using the techniques specified by the client's
 * widget library.
 * </p>
 *
 * <p>
 * This implementation is not intended to be subclassed.
 * </p>
 *
 * @see org.eclipse.core.commands.operations.IOperationHistory
 * @see org.eclipse.core.commands.operations.IOperationApprover
 *
 * @since 3.1
 */
public final class DefaultOperationHistory implements IOperationHistory {

	private static final String FOR_OPERATION = "for operation "; //$NON-NLS-1$
	private static final String OPERATIONHISTORY = "OPERATIONHISTORY"; //$NON-NLS-1$

	/**
	 * This flag can be set to <code>true</code> if the history should print
	 * information to <code>System.out</code> whenever notifications about
	 * changes to the history occur. This flag should be used for debug purposes
	 * only.
	 */
	public static boolean DEBUG_OPERATION_HISTORY_NOTIFICATION;

	/**
	 * This flag can be set to <code>true</code> if the history should print
	 * information to <code>System.out</code> whenever an unexpected condition
	 * arises. This flag should be used for debug purposes only.
	 */
	public static boolean DEBUG_OPERATION_HISTORY_UNEXPECTED;

	/**
	 * This flag can be set to <code>true</code> if the history should print
	 * information to <code>System.out</code> whenever an undo context is
	 * disposed. This flag should be used for debug purposes only.
	 */
	public static boolean DEBUG_OPERATION_HISTORY_DISPOSE;

	/**
	 * This flag can be set to <code>true</code> if the history should print
	 * information to <code>System.out</code> during the open/close sequence.
	 * This flag should be used for debug purposes only.
	 */
	public static boolean DEBUG_OPERATION_HISTORY_OPENOPERATION;

	/**
	 * This flag can be set to <code>true</code> if the history should print
	 * information to <code>System.out</code> whenever an operation is not
	 * approved. This flag should be used for debug purposes only.
	 */
	public static boolean DEBUG_OPERATION_HISTORY_APPROVAL;

	static final int DEFAULT_LIMIT = 20;

	/**
	 * the list of {@link IOperationApprover}s
	 */
	ListenerList<IOperationApprover> approvers = new ListenerList<>(ListenerList.IDENTITY);

	/**
	 * a map of undo limits per context
	 */
	private Map<IUndoContext, Integer> limits = Collections.synchronizedMap(new HashMap<>());

	/**
	 * the list of {@link IOperationHistoryListener}s
	 */
	ListenerList<IOperationHistoryListener> listeners = new ListenerList<>(ListenerList.IDENTITY);

	/**
	 * the list of operations available for redo, LIFO
	 */
	private List<IUndoableOperation> redoList = Collections.synchronizedList(new ArrayList<>());

	/**
	 * the list of operations available for undo, LIFO
	 */
	private List<IUndoableOperation> undoList = Collections.synchronizedList(new ArrayList<>());

	/**
	 * a lock that is used to synchronize access between the undo and redo
	 * history
	 */
	final Object undoRedoHistoryLock = new Object();

	/**
	 * An operation that is "absorbing" all other operations while it is open.
	 * When this is not null, other operations added or executed are added to
	 * this composite.
	 *
	 */
	private ICompositeOperation openComposite;

	/**
	 * a lock that is used to synchronize access to the open composite.
	 */
	final Object openCompositeLock = new Object();

	/**
	 * Create an instance of DefaultOperationHistory.
	 */
	public DefaultOperationHistory() {
		super();
	}

	@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 (IUndoContext context : contexts) {
				flushRedo(context);
			}
		} else {
			// Dispose the operation since we will not have a reference to it.
			operation.dispose();
		}
	}

	/**
	 * <p>
	 * Add the specified approver to the list of operation approvers consulted
	 * by the operation history before an undo or redo is allowed to proceed.
	 * This method has no effect if the instance being added is already in the
	 * list.
	 * </p>
	 * <p>
	 * Operation approvers must be prepared to receive these the operation
	 * approval messages from a background thread. Any UI access occurring
	 * inside the implementation must be properly synchronized using the
	 * techniques specified by the client's widget library.
	 * </p>
	 *
	 * @param approver
	 *            the IOperationApprover to be added as an approver.
	 *
	 */

	@Override
	public void addOperationApprover(IOperationApprover approver) {
		approvers.add(approver);
	}

	/**
	 * <p>
	 * Add the specified listener to the list of operation history listeners
	 * that are notified about changes in the history or operations that are
	 * executed, undone, or redone. This method has no effect if the instance
	 * being added is already in the list.
	 * </p>
	 * <p>
	 * Operation history listeners must be prepared to receive notifications
	 * from a background thread. Any UI access occurring inside the
	 * implementation must be properly synchronized using the techniques
	 * specified by the client's widget library.
	 * </p>
	 *
	 * @param listener
	 *            the IOperationHistoryListener to be added as a listener.
	 *
	 * @see org.eclipse.core.commands.operations.IOperationHistoryListener
	 * @see org.eclipse.core.commands.operations.OperationHistoryEvent
	 */
	@Override
	public void addOperationHistoryListener(IOperationHistoryListener listener) {
		listeners.add(listener);
	}

	@Override
	public boolean canRedo(IUndoContext context) {
		// null context is allowed and passed through
		IUndoableOperation operation = getRedoOperation(context);
		return (operation != null && operation.canRedo());
	}

	@Override
	public boolean canUndo(IUndoContext context) {
		// null context is allowed and passed through
		IUndoableOperation operation = getUndoOperation(context);
		return (operation != null && operation.canUndo());
	}

	/**
	 * Check the redo limit before adding an operation. In theory the redo limit
	 * should never be reached, because the redo items are transferred from the
	 * undo history, which has the same limit. The redo history is cleared
	 * whenever a new operation is added. We check for completeness since
	 * implementations may change over time.
	 *
	 * Return a boolean indicating whether the redo should proceed.
	 */
	private boolean checkRedoLimit(IUndoableOperation operation) {
		IUndoContext[] contexts = operation.getContexts();
		for (IUndoContext context : contexts) {
			int limit = getLimit(context);
			if (limit > 0) {
				forceRedoLimit(context, limit - 1);
			} else {
				// this context has a 0 limit
				operation.removeContext(context);
			}
		}
		return operation.getContexts().length > 0;
	}

	/**
	 * Check the undo limit before adding an operation. Return a boolean
	 * indicating whether the undo should proceed.
	 */
	private boolean checkUndoLimit(IUndoableOperation operation) {
		IUndoContext[] contexts = operation.getContexts();
		for (IUndoContext context : contexts) {
			int limit = getLimit(context);
			if (limit > 0) {
				forceUndoLimit(context, limit - 1);
			} else {
				// this context has a 0 limit
				operation.removeContext(context);
			}
		}
		return operation.getContexts().length > 0;
	}

	@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$
			}
			flushUndo(context);
			flushRedo(context);
			limits.remove(context);
			return;
		}
		if (flushUndo) {
			flushUndo(context);
		}
		if (flushRedo) {
			flushRedo(context);
		}

	}

	/**
	 * Perform the redo. All validity checks have already occurred.
	 *
	 * @param monitor
	 * @param operation
	 */
	private IStatus doRedo(IProgressMonitor monitor, IAdaptable info, IUndoableOperation operation)
			throws ExecutionException {

		IStatus status = getRedoApproval(operation, info);
		if (status.isOK()) {
			notifyAboutToRedo(operation);
			try {
				status = operation.redo(monitor, info);
			} catch (OperationCanceledException e) {
				status = Status.CANCEL_STATUS;
			} catch (ExecutionException e) {
				notifyNotOK(operation);
				if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
					Tracing.printTrace(OPERATIONHISTORY,
							"ExecutionException while redoing " + operation); //$NON-NLS-1$
				}
				throw e;
			} catch (Exception e) {
				notifyNotOK(operation);
				if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
					Tracing.printTrace(OPERATIONHISTORY,
							"Exception while redoing " + operation); //$NON-NLS-1$
				}
				throw new ExecutionException("While redoing the operation, an exception occurred", e); //$NON-NLS-1$
			}
		}

		// if successful, the operation is removed from the redo history and
		// placed back in the undo history.
		if (status.isOK()) {
			boolean addedToUndo = true;
			synchronized (undoRedoHistoryLock) {
				redoList.remove(operation);
				if (checkUndoLimit(operation)) {
					undoList.add(operation);
				} else {
					addedToUndo = false;
				}
			}
			// dispose the operation since we could not add it to the
			// stack and will no longer have a reference to it.
			if (!addedToUndo) {
				operation.dispose();
			}

			// notify listeners must happen after history is updated
			notifyRedone(operation);
		} else {
			notifyNotOK(operation, status);
		}

		return status;
	}

	/**
	 * Perform the undo. All validity checks have already occurred.
	 *
	 * @param monitor
	 * @param operation
	 */
	private IStatus doUndo(IProgressMonitor monitor, IAdaptable info, IUndoableOperation operation)
			throws ExecutionException {
		IStatus status = getUndoApproval(operation, info);
		if (status.isOK()) {
			notifyAboutToUndo(operation);
			try {
				status = operation.undo(monitor, info);
			} catch (OperationCanceledException e) {
				status = Status.CANCEL_STATUS;
			} catch (ExecutionException e) {
				notifyNotOK(operation);
				if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
					Tracing.printTrace(OPERATIONHISTORY,
							"ExecutionException while undoing " + operation); //$NON-NLS-1$
				}
				throw e;
			} catch (Exception e) {
				notifyNotOK(operation);
				if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
					Tracing.printTrace(OPERATIONHISTORY,
							"Exception while undoing " + operation); //$NON-NLS-1$
				}
				throw new ExecutionException(
						"While undoing the operation, an exception occurred", e); //$NON-NLS-1$
			}
		}
		// if successful, the operation is removed from the undo history and
		// placed in the redo history.
		if (status.isOK()) {
			boolean addedToRedo = true;
			synchronized (undoRedoHistoryLock) {
				undoList.remove(operation);
				if (checkRedoLimit(operation)) {
					redoList.add(operation);
				} else {
					addedToRedo = false;
				}
			}
			// dispose the operation since we could not add it to the
			// stack and will no longer have a reference to it.
			if (!addedToRedo) {
				operation.dispose();
			}
			// notification occurs after the undo and redo histories are
			// adjusted
			notifyUndone(operation);
		} else {
			notifyNotOK(operation, status);
		}
		return status;
	}

	@Override
	public IStatus execute(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException {
		Assert.isNotNull(operation);

		// error if operation is invalid
		if (!operation.canExecute()) {
			return IOperationHistory.OPERATION_INVALID_STATUS;
		}

		// check with the operation approvers
		IStatus status = getExecuteApproval(operation, info);
		if (!status.isOK()) {
			// not approved. No notifications are sent, just return the status.
			return status;
		}

		/*
		 * If we are in the middle of an open composite, then we will add this
		 * operation to the open operation rather than add the operation to the
		 * history. We will still execute it.
		 */
		boolean merging = false;
		synchronized (openCompositeLock) {
			if (openComposite != null) {
				// the composite shouldn't be executed explicitly while it is
				// still
				// open
				if (openComposite == operation) {
					return IOperationHistory.OPERATION_INVALID_STATUS;
				}
				openComposite.add(operation);
				merging = true;
			}
		}

		/*
		 * Execute the operation
		 */
		if (!merging) {
			notifyAboutToExecute(operation);
		}
		try {
			status = operation.execute(monitor, info);
		} catch (OperationCanceledException e) {
			status = Status.CANCEL_STATUS;
		} catch (ExecutionException e) {
			notifyNotOK(operation);
			throw e;
		} catch (Exception e) {
			notifyNotOK(operation);
			throw new ExecutionException(
					"While executing the operation, an exception occurred", e); //$NON-NLS-1$
		}

		// if successful, the notify listeners are notified and the operation is
		// added to the history
		if (!merging) {
			if (status.isOK()) {
				notifyDone(operation);
				add(operation);
			} else {
				notifyNotOK(operation, status);
				// dispose the operation since we did not add it to the stack
				// and will no longer have a reference to it.
				operation.dispose();
			}
		}
		// all other severities are not interpreted. Simply return the status.
		return status;
	}

	/*
	 * Filter the specified list to include only the specified undo context.
	 */
	private IUndoableOperation[] filter(List<IUndoableOperation> list, IUndoContext context) {
		/*
		 * This method is used whenever there is a need to filter the undo or
		 * redo history on a particular context. Currently there are no caches
		 * kept to optimize repeated requests for the same filter. If benchmarks
		 * show this to be a common pattern that causes performances problems,
		 * we could implement a filtered cache here that is nullified whenever
		 * the global history changes.
		 */

		List<IUndoableOperation> filtered = new ArrayList<>();
		synchronized (undoRedoHistoryLock) {
			Iterator<IUndoableOperation> iterator = list.iterator();
			while (iterator.hasNext()) {
				IUndoableOperation operation = iterator.next();
				if (operation.hasContext(context)) {
					filtered.add(operation);
				}
			}
		}
		return filtered.toArray(new IUndoableOperation[filtered.size()]);
	}

	/*
	 * Flush the redo stack of all operations that have the given context.
	 */
	private void flushRedo(IUndoContext context) {
		if (DEBUG_OPERATION_HISTORY_DISPOSE) {
			Tracing.printTrace(OPERATIONHISTORY, "Flushing redo history for " + context); //$NON-NLS-1$
		}

		synchronized (undoRedoHistoryLock) {

			Object[] filtered = filter(redoList, context);
			for (Object element : filtered) {
				IUndoableOperation operation = (IUndoableOperation) element;
				if (context == GLOBAL_UNDO_CONTEXT || operation.getContexts().length == 1) {
					// remove the operation if it only has the context or we are
					// flushing all
					redoList.remove(operation);
					internalRemove(operation);
				} else {
					// remove the reference to the context.
					// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=161786
					// It is not enough to simply remove the context. There could
					// be one or more contexts that match the one we are trying to
					// dispose.
					for (IUndoContext undoContext : operation.getContexts()) {
						if (undoContext.matches(context)) {
							operation.removeContext(undoContext);
						}
					}
					if (operation.getContexts().length == 0) {
						redoList.remove(operation);
						internalRemove(operation);
					}
				}
			}
		}
	}

	/*
	 * Flush the undo stack of all operations that have the given context.
	 */
	private void flushUndo(IUndoContext context) {
		if (DEBUG_OPERATION_HISTORY_DISPOSE) {
			Tracing.printTrace(OPERATIONHISTORY, "Flushing undo history for " + context); //$NON-NLS-1$
		}

		synchronized (undoRedoHistoryLock) {

			// Get all operations that have the context (or one that matches)
			Object[] filtered = filter(undoList, context);
			for (Object element : filtered) {
				IUndoableOperation operation = (IUndoableOperation) element;
				if (context == GLOBAL_UNDO_CONTEXT || operation.getContexts().length == 1) {
					// remove the operation if it only has the context or we are
					// flushing all
					undoList.remove(operation);
					internalRemove(operation);
				} else {
					// remove the reference to the context.
					// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=161786
					// It is not enough to simply remove the context. There could
					// be one or more contexts that match the one we are trying to
					// dispose.
					for (IUndoContext undoContext : operation.getContexts()) {
						if (undoContext.matches(context)) {
							operation.removeContext(undoContext);
						}
					}
					if (operation.getContexts().length == 0) {
						undoList.remove(operation);
						internalRemove(operation);
					}
				}
			}
		}
		/*
		 * There may be an open composite. If it has this context, then the
		 * context must be removed. If it has only this context or we are
		 * flushing all operations, then null it out and notify that we are
		 * ending it. We don't remove it since it was never added.
		 */
		ICompositeOperation endedComposite = null;
		synchronized (openCompositeLock) {
			if (openComposite != null) {
				if (openComposite.hasContext(context)) {
					if (context == GLOBAL_UNDO_CONTEXT || openComposite.getContexts().length == 1) {
						endedComposite = openComposite;
						openComposite = null;
					} else {
						openComposite.removeContext(context);
					}
				}
			}
		}
		// notify outside of the synchronized block.
		if (endedComposite != null) {
			notifyNotOK(endedComposite);
		}
	}

	/*
	 * Force the redo history for the given context to contain max or less
	 * items.
	 */
	private void forceRedoLimit(IUndoContext context, int max) {
		synchronized (undoRedoHistoryLock) {
			Object[] filtered = filter(redoList, context);
			int size = filtered.length;
			if (size > 0) {
				int index = 0;
				while (size > max) {
					IUndoableOperation removed = (IUndoableOperation) filtered[index];
					if (context == GLOBAL_UNDO_CONTEXT || removed.getContexts().length == 1) {
						/*
						 * remove the operation if we are enforcing a global limit
						 * or if the operation only has the specified context
						 */
						redoList.remove(removed);
						internalRemove(removed);
					} else {
						/*
						 * if the operation has multiple contexts and we've reached
						 * the limit for only one of them, then just remove the
						 * context, not the operation.
						 */
						removed.removeContext(context);
					}
					size--;
					index++;
				}
			}
		}
	}

	/*
	 * Force the undo history for the given context to contain max or less
	 * items.
	 */
	private void forceUndoLimit(IUndoContext context, int max) {
		synchronized (undoRedoHistoryLock) {
			Object[] filtered = filter(undoList, context);
			int size = filtered.length;
			if (size > 0) {
				int index = 0;
				while (size > max) {
					IUndoableOperation removed = (IUndoableOperation) filtered[index];
					if (context == GLOBAL_UNDO_CONTEXT || removed.getContexts().length == 1) {
						/*
						 * remove the operation if we are enforcing a global limit
						 * or if the operation only has the specified context
						 */
						undoList.remove(removed);
						internalRemove(removed);
					} else {
						/*
						 * if the operation has multiple contexts and we've reached
						 * the limit for only one of them, then just remove the
						 * context, not the operation.
						 */
						removed.removeContext(context);
					}
					size--;
					index++;
				}
			}
		}
	}

	@Override
	public int getLimit(IUndoContext context) {
		if (!limits.containsKey(context)) {
			return DEFAULT_LIMIT;
		}
		return (limits.get(context)).intValue();
	}

	/*
	 * Consult the IOperationApprovers to see if the proposed redo should be
	 * allowed.
	 */
	private IStatus getRedoApproval(IUndoableOperation operation, IAdaptable info) {

		for (IOperationApprover approver : approvers) {
			IStatus approval = approver.proceedRedoing(operation, this, info);
			if (!approval.isOK()) {
				if (DEBUG_OPERATION_HISTORY_APPROVAL) {
					Tracing.printTrace(OPERATIONHISTORY,
							"Redo not approved by " + approver //$NON-NLS-1$
									+ FOR_OPERATION + operation
									+ " approved by " + approval); //$NON-NLS-1$
				}
				return approval;
			}
		}
		return Status.OK_STATUS;
	}

	@Override
	public IUndoableOperation[] getRedoHistory(IUndoContext context) {
		Assert.isNotNull(context);
		return filter(redoList, context);
	}

	@Override
	public IUndoableOperation getRedoOperation(IUndoContext context) {
		Assert.isNotNull(context);
		synchronized (undoRedoHistoryLock) {
			for (int i = redoList.size() - 1; i >= 0; i--) {
				IUndoableOperation operation = redoList.get(i);
				if (operation.hasContext(context)) {
					return operation;
				}
			}
		}
		return null;
	}

	/*
	 * Consult the IOperationApprovers to see if the proposed undo should be
	 * allowed.
	 */
	private IStatus getUndoApproval(IUndoableOperation operation, IAdaptable info) {

		for (IOperationApprover approver : approvers) {
			IStatus approval = approver.proceedUndoing(operation, this, info);
			if (!approval.isOK()) {
				if (DEBUG_OPERATION_HISTORY_APPROVAL) {
					Tracing.printTrace(OPERATIONHISTORY,
							"Undo not approved by " + approver //$NON-NLS-1$
									+ FOR_OPERATION + operation
									+ " with status " + approval); //$NON-NLS-1$
				}
				return approval;
			}
		}
		return Status.OK_STATUS;
	}

	@Override
	public IUndoableOperation[] getUndoHistory(IUndoContext context) {
		Assert.isNotNull(context);
		return filter(undoList, context);
	}

	@Override
	public IUndoableOperation getUndoOperation(IUndoContext context) {
		Assert.isNotNull(context);
		synchronized (undoRedoHistoryLock) {
			for (int i = undoList.size() - 1; i >= 0; i--) {
				IUndoableOperation operation = undoList.get(i);
				if (operation.hasContext(context)) {
					return operation;
				}
			}
		}
		return null;
	}

	/*
	 * Consult the IOperationApprovers to see if the proposed execution should
	 * be allowed.
	 *
	 * @since 3.2
	 */
	private IStatus getExecuteApproval(IUndoableOperation operation, IAdaptable info) {

		for (IOperationApprover tmp : approvers) {
			if (tmp instanceof IOperationApprover2) {
				IOperationApprover2 approver = (IOperationApprover2) tmp;
				IStatus approval = approver.proceedExecuting(operation, this, info);
				if (!approval.isOK()) {
					if (DEBUG_OPERATION_HISTORY_APPROVAL) {
						Tracing.printTrace(OPERATIONHISTORY,
								"Execute not approved by " + approver //$NON-NLS-1$
										+ FOR_OPERATION + operation
										+ " with status " + approval); //$NON-NLS-1$
					}
					return approval;
				}
			}
		}
		return Status.OK_STATUS;
	}

	/*
	 * Remove the operation by disposing it and notifying listeners.
	 */
	private void internalRemove(IUndoableOperation operation) {
		operation.dispose();
		notifyRemoved(operation);
	}

	/*
	 * Notify listeners of an operation event.
	 */
	private void notifyListeners(final OperationHistoryEvent event) {
		if (event.getOperation() instanceof IAdvancedUndoableOperation) {
			final IAdvancedUndoableOperation advancedOp = (IAdvancedUndoableOperation) event.getOperation();
			SafeRunner.run(new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
						Tracing.printTrace(OPERATIONHISTORY,
								"Exception during notification callback " + exception); //$NON-NLS-1$
					}
				}

				@Override
				public void run() throws Exception {
					advancedOp.aboutToNotify(event);
				}
			});
		}
		for (final IOperationHistoryListener listener : listeners) {
			SafeRunner.run(new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
						Tracing.printTrace(OPERATIONHISTORY,
								"Exception during notification callback " + exception); //$NON-NLS-1$
					}
				}

				@Override
				public void run() throws Exception {
					listener.historyNotification(event);
				}
			});
		}
	}

	private void notifyAboutToExecute(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "ABOUT_TO_EXECUTE " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.ABOUT_TO_EXECUTE, this, operation));
	}

	/*
	 * Notify listeners that an operation is about to redo.
	 */
	private void notifyAboutToRedo(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "ABOUT_TO_REDO " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.ABOUT_TO_REDO, this, operation));
	}

	/*
	 * Notify listeners that an operation is about to undo.
	 */
	private void notifyAboutToUndo(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "ABOUT_TO_UNDO " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.ABOUT_TO_UNDO, this, operation));
	}

	/*
	 * Notify listeners that an operation has been added.
	 */
	private void notifyAdd(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "OPERATION_ADDED " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.OPERATION_ADDED, this, operation));
	}

	/*
	 * Notify listeners that an operation is done executing.
	 */
	private void notifyDone(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "DONE " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.DONE, this, operation));
	}

	/*
	 * Notify listeners that an operation did not succeed after an attempt to
	 * execute, undo, or redo was made.
	 */
	private void notifyNotOK(IUndoableOperation operation) {
		notifyNotOK(operation, null);
	}

	/*
	 * Notify listeners that an operation did not succeed after an attempt to
	 * execute, undo, or redo was made. Include the status associated with the
	 * attempt.
	 *
	 * @since 3.2
	 */
	private void notifyNotOK(IUndoableOperation operation, IStatus status) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "OPERATION_NOT_OK " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.OPERATION_NOT_OK, this, operation, status));
	}

	/*
	 * Notify listeners that an operation was redone.
	 */
	private void notifyRedone(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "REDONE " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.REDONE, this, operation));
	}

	/*
	 * Notify listeners that an operation has been removed from the history.
	 */
	private void notifyRemoved(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "OPERATION_REMOVED " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.OPERATION_REMOVED, this, operation));
	}

	/*
	 * Notify listeners that an operation has been undone.
	 */
	private void notifyUndone(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "UNDONE " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.UNDONE, this, operation));
	}

	/*
	 * Notify listeners that an operation has been undone.
	 */
	private void notifyChanged(IUndoableOperation operation) {
		if (DEBUG_OPERATION_HISTORY_NOTIFICATION) {
			Tracing.printTrace(OPERATIONHISTORY, "OPERATION_CHANGED " + operation); //$NON-NLS-1$
		}

		notifyListeners(new OperationHistoryEvent(OperationHistoryEvent.OPERATION_CHANGED, this, operation));
	}

	@Override
	public IStatus redo(IUndoContext context, IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		Assert.isNotNull(context);
		IUndoableOperation operation = getRedoOperation(context);

		// info if there is no operation
		if (operation == null) {
			return IOperationHistory.NOTHING_TO_REDO_STATUS;
		}

		// error if operation is invalid
		if (!operation.canRedo()) {
			if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
				Tracing.printTrace(OPERATIONHISTORY, "Redo operation not valid - " + operation); //$NON-NLS-1$
			}

			return IOperationHistory.OPERATION_INVALID_STATUS;
		}

		return doRedo(monitor, info, operation);
	}

	@Override
	public IStatus redoOperation(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException {
		Assert.isNotNull(operation);
		IStatus status;
		if (operation.canRedo()) {
			status = doRedo(monitor, info, operation);
		} else {
			if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
				Tracing.printTrace(OPERATIONHISTORY, "Redo operation not valid - " + operation); //$NON-NLS-1$
			}
			status = IOperationHistory.OPERATION_INVALID_STATUS;
		}
		return status;
	}

	@Override
	public void removeOperationApprover(IOperationApprover approver) {
		approvers.remove(approver);
	}

	@Override
	public void removeOperationHistoryListener(IOperationHistoryListener listener) {
		listeners.remove(listener);
	}

	@Override
	public void replaceOperation(IUndoableOperation operation, IUndoableOperation[] replacements) {
		// check the undo history first.
		boolean inUndo = false;
		synchronized (undoRedoHistoryLock) {
			int index = undoList.indexOf(operation);
			if (index > -1) {
				inUndo = true;
				undoList.remove(operation);
				// notify listeners after the lock on undoList is released
				ArrayList<IUndoContext> allContexts = new ArrayList<>(replacements.length);
				for (IUndoableOperation replacement : replacements) {
					IUndoContext[] opContexts = replacement.getContexts();
					allContexts.addAll(Arrays.asList(opContexts));
					undoList.add(index, replacement);
					// notify listeners after the lock on the history is
					// released
				}
				// recheck all the limits. We do this at the end so the index
				// doesn't change during replacement
				for (IUndoContext context : allContexts) {
					forceUndoLimit(context, getLimit(context));
				}
			}
		}
		if (inUndo) {
			// notify listeners of operations added and removed
			internalRemove(operation);
			for (IUndoableOperation replacement : replacements) {
				notifyAdd(replacement);
			}
			return;
		}

		// operation was not in the undo history. Check the redo history.

		synchronized (undoRedoHistoryLock) {
			int index = redoList.indexOf(operation);
			if (index == -1) {
				return;
			}
			ArrayList<IUndoContext> allContexts = new ArrayList<>(replacements.length);
			redoList.remove(operation);
			// notify listeners after we release the lock on redoList
			for (IUndoableOperation replacement : replacements) {
				IUndoContext[] opContexts = replacement.getContexts();
				allContexts.addAll(Arrays.asList(opContexts));
				redoList.add(index, replacement);
				// notify listeners after we release the lock on redoList
			}
			// recheck all the limits. We do this at the end so the index
			// doesn't change during replacement
			for (IUndoContext context : allContexts) {
				forceRedoLimit(context, getLimit(context));
			}
		}
		// send listener notifications after we release the lock on the history
		internalRemove(operation);
		for (IUndoableOperation replacement : replacements) {
			notifyAdd(replacement);
		}
	}

	@Override
	public void setLimit(IUndoContext context, int limit) {
		Assert.isTrue(limit >= 0);
		/*
		 * The limit checking methods interpret a null context as a global limit
		 * to be enforced. We do not wish to support a global limit in this
		 * implementation, so we throw an exception for a null context. The rest
		 * of the implementation can handle a null context, so subclasses can
		 * override this if a global limit is desired.
		 */
		Assert.isNotNull(context);
		limits.put(context, Integer.valueOf(limit));
		synchronized (undoRedoHistoryLock) {
			forceUndoLimit(context, limit);
			forceRedoLimit(context, limit);
		}

	}

	@Override
	public IStatus undo(IUndoContext context, IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		Assert.isNotNull(context);
		IUndoableOperation operation = getUndoOperation(context);

		// info if there is no operation
		if (operation == null) {
			return IOperationHistory.NOTHING_TO_UNDO_STATUS;
		}

		// error if operation is invalid
		if (!operation.canUndo()) {
			if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
				Tracing.printTrace(OPERATIONHISTORY, "Undo operation not valid - " + operation); //$NON-NLS-1$
			}
			return IOperationHistory.OPERATION_INVALID_STATUS;
		}

		return doUndo(monitor, info, operation);
	}

	@Override
	public IStatus undoOperation(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException {
		Assert.isNotNull(operation);
		IStatus status;
		if (operation.canUndo()) {
			status = doUndo(monitor, info, operation);
		} else {
			if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
				Tracing.printTrace(OPERATIONHISTORY, "Undo operation not valid - " + operation); //$NON-NLS-1$
			}
			status = IOperationHistory.OPERATION_INVALID_STATUS;
		}
		return status;
	}

	@Override
	public void openOperation(ICompositeOperation operation, int mode) {
		synchronized (openCompositeLock) {
			if (openComposite != null && openComposite != operation) {
				// unexpected nesting of operations.
				if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
					Tracing.printTrace(OPERATIONHISTORY,
							"Open operation called while another operation is open.  old: " //$NON-NLS-1$
									+ openComposite + "; new:  " + operation); //$NON-NLS-1$
				}

				throw new IllegalStateException(
						"Cannot open an operation while one is already open"); //$NON-NLS-1$
			}
			openComposite = operation;
		}
		if (DEBUG_OPERATION_HISTORY_OPENOPERATION) {
			Tracing.printTrace(OPERATIONHISTORY, "Opening operation " + openComposite); //$NON-NLS-1$
		}

		if (mode == EXECUTE) {
			notifyAboutToExecute(openComposite);
		}
	}

	@Override
	public void closeOperation(boolean operationOK, boolean addToHistory, int mode) {
		ICompositeOperation endedComposite = null;

		synchronized (openCompositeLock) {
			if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
				if (openComposite == null) {
					Tracing.printTrace(OPERATIONHISTORY, "Attempted to close operation when none was open"); //$NON-NLS-1$
					return;
				}
			}
			// notifications will occur outside the synchonized block
			if (openComposite != null) {
				if (DEBUG_OPERATION_HISTORY_OPENOPERATION) {
					Tracing.printTrace(OPERATIONHISTORY, "Closing operation " + openComposite); //$NON-NLS-1$
				}
				endedComposite = openComposite;
				openComposite = null;
			}
		}
		// any mode other than EXECUTE was triggered by a request to undo or
		// redo something already in the history, so undo and redo
		// notification will occur at the end of that sequence.
		if (endedComposite != null) {
			if (operationOK) {
				if (mode == EXECUTE) {
					notifyDone(endedComposite);
				}
				if (addToHistory) {
					add(endedComposite);
				}
			} else if (mode == EXECUTE) {
				notifyNotOK(endedComposite);
			}
		}
	}

	@Override
	public void operationChanged(IUndoableOperation operation) {
		if (undoList.contains(operation) || redoList.contains(operation)) {
			notifyChanged(operation);
		}
	}
}
