org.eclipse.emf.transaction.impl
Class TransactionImpl

java.lang.Object
  extended by org.eclipse.emf.transaction.impl.TransactionImpl
All Implemented Interfaces:
InternalTransaction, Transaction
Direct Known Subclasses:
EMFCommandTransaction

public class TransactionImpl
extends Object
implements InternalTransaction

The default transaction implementation.


Field Summary
static String ALLOW_CHANGE_PROPAGATION_BLOCKING
          This option, when provided to a transaction that inherits from this implementation class and has children transactions that are using this implementation class, provides an optional block of the normal propagation of change descriptions to the parent transaction by any transaction in the child subtree of this transaction.
static String BLOCK_CHANGE_PROPAGATION
          This option blocks the propagation of change descriptions to the parent transaction.
protected  CompositeChangeDescription change
           
static Map<Object,Object> DEFAULT_UNDO_REDO_OPTIONS
          The transaction options that should be used when undoing/redoing changes on the command stack.
protected  List<Notification> notifications
           
static String OPTION_IS_TRIGGER_TRANSACTION
          An informative option that tags the transaction as a transaction that is executing trigger commands.
 
Fields inherited from interface org.eclipse.emf.transaction.Transaction
OPTION_IS_UNDO_REDO_TRANSACTION, OPTION_NO_NOTIFICATIONS, OPTION_NO_TRIGGERS, OPTION_NO_UNDO, OPTION_NO_VALIDATION, OPTION_UNPROTECTED, OPTION_VALIDATE_EDIT, OPTION_VALIDATE_EDIT_CONTEXT
 
Constructor Summary
TransactionImpl(TransactionalEditingDomain domain, boolean readOnly)
          Initializes me with my editing domain and read-only state.
TransactionImpl(TransactionalEditingDomain domain, boolean readOnly, Map<?,?> options)
          Initializes me with my editing domain, read-only state, and additional options.
 
Method Summary
 void abort(IStatus status)
          Aborts the transaction with a reason given by the specified status.
 void add(Notification notification)
          Adds the specified notification to the list of notifications received during this transaction.
 void addTriggers(TriggerCommand triggers)
          Adds a group of triggers that were executed during my commit.
protected  void close()
          Closes me.
protected static boolean collectsNotifications(Transaction tx)
          Queries whether the specified transaction collects notifications for broadcast to listeners or for validation.
 void commit()
          Attempts to commit the transaction.
 void endPrivileged(PrivilegedRunnable<?> runnable)
          Returns me to my previous owner, upon completion of the specified privileged runnable.
 TransactionChangeDescription getChangeDescription()
          Obtains the change description summarizing the changes made to the model during the execution of the transaction.
protected static Map<?,?> getDefaultOptions(TransactionalEditingDomain domain)
          Obtains the default transaction options, if any, of the specified editing domain.
 TransactionalEditingDomain getEditingDomain()
          Queries the editing domain in which I am transacting.
protected  InternalTransactionalEditingDomain getInternalDomain()
          Obtains my owning editing domain as the internal interface.
 List<Notification> getNotifications()
          Obtains the list of notifications that were received during execution of this transaction.
 Map<Object,Object> getOptions()
          Obtains the special options with which I was created.
 Thread getOwner()
          Queries the thread that owns me.
 Transaction getParent()
          My parent transaction, if any.
 InternalTransaction getRoot()
          Obtains the root transaction (the one that has no parent).
 IStatus getStatus()
          Obtains the status of the transaction.
 Command getTriggers()
          Obtains the triggers that were executed during my commit.
protected static boolean hasOption(Transaction tx, String option)
          Queries whether the specified transaction has a boolean option.
protected  boolean isAborted()
          Queries whether I have been aborted.
 boolean isActive()
          Queries whether I am active.
protected static boolean isNotificationEnabled(Transaction tx)
          Queries whether the specified transaction should send post-commit events, according to its options.
 boolean isReadOnly()
          Queries whether I am a read-only transaction.
 boolean isRollingBack()
          Queries whether this transaction or any of its ancestors is in the process of rolling back.
protected static boolean isTriggerEnabled(Transaction tx)
          Queries whether the specified transaction should invoke pre-commit, listeners, according to its options and read-only state.
