Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Eclipse EMF Model Transaction Development Guide
Previous Page Home Next Page

Working with EMF Operations

The IWorkspaceCommandStack executes EMF Commands by wrapping them in IUndoableOperations and executing them on its IOperationHistory. However, clients are encouraged to use the AbstractEMFOperation API, instead, to work directly with the operation history, to take advantage of such features as undo contexts.

EMF Operations API
[ as SVG]

AbstractEMFOperations execute themselves within a transaction on their editing domain. In consequence, they provide rollback support and automatic undo/redo just as the RecordingCommand does in the core EMF Transaction API. To use it, simply define a subclass that implements the protected doExecute() method, performing whatever changes are required in the resource set.

// get the workbench's operation history, which is the default history
//   used by the WorkspaceEditingDomainFactory
IOperationHistory history = workbench.getOperationSupport().getOperationHistory();

TransactionalEditingDomain domain = getEditingDomain();

IUndoableOperation operation = new AbstractEMFOperation(domain,
        "Create Books in Libraries") {
    protected IStatus doExecute(IProgressMonitor monitor,
            Iadaptable info) throws ExecutionException {
        Iterator iter = resource.getAllContents();
        while (iter.hasNext()) {  // changes are determined on-the-fly
            Object next = iter.next();
            if (next instanceof Library) {
                ((Library) next).getBooks().add(
                        EXTLibraryFactory.eINSTANCE.createBook());
            }
        }

        return Status.OK_STATUS;
    }};

operation.addUndoContext(myEditorContext);
history.execute(operation, new NullProgressMonitor(), null);

Transaction Options

An AbstractEMFTransaction can be initialized with a map of transaction options. These options are then applied to the operation's transaction when it is executed on the operation history.

As is the case in the core EMF Transaction API, the AbstractEMFOperation's implementations of the undo() and redo() methods use the following options for the transactions created for undoing and redoing its recorded changes:

  • OPTION_NO_UNDO: because we are undoing or redoing an operation whose changes we have already recorded (including, in the case of composite operations, and non-EMF operations), there is no need to record anew
  • OPTION_NO_TRIGGERS: triggers performed during execution were recorded and are automatically undone; any additional changes would be inappropriate
  • OPTION_NO_VALIDATION: there is no need to validate a reversion to a previous state of the data
  • OPTION_IS_UNDO_REDO_TRANSACTION: the transaction's changes are simply undoing or redoing changes made previously

Composite EMF Operations

CompositeEMFOperations can compose both AbstractEMFOperations (including other composites) and operations on other domains. For example, a composite can change objects in an EMF resource as well as edit parts in a GEF drawing surface and code in Java source files that are all interrelated. Undo/redo is fully supported and preserves ordering dependencies between EMF and non-EMF changes. Transaction rollback correctly undoes non-EMF changes.

A CompositeEMFOperation can be initialized with a list of child operations, or they can be appended later. However, they must all be supplied before the composite is executed. Children cannot be added or removed after that time. The composite operation's undo context is an aggregate of the contexts of its children.

IOperationHistory history = workbench.getOperationSupport().getOperationHistory();
TransactionalEditingDomain domain = getEditingDomain();
Library mainBranch = getMainBranch();

CompositeEMFOperation composite = new CompositeEMFOperation(domain,
        "Create Book and EditPart");
        
// some hypothetical AbstractEMFOperation subclass
CreateBookOperation createBook = new CreateBookOperation(domain,
        mainBranch, "Great Expectations");
composite.add(createBook);

// some hypothetical non-EMF operation that visualizes the new book (available in
//   the createBook operation after it has executed) in a GEF viewer
composite.add(new VisualizeBook(viewer, createBook));

history.execute(composite, new NullProgressMonitor(), null);

A CompositeEMFOperation, by default, executes child AbstractEMFOperations in nested transactions. For large nested operation structures, this can induce a lot of overhead that may not be necessary (depending, in particular, on pre-commit trigger requirements). The transaction structure can be optimized by telling the composite not to create a nested transaction for a child operation unless the child uses different transaction options than the parent, using the setTransactionNestingEnabled() method (passing false). Transaction options specified on child operations obey the usual rules for option inheritance in transaction nesting.

Finally, it is worth noting that the CompositeEMFOperation class might be expected to implement the Eclipse ICompositeOperation interface. The reason why it does not is that it does not support the IOperationHistory.openOperation() API. It is good practice with EMF Transactions to keep them as short as possible, especially read/write transactions that block all read access (on other threads) for their duration. The "open operation" would concept contradict this by promoting long, open-ended transactions.


Copyright (c) 2006, 2007 IBM Corporation and others. All Rights Reserved.


 
 
  Published under the terms of the Eclipse Public License Version 1.0 ("EPL") Design by Interspire