Previous Section  < Free Open Study >  Next Section

The Trans.cpp File


// Trans.cpp: The source code for the Transaction classes. The 

// Transaction classes are interesting since they appear on both

// sides of the application. The Transaction objects on each side

// of the application could be completely different definitions.

// For convenience, they were made the same in this example. The

// parts of the public interface unique to one side of the

// application are restricted through the use of the BANK_SIDE or

// ATM_SIDE macros.



#define BANK_SIDE



#ifdef ATM_SIDE

#include ''atm.hpp''

#endif



#ifdef BANK_SIDE

#include ''bank.hpp''

#endif



#include ''trans.hpp''



// The TimeStamp constructor uses the time and ctime standard C

// library functions to create a simple string capturing data and

// time.

TimeStamp::TimeStamp()

{

     time_t timer;



     time(&timer);

     strcpy(date_time, ctime(&timer));

}



void

TimeStamp::print(FILE* fd)

{

     fprintf(fd, ''%s'', date_time);

}





Transaction::Transaction(char* account, char* p, double a)

{

     strcpy(source_account, account);

     strcpy(pin, p);

     amount = a;

}



// These are protected accessor methods for use by the four derived

// classes of the Transaction class.

char*

Transaction::get_source_account()

{

     return(source_account);

}





double

Transaction::get_amount()

{

     return(amount);

}





void

Transaction::set_amount(double new_amount)

{

   amount = new_amount;

}





void

Transaction::print(FILE* fd)

{

     timeStamp.print(fd);

     fprintf(fd, ''\tAccount:%s\tAmount:%4.21f\n'',

      source_account,

       amount);

}





#ifdef ATM_SIDE



// If the application is the ATM side, then define the preprocess,

// postprocess, and update methods to do nothing. The packetize

// method is responsible for building a string, which consists of a

// type field (four characters), the source account (seven

// characters), a space, a PIN number (four characters), a space,

// an amount (nine characters), a space, and a NULL terminator.

// This string is suitable for shipping across a network, or it can

// be transformed into something that can be shipped across a

// network.



int

Transaction::preprocess(ATM*)

{

     return(0);

}



void

Transaction::postprocess(ATM*)

{

}





void

Transaction::update(char* info, int count)

{

}



void

Transaction::packetize(char* buf)

{

   char type_buf[small_string];

   strcpy(type_buf, type());

   type_buf[4]='\0';



   sprintf(buf, ''%s%s %s %4.21f'', type_buf, source_account,

pin, amount);

}

#endif



// If this is the Bank side of the application, include a

// verify_account method, which checks if an account's name and

// PIN match that of the Transaction.



#ifdef BANK_SIDE

int

Transaction::verify_account(Account* a)

{

   return(a->verify_account(source_account, pin));

}





void

Transaction::packetize(int status, char* buf)

{

   sprintf(buf, ''%4d %4.21f'', status, amount);

   cout << ''Bank packetized network object: \'' '' << buf <<

''\''\n'';

}



#endif





Deposit::Deposit(char* account, char* p, double a) :

   Transaction(account, p, a)

{

}





void

Deposit::print(FILE* fd)

{

     fprintf(fd, ''Deposit: '');

     Transaction::print(fd);

}





char*

Deposit::type()

{

   return(''Deposit'');

}





// Preprocessing deposits requires grabbing an envelope. Nothing

// can go wrong with this in the simulation, but in the world of

// hardware we would have to consider timeouts, jammed envelopes,

// etc. In the real world, the DepositSlot::retrieve_envelope

// method would be implemented to handle these cases.

#ifdef ATM_SIDE



int

Deposit::preprocess(ATM* a)

{

     return(a->retrieve_envelope());

}



#endif

// Processing a Deposit transaction involves getting the source

// account, verifying it, and then modifying the balance to reflect

// the deposited amount. This is a bit of a simplification from the

// real world, where a ''shadow'' account might be updated but a

// human needs to retrieve the envelope and check to be sure that

// money was actually included. This method suits our purposes,

// which is to show the design and implementation of a distributed

// process.

#ifdef BANK_SIDE



int

Deposit::process(AccountList* accounts)

{

   Account* account = accounts->find_account(get_source_account());



   if (account == NULL) {

      return(1);

   }

   if (!Transaction::verify_account(account)) {

      return(1);

   }

   account->modify_balance(get_amount());

   return(0);

}



#endif





Withdraw::Withdraw(char* account, char* p, double a) :

   Transaction(account, p, a)

