/**
* The Transaction class is an abstract class implemented by different
* persistence packages for managing persistence operations on groups
* of objects.
*/
package imaginary.persist;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
public abstract class Transaction {
/**
* The properties to use to initiate the transaction.
*/
static public Properties properties = null;
/**
* The URL used to initiate the transaction
*/
static public String url = null;
/**
* Gets an instance of a Transaction subclass based on the URL
* set by the application. Currently, only database persistence
* is supported so all URL's are assumed to be JDBC URL's.
* @return a new Transaction instance
*/
static public Transaction getTransaction() throws PersistenceException {
return new DatabaseTransaction(url, properties);
}
/****************** Instance attributes ******************/
// the list of objects locked by this Transaction.
private Vector objects = new Vector();
/********************* Constructors **********************/
/**
* Creates a new transaction object.
*/
public Transaction() {
super();
}
/***************** Attribute accessors ******************/
/**
* Ties a new Persistent instance to this transactioon.
* @param p the persistent associated with this transaction
*/
synchronized void addPersistent(Persistent p) {
if( !objects.contains(p) ) {
objects.addElement(p);
}
}
/**
* @return an array of persistent objects associated with this
* transaction
*/
synchronized Persistent[] getPersistents() {
Persistent[] obs = new Persistent[objects.size()];
objects.copyInto(obs);
return obs;
}
/**
* Removes the specified persistent from this transaction
* @param p the persistent to be removed
*/
synchronized void removePersistent(Persistent p) {
if( objects.contains(p) ) {
objects.removeElement(p);
}
}
/*************** Persistence operations ****************/
/**
* Aborts any persistence operations in process and allows
* persistent objects which have already done their operation
* to take it back.
*/
public void abort() {
Persistent[] obs = getPersistents();
for(int i=0; i<obs.length; i++) {
try {
if( obs[i].isSaving() ) {
obs[i].abort();
}
}
catch( PersistenceException e ) {
e.printStackTrace();
}
}
}
/**
* This method should be extended in data store specific
* transaction objects for sending a commit to the data store.
* Within the Transaction class, it lets all locked objects know
* that any data store commit was successful.
* @exception imaginary.persist.PersistenceException An error occurred
* trying to commit.
*/
public void commit() throws PersistenceException {
Persistent[] obs = getPersistents();
for(int i=0; i<obs.length; i++) {
if( obs[i].isSaving() ) {
obs[i].commit();
}
}
// commit done, prepare for new set of modifications
objects = new Vector();
}
/**
* Calls for the restoration of a particular object using this
* Transaction.
* @param p the object to restore using this Transaction
*/
public void restore(Persistent p) throws PersistenceException {
p.restore(this);
}
/**
* Calls for the restoration of the specified Persistent using
* a hashtable of query parameters.
* @param p the Persistent to restore
* @param data the query parameters
* @exception imaginary.persist.PersistenceException An error occurred
* during restore.
*/
public void restore(Persistent p, Hashtable data)
throws PersistenceException {
p.restore(this, data);
}
/**
* Calls for the restoration of the specified PersistentSet
* using a hashtable of query parameters.
* @parameter set a set to be restored
* @param data the query parameters for the restore
* @exception imaginary.persist.PersistenceException An error occurred
* during restore.
*/
public void restore(PersistentSet set, Hashtable data)
throws PersistenceException {
set.restore(this, data);
}
/**
* This method goes through and triggers a save on all locked objects.
* If the saves are all successful, then a commit() is triggered. If
* any one of the saves fails, however, then an abort() is triggered.
* @exception imaginary.persist.PersistenceException An error triggering
* an abort occurred.
*/
public void save() throws PersistenceException {
Persistent[] obs = getPersistents();
for(int i=0; i<obs.length; i++) {
try {
if( obs[i].isModified() ) { // only save modified objects
obs[i].save();
}
}
catch( PersistenceException e ) {
abort(); // abort on error
throw e;
}
}
try {
commit(); // commit on success
}
catch( PersistenceException e ) {
abort(); // abort if the commit failed
throw e;
}
}
}
|