protected static boolean isUndoEnabled(Transaction tx)
          Queries whether the specified transaction should record undo information, according to its options and read-only state.
protected static boolean isUnprotected(Transaction tx)
          Queries whether the specified transaction is an unprotected write, according to its options and read-only state.
protected static boolean isValidationEnabled(Transaction tx)
          Queries whether the specified transaction should validate changes, according to its options and read-only state.
 void pause()
          Pauses me while a child transaction is active, so that I do not collect either notifications or recorded changes during that time.
 void resume(TransactionChangeDescription nestedChanges)
          Resumes me after completion of a child transaction.
 void rollback()
          Rolls back the transaction, undoing all of the pending model changes.
 void setParent(InternalTransaction parent)
          Assigns my parent transaction (the one in which I am nested).
 void setStatus(IStatus status)
          Sets the status of the transaction.
 void start()
          Starts me.
 void startPrivileged(PrivilegedRunnable<?> runnable)
          Transfers ownership of this transaction to the specified privileged runnable.
 String toString()
           
protected  IStatus validate()
          Validates me.
 void yield()
          Temporarily yields access to another read-only transaction.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

ALLOW_CHANGE_PROPAGATION_BLOCKING

public static final String ALLOW_CHANGE_PROPAGATION_BLOCKING
This option, when provided to a transaction that inherits from this implementation class and has children transactions that are using this implementation class, provides an optional block of the normal propagation of change descriptions to the parent transaction by any transaction in the child subtree of this transaction. The child exercises its option to negate the propagation of change descriptions by adding the BLOCK_CHANGE_PROPAGATION option to its own options with the value of Boolean.TRUE. This option IS inherited by child transactions.

See Also:
Constant Field Values

BLOCK_CHANGE_PROPAGATION

public static final String BLOCK_CHANGE_PROPAGATION
This option blocks the propagation of change descriptions to the parent transaction. The option has no effect unless the parent transaction has allowed this negation to happen by having the ALLOW_CHANGE_PROPAGATION_BLOCKING option added either directly or through option inheritance. Note that to enable this option it must be added to the options map with the value of Boolean.TRUE. This option is NOT inherited by child transactions.

See Also:
Constant Field Values

OPTION_IS_TRIGGER_TRANSACTION

public static final String OPTION_IS_TRIGGER_TRANSACTION
An informative option that tags the transaction as a transaction that is executing trigger commands.

See Also:
Constant Field Values

DEFAULT_UNDO_REDO_OPTIONS

public static final Map<Object,Object> DEFAULT_UNDO_REDO_OPTIONS
The transaction options that should be used when undoing/redoing changes on the command stack. Undo and redo must not perform triggers because these were implemented as chained commands during the original execution. Moreover, validation is not required during undo/redo because we can only return the model from a valid state to another valid state if the original execution did so. Finally, it is not necessary to record undo information when we are undoing or redoing.

As of the 1.2 release, this map is immutable.


notifications

protected List<Notification> notifications

change

protected final CompositeChangeDescription change
Constructor Detail

TransactionImpl

public TransactionImpl(TransactionalEditingDomain domain,
                       boolean readOnly)
Initializes me with my editing domain and read-only state.

Parameters:
domain - the editing domain in which I operate
readOnly - true if I am read-only; false if I am read/write

TransactionImpl

public TransactionImpl(TransactionalEditingDomain domain,
                       boolean readOnly,
                       Map<?,?> options)
Initializes me with my editing domain, read-only state, and additional options.

Parameters:
domain - the editing domain in which I operate
readOnly - true if I am read-only; false if I am read/write
options - my options, or null for defaults
Method Detail

start

public void start()
           throws InterruptedException
Description copied from interface: InternalTransaction
Starts me. Usually, this will delegate to the editing domain to activate me.

Note that this call should block the current thread until the editing domain grants exclusive access.

Specified by:
start in interface InternalTransaction
Throws:
InterruptedException - if the current thread is interrupted while waiting for activation

getEditingDomain

public final TransactionalEditingDomain getEditingDomain()
Description copied from interface: Transaction
Queries the editing domain in which I am transacting. Note that this is available also before I start and after I close.

