/**
* The Account class represents any kind of bank account.
* It stores information like which customer owns it and what
* the balance is. This should get subclasses to implement rules
* specific to different types of accounts.
*/
package bank.server;
import imaginary.persist.LockException;
import imaginary.persist.PersistenceException;
import imaginary.persist.Persistent;
import imaginary.persist.PersistentPeer;
import imaginary.persist.RemoteLockHolder;
import imaginary.persist.Transaction;
import java.rmi.RemoteException;
import java.util.Hashtable;
public class Account extends Persistent implements RemoteAccount {
// Just need one account peer for all accounts to share
static final AccountPeer peer = new AccountPeer();
// How much money is in the account
private float balance = 0;
// The customer that owns this account (no join accounts)
private Customer customer = null;
// The account type
private String type = "C";
public Account() throws RemoteException {
super();
}
/**
* The account balance is how much money is currently in the account
* @return the account balance
*/
public synchronized float getBalance() {
return balance;
}
/**
* @return the Customer object that owns this account
*/
public synchronized RemoteCustomer getCustomer() {
return customer;
}
/**
* The customer ID is an attribute that unique identifies the owning
* customer.
* @return the customer ID owning this account
*/
public synchronized int getCustomerId() {
return customer.getId();
}
/**
* Implementation of the Persistent method setId(Hashtable).
* Allows this object to pick the account ID out of a Hashtable
* and set the ID using that value.
* @param h a Hashtable of values taken from a data store
*/
public synchronized void setId(Hashtable h) {
setId(((Integer)h.get("t_accounts.account_id")).intValue());
}
/**
* Implementation of the Persistent method that specifies what
* PersistentPeer to use for data store operations.
* @return the PersistentPeer for this class
*/
protected synchronized PersistentPeer getPersistentPeer() {
return Account.peer;
}
/**
* The account type can be "S" for savings and "C" for checking.
* @return the account type for this account
*/
public synchronized String getAccountType() {
return type;
}
/**
* Deposits the specified amount of money into the account.
* @param trans the Transaction used to perform the modification
* @param amount the amount being deposited
* @exception AccountException An attempt to deposit a negative amount
* @exception LockException Another Transaction is holding a lock
*/
public synchronized void deposit(RemoteLockHolder h, float amount)
throws AccountException, LockException {
// will throw a LockException if another lock is held
modify(h);
if( amount < 0 ) {
throw new AccountException("Deposits may not be negative.");
}
balance += amount;
}
/**
* Implementation of the Persistent method for filling in
* object attributes based on a Hashtable of values from
* a data store.
* @param trans the Transaction for this restore
* @param h the Hashtable containing values from the data store
* @exception imaginary.persist.PersistenceException An error occurred
* restoring the object attributes
*/
public synchronized void restore(Transaction t, Hashtable h)
throws PersistenceException{
Integer i = (Integer)h.get("t_accounts.account_id");
Float f = (Float)h.get("t_accounts.balance");
setId(i.intValue()); // Set the ID
i = (Integer)h.get("t_accounts.cust_id");
// Get the customer object for this account
customer =
(Customer)Persistent.getPersistent(t, i.intValue(),
"bank.server.Customer");
// Set the account type
type = (String)h.get("t_accounts.account_type");
// Set the balance
balance = f.floatValue();
}
/**
* Transfers the specified amount of money from this account to another
* This is done as a withdraw from this account followed by a
* deposit into the remote account.
* @param trans the Transaction used to perform the modification
* @param amount the amount being withdrawn
* @exception AccountException A deposit or withdrawal failed
* @exception LockException Another Transaction is holding a lock
*/
public synchronized void transfer(RemoteLockHolder h, float amount,
RemoteAccount acct)
throws AccountException, LockException, RemoteException {
float current_balance = getBalance();
try {
withdraw(h, amount);
acct.deposit(h, amount);
}
catch( AccountException e ) {
balance = current_balance; // restore the balance here!
throw e;
}
catch( LockException e ) {
balance = current_balance; // restore the balance here!
throw e;
}
catch( RemoteException e ) {
balance = current_balance; // you know the routine
throw e;
}
}
/**
* Withdraws the specified amount of money from the account.
* This method places no restrictions on what may or may not be
* withdrawn (negative balances allowed).
* @param trans the Transaction used to perform the modification
* @param amount the amount being withdrawn
* @exception AccountException An attempt to withdraw a negative amount
* @exception LockException Another Transaction is holding a lock
*/
public synchronized void withdraw(RemoteLockHolder h, float amount)
throws AccountException, LockException, RemoteException {
// will throw a LockException if another lock is held
modify(h);
if( amount < 0 ) {
throw new AccountException("Attempt to withdraw a negative " +
"amount of money.");
}
balance -= amount;
}
}
|