blob: 48f3382af384f23cb042107570b6e8b94bf7b889 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.emf.ui.action;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.common.ui.action.AbstractActionDelegate;
import org.eclipse.gmf.runtime.common.ui.action.IActionWithProgress;
import org.eclipse.gmf.runtime.emf.ui.internal.MslUIDebugOptions;
import org.eclipse.gmf.runtime.emf.ui.internal.MslUIPlugin;
import org.eclipse.gmf.runtime.emf.ui.internal.MslUIStatusCodes;
/**
* The abstract parent of all concrete action delegates that execute model
* commands. Concrete subclasses must provide a definition of the
* <code>doRun()</code> method to gather any required input and execute a
* model command.
* <P>
* Subclasses that execute a command must return <code>false</code>from
* {@link #isReadOnly()}. The superclass performs the
* {@link #doRun(IProgressMonitor)} method in an EMF operation executed on the
* operation history. Subclasses should set the action delegate status using
* {@link #setStatus(IStatus)} to their command execution status.
* <P>
* Subclasses that only want to read from the model must return
* <code>true</code> from {@link #isReadOnly()}.
*
* @author khussey
* @auther ldamus
*/
public abstract class AbstractModelActionDelegate
extends AbstractActionDelegate {
private IStatus status;
/**
* Intializes me with the singleton editing domain.
*/
protected AbstractModelActionDelegate() {
super();
}
/**
* Runs this model action delegate as a read action.
*
* @see IActionWithProgress#run(IProgressMonitor)
*/
public final void run(final IProgressMonitor progressMonitor) {
if (isReadOnly()) {
// run exclusive so that subclasses can only read from the model
try {
getEditingDomain().runExclusive(new Runnable() {
public void run() {
AbstractModelActionDelegate.super.run(progressMonitor);
}
});
} catch (InterruptedException e) {
Trace
.catching(MslUIPlugin.getDefault(),
MslUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
"run", e); //$NON-NLS-1$
}
} else {
// Run in a composite transactional operation so that subclasses can
// both read and write to the model. Commands executed by subclasses
// to modify the model will be appended to this composite
// transactional operation.
Runnable runnable = new Runnable() {
public void run() {
AbstractModelActionDelegate.super
.run(progressMonitor);
}
};
WriteCommand write = new WriteCommand(getEditingDomain(),
getLabel(), getActionManager().getOperationHistory(),
runnable) {
public IStatus getStatus() {
return AbstractModelActionDelegate.this.getStatus();
}
};
execute(write, new NullProgressMonitor(), null);
}
}
/**
* Gets my editing domain. Can be <code>null</code> if I don't modify
* model resources.
*
* @return my editing domain.
*/
protected abstract TransactionalEditingDomain getEditingDomain();
/**
* Answers whether or not I am a read-only action. Returns
* <code>false</code> by default. Subclasses may override.
*
* @return <code>false</code>
*/
protected boolean isReadOnly() {
return false;
}
/**
* Gets the status of running this action delegate.
*
* @return my status
*/
protected IStatus getStatus() {
if (status == null) {
return Status.OK_STATUS;
}
return status;
}
/**
* Sets the action delegate status. Subclasses should set the status when they
* execute a command.
*
* @param status
* the new status
*/
protected void setStatus(IStatus status) {
this.status = status;
}
/**
* Convenience method for subclasses to execute an undoable operation on the
* action manager's operation history. Sets my status to the status of the
* operation execution, and returns that status.
*
* @param operation
* the operation to be executed
* @param progressMonitor
* the progress monitor
* @param info
* the adaptable info, may be <code>null</code>
* @return the status of the operation execution.
*/
protected IStatus execute(IUndoableOperation operation,
IProgressMonitor progressMonitor, IAdaptable info) {
try {
setStatus(getActionManager().getOperationHistory().execute(
operation, progressMonitor, info));
} catch (ExecutionException e) {
setStatus(new Status(Status.ERROR, MslUIPlugin.getPluginId(),
MslUIStatusCodes.IGNORED_EXCEPTION_WARNING, e
.getLocalizedMessage(), e));
Trace
.catching(MslUIPlugin.getDefault(),
MslUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
"run", e); //$NON-NLS-1$
Log.error(MslUIPlugin.getDefault(),
MslUIStatusCodes.IGNORED_EXCEPTION_WARNING, e
.getLocalizedMessage(), e);
}
return getStatus();
}
}