Specified by:
getEditingDomain in interface Transaction
Returns:
my editing domain

getParent

public final Transaction getParent()
Description copied from interface: Transaction
My parent transaction, if any. The thread that owns an editing domain's active transaction can create nested transactions simply by starting new ones. Nested transactions commit differently from top-level transactions: although they send pre-commit events, they do not send post-commit events, nor are they validated. Validation is performed only by the top-level transaction to validate all changes made in its scope, and only the top-level transaction then can send the post-commit event. Nested transactions can roll back their changes without affecting their parent transactions.

Transactions can nest as follows:

Specified by:
getParent in interface Transaction
Returns:
my parent transaction

setParent

public final void setParent(InternalTransaction parent)
Description copied from interface: InternalTransaction
Assigns my parent transaction (the one in which I am nested). This must be done by the editing domain immediately upon activating me.

Specified by:
setParent in interface InternalTransaction
Parameters:
parent - my parent transaction

getRoot

public final InternalTransaction getRoot()
Description copied from interface: InternalTransaction
Obtains the root transaction (the one that has no parent). This could be me if I am the root.

Specified by:
getRoot in interface InternalTransaction
Returns:
the root transaction in a nested transaction structure

getOwner

public final Thread getOwner()
Description copied from interface: Transaction
Queries the thread that owns me. Only this thread is allowed to read or write (in the case of read/write transactions) the editing domain's resource set while I am open.

Specified by:
getOwner in interface Transaction
Returns:
my owning thread

isReadOnly

public final boolean isReadOnly()
Description copied from interface: Transaction
Queries whether I am a read-only transaction. Even my owning thread is not permitted to make changes to the model if I am read-only.

Specified by:
isReadOnly in interface Transaction
Returns:
true if I am read-only; false, otherwise

getOptions

public final Map<Object,Object> getOptions()
Description copied from interface: Transaction
Obtains the special options with which I was created. The options (map keys) are defined by the TransactionalEditingDomain interface.

Specified by:
getOptions in interface Transaction
Returns:
an unmodifiable view of my options

isActive

public boolean isActive()
Description copied from interface: Transaction
Queries whether I am active. I am active after I have started and before I have closed (committed or rolled back).

Specified by:
isActive in interface Transaction
Returns:
whether I am active

getStatus

public IStatus getStatus()
Description copied from interface: Transaction
Obtains the status of the transaction. This may provide warning or or error messages from validation (after I have committed/rolled back) or other sources, or it might be OK.

Note that while I am still active, my status is usually OK. It may not be OK if I have been aborted, in which case I will roll back on attempt to commit.

Specified by:
getStatus in interface Transaction
Returns:
my status, most interesting after I have closed

setStatus

public void setStatus(IStatus status)
Description copied from interface: InternalTransaction
Sets the status of the transaction.

Specified by:
setStatus in interface InternalTransaction
Parameters:
status - my status

abort

public void abort(IStatus status)
Description copied from interface: InternalTransaction
Aborts the transaction with a reason given by the specified status. This is used, for example, when a transaction is corrupted by another thread concurrently writing the model (obviously without an active transaction!). The transaction is expected to rollback when it attempts to commit, and to propagate this status up to the root transaction.

Specified by:
abort in interface InternalTransaction
Parameters:
status - a status object providing the reason. It should be the status attached to the eventual RollbackException, and should be set as my status

isAborted

protected boolean isAborted()
Queries whether I have been aborted.

Returns:
true if I have been aborted; false, otherwise
See Also:
InternalTransaction.abort(IStatus)

commit

public void commit()
            throws RollbackException
Description copied from interface: Transaction
Attempts to commit the transaction. The transaction may only commit if it is the currently active transaction in the editing domain. After the transaction has committed, it is no longer active and cannot be started again.

Commit proceeds in three phases: pre-commit events and triggers, validation, and the post-commit events.

Pre-commit notifications are sent to the editing domain's registered ResourceSetListeners to inform them that the transaction is committing. If any listener throws a RollbackException, then the transaction is rolled back and the exception is propagated to the caller. Any trigger commands returned by pre-commit listeners are executed after all listeners are invoked, in a nested transaction. This nested transaction, then, follows the commit protocol to send out pre-commit notifications again. This process continues until no more trigger commands are executed or some listener causes rollback.