{

}





void

Withdraw::print(FILE* fd)

{

     fprintf(fd, ''Withdraw: '');

     Transaction::print(fd);

}



char*

Withdraw::type()

{

     return(''Withdraw'');

}





// Preprocessing a withdrawal involves checking the cash

// dispenser to be sure the ATM has enough cash. Postprocessing

// gives the user the cash.

#ifdef ATM_SIDE

int

Withdraw::preprocess(ATM* a)

{

     return(!a->enough_cash(get_amount()));

}



void

Withdraw::postprocess(ATM* a)

{

     a->dispense_cash(get_amount());

}



#endif





// The processing of a Withdraw transaction requires finding the

// source account, verifying the account, ensuring there is enough

// cash in the account, and, only then, reducing the amount of money

// in the account.

#ifdef BANK_SIDE



int

Withdraw::process(AccountList* accounts)

{

     Account* account = accounts->find_account(get_source_account());



     if (account == NULL || || !account->check_balance

(get_amount()))

{

     return(1);

   }

   if (! Transaction::verify_account(account)) {

       return(1);

   }

   account->modify_balance(-get_amount());

   return(0);

}



#endif





Balance::Balance(char* account, char* p) : Transaction(account,

p, 0.0)

{

}



void

Balance::print(FILE* fd)

{

     fprintf(fd, ''Balance: '');

     Transaction::print(fd);

}



char*

Balance::type()

{

     return(''Balance'');

}





// Processing a Balance involves finding the source account and

// copying its balance into the Amount field of the Transaction

// object. This assumes the account name and PIN were verified.

#ifdef BANK_SIDE



int

Balance::process(AccountList* accounts)

{

   Account* account = accounts->find_account(get_source_account());



   if (account == NULL) {

      return(1);

   }

   if (!Transaction::verify_account(account)) {

      return(1);

   }

   set_amount(account->get_balance());

   return(0);

}



#endif



// The update method for Balance (on the ATM side of the

// application) is used to copy the retrieved balance back into the

// corresponding Transaction object on the ATM side.

#ifdef ATM_SIDE

void

Balance::update(char* info, int count)

{

   set_amount(atof(info));

}



#endif





Transfer::Transfer(char* s_account, char* p, char* t_account,

double a)

     : Transaction(s_account, p, a)

{

     strcpy(target_account, t_account);

}





void

Transfer::print(FILE* fd)

{

     fprintf(fd, ''Transfer: '');

     Transaction::print(fd);

     fprintf(fd, ''\tTarget Account: %s\n\n'', target_

      account);

}





char*

Transfer::type()

{

     return(''Transfer'');

}



// Packetizing a transfer implies including the target account at

// the end of the packet.

#ifdef ATM_SIDE



void

Transfer::packetize(char* buf)

{

     Transaction::packetize(buf);

     strcat(buf, '' '');

     strcat(buf, target_account);

}



#endif



// Processing a Transfer object requires that we retrieve the

// source and target accounts, verify the source account, ensure

// that the source account has enough money for the transfer, and

// only then update the balances of the source (by subtracting the

// amount) and the target (by adding the equivalent amount).



#ifdef BANK_SIDE



int

Transfer::process(AccountList* accounts)

{

   Account* src_account = accounts->find_account

    (get_source_account());

   Account* tar_account = accounts->find_account(target_account);



   if (src_account == NULL || tar_account == NULL) {

      return(1);

   }

   if (!Transaction::verify_account(src_account)) {

      return(1);

   }

   if (!src_account->check_balance(get_amount())) {

      return(1);

   }

   src_account->modify_balance(-get_amount());

   tar_account->modify_balance(get_amount());

   return(0);

}

#endif





TransactionList::TransactionList(unsigned sz)

{

     transnum = 0;

     TransList = new Transaction*[size=sz];

}



TransactionList::~TransactionList()

{

     cleanup();

     delete TransList;

}



int

TransactionList::add_trans(Transaction* t)

{

     if (transnum < size) {

          TransList[transnum++] = t;

          return(0);

     }

     return(1);

}



void

TransactionList::cleanup()

{

     int i;

     for (i=0; i < transnum; i++) {

          delete TransList[i];

     }

}





void

TransactionList:sprint(FILE* fd)

{

     int i;

     for (i=0; i < transnum; i++) {

          TransList[i]->print{fd);

     }

}

    Previous Section  < Free Open Study >  Next Section