After all pre-commit processing completes, the transaction is validated. Validation checks all of the notifications received from the model during the transaction (including any nested transactions, esp. those that executed triggers). If the validation yields an error status (or more severe), then the transaction is rolled back, throwing a RollbackException with the validation status.

The final phase, if validation passes, is to send out the post-commit event to the resource set listeners. This event includes all of the notifications received during the transaction, including triggers. Note that, because these listeners can read the model, they may cause further notifications (by resolving proxies, loading resources, etc.). Listeners are invoked in a nested read-only transaction, so it will also commit and send out a post-commit event if necessary with additional notifications.

Note that even a read-only transaction can roll back. This should only occur, however, if it is corrupted by a concurrent modification by another thread, which means that invalid data could have been read.

Specified by:
commit in interface Transaction
Throws:
RollbackException - if a listener or validation caused the transaction to roll back instead of committing successfully

rollback

public void rollback()
Description copied from interface: Transaction
Rolls back the transaction, undoing all of the pending model changes. Once it has rolled back, the transaction is no longer active and cannot be started again. No events are sent when the transaction rolls back; to listeners it appears that nothing ever happened.

Specified by:
rollback in interface Transaction

yield

public void yield()
Description copied from interface: Transaction
Temporarily yields access to another read-only transaction. The TransactionalEditingDomain supports any number of pseudo-concurrent read-only transactions. Transactions that are expected to be long-running should yield frequently, as a task running in a progress monitor is expected to check for cancellation frequently. However, there is a higher cost (in time) associated with yielding, so it should not be overdone.

Only read-only transactions may yield, and only the transaction that is currently active in the editing domain may yield. The yielding transaction may be nested, but not within a read/write transaction at any depth.

Upon yielding, some other read-only transaction that is attempting to start or to return from a yield will take control of the editing domain. Control is never yielded to a read/write transaction (not even to a read-only transaction nested in a read/write) because this would introduce dirty reads (transactions reading uncommitted changes). If there are no other read-only transactions to receive the transfer of control, then the call returns immediately. Otherwise, control is transferred in FIFO fashion to waiting transactions.

Specified by:
yield in interface Transaction

getChangeDescription

public TransactionChangeDescription getChangeDescription()
Description copied from interface: Transaction
Obtains the change description summarizing the changes made to the model during the execution of the transaction. The change description must not be used until after the transaction has successfully committed. If the transaction rolls back, then it has no change description.

Specified by:
getChangeDescription in interface Transaction
Returns:
the change description, or null if the transaction rolled back or is still active

getInternalDomain

protected InternalTransactionalEditingDomain getInternalDomain()
Obtains my owning editing domain as the internal interface.

Returns:
the internal view of my editing domain

pause

public void pause()
Description copied from interface: InternalTransaction
Pauses me while a child transaction is active, so that I do not collect either notifications or recorded changes during that time.

Specified by:
pause in interface InternalTransaction

resume

public void resume(TransactionChangeDescription nestedChanges)
Description copied from interface: InternalTransaction
Resumes me after completion of a child transaction. If the child committed, then I add its change description to my changes.

Specified by:
resume in interface InternalTransaction
Parameters:
nestedChanges - the nested transaction's recorded changes, or null if it rolled back (in which case, I do not add anything to my changes)

isRollingBack

public boolean isRollingBack()
Description copied from interface: InternalTransaction
Queries whether this transaction or any of its ancestors is in the process of rolling back.

Specified by:
isRollingBack in interface InternalTransaction
Returns:
true if I or my parent (if any) am rolling back; false otherwise

close

protected void close()
Closes me. This is the last step in committing or rolling back, deactivating me in my editing domain. Also, if I have a parent transaction, I resume it.

If a subclass overrides this method, it must ensure that this implementation is also invoked.


add

public void add(Notification notification)
Description copied from interface: InternalTransaction
Adds the specified notification to the list of notifications received during this transaction.

Specified by:
add in interface InternalTransaction
Parameters:
notification - the notification to add
See Also:
InternalTransaction.getNotifications()

getNotifications

public List<Notification> getNotifications()
Description copied from interface: InternalTransaction
Obtains the list of notifications that were received during execution of this transaction. These are the notifications that later will be sent to pre-commit listeners, validation, and eventually to post-commit listeners (if I successfully commit).

Specified by:
getNotifications in interface InternalTransaction
Returns:
my notifications
See Also:
InternalTransaction.add(Notification)

validate

protected IStatus validate()
Validates me. Should only be called during commit.

Returns:
the result of validation. If this is an error or worse, then I must roll back

getTriggers

public Command getTriggers()
Description copied from interface: InternalTransaction
Obtains the triggers that were executed during my commit.

Specified by:
getTriggers in interface InternalTransaction
Returns:
my pre-commit trigger commands, or null if I have no triggers (perhaps because the Transaction.OPTION_NO_TRIGGERS was applied). This may be a single Command or a compound of multiple

addTriggers

public void addTriggers(TriggerCommand triggers)
Description copied from interface: InternalTransaction
Adds a group of triggers that were executed during my commit.

Specified by:
addTriggers in interface InternalTransaction
Parameters:
triggers - the triggers to add

startPrivileged

public void startPrivileged(PrivilegedRunnable<?> runnable)
Description copied from interface: InternalTransaction
Transfers ownership of this transaction to the specified privileged runnable.

Specified by:
startPrivileged in interface InternalTransaction
Parameters:
runnable - the runnable whose thread is to borrow me

endPrivileged

public void endPrivileged(PrivilegedRunnable<?> runnable)
Description copied from interface: InternalTransaction
Returns me to my previous owner, upon completion of the specified privileged runnable.

Specified by:
endPrivileged in interface InternalTransaction
Parameters:
runnable - the runnable whose thread had borrowed me

toString

public String toString()
Overrides:
toString in class Object

isUndoEnabled

protected static boolean isUndoEnabled(Transaction tx)
Queries whether the specified transaction should record undo information, according to its options and read-only state.

Parameters:
tx - a transaction
Returns:
true if the transaction should record undo information; false, otherwise

isValidationEnabled

protected static boolean isValidationEnabled(Transaction tx)
Queries whether the specified transaction should validate changes, according to its options and read-only state.

Parameters:
tx - a transaction
Returns:
true if the transaction should validate changes; false, otherwise

isTriggerEnabled

protected static boolean isTriggerEnabled(Transaction tx)
Queries whether the specified transaction should invoke pre-commit, listeners, according to its options and read-only state.

Parameters:
tx - a transaction
Returns:
true if the transaction should perform the pre-commit procedures; false, otherwise

isNotificationEnabled

protected static boolean isNotificationEnabled(Transaction tx)
Queries whether the specified transaction should send post-commit events, according to its options.

Parameters:
tx - a transaction
Returns:
true if the transaction should send post-commit events; false, otherwise

isUnprotected

protected static boolean isUnprotected(Transaction tx)
Queries whether the specified transaction is an unprotected write, according to its options and read-only state.

Parameters:
tx - a transaction
Returns:
true if the transaction is an unprotected write transaction; false, otherwise

collectsNotifications

protected static boolean collectsNotifications(Transaction tx)
Queries whether the specified transaction collects notifications for broadcast to listeners or for validation. This is determined by the transaction's options.

Parameters:
tx - a transaction
Returns:
true any of notification, triggers, and validation are enabled; false, otherwise
See Also:
isNotificationEnabled(Transaction), isTriggerEnabled(Transaction), isValidationEnabled(Transaction)

hasOption

protected static boolean hasOption(Transaction tx,
                                   String option)
Queries whether the specified transaction has a boolean option.

Parameters:
tx - a transaction
option - the boolean-valued option to query
Returns:
true if the transaction has the option; false if it does not

getDefaultOptions

protected static Map<?,?> getDefaultOptions(TransactionalEditingDomain domain)
Obtains the default transaction options, if any, of the specified editing domain.

Parameters:
domain - an editing domain
Returns:
its default transaction options, or an empty map if none are defined
Since:
1.2

Copyright 2002, 2007 IBM Corporation and others.
All Rights Reserved.