ATM.zip

ATM/.classpath

ATM/.project

ATM org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature

ATM/.settings/org.eclipse.jdt.core.prefs

eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.7

ATM/bin/atm/ATM.class

package atm;
public synchronized class ATM implements Runnable {
    private int id;
    private String place;
    private String bankName;
    private java.net.InetAddress bankAddress;
    private physical.CardReader cardReader;
    private physical.CashDispenser cashDispenser;
    private physical.CustomerConsole customerConsole;
    private physical.EnvelopeAcceptor envelopeAcceptor;
    private physical.Log log;
    private physical.NetworkToBank networkToBank;
    private physical.OperatorPanel operatorPanel;
    private physical.ReceiptPrinter receiptPrinter;
    private int state;
    private boolean switchOn;
    private boolean cardInserted;
    private static final int OFF_STATE = 0;
    private static final int IDLE_STATE = 1;
    private static final int SERVING_CUSTOMER_STATE = 2;
    public void ATM(int, String, String, java.net.InetAddress);
    public void run();
    public synchronized void switchOn();
    public synchronized void switchOff();
    public synchronized void cardInserted();
    public int getID();
    public String getPlace();
    public String getBankName();
    public physical.CardReader getCardReader();
    public physical.CashDispenser getCashDispenser();
    public physical.CustomerConsole getCustomerConsole();
    public physical.EnvelopeAcceptor getEnvelopeAcceptor();
    public physical.Log getLog();
    public physical.NetworkToBank getNetworkToBank();
    public physical.OperatorPanel getOperatorPanel();
    public physical.ReceiptPrinter getReceiptPrinter();
    private void performStartup();
    private void performShutdown();
}

ATM/bin/atm/physical/CardReader.class

package atm.physical;
public synchronized class CardReader {
    private atm.ATM atm;
    public void CardReader(atm.ATM);
    public banking.Card readCard();
    public void ejectCard();
    public void retainCard();
}

ATM/bin/atm/physical/CashDispenser.class

package atm.physical;
public synchronized class CashDispenser {
    private Log log;
    private banking.Money cashOnHand;
    public void CashDispenser(Log);
    public void setInitialCash(banking.Money);
    public boolean checkCashOnHand(banking.Money);
    public void dispenseCash(banking.Money);
}

ATM/bin/atm/physical/CustomerConsole$Cancelled.class

package atm.physical;
public synchronized class CustomerConsole$Cancelled extends Exception {
    public void CustomerConsole$Cancelled();
}

ATM/bin/atm/physical/CustomerConsole.class

package atm.physical;
public synchronized class CustomerConsole {
    public void CustomerConsole();
    public void display(String);
    public int readPIN(String) throws CustomerConsole$Cancelled;
    public synchronized int readMenuChoice(String, String[]) throws CustomerConsole$Cancelled;
    public synchronized banking.Money readAmount(String) throws CustomerConsole$Cancelled;
}

ATM/bin/atm/physical/EnvelopeAcceptor.class

package atm.physical;
public synchronized class EnvelopeAcceptor {
    private Log log;
    public void EnvelopeAcceptor(Log);
    public void acceptEnvelope() throws CustomerConsole$Cancelled;
}

ATM/bin/atm/physical/Log.class

package atm.physical;
public synchronized class Log {
    public void Log();
    public void logSend(banking.Message);
    public void logResponse(banking.Status);
    public void logCashDispensed(banking.Money);
    public void logEnvelopeAccepted();
}

ATM/bin/atm/physical/NetworkToBank.class

package atm.physical;
public synchronized class NetworkToBank {
    private Log log;
    private java.net.InetAddress bankAddress;
    public void NetworkToBank(Log, java.net.InetAddress);
    public void openConnection();
    public void closeConnection();
    public banking.Status sendMessage(banking.Message, banking.Balances);
}

ATM/bin/atm/physical/OperatorPanel.class

package atm.physical;
public synchronized class OperatorPanel {
    private atm.ATM atm;
    public void OperatorPanel(atm.ATM);
    public banking.Money getInitialCash();
}

ATM/bin/atm/physical/ReceiptPrinter.class

package atm.physical;
public synchronized class ReceiptPrinter {
    public void ReceiptPrinter();
    public void printReceipt(banking.Receipt);
}

ATM/bin/atm/Session.class

package atm;
public synchronized class Session {
    private ATM atm;
    private int pin;
    private int state;
    private static final int READING_CARD_STATE = 1;
    private static final int READING_PIN_STATE = 2;
    private static final int CHOOSING_TRANSACTION_STATE = 3;
    private static final int PERFORMING_TRANSACTION_STATE = 4;
    private static final int EJECTING_CARD_STATE = 5;
    private static final int FINAL_STATE = 6;
    public void Session(ATM);
    public void performSession();
    public void setPIN(int);
}

ATM/bin/atm/transaction/Deposit$1.class

package atm.transaction;
synchronized class Deposit$1 extends banking.Receipt {
    void Deposit$1(Deposit, atm.ATM, banking.Card, Transaction, banking.Balances);
}

ATM/bin/atm/transaction/Deposit.class

package atm.transaction;
public synchronized class Deposit extends Transaction {
    private int to;
    private banking.Money amount;
    public void Deposit(atm.ATM, atm.Session, banking.Card, int);
    protected banking.Message getSpecificsFromCustomer() throws atm.physical.CustomerConsole$Cancelled;
    protected banking.Receipt completeTransaction() throws atm.physical.CustomerConsole$Cancelled;
}

ATM/bin/atm/transaction/Inquiry$1.class

package atm.transaction;
synchronized class Inquiry$1 extends banking.Receipt {
    void Inquiry$1(Inquiry, atm.ATM, banking.Card, Transaction, banking.Balances);
}

ATM/bin/atm/transaction/Inquiry.class

package atm.transaction;
public synchronized class Inquiry extends Transaction {
    private int from;
    public void Inquiry(atm.ATM, atm.Session, banking.Card, int);
    protected banking.Message getSpecificsFromCustomer() throws atm.physical.CustomerConsole$Cancelled;
    protected banking.Receipt completeTransaction();
}

ATM/bin/atm/transaction/Transaction$CardRetained.class

package atm.transaction;
public synchronized class Transaction$CardRetained extends Exception {
    public void Transaction$CardRetained();
}

ATM/bin/atm/transaction/Transaction.class

package atm.transaction;
public abstract synchronized class Transaction {
    protected atm.ATM atm;
    protected atm.Session session;
    protected banking.Card card;
    protected int pin;
    protected int serialNumber;
    protected banking.Message message;
    protected banking.Balances balances;
    private static final String[] TRANSACTION_TYPES_MENU;
    private static int nextSerialNumber;
    private int state;
    private static final int GETTING_SPECIFICS_STATE = 1;
    private static final int SENDING_TO_BANK_STATE = 2;
    private static final int INVALID_PIN_STATE = 3;
    private static final int COMPLETING_TRANSACTION_STATE = 4;
    private static final int PRINTING_RECEIPT_STATE = 5;
    private static final int ASKING_DO_ANOTHER_STATE = 6;
    static void <clinit>();
    protected void Transaction(atm.ATM, atm.Session, banking.Card, int);
    public static Transaction makeTransaction(atm.ATM, atm.Session, banking.Card, int) throws atm.physical.CustomerConsole$Cancelled;
    public boolean performTransaction() throws Transaction$CardRetained;
    public banking.Status performInvalidPINExtension() throws atm.physical.CustomerConsole$Cancelled, Transaction$CardRetained;
    public int getSerialNumber();
    protected abstract banking.Message getSpecificsFromCustomer() throws atm.physical.CustomerConsole$Cancelled;
    protected abstract banking.Receipt completeTransaction() throws atm.physical.CustomerConsole$Cancelled;
}

ATM/bin/atm/transaction/Transfer$1.class

package atm.transaction;
synchronized class Transfer$1 extends banking.Receipt {
    void Transfer$1(Transfer, atm.ATM, banking.Card, Transaction, banking.Balances);
}

ATM/bin/atm/transaction/Transfer.class

package atm.transaction;
public synchronized class Transfer extends Transaction {
    private int from;
    private int to;
    private banking.Money amount;
    public void Transfer(atm.ATM, atm.Session, banking.Card, int);
    protected banking.Message getSpecificsFromCustomer() throws atm.physical.CustomerConsole$Cancelled;
    protected banking.Receipt completeTransaction();
}

ATM/bin/atm/transaction/Withdrawal$1.class

package atm.transaction;
synchronized class Withdrawal$1 extends banking.Receipt {
    void Withdrawal$1(Withdrawal, atm.ATM, banking.Card, Transaction, banking.Balances);
}

ATM/bin/atm/transaction/Withdrawal.class

package atm.transaction;
public synchronized class Withdrawal extends Transaction {
    private int from;
    private banking.Money amount;
    public void Withdrawal(atm.ATM, atm.Session, banking.Card, int);
    protected banking.Message getSpecificsFromCustomer() throws atm.physical.CustomerConsole$Cancelled;
    protected banking.Receipt completeTransaction();
}

ATM/bin/banking/AccountInformation.class

package banking;
public synchronized class AccountInformation {
    public static final String[] ACCOUNT_NAMES;
    public static final String[] ACCOUNT_ABBREVIATIONS;
    static void <clinit>();
    public void AccountInformation();
}

ATM/bin/banking/Balances.class

package banking;
public synchronized class Balances {
    private Money total;
    private Money available;
    public void Balances();
    public void setBalances(Money, Money);
    public Money getTotal();
    public Money getAvailable();
}

ATM/bin/banking/Card.class

package banking;
public synchronized class Card {
    private int number;
    public void Card(int);
    public int getNumber();
}

ATM/bin/banking/Message.class

package banking;
public synchronized class Message {
    public static final int WITHDRAWAL = 0;
    public static final int INITIATE_DEPOSIT = 1;
    public static final int COMPLETE_DEPOSIT = 2;
    public static final int TRANSFER = 3;
    public static final int INQUIRY = 4;
    private int messageCode;
    private Card card;
    private int pin;
    private int serialNumber;
    private int fromAccount;
    private int toAccount;
    private Money amount;
    public void Message(int, Card, int, int, int, int, Money);
    public String toString();
    public void setPIN(int);
    public int getMessageCode();
    public Card getCard();
    public int getPIN();
    public int getSerialNumber();
    public int getFromAccount();
    public int getToAccount();
    public Money getAmount();
}

ATM/bin/banking/Money.class

package banking;
public synchronized class Money {
    private long cents;
    public void Money(int);
    public void Money(int, int);
    public void Money(Money);
    public String toString();
    public void add(Money);
    public void subtract(Money);
    public boolean lessEqual(Money);
}

ATM/bin/banking/Receipt$1.class

package banking;
synchronized class Receipt$1 implements java.util.Enumeration {
    private int portion;
    private int index;
    void Receipt$1(Receipt);
    public boolean hasMoreElements();
    public Object nextElement();
}

ATM/bin/banking/Receipt.class

package banking;
public abstract synchronized class Receipt {
    private String[] headingPortion;
    protected String[] detailsPortion;
    private String[] balancesPortion;
    protected void Receipt(atm.ATM, Card, atm.transaction.Transaction, Balances);
    public java.util.Enumeration getLines();
}

ATM/bin/banking/Status.class

package banking;
public abstract synchronized class Status {
    public void Status();
    public String toString();
    public abstract boolean isSuccess();
    public abstract boolean isInvalidPIN();
    public abstract String getMessage();
}

ATM/bin/main/ATMApplet.class

package main;
public synchronized class ATMApplet extends java.applet.Applet {
    public void ATMApplet();
    public void init();
}

ATM/bin/main/ATMMain$1.class

package main;
synchronized class ATMMain$1 implements java.awt.event.ActionListener {
    void ATMMain$1();
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/main/ATMMain$2.class

package main;
synchronized class ATMMain$2 extends java.awt.event.WindowAdapter {
    void ATMMain$2();
    public void windowClosing(java.awt.event.WindowEvent);
}

ATM/bin/main/ATMMain.class

package main;
public synchronized class ATMMain {
    public void ATMMain();
    public static void main(String[]);
}

ATM/bin/simulation/ATMPanel$1.class

package simulation;
synchronized class ATMPanel$1 implements java.awt.event.ActionListener {
    void ATMPanel$1(ATMPanel, GUI);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/ATMPanel.class

package simulation;
synchronized class ATMPanel extends java.awt.Panel {
    public static final int DISPLAYABLE_LINES = 9;
    public static final String BLANK_DISPLAY_LINE =                                              ;
    public static final int PRINTABLE_LINES = 9;
    public static final int PRINTABLE_CHARS = 30;
    private static final int DISPLAY_ROW = 0;
    private static final int DISPLAY_COL = 0;
    private static final int DISPLAY_WIDTH = 3;
    private static final int DISPLAY_HEIGHT = 1;
    private static final int DISPLAY_FILL = 1;
    private static final int PRINTER_ROW = 0;
    private static final int PRINTER_COL = 3;
    private static final int PRINTER_WIDTH = 1;
    private static final int PRINTER_HEIGHT = 1;
    private static final int PRINTER_FILL = 0;
    private static final int ENVELOPE_ROW = 1;
    private static final int ENVELOPE_COL = 0;
    private static final int ENVELOPE_WIDTH = 1;
    private static final int ENVELOPE_HEIGHT = 1;
    private static final int ENVELOPE_FILL = 0;
    private static final int DISPENSER_ROW = 1;
    private static final int DISPENSER_COL = 1;
    private static final int DISPENSER_WIDTH = 1;
    private static final int DISPENSER_HEIGHT = 1;
    private static final int DISPENSER_FILL = 0;
    private static final int READER_ROW = 1;
    private static final int READER_COL = 2;
    private static final int READER_WIDTH = 1;
    private static final int READER_HEIGHT = 1;
    private static final int READER_FILL = 0;
    private static final int KEYBOARD_ROW = 1;
    private static final int KEYBOARD_COL = 3;
    private static final int KEYBOARD_WIDTH = 1;
    private static final int KEYBOARD_HEIGHT = 1;
    private static final int KEYBOARD_FILL = 0;
    private static final int SHOW_LOG_BUTTON_ROW = 2;
    private static final int SHOW_LOG_BUTTON_COL = 0;
    private static final int SHOW_LOG_BUTTON_WIDTH = 1;
    private static final int SHOW_LOG_BUTTON_HEIGHT = 1;
    private static final int SHOW_LOG_BUTTON_FILL = 1;
    private static final int OPERATOR_ROW = 2;
    private static final int OPERATOR_COL = 1;
    private static final int OPERATOR_WIDTH = 3;
    private static final int OPERATOR_HEIGHT = 1;
    private static final int OPERATOR_FILL = 1;
    private static final int TOTAL_ROWS = 3;
    private static final int TOTAL_COLS = 3;
    void ATMPanel(GUI, SimOperatorPanel, SimCardReader, SimDisplay, SimKeyboard, SimCashDispenser, SimEnvelopeAcceptor, SimReceiptPrinter);
}

ATM/bin/simulation/BillsPanel$1.class

package simulation;
synchronized class BillsPanel$1 implements java.awt.event.ActionListener {
    void BillsPanel$1(BillsPanel);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/BillsPanel.class

package simulation;
synchronized class BillsPanel extends java.awt.Panel {
    private java.awt.TextField billsNumberField;
    void BillsPanel();
    synchronized int readBills();
}

ATM/bin/simulation/CardPanel$1.class

package simulation;
synchronized class CardPanel$1 implements java.awt.event.ActionListener {
    void CardPanel$1(CardPanel);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/CardPanel.class

package simulation;
synchronized class CardPanel extends java.awt.Panel {
    private java.awt.TextField cardNumberField;
    void CardPanel();
    synchronized int readCardNumber();
}

ATM/bin/simulation/GUI.class

package simulation;
synchronized class GUI extends java.awt.Panel {
    private java.awt.CardLayout mainLayout;
    private ATMPanel atmPanel;
    private BillsPanel billsPanel;
    private CardPanel cardPanel;
    private LogPanel logPanel;
    void GUI(SimOperatorPanel, SimCardReader, SimDisplay, SimKeyboard, SimCashDispenser, SimEnvelopeAcceptor, SimReceiptPrinter);
    public banking.Money getInitialCash();
    public banking.Card readCard();
    public void printLogLine(String);
    void showCard(String);
    static java.awt.GridBagConstraints makeConstraints(int, int, int, int, int);
}

ATM/bin/simulation/LogPanel$1.class

package simulation;
synchronized class LogPanel$1 implements java.awt.event.ActionListener {
    void LogPanel$1(LogPanel);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/LogPanel$2.class

package simulation;
synchronized class LogPanel$2 implements java.awt.event.ActionListener {
    void LogPanel$2(LogPanel, GUI);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/LogPanel.class

package simulation;
synchronized class LogPanel extends java.awt.Panel {
    private java.awt.TextArea logPrintArea;
    void LogPanel(GUI);
    void println(String);
}

ATM/bin/simulation/SimCardReader$1.class

package simulation;
synchronized class SimCardReader$1 implements java.awt.event.ActionListener {
    void SimCardReader$1(SimCardReader, Simulation);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimCardReader.class

package simulation;
synchronized class SimCardReader extends java.awt.Button {
    private java.awt.Rectangle originalBounds;
    void SimCardReader(Simulation);
    void animateInsertion();
    void animateEjection();
    void animateRetention();
}

ATM/bin/simulation/SimCashDispenser.class

package simulation;
synchronized class SimCashDispenser extends java.awt.Panel {
    private java.awt.Label label;
    void SimCashDispenser();
    public void animateDispensingCash(banking.Money);
}

ATM/bin/simulation/SimDisplay.class

package simulation;
synchronized class SimDisplay extends java.awt.Panel {
    private java.awt.Label[] displayLine;
    private int currentDisplayLine;
    void SimDisplay();
    void clearDisplay();
    void display(String);
    void setEcho(String);
    public java.awt.Insets getInsets();
}

ATM/bin/simulation/SimEnvelopeAcceptor$1.class

package simulation;
synchronized class SimEnvelopeAcceptor$1 implements java.awt.event.ActionListener {
    void SimEnvelopeAcceptor$1(SimEnvelopeAcceptor);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimEnvelopeAcceptor.class

package simulation;
synchronized class SimEnvelopeAcceptor extends java.awt.Button {
    private boolean inserted;
    private static long MAXIMUM_WAIT_TIME;
    static void <clinit>();
    void SimEnvelopeAcceptor();
    public synchronized boolean acceptEnvelope();
    public synchronized void cancelRequested();
}

ATM/bin/simulation/SimKeyboard$1.class

package simulation;
synchronized class SimKeyboard$1 implements java.awt.event.ActionListener {
    void SimKeyboard$1(SimKeyboard);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimKeyboard$2.class

package simulation;
synchronized class SimKeyboard$2 implements java.awt.event.ActionListener {
    void SimKeyboard$2(SimKeyboard);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimKeyboard$3.class

package simulation;
synchronized class SimKeyboard$3 implements java.awt.event.ActionListener {
    void SimKeyboard$3(SimKeyboard);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimKeyboard$4.class

package simulation;
synchronized class SimKeyboard$4 implements java.awt.event.ActionListener {
    void SimKeyboard$4(SimKeyboard);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimKeyboard$5.class

package simulation;
synchronized class SimKeyboard$5 extends java.awt.event.KeyAdapter {
    void SimKeyboard$5(SimKeyboard);
    public void keyPressed(java.awt.event.KeyEvent);
}

ATM/bin/simulation/SimKeyboard.class

package simulation;
synchronized class SimKeyboard extends java.awt.Panel {
    private SimDisplay display;
    private SimEnvelopeAcceptor envelopeAcceptor;
    private int mode;
    private static final int IDLE_MODE = 0;
    private static final int PIN_MODE = 1;
    private static final int AMOUNT_MODE = 2;
    private static final int MENU_MODE = 3;
    private StringBuffer currentInput;
    private boolean cancelled;
    private int maxValue;
    void SimKeyboard(SimDisplay, SimEnvelopeAcceptor);
    synchronized String readInput(int, int);
    private synchronized void digitKeyPressed(int);
    private synchronized void enterKeyPressed();
    private synchronized void clearKeyPressed();
    private synchronized void cancelKeyPressed();
    private void setEcho(String);
}

ATM/bin/simulation/SimOperatorPanel$1.class

package simulation;
synchronized class SimOperatorPanel$1 implements java.awt.event.ActionListener {
    void SimOperatorPanel$1(SimOperatorPanel, java.awt.Button, java.awt.Label, Simulation);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimOperatorPanel$2.class

package simulation;
synchronized class SimOperatorPanel$2 extends Thread {
    void SimOperatorPanel$2(SimOperatorPanel, java.awt.Label, java.awt.Button);
    public void run();
}

ATM/bin/simulation/SimOperatorPanel.class

package simulation;
synchronized class SimOperatorPanel extends java.awt.Panel {
    void SimOperatorPanel(Simulation);
}

ATM/bin/simulation/SimReceiptPrinter$1.class

package simulation;
synchronized class SimReceiptPrinter$1 implements java.awt.event.ActionListener {
    void SimReceiptPrinter$1(SimReceiptPrinter);
    public void actionPerformed(java.awt.event.ActionEvent);
}

ATM/bin/simulation/SimReceiptPrinter.class

package simulation;
synchronized class SimReceiptPrinter extends java.awt.Panel {
    private java.awt.TextArea printArea;
    private java.awt.Button take;
    void SimReceiptPrinter();
    void println(String);
}

ATM/bin/simulation/SimulatedBank$Failure.class

package simulation;
synchronized class SimulatedBank$Failure extends banking.Status {
    private String message;
    public void SimulatedBank$Failure(String);
    public boolean isSuccess();
    public boolean isInvalidPIN();
    public String getMessage();
}

ATM/bin/simulation/SimulatedBank$InvalidPIN.class

package simulation;
synchronized class SimulatedBank$InvalidPIN extends SimulatedBank$Failure {
    public void SimulatedBank$InvalidPIN();
    public boolean isInvalidPIN();
}

ATM/bin/simulation/SimulatedBank$Success.class

package simulation;
synchronized class SimulatedBank$Success extends banking.Status {
    private void SimulatedBank$Success();
    public boolean isSuccess();
    public boolean isInvalidPIN();
    public String getMessage();
}

ATM/bin/simulation/SimulatedBank.class

package simulation;
public synchronized class SimulatedBank {
    private static final int[] PIN;
    private static final int[][] ACCOUNT_NUMBER;
    private static banking.Money[] WITHDRAWALS_TODAY;
    private static final banking.Money DAILY_WITHDRAWAL_LIMIT;
    private banking.Money[] BALANCE;
    private banking.Money[] AVAILABLE_BALANCE;
    static void <clinit>();
    public void SimulatedBank();
    public banking.Status handleMessage(banking.Message, banking.Balances);
    private banking.Status withdrawal(banking.Message, banking.Balances);
    private banking.Status initiateDeposit(banking.Message);
    private banking.Status completeDeposit(banking.Message, banking.Balances);
    private banking.Status transfer(banking.Message, banking.Balances);
    private banking.Status inquiry(banking.Message, banking.Balances);
}

ATM/bin/simulation/Simulation.class

package simulation;
public synchronized class Simulation {
    public static final int PIN_MODE = 1;
    public static final int AMOUNT_MODE = 2;
    public static final int MENU_MODE = 3;
    private atm.ATM atm;
    private SimOperatorPanel operatorPanel;
    private SimCardReader cardReader;
    private SimDisplay display;
    private SimKeyboard keyboard;
    private SimCashDispenser cashDispenser;
    private SimEnvelopeAcceptor envelopeAcceptor;
    private SimReceiptPrinter receiptPrinter;
    private GUI gui;
    private SimulatedBank simulatedBank;
    private static Simulation theInstance;
    public void Simulation(atm.ATM);
    public static Simulation getInstance();
    public banking.Money getInitialCash();
    public banking.Card readCard();
    public void ejectCard();
    public void retainCard();
    public void clearDisplay();
    public void display(String);
    public String readInput(int, int);
    public void dispenseCash(banking.Money);
    public boolean acceptEnvelope();
    public void printReceiptLine(String);
    public void printLogLine(String);
    public banking.Status sendMessage(banking.Message, banking.Balances);
    void switchChanged(boolean);
    void cardInserted();
    public GUI getGUI();
    public SimulatedBank getSimulatedBank();
}

ATM/src/atm/ATM.java

ATM/src/atm/ATM.java

/*
 * ATM Example system - file ATM.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm ;
import  java . net . InetAddress ;
import  atm . physical . * ;
import  banking . Card ;
import  banking . Money ;

/** Representation for the ATM itself.  An object of this class "owns"
 *  the objects representing the component parts of the ATM, and the
 *  communications network, and is responsible for creating customer 
 *  sessions which then use it to gain access to the component parts.
 *  This is an active class - when an instance of the class is created,
 *  a thread is executed that actually runs the system.
 */
 
public   class  ATM  implements   Runnable
{
     /** Constructor
     *
     *   @param  id the unique ID for this ATM
     *   @param  place the physical location of this ATM
     *   @param  bankName the name of the bank owning this ATM
     *   @param  bankAddress the Internet address of the bank
     */
     public  ATM ( int  id ,   String  place ,   String  bankName ,   InetAddress  bankAddress )
     {
         this . id  =  id ;
         this . place  =  place ;
         this . bankName  =  bankName ;
         this . bankAddress  =  bankAddress ;
        
         // Create objects corresponding to component parts

        log  =   new   Log ();
        cardReader  =   new   CardReader ( this );
        cashDispenser  =   new   CashDispenser ( log );
        customerConsole  =   new   CustomerConsole ();
        envelopeAcceptor  =   new   EnvelopeAcceptor ( log );
        networkToBank  =   new   NetworkToBank ( log ,  bankAddress );
        operatorPanel  =   new   OperatorPanel ( this );
        receiptPrinter  =   new   ReceiptPrinter ();   
    
         // Set up initial conditions when ATM first created
        
        state  =  OFF_STATE ;
        switchOn  =   false ;
        cardInserted  =   false ;        
     }
    
     // Methods corresponding to major responsibilities of the ATM
    
     /** The main program/applet will create a Thread that executes
     *  this code.
     */
     public   void  run ()
     {
         Session  currentSession  =   null ;
        
         while   ( true )
         {
             switch ( state )
             {
                 case  OFF_STATE :
                
                    customerConsole . display ( "Not currently available" );

                     synchronized ( this )
                     {
                         try
                         {  
                            wait ();
                         }
                         catch ( InterruptedException  e )
                         {   }
                     }
                    
                     if   ( switchOn )
                     {
                        performStartup ();
                        state  =  IDLE_STATE ;
                     }
                                            
                     break ;
                    
                 case  IDLE_STATE :
                
                    customerConsole . display ( "Please insert your card" );
                    cardInserted  =   false ;
                                        
                     synchronized ( this )
                     {
                         try
                         {  
                            wait ();
                         }
                         catch ( InterruptedException  e )
                         {   }
                     }        
                    
                     if   ( cardInserted )
                     {
                        currentSession  =   new   Session ( this );
                        state  =  SERVING_CUSTOMER_STATE ;
                     }
                     else   if   ( !  switchOn )
                     {
                        performShutdown ();
                        state  =  OFF_STATE ;
                     }
                    
                     break ;
            
                 case  SERVING_CUSTOMER_STATE :
                                    
                     // The following will not return until the session has
                     // completed
                    
                    currentSession . performSession ();
                    
                    state  =  IDLE_STATE ;
                    
                     break ;
                
             }
         }
     }
                
     /** Inform the ATM that the switch on the operator console has been moved
     *  to the "on" position.
     */
     public   synchronized   void  switchOn ()
     {
        switchOn  =   true ;
        notify ();
     }
    
     /** Inform the ATM that the switch on the operator console has been moved
     *  to the "off" position.
     */
     public   synchronized   void  switchOff ()
     {
        switchOn  =   false ;
        notify ();
     }
    
     /** Inform the ATM that a card has been inserted into the card reader.
     */
     public   synchronized   void  cardInserted ()
     {
        cardInserted  =   true ;
        notify ();
     }
    
     // The following methods allow objects of other classes to access component
     // parts of the ATM
    
     /** Accessor for id
     *
     *   @return  unique id of this ATM
     */
     public   int  getID ()
     {
         return  id ;
     }
    
     /** Accessor for place
     *
     *   @return  physical location of this ATM
     */
     public   String  getPlace ()
     {
         return  place ;
     }
    
     /** Accessor for bank name
     *
     *   @return  name of bank owning this ATM
     */
     public   String  getBankName ()
     {
         return  bankName ;
     }
    
     /** Accessor for card reader
     *
     *   @return  card reader component of this ATM
     */
     public   CardReader  getCardReader ()
     {
         return  cardReader ;
     }
    
     /** Accessor for cash dispenser
     *
     *   @return  cash dispenser component of this ATM
     */
     public   CashDispenser  getCashDispenser ()
     {
         return  cashDispenser ;
     }
    
     /** Accessor for customer console 
     *
     *   @return  customer console component of this ATM
     */
     public   CustomerConsole  getCustomerConsole ()
     {
         return  customerConsole ;
     }
    
     /** Accessor for envelope acceptor
     *
     *   @return  envelope acceptor component of this ATM
     */
     public   EnvelopeAcceptor  getEnvelopeAcceptor ()
     {
         return  envelopeAcceptor ;
     }
    
     /** Accessor for log
     *
     *   @return  log component of this ATM
     */
     public   Log  getLog ()
     {
         return  log ;
     }
    
     /** Accessor for network to bank
     *
     *   @return  network connection to bank of this ATM
     */
     public   NetworkToBank  getNetworkToBank ()
     {
         return  networkToBank ;
     }
    
     /** Accessor for operator panel
     *
     *   @return  operator panel component of this ATM
     */
     public   OperatorPanel  getOperatorPanel ()
     {
         return  operatorPanel ;
     }
    
     /** Accessor for receipt printer
     *
     *   @return  receipt printer component of this ATM
     */
     public   ReceiptPrinter  getReceiptPrinter ()
     {
         return  receiptPrinter ;
     }

     // Private methods

     /** Perform the System Startup use case when switch is turned on
     */
     private   void  performStartup ()
     {
         Money  initialCash  =  operatorPanel . getInitialCash ();
        cashDispenser . setInitialCash ( initialCash );
        networkToBank . openConnection ();      
     }
    
     /** Perform the System Shutdown use case when switch is turned off
     */
     private   void  performShutdown ()
     {
        networkToBank . closeConnection ();
     }
    
    
     // Instance variables recording information about the ATM
    
    
     /** Unique ID for this ATM
     */
     private   int  id ;
    
     /** Physical location of this ATM
     */
     private   String  place ;
    
     /** Name of the bank owning this ATM
     */
     private   String  bankName ;
    
     /** Internet address of the bank
     */
     private   InetAddress  bankAddress ;
    
    
     // Instance variables referring to the omponent parts of the ATM
    
     /** The ATM's card reader
     */
     private   CardReader  cardReader ;
    
     /** The ATM's cash dispenser
     */
     private   CashDispenser  cashDispenser ;
    
     /** The ATM's customer console
     */
     private   CustomerConsole  customerConsole ;
    
     /** The ATM's envelope acceptor
     */
     private   EnvelopeAcceptor  envelopeAcceptor ;
    
     /** The ATM's log
     */
     private   Log  log ;
    
     /** The ATM's network connection to the bank
     */
     private   NetworkToBank  networkToBank ;
    
     /** The ATM's operator panel
     */
     private   OperatorPanel  operatorPanel ;
    
     /** The ATM's receipt printer
     */
     private   ReceiptPrinter  receiptPrinter ;
    

     // State information

    
     /** The current state of the ATM - one of the possible values listed below
     */
     private   int  state ;
    
     /** Becomes true when the operator panel informs the ATM that the switch has
     *  been turned on - becomes false when the operator panel informs the ATM
     *  that the switch has been turned off.
     */
     private   boolean  switchOn ;
    
     /** Becomes true when the card reader informs the ATM that a card has been
     *  inserted - the ATM will make this false when it has tried to read the
     *  card
     */
     private   boolean  cardInserted ;  


     // Possible values for state
    
    
     /** The ATM is off.  The switch must be turned on before it can operate
     */
     private   static   final   int  OFF_STATE  =   0 ;
    
     /** The ATM is on, but idle.  It can service a customer, or it can be shut down
     */
     private   static   final   int  IDLE_STATE  =   1 ;
    
     /** The ATM is servicing a customer.
     */
     private   static   final   int  SERVING_CUSTOMER_STATE  =   2 ;
}

ATM/src/atm/ATMApplet.java

ATM/src/atm/ATMApplet.java

/*
 * ATM Example system - file ATMApplet.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
import  java . awt . * ;
import  java . applet . Applet ;
import  atm . ATM ;
import  simulation . Simulation ;

/** Applet class for the applet version of the ATM simulation.
 *  Create an instance of the ATM, display in the applet, and then let the GUI
 *  do the work.
 */
 
public   class   ATMApplet   extends   Applet
{
     public   void  init ()
     {
         // Create the ATM software and the software that simulates it via a GUI
        
        ATM theATM  =   new  ATM ( 42 ,   "Gordon College" ,   "First National Bank of Podunk" ,
                              null   /* We're not really talking to a bank! */ );
         Simulation  theSimulation  =   new   Simulation ( theATM );
        
         // Start the Thread that runs the ATM
        
         new   Thread ( theATM ). start ();
        
         // Display the simulation's GUI in this applet
        
         Panel  gui  =  theSimulation . getGUI ();
        setBackground ( gui . getBackground ());
        add ( gui );
     }
}
    

ATM/src/atm/physical/CardReader.java

ATM/src/atm/physical/CardReader.java

/*
 * ATM Example system - file CardReader.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;
import  atm . ATM ;
import  banking . Card ;
import  simulation . Simulation ;

/** Manager for the ATM's card reader.  In a real ATM, this would 
 *  manage a physical device; in this simulation, it uses classes 
 *  in package simulation to simulate the device.  
 */
 
public   class   CardReader
{
     /** Constructor
     *
     *   @param  atm the ATM that owns this card reader
     */
     public   CardReader ( ATM atm )
     {
         this . atm  =  atm ;
     }
    
     // In a real ATM, code would be needed to sense insertion of a card into the
     // slot and notify the ATM - simulated in this case by a button in the GUI
    
     /** Read a card that has been partially inserted into the reader
     *
     *   @return  Card object representing information on the card if read
     *          successfully, null if not read successfully
     */
     public   Card  readCard ()
     {
         return   Simulation . getInstance (). readCard ();
     }
    
     /** Eject the card that is currently inside the reader.  
     */
     public   void  ejectCard ()
     {
         Simulation . getInstance (). ejectCard ();
     }
    
     /** Retain the card that is currently inside the reader for action by the
     *  bank.
     */
     public   void  retainCard ()
     {
         Simulation . getInstance (). retainCard ();
     }
    
     /** The ATM to which this card reader belongs
     */
     private  ATM atm ;     
}

ATM/src/atm/physical/CashDispenser.java

ATM/src/atm/physical/CashDispenser.java

/*
 * ATM Example system - file CashDispenser.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;

import  banking . Money ;
import  simulation . Simulation ;

/** Manager for the ATM's cash dispenser.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   CashDispenser
{
     /** Constructor
     *
     *   @param  log the log in which to record dispensing cash
     */
     public   CashDispenser ( Log  log )
     {
         this . log  =  log ;
        
        cashOnHand  =   new   Money ( 0 );
     }
    
     /** Set the amount of cash initially on hand 
     *
     *   @param  initialCash the amount of money in the dispenser
     */
     public   void  setInitialCash ( Money  initialCash )
     {
        cashOnHand  =  initialCash ;
     }
    
     /** See if there is enough cash on hand to satisfy a request
     *
     *   @param  amount the amount of cash the customer wants
     *   @return  true if at least this amount of money is available
     */
     public   boolean  checkCashOnHand ( Money  amount )
     {
         return  amount . lessEqual ( cashOnHand );
     }
    
     /** Dispense cash to a customer
     *
     *   @param  amount the amount of cash to dispense
     *
     *  Precondition: amount is <= cash on hand
     */
     public   void  dispenseCash ( Money  amount )
     {
        cashOnHand . subtract ( amount );
        
         Simulation . getInstance (). dispenseCash ( amount );
        
         // Log cash having been dispensed
        
        log . logCashDispensed ( amount );
     }

     /** Log into which cash amounts dispensed will be recorded
     */  
     private   Log  log ;
    
     /** Current cash on hand
     */
     private   Money  cashOnHand ;
}

ATM/src/atm/physical/CustomerConsole.java

ATM/src/atm/physical/CustomerConsole.java

/*
 * ATM Example system - file CustomerConsole.java   
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;

import  banking . Money ;
import  banking . Status ;

import  simulation . Simulation ;

/** Manager for the ATM's customer console.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device (actually two separate
 *  devices - the display and the keyboard.)
 */
 
public   class   CustomerConsole
{
     /** Constructor
     */
     public   CustomerConsole ()
     {
     }
    
     /** Display a message to the customer
     *
     *   @param  message the message to display
     */
     public   void  display ( String  message )
     {
         Simulation . getInstance (). clearDisplay ();
         Simulation . getInstance (). display ( message );
     }
    
     /** Read a PIN entered by the customer (echoed as asterisks)
     *
     *   @param  prompt the message to display prompting the customer to enter PIN
     *   @return  the PIN that was entered
     *   @exception  Cancelled if customer presses the CANCEL key before pressing ENTER
     */
     public   int  readPIN ( String  prompt )   throws   Cancelled
     {
         Simulation . getInstance (). clearDisplay ();
         Simulation . getInstance (). display ( prompt );
         Simulation . getInstance (). display ( "" );
        
         String  input  =   Simulation . getInstance (). readInput ( Simulation . PIN_MODE ,   0 );
        
         Simulation . getInstance (). clearDisplay ();
        
         if   ( input  ==   null )
             throw   new   Cancelled ();
         else
             return   Integer . parseInt ( input );
     }
    
     /** Display a menu of options and return choice made by customer
     *
     *   @param  prompt message to display before the list of options
     *   @param  menu the options
     *   @return  the number of the option chosen (0 .. # of options - 1)
     *  Note: the options are numbered 1 .. # of options when displayed for the
     *  customer - but the menu array indices and the final result returned are in
     *  the range 0 .. # of options - 1
     *
     *   @exception  Cancelled if customer presses the CANCEL key before choosing option
     */
     public   synchronized   int  readMenuChoice ( String  prompt ,   String []  menu )   throws   Cancelled
     {
         Simulation . getInstance (). clearDisplay ();
         Simulation . getInstance (). display ( prompt );
         for   ( int  i  =   0 ;  i  <  menu . length ;  i  ++ )
             Simulation . getInstance (). display (( i + 1 )   +   ") "   +  menu [ i ]);

         String  input  =  
             Simulation . getInstance (). readInput ( Simulation . MENU_MODE ,  menu . length );
            
         Simulation . getInstance (). clearDisplay ();
        
         if   ( input  ==   null )
             throw   new   Cancelled ();
         else
             return   Integer . parseInt ( input )   -   1 ;
     }
    
     /** Read a money amount entered by the customer
     *
     *   @param  prompt the message to display prompting the customer to enter amount
     *   @return  the amount entered by the customer
     *   @exception  Cancelled if customer presses the CANCEL key before pressing ENTER
     */
     public   synchronized   Money  readAmount ( String  prompt )   throws   Cancelled
     {
         Simulation . getInstance (). clearDisplay ();
         Simulation . getInstance (). display ( prompt );
         Simulation . getInstance (). display ( "" );
        
         String  input  =   Simulation . getInstance (). readInput ( Simulation . AMOUNT_MODE ,   0 );
        
         Simulation . getInstance (). clearDisplay ();
        
         if   ( input  ==   null )
             throw   new   Cancelled ();
         else
         {
             int  dollars  =   Integer . parseInt ( input )   /   100 ;
             int  cents  =   Integer . parseInt ( input )   %   100 ;
             return   new   Money ( dollars ,  cents );
         }
     }
    
     /** Exception thrown when the user presses the cancel key while the ATM is
     *  waiting for some action
     */
     public   static   class   Cancelled   extends   Exception
     {
         /** Constructor
         */
         public   Cancelled ()
         {
             super ( "Cancelled by customer" );
         }
     }
}

ATM/src/atm/physical/EnvelopeAcceptor.java

ATM/src/atm/physical/EnvelopeAcceptor.java

/*
 * ATM Example system - file EnvelopeAcceptor.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;

import  simulation . Simulation ;

/** Manager for the ATM's envelope acceptor.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   EnvelopeAcceptor
{

     /** Constructor
     *
     *   @param  log the log in which to record receiving an envelope
     */
     public   EnvelopeAcceptor ( Log  log )
     {
         this . log  =  log ;
     }
    
     /** Accept an envelope from customer.
     *
     *   @exception  CustomerConsole.Cancelled if operation timed out or the
     *             customer cancelled it
     */
     public   void  acceptEnvelope ()   throws   CustomerConsole . Cancelled
     {
         boolean  inserted  =   Simulation . getInstance (). acceptEnvelope ();
         if   ( inserted )
            log . logEnvelopeAccepted ();
         else
             throw   new   CustomerConsole . Cancelled ();
     }
    
     /** Log in which to record receiving an envelope
     */
     private   Log  log ;
}

ATM/src/atm/physical/Log.java

ATM/src/atm/physical/Log.java

/*
 * ATM Example system - file Log.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;
import  simulation . Simulation ;

/** Manager for the ATM's internal log.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   Log
{
     /** Constructor
     */
     public   Log ()
     {
     }
    
     /** Log the sending of a message to the bank
     *
     *   @param  message the message to be logged
     */
     public   void  logSend ( Message  message )
     {
         Simulation . getInstance (). printLogLine ( "Message:   "   +  message . toString ());  
     }
    
     /** Log a response received from a message
     *
     *   @param  status the status object returned by the bank in response
     */
     public   void  logResponse ( Status  response )
     {
         Simulation . getInstance (). printLogLine ( "Response:  "   +  response . toString ());
     }
    
     /** Log the dispensing of cash by the cash dispenser
     *
     *   @param  amount the amount of cash being dispensed
     */
     public   void  logCashDispensed ( Money  amount )
     {
         Simulation . getInstance (). printLogLine ( "Dispensed: "   +  amount . toString ());
     }
    
     /** Log accepting an envelope.  This method is only called if an envelope
     *  is actually received from the customer
     */
     public   void  logEnvelopeAccepted ()
     {
         Simulation . getInstance (). printLogLine ( "Envelope:  received" );
     }
}

ATM/src/atm/physical/NetworkToBank.java

ATM/src/atm/physical/NetworkToBank.java

/*
 * ATM Example system - file NetworkToBank.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;

import  java . net . InetAddress ;

import  banking . Message ;
import  banking . Balances ;
import  banking . Status ;
import  simulation . Simulation ;

/** Manager for the ATM's network connection.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   NetworkToBank
{
     /** Constructor
     *
     *   @param  log the log in which to record sending of messages and responses
     *   @param  bankAddress the network address of the bank
     */
     public   NetworkToBank ( Log  log ,   InetAddress  bankAddress )
     {
         this . log  =  log ;
         this . bankAddress  =  bankAddress ;
     }
    
     /** Open connection to bank at system startup
     */
     public   void  openConnection ()
     {
         // Since the network is simulated, we don't have to do anything
     }
    
     /** Close connection to bank at system shutdown
     */
     public   void  closeConnection ()
     {
         // Since the network is simulated, we don't have to do anything
     }
    
     /** Send a message to bank
     *
     *   @param  message the message to send
     *   @param  balances (out) balances in customer's account as reported
     *         by bank
     *   @return  status code returned by bank
     */
     public   Status  sendMessage ( Message  message ,   Balances  balances )
     {
         // Log sending of the message
        
        log . logSend ( message );
        
         // Simulate the sending of the message - here is where the real code
         // to actually send the message over the network would go
        
         Status  result  =   Simulation . getInstance (). sendMessage ( message ,  balances );
        
         // Log the response gotten back
        
        log . logResponse ( result );
        
         return  result ;
     }
    
     // Log into which to record messages
    
     private   Log  log ;
    
     // Network address of the bank
    
     private   InetAddress  bankAddress ;
}

ATM/src/atm/physical/OperatorPanel.java

ATM/src/atm/physical/OperatorPanel.java

/*
 * ATM Example system - file OperatorPanel.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;
import  atm . ATM ;
import  banking . Money ;
import  simulation . Simulation ;

/** Manager for the ATM's operator panel.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   OperatorPanel
{
     /** Constructor
     *
     *   @param  atm the ATM this panel is part of
     */
     public   OperatorPanel ( ATM atm )
     {
         this . atm  =  atm ;
     }
    
     // In a real ATM, code would be needed to sense a change in the state of the
     // switch and notify the ATM - simulated in this case by a button in the GUI
    
     /** Get the amount of cash in the cash dispenser from the operator at start up
     *
     *   @return  dollar value of the bills in the cash dispenser (# of bills x $20)
     */
    
     public   Money  getInitialCash ()
     {
         return   Simulation . getInstance (). getInitialCash ();
     }
    
     /** ATM this panel is part of.  The ATM object will be notified when
     * the switch on the panel is turned on or off
     */
     private  ATM atm ;     
}

ATM/src/atm/physical/ReceiptPrinter.java

ATM/src/atm/physical/ReceiptPrinter.java

/*
 * ATM Example system - file ReceiptPrinter.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . physical ;

import  java . util . Enumeration ;

import  banking . Balances ;
import  banking . Receipt ;
import  simulation . Simulation ;

/** Manager for the ATM's receipt printer.  In a real ATM, this would 
 *  manage a physical device; in this simulation,  it uses classes 
 *  in package simulation to simulate the device.
 */
 
public   class   ReceiptPrinter
{
     /** Constructor
     */
     public   ReceiptPrinter ()
     {  
     }
    
     /** Print a receipt
     *
     *   @param  receipt object containing the information to be printed
     */
     public   void  printReceipt ( Receipt  receipt )
     {
         Enumeration  receiptLines  =  receipt . getLines ();
        
         // Animate the printing of the receipt

         while   ( receiptLines . hasMoreElements ())
         {
             Simulation . getInstance (). printReceiptLine (
                 (( String )  receiptLines . nextElement ()));
         }
     }
}

ATM/src/atm/Session.java

ATM/src/atm/Session.java

/*
 * ATM Example system - file Session.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm ;
import  banking . Card ;
import  banking . Status ;
import  banking . Receipt ;
import  atm . physical . CustomerConsole ;
import  atm . transaction . Transaction ;

/** Representation for one ATM session serving a single customer. */

public   class   Session
{
     /** Constructor
     *
     *   @param  atm the ATM on which the session is performed
     */
     public   Session ( ATM atm )
     {
         this . atm  =  atm ;
        
        state  =  READING_CARD_STATE ;
     }

     /** Perform the Session Use Case
     */
     public   void  performSession ()
     {
         Card  card  =   null ;
         Transaction  currentTransaction  =   null ;
        
         while   ( state  !=  FINAL_STATE )
         {
             switch ( state )
             {
                 case  READING_CARD_STATE :
                
                
                    card  =  atm . getCardReader (). readCard ();
                    
                     if   ( card  !=   null )
                        state  =  READING_PIN_STATE ;
                     else
                     {
                        atm . getCustomerConsole (). display ( "Unable to read card" );
                        state  =  EJECTING_CARD_STATE ;
                     }
                     break ;
                    
                 case  READING_PIN_STATE :
                
                     try
                     {
                        pin  =  atm . getCustomerConsole (). readPIN (
                             "Please enter your PIN\n"   +
                             "Then press ENTER" );
                        state  =  CHOOSING_TRANSACTION_STATE ;
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                        state  =  EJECTING_CARD_STATE ;
                     }
                     break ;
                
                 case  CHOOSING_TRANSACTION_STATE :
                
                     try
                     {
                        currentTransaction  =  
                             Transaction . makeTransaction ( atm ,   this ,  card ,  pin );
                        state  =  PERFORMING_TRANSACTION_STATE ;
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                        state  =  EJECTING_CARD_STATE ;
                     }
                     break ;
                    
                 case  PERFORMING_TRANSACTION_STATE :
                
                     try
                     {
                         boolean  doAgain  =  
                            currentTransaction . performTransaction ();
                         if   ( doAgain )
                            state  =  CHOOSING_TRANSACTION_STATE ;
                         else
                            state  =  EJECTING_CARD_STATE ;
                     }
                     catch ( Transaction . CardRetained  e )
                     {
                        state  =  FINAL_STATE ;
                     }
                     break ;
                    
                 case  EJECTING_CARD_STATE :
                
                    atm . getCardReader (). ejectCard ();
                    state  =  FINAL_STATE ;
                     break ;
             }
         }
     }
    
     /** Change the pin recorded for the customer (if invalid pin extension
     *  was performed by a transaction
     *
     *   @param  pin the newly entered pin
     */
     public   void  setPIN ( int  pin )
     {
         this . pin  =  pin ;
     }
    

     // Instance variables


     /** The ATM on which the session is performed
     */
     private  ATM atm ;
    
     /** The PIN entered (or re-entered) by the customer
     */
     private   int  pin ;

     /** The current state of the session
     */
     private   int  state ;
    
     // Possible values for state
    
     /** Reading the customer's card
     */
     private   static   final   int  READING_CARD_STATE  =   1 ;
    
     /** Asking the customer to enter a PIN
     */
     private   static   final   int  READING_PIN_STATE  =   2 ;
    
     /** Asking the customer to choose a transaction type
     */
     private   static   final   int  CHOOSING_TRANSACTION_STATE  =   3 ;
    
     /** Peforming a transaction
     */
     private   static   final   int  PERFORMING_TRANSACTION_STATE  =   4 ;
    
     /** Ejecting the customer's card
     */
     private   static   final   int  EJECTING_CARD_STATE  =   5 ;
    
     /** Session finished
     */
     private   static   final   int  FINAL_STATE  =   6 ;
    
}

ATM/src/atm/transaction/Deposit.java

ATM/src/atm/transaction/Deposit.java

/*
 * ATM Example system - file Deposit.java   
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . transaction ;
import  atm . ATM ;
import  atm . Session ;
import  atm . physical . * ;
import  banking . AccountInformation ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;
import  banking . Receipt ;

/** Representation for a deposit transaction
 */
public   class   Deposit   extends   Transaction
{
     /** Constructor
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which the transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     */
     public   Deposit ( ATM atm ,   Session  session ,   Card  card ,   int  pin )
     {
         super ( atm ,  session ,  card ,  pin );
     }
    
     /** Get specifics for the transaction from the customer
     *
     *   @return  message to bank for initiating this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   Message  getSpecificsFromCustomer ()   throws   CustomerConsole . Cancelled
     {
        to  =  atm . getCustomerConsole (). readMenuChoice (
             "Account to deposit to" ,
             AccountInformation . ACCOUNT_NAMES );

        amount  =  atm . getCustomerConsole (). readAmount ( "Amount to deposit" );
        
         return   new   Message ( Message . INITIATE_DEPOSIT ,
                           card ,  pin ,  serialNumber ,   - 1 ,  to ,  amount );
     }
    
     /** Complete an approved transaction
     *
     *   @return  receipt to be printed for this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled or 
     *             transaction timed out
     */
     protected   Receipt  completeTransaction ()   throws   CustomerConsole . Cancelled
     {
        atm . getEnvelopeAcceptor (). acceptEnvelope ();
         Status  status  =  atm . getNetworkToBank (). sendMessage (
             new   Message ( Message . COMPLETE_DEPOSIT ,
                        card ,  pin ,  serialNumber ,   - 1 ,  to ,  amount ),  
            balances );
            
         return   new   Receipt ( this . atm ,   this . card ,   this ,   this . balances )   {
             {
                detailsPortion  =   new   String [ 2 ];
                detailsPortion [ 0 ]   =   "DEPOSIT TO: "   +  
                                     AccountInformation . ACCOUNT_ABBREVIATIONS [ to ];
                detailsPortion [ 1 ]   =   "AMOUNT: "   +  amount . toString ();
             }
         };
     }
    
     /** Account to deposit to
     */  
     private   int  to ;
    
     /** Amount of money to deposit
     */
     private   Money  amount ;
            
}

ATM/src/atm/transaction/Inquiry.java

ATM/src/atm/transaction/Inquiry.java

/*
 * ATM Example system - file Inquiry.java   
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . transaction ;
import  atm . ATM ;
import  atm . Session ;
import  atm . physical . * ;
import  banking . AccountInformation ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;
import  banking . Receipt ;

/** Representation for a balance inquiry transaction
 */
public   class   Inquiry   extends   Transaction
{
     /** Constructor
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which the transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     */
     public   Inquiry ( ATM atm ,   Session  session ,   Card  card ,   int  pin )
     {
         super ( atm ,  session ,  card ,  pin );
     }
    
     /** Get specifics for the transaction from the customer
     *
     *   @return  message to bank for initiating this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   Message  getSpecificsFromCustomer ()   throws   CustomerConsole . Cancelled
     {
        from  =  atm . getCustomerConsole (). readMenuChoice (
             "Account to inquire from" ,
             AccountInformation . ACCOUNT_NAMES );
         return   new   Message ( Message . INQUIRY ,  
                        card ,  pin ,  serialNumber ,  from ,   - 1 ,   new   Money ( 0 ));
     }
    
     /** Complete an approved transaction
     *
     *   @return  receipt to be printed for this transaction
     */
     protected   Receipt  completeTransaction ()
     {
         return   new   Receipt ( this . atm ,   this . card ,   this ,   this . balances )   {
             {
                detailsPortion  =   new   String [ 2 ];
                detailsPortion [ 0 ]   =   "INQUIRY FROM: "   +  
                                     AccountInformation . ACCOUNT_ABBREVIATIONS [ from ];
                detailsPortion [ 1 ]   =   "" ;
             }
         };
     }
    
     /** Account to inquire about
     */
     private   int  from ;
    
}

ATM/src/atm/transaction/Transaction.java

ATM/src/atm/transaction/Transaction.java

/*
 * ATM Example system - file Transaction.java   
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . transaction ;
import  atm . ATM ;
import  atm . Session ;
import  atm . physical . * ;
import  banking . Balances ;
import  banking . Card ;
import  banking . Message ;
import  banking . Status ;
import  banking . Receipt ;

/** Abstract base class for classes representing the various kinds of
 *  transaction the ATM can perform
 */
public   abstract   class   Transaction
{
     /** Constructor
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which this transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     */
     
     protected   Transaction ( ATM atm ,   Session  session ,   Card  card ,   int  pin )
     {
         this . atm  =  atm ;
         this . session  =  session ;
         this . card  =  card ;
         this . pin  =  pin ;
         this . serialNumber  =  nextSerialNumber  ++ ;
         this . balances  =   new   Balances ();
        
        state  =  GETTING_SPECIFICS_STATE ;
     }
         
     /** Create a transaction of an appropriate type by asking the customer
     *  what type of transaction is desired and then returning a newly-created
     *  member of the appropriate subclass
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which this transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     *   @return  a newly created Transaction object of the appropriate type
     *   @exception  CustomerConsole.Cancelled if the customer presses cancel instead
     *         of choosing a transaction type
     */
     public   static   Transaction  makeTransaction ( ATM atm ,   Session  session ,
                                               Card  card ,   int  pin )
                                 throws   CustomerConsole . Cancelled               
     {
         int  choice  =  atm . getCustomerConsole (). readMenuChoice (
                 "Please choose transaction type" ,  TRANSACTION_TYPES_MENU );
                
         switch ( choice )
         {
             case   0 :
            
                 return   new   Withdrawal ( atm ,  session ,  card ,  pin );
                
             case   1 :
            
                 return   new   Deposit ( atm ,  session ,  card ,  pin );
                
             case   2 :
            
                 return   new   Transfer ( atm ,  session ,  card ,  pin );
                
             case   3 :
            
                 return   new   Inquiry ( atm ,  session ,  card ,  pin );
                
             default :
            
                 return   null ;      // To keep compiler happy - should not happen!
         }
     }
    
     /** Peform a transaction.  This method depends on the three abstract methods
     *  that follow to perform the operations unique to each type of transaction
     *  in the appropriate way.
     *
     *   @return  true if customer indicates a desire to do another transaction;
     *          false if customer does not desire to do another transaction
     *   @exception  CardRetained if card was retained due to too many invalid PIN's
     */
     public   boolean  performTransaction ()   throws   CardRetained
     {
         String  doAnotherMessage  =   "" ;
         Status  status  =   null ;
         Receipt  receipt  =   null ;
        
         while   ( true )      // Terminates by return in ASKING_DO_ANOTHER_STATE or exception
         {
             switch ( state )
             {
                 case  GETTING_SPECIFICS_STATE :
                
                     try
                     {            
                        message  =  getSpecificsFromCustomer ();
                        atm . getCustomerConsole (). display ( "" );
                        state  =  SENDING_TO_BANK_STATE ;
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                        doAnotherMessage  =   "Last transaction was cancelled" ;
                        state  =  ASKING_DO_ANOTHER_STATE ;
                     }
                    
                     break ;
                    
                 case  SENDING_TO_BANK_STATE :
                                
                    status  =  atm . getNetworkToBank (). sendMessage ( message ,  balances );
                
                     if   ( status . isInvalidPIN ())
                        state  =  INVALID_PIN_STATE ;
                     else   if   ( status . isSuccess ())
                        state  =  COMPLETING_TRANSACTION_STATE ;
                     else
                     {
                        doAnotherMessage  =  status . getMessage ();
                        state  =  ASKING_DO_ANOTHER_STATE ;
                     }
                    
                     break ;
                
                 case  INVALID_PIN_STATE :
                
                     try
                     {
                        status  =  performInvalidPINExtension ();
                    
                         // If customer repeatedly enters invalid PIN's, a
                         // CardRetained exception is thrown, and this method
                         // terminates
                        
                         if   ( status . isSuccess ())
                            state  =  COMPLETING_TRANSACTION_STATE ;
                         else
                         {
                            doAnotherMessage  =  status . getMessage ();
                            state  =  ASKING_DO_ANOTHER_STATE ;
                         }
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                        doAnotherMessage  =   "Last transaction was cancelled" ;
                        state  =  ASKING_DO_ANOTHER_STATE ;
                     }

                     break ;
                        
                 case  COMPLETING_TRANSACTION_STATE :

                     try
                     {
                        receipt  =  completeTransaction ();
                        state  =  PRINTING_RECEIPT_STATE ;
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                        doAnotherMessage  =   "Last transaction was cancelled" ;
                        state  =  ASKING_DO_ANOTHER_STATE ;
                     }
                    
                     break ;
                    
                 case  PRINTING_RECEIPT_STATE :
                
                    atm . getReceiptPrinter (). printReceipt ( receipt );
                    state  =  ASKING_DO_ANOTHER_STATE ;
                    
                     break ;
                    
                 case  ASKING_DO_ANOTHER_STATE :
                
                     if   ( doAnotherMessage . length ()   >   0 )
                        doAnotherMessage  +=   "\n" ;
                        
                     try
                     {
                         String   []  yesNoMenu  =   {   "Yes" ,   "No"   };

                         boolean  doAgain  =  atm . getCustomerConsole (). readMenuChoice (
                            doAnotherMessage  +  
                             "Would you like to do another transaction?" ,
                            yesNoMenu )   ==   0 ;
                         return  doAgain ;
                     }
                     catch ( CustomerConsole . Cancelled  e )
                     {
                         return   false ;
                     }
             }
         }
     }
        
    
     /** Perform the Invalid PIN Extension - reset session pin to new value if successful
     *
     *   @return  status code returned by bank from most recent re-submission
     *          of transaction
     *   @exception  CustomerConsole.Cancelled if customer presses the CANCEL key
     *             instead of re-entering PIN
     *   @exception  CardRetained if card was retained due to too many invalid PIN's
     */
     public   Status  performInvalidPINExtension ()   throws   CustomerConsole . Cancelled ,
                                                       CardRetained
     {
         Status  status  =   null ;
         for   ( int  i  =   0 ;  i  <   3 ;  i  ++ )
         {
            pin  =  atm . getCustomerConsole (). readPIN (
                 "PIN was incorrect\nPlease re-enter your PIN\n"   +
                 "Then press ENTER" );
            atm . getCustomerConsole (). display ( "" );
            
            message . setPIN ( pin );
            status  =  atm . getNetworkToBank (). sendMessage ( message ,  balances );
             if   ( !  status . isInvalidPIN ())
             {
                session . setPIN ( pin );
                 return  status ;
             }
         }
        
        atm . getCardReader (). retainCard ();
        atm . getCustomerConsole (). display (
             "Your card has been retained\nPlease contact the bank." );
         try
         {
             Thread . sleep ( 5000 );
         }
         catch ( InterruptedException  e )
         {   }
        atm . getCustomerConsole (). display ( "" );
                
         throw   new   CardRetained ();
     }
    

     /** Get serial number of this transaction
     *
     *   @return  serial number
     */
     public   int  getSerialNumber ()
     {
         return  serialNumber ;
     }
    
     /** Get specifics for the transaction from the customer - each
     *  subclass must implement this appropriately.
     *
     *   @return  message to bank for initiating this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   abstract   Message  getSpecificsFromCustomer ()   throws   CustomerConsole . Cancelled ;
    
     /** Complete an approved transaction  - each subclass must implement
     *  this appropriately.
     *
     *   @return  receipt to be printed for this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   abstract   Receipt  completeTransaction ()   throws   CustomerConsole . Cancelled ;
    
    
     // Local class representing card retained exception
   
    
     /** Exception that is thrown when the customer's card is retained due to too
     *  many invalid PIN entries
     */
     public   static   class   CardRetained   extends   Exception
     {
         /** Constructor
         */
         public   CardRetained ()
         {
             super ( "Card retained due to too many invalid PINs" );
         }
     }
    
    
     // Instance variables


     /** ATM to use for communication with the customer
     */
     protected  ATM atm ;
    
     /** Session in which this transaction is being performed
     */
     protected   Session  session ;
    
     /** Customer card for the session this transaction is part of
     */
     protected   Card  card ;
    
     /** PIN entered or re-entered by customer
     */
     protected   int  pin ;
    
     /** Serial number of this transaction
     */
     protected   int  serialNumber ;
    
     /** Message to bank describing this transaction
     */
     protected   Message  message ;
    
     /** Used to return account balances from the bank
     */
     protected   Balances  balances ;
    
     /** List of available transaction types to display as a menu
     */
     private   static   final   String   []  TRANSACTION_TYPES_MENU  =  
         {   "Withdrawal" ,   "Deposit" ,   "Transfer" ,   "Balance Inquiry"   };
        
     /** Next serial number - used to assign a unique serial number to
     *  each transaction
     */
     private   static   int  nextSerialNumber  =   1 ;
    
     /** The current state of the transaction
     */
     private   int  state ;
    
     // Possible values for state
    
     /** Getting specifics of the transaction from customer
     */
     private   static   final   int  GETTING_SPECIFICS_STATE  =   1 ;
    
     /** Sending transaction to bank
     */
     private   static   final   int  SENDING_TO_BANK_STATE  =   2 ;
    
     /** Performing invalid PIN extension
     */
     private   static   final   int  INVALID_PIN_STATE  =   3 ;
    
     /** Completing transaction
     */
     private   static   final   int  COMPLETING_TRANSACTION_STATE  =   4 ;
    
     /** Printing receipt
     */
     private   static   final   int  PRINTING_RECEIPT_STATE  =   5 ;
    
     /** Asking if customer wants to do another transaction
     */
     private   static   final   int  ASKING_DO_ANOTHER_STATE  =   6 ;
}

ATM/src/atm/transaction/Transfer.java

ATM/src/atm/transaction/Transfer.java

/*
 * ATM Example system - file Transfer.java  
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . transaction ;
import  atm . ATM ;
import  atm . Session ;
import  atm . physical . * ;
import  banking . AccountInformation ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;
import  banking . Receipt ;

/** Representation for a transfer transaction
 */
public   class   Transfer   extends   Transaction
{
     /** Constructor
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which the transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     */
     public   Transfer ( ATM atm ,   Session  session ,   Card  card ,   int  pin )
     {
         super ( atm ,  session ,  card ,  pin );
     }
    
     /** Get specifics for the transaction from the customer
     *
     *   @return  message to bank for initiating this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   Message  getSpecificsFromCustomer ()   throws   CustomerConsole . Cancelled
     {
        from  =  atm . getCustomerConsole (). readMenuChoice (
             "Account to transfer from" ,
             AccountInformation . ACCOUNT_NAMES );

        to  =  atm . getCustomerConsole (). readMenuChoice (
             "Account to transfer to" ,
             AccountInformation . ACCOUNT_NAMES );

        amount  =  atm . getCustomerConsole (). readAmount ( "Amount to transfer" );
        
         return   new   Message ( Message . TRANSFER ,  
                        card ,  pin ,  serialNumber ,  from ,  to ,  amount );
     }
    
     /** Complete an approved transaction
     *
     *   @return  receipt to be printed for this transaction
     */
     protected   Receipt  completeTransaction ()
     {
         return   new   Receipt ( this . atm ,   this . card ,   this ,   this . balances )   {
             {
                detailsPortion  =   new   String [ 2 ];
                detailsPortion [ 0 ]   =   "TRANSFER FROM: "   +  
                                     AccountInformation . ACCOUNT_ABBREVIATIONS [ from ]   +
                                     " TO: "   +  
                                     AccountInformation . ACCOUNT_ABBREVIATIONS [ to ]   ;
                detailsPortion [ 1 ]   =   "AMOUNT: "   +  amount . toString ();
             }
         };
     }
    
     /** Accounts to transfer from
     */
     private   int  from ;
    
     /** Account to transfer to
     */
     private   int  to ;
    
     /** Amount of money to transfer
     */
     private   Money  amount ;            
}

ATM/src/atm/transaction/Withdrawal.java

ATM/src/atm/transaction/Withdrawal.java

/*
 * ATM Example system - file Withdrawal.java    
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  atm . transaction ;
import  atm . ATM ;
import  atm . Session ;
import  atm . physical . * ;
import  banking . AccountInformation ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;
import  banking . Receipt ;

/** Representation for a cash withdrawal transaction
 */
public   class   Withdrawal   extends   Transaction
{
     /** Constructor
     *
     *   @param  atm the ATM used to communicate with customer
     *   @param  session the session in which the transaction is being performed
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     */
     public   Withdrawal ( ATM atm ,   Session  session ,   Card  card ,   int  pin )
     {
         super ( atm ,  session ,  card ,  pin );
     }
    
     /** Get specifics for the transaction from the customer
     *
     *   @return  message to bank for initiating this transaction
     *   @exception  CustomerConsole.Cancelled if customer cancelled this transaction
     */
     protected   Message  getSpecificsFromCustomer ()   throws   CustomerConsole . Cancelled
     {
        from  =  atm . getCustomerConsole (). readMenuChoice (
             "Account to withdraw from" ,
             AccountInformation . ACCOUNT_NAMES );

         String   []  amountOptions  =   {   "$20" ,   "$40" ,   "$60" ,   "$100" ,   "$200"   };
         Money   []  amountValues  =   {  
                                   new   Money ( 20 ),   new   Money ( 40 ),   new   Money ( 60 ),
                                   new   Money ( 100 ),   new   Money ( 200 )
                                 };
                                  
         String  amountMessage  =   "" ;
         boolean  validAmount  =   false ;
        
         while   ( !  validAmount )
         {
            amount  =  amountValues  [  
                atm . getCustomerConsole (). readMenuChoice (
                    amountMessage  +   "Amount of cash to withdraw" ,  amountOptions )   ];
                            
            validAmount  =  atm . getCashDispenser (). checkCashOnHand ( amount );

             if   ( !  validAmount )
                amountMessage  =   "Insufficient cash available\n" ;
         }
        
         return   new   Message ( Message . WITHDRAWAL ,  
                           card ,  pin ,  serialNumber ,  from ,   - 1 ,  amount );

     }
    
     /** Complete an approved transaction
     *
     *   @return  receipt to be printed for this transaction
     */
     protected   Receipt  completeTransaction ()
     {
        atm . getCashDispenser (). dispenseCash ( amount );
         return   new   Receipt ( this . atm ,   this . card ,   this ,   this . balances )   {
             {
                detailsPortion  =   new   String [ 2 ];
                detailsPortion [ 0 ]   =   "WITHDRAWAL FROM: "   +  
                                     AccountInformation . ACCOUNT_ABBREVIATIONS [ from ];
                detailsPortion [ 1 ]   =   "AMOUNT: "   +  amount . toString ();
             }
         };
     }
    
     /** Account to withdraw from
     */  
     private   int  from ;
    
     /** Amount of money to withdraw
     */
     private   Money  amount ;            
}

ATM/src/banking/AccountInformation.java

ATM/src/banking/AccountInformation.java

/*
 * ATM Example system - file AccountInformation.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** The static members of this class incorporate information about accounts
 *  offered by the bank.  Actual communication with the bank uses account type
 *  numbers - e.g. 0 represents the first type of account listed. 
 */
public   class   AccountInformation
{
     /** Names for accounts to be offered in menu to customer
     */
     public   static   final   String   []  ACCOUNT_NAMES  =
          {   "Checking" ,   "Savings" ,   "Money Market"   };
         
     /** Abbreviations for account names to be printed on receipts.
     */
     public   static   final   String   []  ACCOUNT_ABBREVIATIONS  =
         {   "CHKG" ,   "SVGS" ,   "MMKT"   };
}     

ATM/src/banking/Balances.java

ATM/src/banking/Balances.java

/*
 * ATM Example system - file Balances.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** Representation for customer's current account balances as returned by the 
 *  bank.  An empty object of this class is created and sent along with the
 *  transaction message; the bank fills it in with values.
 */

public   class   Balances
{
     /** Constructor.  Create an object whose values will be filled in later, when
     *  returning a value to the creator.
     */
     public   Balances ()
     {
     }
    
     /** Mutator.  Fill in values
     *
     *   @param  total the total balance in the account
     *   @param  available the available balance
     */
     public   void  setBalances ( Money  total ,   Money  available )
     {
         this . total  =  total ;
         this . available  =  available ;
     }
    
     /** Accessor for total balance
     *
     *   @return  total balance in the account
     */
     public   Money  getTotal ()
     {
         return  total ;
     }
    
     /** Accessor for available balance
     *
     *   @return  available balance
     */
     public   Money  getAvailable ()
     {
         return  available ;
     }
    
     // Instance variables
    
     /** Current total balance in the account 
    */
     private   Money  total ;
    
     /** Current available balance in the account
     */
     private   Money  available ;
}

ATM/src/banking/Card.java

ATM/src/banking/Card.java

/*
 * ATM Example system - file Card.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** Representation for customer's ATM card
 */
public   class   Card
{
     /** Constructor
     *
     *   @param  number the card number
     */
     public   Card ( int  number )
     {
         this . number  =  number ;
     }
    
     /** Accessor for number
     *
     *   @return  the number of the card
     */
     public   int  getNumber ()
     {
         return  number ;
     }
    
     /** Card number encoded on the card
     */
     private   int  number ;
}

ATM/src/banking/Message.java

ATM/src/banking/Message.java

/*
 * ATM Example system - file Message.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** Representations of a message from the ATM to the bank.
 *  Messages to the bank use a fixed format with fixed slots, not all of which
 *  pertain to any given type of transaction.  Each type of transaction creates
 *  one or more subclasses using the slots that it needs, and supplying appropriate
 *  "not needed" values for the rest.
 */
public   class   Message
{
     /** Constructor
     *
     *   @param  messageCode identifying the type of message
     *   @param  card the customer's card
     *   @param  pin the PIN entered by the customer
     *   @param  serialNumber serial number of the transaction
     *   @param  fromAccount the type of the "from" account of the transaction - can
     *         be -1 if the particular type of transaction does not have a "from"
     *         account (e.g. a deposit) 
     *   @param  toAccount the type of the "to" account of the transaction - can
     *         be -1 if the particular type of transaction does not have a "to"
     *         account (e.g. a withdrawal)
     *   @param  amount the amount of the transaction - can be null if the particular
     *         type of transaction does not have an amount (e.g. an inquiry)
     */
     public   Message ( int  messageCode ,   Card  card ,   int  pin ,  
                    int  serialNumber ,   int  fromAccount ,   int  toAccount ,   Money  amount )
     {
         this . messageCode  =  messageCode ;
         this . card  =  card ;
         this . pin  =  pin ;
         this . serialNumber  =  serialNumber ;
         this . fromAccount  =  fromAccount ;
         this . toAccount  =  toAccount ;
         this . amount  =  amount ;
     }
    
     /** Create a printable string representing this message
     *
     *   @return  string representation
     */
     public   String  toString ()
     {
         String  result  =   "" ;
        
         switch   ( messageCode )
         {
             case  WITHDRAWAL :
            
                result  +=   "WITHDRAW" ;
                 break ;
                
             case  INITIATE_DEPOSIT :
            
                result  +=   "INIT_DEP" ;
                 break ;
                
             case  COMPLETE_DEPOSIT :
            
                result  +=   "COMP_DEP" ;
                 break ;
                
             case  TRANSFER :
            
                result  +=   "TRANSFER" ;
                 break ;
                
             case  INQUIRY :
            
                result  +=   "INQUIRY " ;
                 break ;
         }
        
        result  +=   " CARD# "   +  card . getNumber ();
        result  +=   " TRANS# "   +  serialNumber ;
         if   ( fromAccount  >=   0 )
            result  +=   " FROM  "   +  fromAccount ;
         else
            result  +=   " NO FROM" ;
         if   ( toAccount  >=   0 )
            result  +=   " TO  "   +  toAccount ;
         else
            result  +=   " NO TO" ;
         if   ( !  amount . lessEqual ( new   Money ( 0 )))
            result  +=   " "   +  amount ;
         else
            result  +=   " NO AMOUNT" ;
        
         return  result ;
     }  
                
     /** Set PIN to a new value (if original pin was invalid and customer is
     *  asked to re-enter PIN)
     *
     *   @param  pin the new pin to set
     */
     public   void  setPIN ( int  pin )
     {
         this . pin  =  pin ;
     }
    
     /** Accessor for message code
     *
     *   @return  the code identifying the type of message
     */
     public   int  getMessageCode ()
     {
         return  messageCode ;
     }
    
     /** Accessor for customer's card
     *
     *   @return  the customer's card
     */
     public   Card  getCard ()
     {
         return  card ;
     }
    
     /** Accessor for PIN
     *
     *   @return  the PIN entered by the customer
     */
     public   int  getPIN ()
     {
         return  pin ;
     }
    
     /** Accessor for transaction serial number
     *
     *   @return  the serial number of the transaction
     */
     public   int  getSerialNumber ()
     {
         return  serialNumber ;
     }
    
     /** Accessor for "from" account
     *
     *   @return  the type of the "from" account
     */
     public   int  getFromAccount ()
     {
         return  fromAccount ;
     }
    
     /** Accessor for "to" account
     *
     *   @return  the type of the "to" account
     */
     public   int  getToAccount ()
     {
         return  toAccount ;
     }
    
     /** Accessor for acmount
     *
     *   @return  the transaction amount
     */
     public   Money  getAmount ()
     {
         return  amount ;
     }
    

     // Possible values for messageCode
    

     /** messageCode value for a cash withdrawal message
     */  
     public   static   final   int  WITHDRAWAL  =   0 ;
    
     /** messageCode value for a message initiating a deposit
     */  
     public   static   final   int  INITIATE_DEPOSIT  =   1 ;
    
     /** messageCode value for a message completing a deposit (envelope received).
     */  
     public   static   final   int  COMPLETE_DEPOSIT  =   2 ;
    
     /** messageCode value for a transfer between accounts message
     */  
     public   static   final   int  TRANSFER  =   3 ;
    
     /** messageCode value for an inquiry message
     */  
     public   static   final   int  INQUIRY  =   4 ;


     // Fixed slots in the message - may not all be used for any given message


     /** Code identifying the type of message - one of the above values
     */
     private   int  messageCode ;
    
     /** The customer's card
     */
     private   Card  card ;
    
     /** PIN entered by customer
     */
     private   int  pin ;
    
     /** Serial number of the transaction
     */
     private   int  serialNumber ;
    
     /** "From" account specified by customer - if needed (else - 1)
     */
     private   int  fromAccount ;
    
     /** "To" account specified by customer - if needed (else - 1)
     */
     private   int  toAccount ;
    
     /** Transaction amount specified by customer - if needed (else $0.00)
     */
     private   Money  amount ;
}

ATM/src/banking/Money.java

ATM/src/banking/Money.java

/*
 * ATM Example system - file Money.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** Representation for money amounts */

public   class   Money
{
     /** Constructor
     *
     *   @param  dollars whole dollar amount
     */
     public   Money ( int  dollars )
     {
         this ( dollars ,   0 );
     }
    
     /** Constructor
     *
     *   @param  dollars dollar part of amount
     *   @param  cents cents part of amount
     */
     public   Money ( int  dollars ,   int  cents )
     {
         this . cents  =   100L   *  dollars  +  cents ;
     }
    
     /** Copy constructor
     *
     *   @param  toCopy the Money object to copy
     */
     public   Money ( Money  toCopy )
     {
         this . cents  =  toCopy . cents ;
     }
    
     /** Create a string representation of this amount
     *
     *   @return  string representation of this amount
     */
     public   String  toString ()
     {
         return   "$"   +  cents / 100   +  
             ( cents  % 100   >=   10    ?   "."   +  cents  %   100   :   ".0"   +  cents  %   100 );
     }
    
     /** Add an amount of money to this
     *
     *   @param  amountToAdd the amount to add
     */
     public   void  add ( Money  amountToAdd )
     {
         this . cents  +=  amountToAdd . cents ;
     }
    
     /** Subtract an amount of money from this
     *
     *   @param  amountToSubtract the amount to subtract
     *
     *  Precondition: amount must be <= this amount
     */
     public   void  subtract ( Money  amountToSubtract )
     {
         this . cents  -=  amountToSubtract . cents ;
     }
    
     /** Compare this to another amount
     *
     *   @param  compareTo the amount to compare to
     *   @return  true if this amount is <= compareTo amount
     */
     public   boolean  lessEqual ( Money  compareTo )
     {
         return   this . cents  <=  compareTo . cents ;
     }
    
     /** Instance variable: this amount represented as a number of cents 
     */
     private   long  cents ;  
}

ATM/src/banking/Receipt.java

ATM/src/banking/Receipt.java

/*
 * ATM Example system - file Receipt.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;
import  atm . ATM ;
import  atm . transaction . Transaction ;

import  java . util . Date ;
import  java . util . Enumeration ;

/** Abstract base class for representation of a receipt to be printed.  Each
 *  specific type of transaction creates an instance of a concrete subclass
 *  of this class.  
 */

public   abstract   class   Receipt
{
     /** Constructor.  This base class constructor will create the portions of the
     *  receipt that are common to all types of transaction, and the subclass
     *  constructor will create the details portion unique to each type.
     *
     *   @param  atm the ATM where the transaction was done
     *   @param  card the card that was used
     *   @param  transaction the Transaction object for the transaction
     *   @param  balances Balances object giving final balances for account used
     */
     
     protected   Receipt ( ATM atm ,   Card  card ,   Transaction  transaction ,   Balances  balances )
     {
         // Heading portion of the receipt
        
        headingPortion  =   new   String [ 4 ];
        headingPortion [ 0 ]   =   new   Date (). toString ();
        headingPortion [ 1 ]   =  atm . getBankName ();
        headingPortion [ 2 ]   =   "ATM #"   +  atm . getID ()   +   " "   +  atm . getPlace ();
        headingPortion [ 3 ]   =   "CARD "   +  card . getNumber ()   +  
                      " TRANS #"   +  transaction . getSerialNumber ();

         // The constructor for each subclass will fill in the details array
         // appropriately
        
         // Balances portion of the receipt
        
        balancesPortion  =   new   String [ 2 ];
        balancesPortion [ 0 ]   =   "TOTAL BAL: "   +  balances . getTotal ();
        balancesPortion [ 1 ]   =   "AVAILABLE: "   +  balances . getAvailable ();
     }

     /** Get the individual lines to be printed.  Each call to the nextElement()
     *  of the enumeration gets one line (as a String)
     */
     
     public   Enumeration  getLines ()
     {
         return   new   Enumeration ()   {
        
             // The current portion of the receipt being printed
            
             private   int  portion  =   0 ;
            
             // The index of the line in the current portion
            
             private   int  index  =   0 ;
            
             public   boolean  hasMoreElements ()
             {
                 return  portion  <   2   ||  index  <  balancesPortion . length ;
             }
            
             public   Object  nextElement ()
             {
                 String  line  =   null ;
                
                 switch   ( portion )
                 {
                     case   0 :
                    
                        line  =  headingPortion [ index  ++ ];
                         if   ( index  >=  headingPortion . length )
                         {
                            portion  ++ ;
                            index  =   0 ;
                         }
                         break ;
                    
                     case   1 :
                    
                        line  =  detailsPortion [ index  ++ ];
                         if   ( index  >=  detailsPortion . length )
                         {
                            portion  ++ ;
                            index  =   0 ;
                         }
                         break ;
                        
                     case   2 :
                    
                        line  =  balancesPortion [ index  ++ ];
                         break ;
                 }
                 return  line ;
             }
         };
     }


     // Instance variables


     /** Heading portion of the receipt - common to all forms of receipt
     */
     private   String   []  headingPortion ;
    
     /** Transaction details portion of the receipt - specific to each type of
     *  transaction, and therefore filled in by subclasses
     */
     protected   String   []  detailsPortion ;
    
     /** Ending balances portion of the receipt - common to all forms of receipt
     */
     private   String   []  balancesPortion ;   
}

ATM/src/banking/Status.java

ATM/src/banking/Status.java

/*
 * ATM Example system - file Status.java    
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  banking ;

/** Abstract base class for representation of various status codes returned
 *  by bank for a transaction.  The bank will create appropriate subclasses.
 */
public   abstract   class   Status
{
     /** Create a printable string representing this status
     *
     *   @return  string representation
     */
     public   String  toString ()
     {
         if   ( isSuccess ())
             return   "SUCCESS" ;
         else   if   ( isInvalidPIN ())
             return   "INVALID PIN" ;
         else
             return   "FAILURE "   +  getMessage ();
     }
    
     /** See if this status represents success
     *
     *   @return  true if this status represents success
     */
     public   abstract   boolean  isSuccess ();
    
     /** See if this status represents an invalid PIN
     *
     *   @return  true if this status represents an invalid PIN
     */
     public   abstract   boolean  isInvalidPIN ();
    
     /** Accessor for message describing this status (used if status is
     *  not success)
     *
     *   @return  description of the problem
     */
     public   abstract   String  getMessage ();
}

ATM/src/main/ATMApplet.java

ATM/src/main/ATMApplet.java

package  main ;

/*
 * ATM Example system - file ATMApplet.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
import  java . awt . * ;
import  java . applet . Applet ;
import  atm . ATM ;
import  simulation . Simulation ;

/** Applet class for the applet version of the ATM simulation.
 *  Create an instance of the ATM, display in the applet, and then let the GUI
 *  do the work.
 */
 
public   class   ATMApplet   extends   Applet
{
     public   void  init ()
     {
         // Create the ATM software and the software that simulates it via a GUI
        
        ATM theATM  =   new  ATM ( 42 ,   "Gordon College" ,   "First National Bank of Podunk" ,
                              null   /* We're not really talking to a bank! */ );
         Simulation  theSimulation  =   new   Simulation ( theATM );
        
         // Start the Thread that runs the ATM
        
         new   Thread ( theATM ). start ();
        
         // Display the simulation's GUI in this applet
        
         Panel  gui  =  theSimulation . getGUI ();
        setBackground ( gui . getBackground ());
        add ( gui );
     }
}
    

ATM/src/main/ATMMain.java

ATM/src/main/ATMMain.java

package  main ;

/*
 * ATM Example system - file ATMMain.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 

import  java . awt . * ;
import  java . awt . event . * ;
import  atm . ATM ;
import  simulation . Simulation ;

/** Main program class for the application version of the ATM simulation.
 *  Create an instance of the ATM, put it in a frame, and then let the GUI
 *  do the work.
 */
 
public   class   ATMMain
{
     public   static   void  main ( String []  args )
     {
        ATM theATM  =   new  ATM ( 42 ,   "Gordon College" ,   "First National Bank of Podunk" ,
                              null   /* We're not really talking to a bank! */ );
         Simulation  theSimulation  =   new   Simulation ( theATM );
        
         // Create the frame that will display the simulated ATM, and add the
         // GUI simulation to it
        
         Frame  mainFrame  =   new   Frame ( "ATM Simulation" );
        mainFrame . add ( theSimulation . getGUI ());
        
         // Arrange for a file menu with a Quit option, plus quit on window close
        
         MenuBar  menuBar  =   new   MenuBar ();
         Menu  fileMenu  =   new   Menu ( "File" );
         MenuItem  quitItem  =   new   MenuItem ( "Quit" ,   new   MenuShortcut ( 'Q' ));
        quitItem . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                 System . exit ( 0 );
             }
         });
        fileMenu . add ( quitItem );
        menuBar . add ( fileMenu );
        mainFrame . setMenuBar ( menuBar );
        mainFrame . addWindowListener ( new   WindowAdapter ()   {
             public   void  windowClosing ( WindowEvent  e )
             {
                 System . exit ( 0 );
             }
         });
        
         // Start the Thread that runs the ATM
        
         new   Thread ( theATM ). start ();
        
         // Pack the GUI frame, show it, and off we go!
                
        mainFrame . setResizable ( false );
        mainFrame . pack ();
        mainFrame . setVisible ( true );
     }
}
    

ATM/src/simulation/ATMPanel.java

ATM/src/simulation/ATMPanel.java

/*
 * ATM Example system - file ATMPanel.java  
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  atm . ATM ;

import  java . awt . * ;
import  java . awt . event . * ;

/** The GUI panel that simulates the ATM itself
 */
class   ATMPanel   extends   Panel
{
     /** Constructor
     *
     *   @param  gui the the overall GUI
     *   @param  operatorPanel the simulation of the card reader
     *   @param  cardReader the simulation of the card reader
     *   @param  display the simulation of the display
     *   @param  keyboard the simulation of the keyboard
     *   @param  cashDispenser the simulation of the cash dispenser
     *   @param  receiptPrinter the simulation of the receipt printer
     */
     ATMPanel ( final  GUI gui ,
              SimOperatorPanel  operatorPanel ,
              SimCardReader  cardReader ,
              SimDisplay  display ,
              SimKeyboard  keyboard ,
              SimCashDispenser  cashDispenser ,
              SimEnvelopeAcceptor  envelopeAcceptor ,
              SimReceiptPrinter  receiptPrinter )
     {
         GridBagLayout  atmLayout  =   new   GridBagLayout ();
        setLayout ( atmLayout );
        
         // Add the operator panel
        
        add ( operatorPanel );
        atmLayout . setConstraints ( operatorPanel ,
                GUI . makeConstraints ( OPERATOR_ROW ,  OPERATOR_COL ,
                                OPERATOR_WIDTH ,  OPERATOR_HEIGHT ,
                                OPERATOR_FILL ));
                                
         // Put cardReader in a Panel with GridLayout to ensure it gets space
         // even when invisible, then add it
        
         Panel  cardReaderPanel  =   new   Panel ();
        cardReaderPanel . setLayout ( new   GridLayout ( 1 , 1 ));
        cardReaderPanel . add ( cardReader );
        add ( cardReaderPanel );
        atmLayout . setConstraints ( cardReaderPanel ,  
                GUI . makeConstraints ( READER_ROW ,  READER_COL ,
                                READER_WIDTH ,  READER_HEIGHT ,  
                                READER_FILL ));
                                
         // The customer console consists of two components (display and keyboard)
         // that must be added individually in different places in the GUI
        
        add ( display );
        atmLayout . setConstraints ( display ,  
                GUI . makeConstraints ( DISPLAY_ROW ,  DISPLAY_COL ,
                                DISPLAY_WIDTH ,  DISPLAY_HEIGHT ,
                                DISPLAY_FILL ));
                                
        add ( keyboard );
        atmLayout . setConstraints ( keyboard ,
                GUI . makeConstraints ( KEYBOARD_ROW ,  KEYBOARD_COL ,
                                KEYBOARD_WIDTH ,  KEYBOARD_HEIGHT ,
                                KEYBOARD_FILL ));
                                
         // Add the cash dispenser
        
        add ( cashDispenser );
        atmLayout . setConstraints ( cashDispenser ,
                GUI . makeConstraints ( DISPENSER_ROW ,  DISPENSER_COL ,
                                DISPENSER_WIDTH ,  DISPENSER_HEIGHT ,
                                DISPENSER_FILL ));                                 
                                
         // Put envelope acceptor in a Panel with GridLayout to ensure it gets space
         // even when invisible, then add it
        
         Panel  envelopeAcceptorPanel  =   new   Panel ();
        envelopeAcceptorPanel . setLayout ( new   GridLayout ( 1 , 1 ));
        envelopeAcceptorPanel . add ( envelopeAcceptor );
        add ( envelopeAcceptorPanel );
        atmLayout . setConstraints ( envelopeAcceptorPanel ,
                GUI . makeConstraints ( ENVELOPE_ROW ,  ENVELOPE_COL ,  
                                ENVELOPE_WIDTH ,  ENVELOPE_HEIGHT ,
                                ENVELOPE_FILL ));
        envelopeAcceptor . setVisible ( false );
        
         // Add the receipt printer
        
        add ( receiptPrinter );
        atmLayout . setConstraints ( receiptPrinter ,
                GUI . makeConstraints ( PRINTER_ROW ,  PRINTER_COL ,
                                PRINTER_WIDTH ,  PRINTER_HEIGHT ,
                                PRINTER_FILL ));
                                
         // Add a button for showing the log
        
         Panel  showLogButtonPanel  =   new   Panel ();
        showLogButtonPanel . setBackground ( operatorPanel . getBackground ());
         Button  showLogButton  =   new   Button ( "Show Log" );
        showLogButton . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                gui . showCard ( "LOG" );
             }
         });
        showLogButtonPanel . add ( showLogButton );
        add ( showLogButtonPanel );
        atmLayout . setConstraints ( showLogButtonPanel ,
                GUI . makeConstraints ( SHOW_LOG_BUTTON_ROW ,  SHOW_LOG_BUTTON_COL ,
                                SHOW_LOG_BUTTON_WIDTH ,  SHOW_LOG_BUTTON_HEIGHT ,
                                SHOW_LOG_BUTTON_FILL ));
     }

     // The GUI representing the ATM is laid out using a GridBagLayout.  
     // The following constants determine the positioning of the various
     // components within the grid bag.  Each component has a row and column
     // coordinate for its upper left hand corner, plus a height in rows and
     // a width in columns.  The following is the arrangement:
    
     // ----------------------------------------------------------------------
     // |       DISPLAY                                     |     RECEIPT    |
     // |                                                   |     PRINTER    |
     // |                                                   |                |
     // |                                                   |                |
     // |                                                   |                |
     // |                                                   |                |
     // |                                                   |                |
     // |                                                   |                |
     // |--------------------------------------------------------------------|
     // |  ENVELOPE       |    CASH        |    CARD        |   KEYBOARD     |
     // |  ACCEPTOR       |    DISPENSER   |    READER      |                |
     // |                 |                |                |                |
     // |                 |                |                |                |
     // |                 |                |                |                |
     // |                 |                |                |                |
     // ----------------------------------------------------------------------
     // | SHOW LOG BUTTON | OPERATOR PANEL                                   |
     // |                 |                                                  |
     // ----------------------------------------------------------------------
    
     // The following constants govern the size of various components, and
     // need to be used by the component
    
     public   static   final   int  DISPLAYABLE_LINES  =       9 ;
     public   static   final   String  BLANK_DISPLAY_LINE  =  
         "                                             " ;
     public   static   final   int  PRINTABLE_LINES  =         9 ;
     public   static   final   int  PRINTABLE_CHARS  =        30 ;
    
     // The following are used only for doing the layout

     private   static   final   int  DISPLAY_ROW  =            0 ;
     private   static   final   int  DISPLAY_COL  =            0 ;
     private   static   final   int  DISPLAY_WIDTH  =          3 ;
     private   static   final   int  DISPLAY_HEIGHT  =         1 ;
     private   static   final   int  DISPLAY_FILL  =           GridBagConstraints . BOTH ;
    
     private   static   final   int  PRINTER_ROW  =            0 ;
     private   static   final   int  PRINTER_COL  =           DISPLAY_COL  +  DISPLAY_WIDTH ;
     private   static   final   int  PRINTER_WIDTH  =          1 ;
     private   static   final   int  PRINTER_HEIGHT  =         1 ;
     private   static   final   int  PRINTER_FILL  =           GridBagConstraints . NONE ;
    
     private   static   final   int  ENVELOPE_ROW  =          DISPLAY_ROW  +  DISPLAY_HEIGHT ;
     private   static   final   int  ENVELOPE_COL  =           0 ;
     private   static   final   int  ENVELOPE_WIDTH  =         1 ;
     private   static   final   int  ENVELOPE_HEIGHT  =        1 ;
     private   static   final   int  ENVELOPE_FILL  =          GridBagConstraints . NONE ;
        
     private   static   final   int  DISPENSER_ROW  =         ENVELOPE_ROW ;
     private   static   final   int  DISPENSER_COL  =         ENVELOPE_COL  +  ENVELOPE_WIDTH ;
     private   static   final   int  DISPENSER_WIDTH  =        1 ;
     private   static   final   int  DISPENSER_HEIGHT  =       1 ;
     private   static   final   int  DISPENSER_FILL  =         GridBagConstraints . NONE ;

     private   static   final   int  READER_ROW  =            ENVELOPE_ROW ;
     private   static   final   int  READER_COL  =            DISPENSER_COL  +  DISPENSER_WIDTH ;
     private   static   final   int  READER_WIDTH  =           1 ;
     private   static   final   int  READER_HEIGHT  =          1 ;
     private   static   final   int  READER_FILL  =            GridBagConstraints . NONE ;
    
     private   static   final   int  KEYBOARD_ROW  =          ENVELOPE_ROW ;
     private   static   final   int  KEYBOARD_COL  =          READER_COL  +  READER_WIDTH ;
     private   static   final   int  KEYBOARD_WIDTH  =         1 ;
     private   static   final   int  KEYBOARD_HEIGHT  =        1 ;
     private   static   final   int  KEYBOARD_FILL  =          GridBagConstraints . NONE ;
    
     private   static   final   int  SHOW_LOG_BUTTON_ROW  =   ENVELOPE_ROW  +  ENVELOPE_HEIGHT ;
     private   static   final   int  SHOW_LOG_BUTTON_COL  =    0 ;
     private   static   final   int  SHOW_LOG_BUTTON_WIDTH =   1 ;
     private   static   final   int  SHOW_LOG_BUTTON_HEIGHT = 1 ;
     private   static   final   int  SHOW_LOG_BUTTON_FILL  =   GridBagConstraints . BOTH ;
    
     private   static   final   int  OPERATOR_ROW  =          SHOW_LOG_BUTTON_ROW ;
     private   static   final   int  OPERATOR_COL  =          SHOW_LOG_BUTTON_COL  +  SHOW_LOG_BUTTON_WIDTH ;
     private   static   final   int  OPERATOR_WIDTH  =         3 ;
     private   static   final   int  OPERATOR_HEIGHT  =        1 ;
     private   static   final   int  OPERATOR_FILL  =          GridBagConstraints . BOTH ;
    
     private   static   final   int  TOTAL_ROWS  =   3 ;
     private   static   final   int  TOTAL_COLS  =   3 ;
}
                                            

ATM/src/simulation/BillsPanel.java

ATM/src/simulation/BillsPanel.java

/*
 * ATM Example system - file BillsPanel.java    
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  banking . Money ;

import  java . awt . * ;
import  java . awt . event . * ;

/** The GUI panel that allows the operator to enter the number of bills in the
 *  ATM at startup
 */
class   BillsPanel   extends   Panel
{
     /** Constructor
     */
     BillsPanel ()
     {
        setLayout ( new   GridLayout ( 0 ,   1 ,   0 ,   0 ));
        setFont ( new   Font ( "Monospaced" ,   Font . PLAIN ,   14 ));
        
        add ( new   Label ( "A real ATM would have a mechanism to sense" ,
                       Label . CENTER ));
        add ( new   Label ( "or allow the operator to enter the number" ,
                       Label . CENTER ));
        add ( new   Label ( "of $20 bills in the cash dispenser." ,
                       Label . CENTER ));
        add ( new   Label ( "For purposes of the simulation," ,
                       Label . CENTER ));
        add ( new   Label ( "please enter the number of $20 bills manually." ,
                       Label . CENTER ));
        add ( new   Label ( "Then press RETURN" ,
                       Label . CENTER ));
        
        billsNumberField  =   new   TextField ( 30 );
        billsNumberField . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                 synchronized ( BillsPanel . this )
                 {
                     BillsPanel . this . notify ();
                 }
             }
         });
         Panel  billsNumberPanel  =   new   Panel ();
        billsNumberPanel . add ( billsNumberField );
        add ( billsNumberPanel );   
     }

     /** Ask the operator to enter the number of bills in the cash dispenser
     *
     *   @return  the number entered
     */
     synchronized   int  readBills ()
     {
         boolean  validNumberRead  =   false ;
         int  billsNumber  =   0 ;
        
        billsNumberField . setText ( "" );
        
         while ( !  validNumberRead )
         {
            billsNumberField . requestFocus ();
             try
             {
                wait ();
             }
             catch ( InterruptedException  e )
             {   }
                    
             try
             {
                billsNumber  =   Integer . parseInt ( billsNumberField . getText ());
                 if   ( billsNumber  >=   0 )
                    validNumberRead  =   true ;
                 else
                    getToolkit (). beep ();
             }
             catch ( NumberFormatException  e )
             {
                getToolkit (). beep ();
             }
             if   ( !  validNumberRead )
             {
                billsNumberField . setText ( "Must be a valid integer >= 0" );
                billsNumberField . selectAll ();
             }
         }
         return  billsNumber ;
     }
    
     /** The field into which the number of bills is to be entered
     */
     private   TextField  billsNumberField ;
}

ATM/src/simulation/CardPanel.java

ATM/src/simulation/CardPanel.java

/*
 * ATM Example system - file BillsPanel.java    
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;

/** The GUI panel that simulates the reading of the ATM card's magnetic stripe
 *  by asking the user to enter the number
 */
class   CardPanel   extends   Panel
{
     /** Constructor
     */
     CardPanel ()
     {
        setLayout ( new   GridLayout ( 0 ,   1 ,   0 ,   0 ));
        setFont ( new   Font ( "Monospaced" ,   Font . PLAIN ,   14 ));
        
        add ( new   Label ( "A real ATM would have a magnetic" ,
                       Label . CENTER ));
        add ( new   Label ( "stripe reader to read the card" ,
                       Label . CENTER ));
        add ( new   Label ( "For purposes of the simulation," ,
                       Label . CENTER ));
        add ( new   Label ( "please enter the card number manually." ,
                       Label . CENTER ));
        add ( new   Label ( "Then press RETURN" ,
                       Label . CENTER ));
        add ( new   Label ( "(An invalid integer or an integer not" ,
                       Label . CENTER ));
        add ( new   Label ( "greater than zero will be treated as" ,
                       Label . CENTER ));
        add ( new   Label ( "an unreadable card)" ,
                       Label . CENTER ));
        
        cardNumberField  =   new   TextField ( 30 );
        cardNumberField . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                 synchronized ( CardPanel . this )
                 {
                     CardPanel . this . notify ();
                 }
             }
         });
         Panel  cardNumberPanel  =   new   Panel ();
        cardNumberPanel . add ( cardNumberField );
        add ( cardNumberPanel );
     }
    
     /** Ask the customer to enter the number on the card
     *
     *   @return  the number entered
     */
     synchronized   int  readCardNumber ()
     {
        cardNumberField . setText ( "" );
        
        cardNumberField . requestFocus ();
         try
         {
            wait ();
         }
         catch ( InterruptedException  e )
         {   }
                
         int  cardNumber ;
         try
         {
            cardNumber  =   Integer . parseInt ( cardNumberField . getText ());
             if   ( cardNumber  <=   0 )
                cardNumber  =   - 1 ;
         }
         catch ( NumberFormatException  e )
         {
            cardNumber  =   - 1 ;
         }
        
         return  cardNumber ;
     }

     /** The field into which the card number is to be entered
     */
     private   TextField  cardNumberField ;
}

ATM/src/simulation/GUI.java

ATM/src/simulation/GUI.java

/*
 * ATM Example system - file GUI.java   
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;
import  atm . ATM ;
import  banking . Card ;
import  banking . Money ;

import  java . awt . * ;
import  java . awt . event . * ;
     
/** The GUI for the ATM simulation 
 */
class  GUI  extends   Panel
{    
     /** Constructor.
     *
     *   @param  operatorPanel the simulation of the card reader
     *   @param  cardReader the simulation of the card reader
     *   @param  display the simulation of the display
     *   @param  keyboard the simulation of the keyboard
     *   @param  cashDispenser the simulation of the cash dispenser
     *   @param  receiptPrinter the simulation of the receipt printer
     */
    GUI ( SimOperatorPanel  operatorPanel ,
         SimCardReader  cardReader ,
         SimDisplay  display ,
         SimKeyboard  keyboard ,
         SimCashDispenser  cashDispenser ,
         SimEnvelopeAcceptor  envelopeAcceptor ,
         SimReceiptPrinter  receiptPrinter )
     {
        setBackground ( Color . lightGray );
        
         // The overall GUI is a panel that uses a card layout, with four cards:
         //
         // - The card representing the ATM itself
         // - A card simulating the facilty on the operator panel that allows
         //   the operator to enter the number of bills in the machine (or
         //   perhaps to sense this)
         // - A card simulating the reading of the magnetic stripe on the
         //   customer's ATM card
         // - A card displaying the internal log
         //
         // Normally, the ATM card is displayed.  The initial money entry card
         // is displayed during the startup sequence.  The magnetic stripe reader
         // card is displayed when a card is inserted.  The log card is displayed
         // when the user clicks "Show Log" and is dismissed when the user clicks
         // "Hide log".
        
        mainLayout  =   new   CardLayout ( 5 , 5 );
        setLayout ( mainLayout );
        
        atmPanel  =   new   ATMPanel ( this ,  
                                operatorPanel ,  cardReader ,  
                                display ,  keyboard ,
                                cashDispenser ,  envelopeAcceptor ,  receiptPrinter );
         this . add ( atmPanel ,   "ATM" );

        billsPanel  =   new   BillsPanel ();
        add ( billsPanel ,   "BILLS" );
        
        cardPanel  =   new   CardPanel ();
        add ( cardPanel ,   "CARD" );

        logPanel  =   new   LogPanel ( this );
        add ( logPanel ,   "LOG" );

        mainLayout . show ( this ,   "ATM" );
     }

     /** Simulate getting the amount of cash in the cash dispenser from the operator
     *  at start up
     *
     *   @return  dollar value of the bills in the cash dispenser (# of bills x $20)
     */
    
     public   Money  getInitialCash ()
     {
        mainLayout . show ( this ,   "BILLS" );
         int  numberOfBills  =  billsPanel . readBills ();
        mainLayout . show ( this ,   "ATM" );
        
         return   new   Money ( 20   *  numberOfBills );
     }
    
     /** Simulate reading of a card
     *
     *
     *   @return  Card object representing information on the card if read
     *          successfully, null if not read successfully
     */
     public   Card  readCard ()
     {
        mainLayout . show ( this ,   "CARD" );
         int  cardNumber  =  cardPanel . readCardNumber ();
        mainLayout . show ( this ,   "ATM" );
        
         if   ( cardNumber  >   0 )
             return   new   Card ( cardNumber );
         else
             return   null ;
     }
    
     /** Simulate printing a line to the log
     *
     *   @param  text the line to print
     */
     public   void  printLogLine ( String  text )
     {
        logPanel . println ( text );
     }
    
     /** Show a specific card
     *
     *   @param  cardName the name of the card to show
     */
     void  showCard ( String  cardName )
     {
        mainLayout . show ( this ,  cardName );
     }
    
     /** Create a GridBagConstraints object with specified constraints, and 
     *  others defaulted.
     *
     *   @param  row the row (y coordinate)
     *   @param  col the column (x coordinate)
     *   @param  width the width
     *   @param  height the height
     *   @param  fill the fill
     *   @return  GridBagConstraints object representing the above
     */
    static   GridBagConstraints  makeConstraints (
                     int  row ,   int  col ,   int  width ,   int  height ,   int  fill )
     {  
         GridBagConstraints  g  =   new   GridBagConstraints ();
        g . gridy  =  row ;
        g . gridx  =  col ;
        g . gridheight  =  height ;
        g . gridwidth  =  width ;
        g . fill  =  fill ;
        g . insets  =   new   Insets ( 2 , 2 , 2 , 2 );
        g . weightx  =   1 ;
        g . weighty  =   1 ;
        g . anchor  =   GridBagConstraints . CENTER ;
         return  g ;
     }

     /** The card layout for this panel
     */
     private   CardLayout  mainLayout ;
    
     /** The panel displaying the ATM itself
     */
     private   ATMPanel  atmPanel ;
    
     /** The panel asking the operator to enter the number of bills
     */
     private   BillsPanel  billsPanel ;
    
     /** The panel asking the user to enter the number of the ATM Card
     */
     private   CardPanel  cardPanel ;
    
     /** The panel displaying the log
     */
     private   LogPanel  logPanel ;
}     

ATM/src/simulation/LogPanel.java

ATM/src/simulation/LogPanel.java

/*
 * ATM Example system - file LogPanel.java  
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;

/** The GUI panel that displays the ATM's internal log
 */
class   LogPanel   extends   Panel
{
     /** Constructor
     *
     *   @param  gui the the overall GUI
     */
     
     LogPanel ( final  GUI gui )
     {
         GridBagLayout  logLayout  =   new   GridBagLayout ();
        setLayout ( logLayout );
        setFont ( new   Font ( "Monospaced" ,   Font . PLAIN ,   14 ));
        
         Label  logPanelLabel  =   new   Label ( "Log" ,   Label . CENTER );
        add ( logPanelLabel );
         GridBagConstraints  constraints  =  
            GUI . makeConstraints ( 0 ,   0 ,   1 ,   1 ,   GridBagConstraints . NONE );
        constraints . weighty  =   0 ;
        logLayout . setConstraints ( logPanelLabel ,  constraints );  
            
        logPrintArea  =   new   TextArea ();
        logPrintArea . setBackground ( Color . white );
        logPrintArea . setForeground ( Color . black );
        logPrintArea . setFont ( new   Font ( "Monospaced" ,   Font . PLAIN ,   12 ));
        logPrintArea . setEditable ( false );         

        add ( logPrintArea );
        constraints  =  GUI . makeConstraints ( 1 ,   0 ,   1 ,   1 ,   GridBagConstraints . BOTH );
        constraints . weighty  =   1 ;
        logLayout . setConstraints ( logPrintArea ,  constraints );
        
         Panel  logButtonPanel  =   new   Panel ();
        logButtonPanel . setLayout ( new   FlowLayout ());
        
         Button  clearLogButton  =   new   Button ( "Clear Log" );
        clearLogButton . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                logPrintArea . setText ( "" );
             }
         });
        logButtonPanel . add ( clearLogButton );
        
         Button  dismissLogButton  =   new   Button ( " Hide Log " );
        dismissLogButton . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                gui . showCard ( "ATM" );
             }
         });
        
        logButtonPanel . add ( dismissLogButton );
        add ( logButtonPanel );
        constraints  =  GUI . makeConstraints ( 2 ,   0 ,   1 ,   1 ,   GridBagConstraints . NONE );
        constraints . weighty  =   0 ;
        logLayout . setConstraints ( logButtonPanel ,  constraints );
     }
    
     /** Add text to the log
     *
     *   @param  text the text to be printed
     */
     void  println ( String  text )
     {
        logPrintArea . append ( text  +   "\n" );
     }
    
     /** Area into which the log is to be printed
     */
     private   TextArea  logPrintArea ;
}
    
        
        

ATM/src/simulation/SimCardReader.java

ATM/src/simulation/SimCardReader.java

/*
 * ATM Example system - file SimCardReader.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  atm . ATM ;
import  banking . Card ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the card reader
 */
class   SimCardReader   extends   Button
{
     /** Constructor
     *
     *   @param  simulation the Simulation object
     */
     SimCardReader ( final   Simulation  simulation )
     {
         super ( "Click to insert card" );

        addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                simulation . cardInserted ();
             }
         });
        
         // Not available until machine is turned on
        
        setVisible ( false );
     }
    
     /** Animate card going into the machine
     */
     void  animateInsertion ()
     {
        originalBounds  =  getBounds ();
         Rectangle  currentBounds  =
            new   Rectangle ( originalBounds . x ,  originalBounds . y ,
                         originalBounds . width ,  originalBounds . height );
                         
         while   ( currentBounds . width  >   0   &&  currentBounds . height  >   0 )
         {  
            setBounds ( currentBounds . x ,  currentBounds . y ,
                      currentBounds . width ,  currentBounds . height );
            repaint ();
             try  
             {  
                 Thread . sleep ( 100 );
             }  
             catch   ( InterruptedException  e )  
             {   }
            
            currentBounds . height  -=   1 ;
            currentBounds . width  =  
               ( originalBounds . width  *  currentBounds . height )   /  originalBounds . height ;
            currentBounds . =
              originalBounds . +   ( originalBounds . width  -  currentBounds . width )   /   2 ;
            currentBounds . =
              originalBounds . +   ( originalBounds . height  -  currentBounds . height )   /   2 ;
         }
          
        setVisible ( false );   
     }
    
     /** Animate ejecting the card that is currently inside the reader.  
     */
     void  animateEjection ()
     {
        setLabel ( "Ejecting card" );
        setVisible ( true );
        
         Rectangle  currentBounds  =  
            new   Rectangle ( originalBounds . +  originalBounds . width  /   2 ,
                         originalBounds . +  originalBounds . height  /   2 ,
                         originalBounds . width  /  originalBounds . height ,   1 );
        
         while   ( currentBounds . height  <=  originalBounds . height  &&
               currentBounds . width  <=  originalBounds . width )
         {  
            setBounds ( currentBounds . x ,  currentBounds . y ,
                      currentBounds . width ,  currentBounds . height );
            repaint ();
             try  
             {  
                 Thread . sleep ( 100 );
             }  
             catch   ( InterruptedException  e )  
             {   }
            currentBounds . height  +=   1 ;
            currentBounds . width  =  
               ( originalBounds . width  *  currentBounds . height )   /  originalBounds . height ;
            currentBounds . =
              originalBounds . +   ( originalBounds . width  -  currentBounds . width )   /   2 ;
            currentBounds . =
              originalBounds . +   ( originalBounds . height  -  currentBounds . height )   /   2 ;
         }
          
        setLabel ( "Click to insert card" );
     }

     /** Animate retaining the card that is currently inside the reader for action by the
     *  bank. 
     */
     void  animateRetention ()
     {
        setLabel ( "Click to insert card" );
        setVisible ( true );
     }

     /** To animate card insertion/ejection, we change the bounds of this button.
     *  These are the original bounds we ultimately restore to
     */  
     private   Rectangle  originalBounds ;
}                                
    
    

ATM/src/simulation/SimCashDispenser.java

ATM/src/simulation/SimCashDispenser.java

/*
 * ATM Example system - file SimCashDispenser.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  banking . Money ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the cash dispenser
 */
class   SimCashDispenser   extends   Panel
{
     /** Constructor
     */
     SimCashDispenser ()
     {
        setLayout ( new   GridLayout ( 1 , 1 ));
        label  =   new   Label ( "$XXX.XX" ,   Label . CENTER );
        label . setFont ( new   Font ( "SansSerif" ,   Font . PLAIN ,   24 ));
        label . setForeground ( new   Color ( 0 ,   64 ,   0 ));
        add ( label );
        label . setVisible ( false );
     }
    
     /** Animate dispensing cash to a customer
     *
     *   @param  amount the amount of cash to dispense
     *
     *  Precondition: amount is <= cash on hand
     */
     public   void  animateDispensingCash ( Money  amount )
     {
        label . setText ( amount . toString ());
         for   ( int  size  =   3 ;  size  <=   24 ;  size  +=   1 )
         {  
            label . setFont ( new   Font ( "SansSerif" ,   Font . PLAIN ,  size ));
            label . setVisible ( true );
             try
             {  
                 Thread . sleep ( 250 );
             }
             catch   ( InterruptedException  e )
             {   }
            label . setVisible ( false );
         }
     }
    
     /** Label that shows the amount of money being dispensed - starts out
     *  small and grows to simulate cash coming out of the machine
     */
     private   Label  label ;
}                                
    
    

ATM/src/simulation/SimDisplay.java

ATM/src/simulation/SimDisplay.java

/*
 * ATM Example system - file SimDisplay.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;
import  java . util . StringTokenizer ;

/** Simulate the display portion of the customer console
 */
class   SimDisplay   extends   Panel
{
     /** Constructor
     */
     SimDisplay ()
     {
        setLayout ( new   GridLayout ( ATMPanel . DISPLAYABLE_LINES ,   1 ));
        setBackground ( new   Color ( 0 ,   96 ,   0 ));    // Dark green
        setForeground ( Color . white );
        
         Font  lineFont  =   new   Font ( "Monospaced" ,   Font . PLAIN ,   14 );
        displayLine  =   new   Label [ ATMPanel . DISPLAYABLE_LINES ];
         for   ( int  i  =   0 ;  i  <   ATMPanel . DISPLAYABLE_LINES ;  i  ++ )
         {
            displayLine [ i ]   =   new   Label ( ATMPanel . BLANK_DISPLAY_LINE );
            displayLine [ i ]. setFont ( lineFont );
            add ( displayLine [ i ]);
         }
        currentDisplayLine  =   0 ;
        
     }
    
     /** Clear the display
     */
     void  clearDisplay ()
     {  
         for   ( int  i  =   0 ;  i  <  displayLine . length ;  i  ++ )
            displayLine [ i ]. setText ( "" );
        currentDisplayLine  =   0 ;
     }
      
     /** Add text to the display - may contain one or more lines delimited by \n
     *
     *   @param  text the text to display
     */
     void  display ( String  text )
     {  
         StringTokenizer  tokenizer  =   new   StringTokenizer ( text ,   "\n" ,   false );
         while   ( tokenizer . hasMoreTokens ())
         {  
             try
             {  
                displayLine [ currentDisplayLine  ++ ]. setText ( tokenizer . nextToken ());  
             }
             catch   ( Exception  e )
             {   }
         }
     }
    
     /** Set echoed input on the display
     *
     *   @param  echo the line to be echoed - always the entire line
     */
     void  setEcho ( String  echo )
     {
        displayLine [ currentDisplayLine ]. setText (
             ATMPanel . BLANK_DISPLAY_LINE . substring ( 0 ,  
                 ATMPanel . BLANK_DISPLAY_LINE . length ()   /   2   -  echo . length ())   +  echo );
     }
    
     /** Override the getInsets() method to provide additional spacing all
     *  around
     */
     public   Insets  getInsets ()
     {
         Insets  insets  =   super . getInsets ();
        insets . top  +=   5 ;
        insets . bottom  +=   5 ;
        insets . left  +=   10 ;
        insets . right  +=   10 ;
         return  insets ;
     }

     /** Individual lines comprising the display
     */
     private   Label   []  displayLine ;
    
     /** Number of the current line to write to
     */
     private   int  currentDisplayLine ;
}                                
    
    

ATM/src/simulation/SimEnvelopeAcceptor.java

ATM/src/simulation/SimEnvelopeAcceptor.java

/*
 * ATM Example system - file SimEnvelopeAcceptor.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the envelope acceptor
 */
class   SimEnvelopeAcceptor   extends   Button
{
     /** Constructor
     */
     SimEnvelopeAcceptor ()
     {
         super ( "Click to insert envelope" );
        addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                 synchronized ( SimEnvelopeAcceptor . this )
                 {
                    inserted  =   true ;
                     SimEnvelopeAcceptor . this . notify ();
                 }
             }
         });
     }
    
     /** Simulate accepting an envelope from customer.
     *
     *  return true if an envelope was received within the prescribed time,
     *         else false
     */
     public   synchronized   boolean  acceptEnvelope ()
     {
        inserted  =   false ;
        setVisible ( true );
            
         // Wait for user to simulate inserting envelope by clicking button.
         // If we wait 20 seconds and no envelope is entered, we time out

         try
         {  
            wait ( MAXIMUM_WAIT_TIME );
         }
         catch ( InterruptedException  e )
         {   }
        
         if   ( inserted )
         {
             // Animate envelope going into the machine
            
             Rectangle  originalBounds  =  getBounds ();
            
             Rectangle  currentBounds  =
                new   Rectangle ( originalBounds . x ,  originalBounds . y ,
                             originalBounds . width ,  originalBounds . height );
                             
             while   ( currentBounds . width  >   0   &&  currentBounds . height  >   0 )
             {  
                setBounds ( currentBounds . x ,  currentBounds . y ,
                        currentBounds . width ,  currentBounds . height );
                repaint ();
                 try  
                 {  
                     Thread . sleep ( 100 );
                 }  
                 catch   ( InterruptedException  e )  
                 {   }
                currentBounds . height  -=   1 ;
                currentBounds . width  =  
                   ( originalBounds . width  *  currentBounds . height )   /  originalBounds . height ;
                currentBounds . =
                  originalBounds . +   ( originalBounds . width  -  currentBounds . width )   /   2 ;
                currentBounds . =
                  originalBounds . +   ( originalBounds . height  -  currentBounds . height )   /   2 ;
             }
            
            setVisible ( false );
            setBounds ( originalBounds );
         }
         else
         {
            setVisible ( false );
         }
         return  inserted ;
     }

     /** Inform the envelope acceptor that the customer has pressed the CANCEL
     *  key.  Ignored if not waiting for an envelope
     */
     public   synchronized   void  cancelRequested ()
     {
        notify ();         // End the wait for the envelope - inserted will still
                         // be false so acceptEnvelope() will return false
     }
    
     /** Becomes true when an envelope has been inserted
     */
     private   boolean  inserted ;
    
     /** Maximum time to wait for an envelope before timing out - in milliseconds
     */
     private   static   long  MAXIMUM_WAIT_TIME  =   20   *   1000 ;
}                                
    
    

ATM/src/simulation/SimKeyboard.java

ATM/src/simulation/SimKeyboard.java

/*
 * ATM Example system - file SimKeyboard.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the keyboard portion of the customer console
 */
class   SimKeyboard   extends   Panel
{
     /** Constructor
     *
     *   @param  display the display on which to echo typed input
     *   @param  envelopeAcceptor - to be notified if cancel is pressed
     */
     SimKeyboard ( SimDisplay  display ,
                 SimEnvelopeAcceptor  envelopeAcceptor )
     {
         this . display  =  display ;
         this . envelopeAcceptor  =  envelopeAcceptor ;
        
        setLayout ( new   GridLayout ( 5 , 3 ));
        
         // Create the keys representing digits
        
         Button   []  digitKey  =   new   Button [ 10 ];
         for   ( int  i  =   1 ;  i  <   10 ;  i  ++ )
         {  
            digitKey [ i ]   =   new   Button ( ""   +  i );
            add ( digitKey [ i ]);
         }
        
        add ( new   Label ( "" ));
        
        digitKey [ 0 ]   =   new   Button ( "0" );
        add ( digitKey [ 0 ]);
        
        add ( new   Label ( "" ));
        
         // Create the function keys
        
         Button  enterKey  =   new   Button ( "ENTER" );
        enterKey . setForeground ( Color . black );
        enterKey . setBackground ( new   Color ( 128 ,   128 ,   255 ));   // Light blue
        add ( enterKey );
        
         Button  clearKey  =   new   Button ( "CLEAR" );
        clearKey . setForeground ( Color . black );
        clearKey . setBackground ( new   Color ( 255 ,   128 ,   128 ));   // Light red
        add ( clearKey );
        
         Button  cancelKey  =   new   Button ( "CANCEL" );
        cancelKey . setBackground ( Color . red );
        cancelKey . setForeground ( Color . black );
        add ( cancelKey );
        
         // Add action listeners to each key
        
         for   ( int  i  =   0 ;  i  <   10 ;  i  ++ )
            digitKey [ i ]. addActionListener ( new   ActionListener ()   {
                 public   void  actionPerformed ( ActionEvent  e )
                 {
                    digitKeyPressed ( Integer . parseInt ( e . getActionCommand ()));
                 }
             });
            
        enterKey . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                enterKeyPressed ();
             }
         });

        clearKey . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                clearKeyPressed ();
             }
         });

        cancelKey . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                cancelKeyPressed ();
             }
         });
        
         // Allow the user to use the regular keyboard instead of the awt keyboard

        addKeyListener ( new   KeyAdapter ()   {
             public   void  keyPressed ( KeyEvent  e )
             {
                 char  keyChar  =  e . getKeyChar ();
                 int  keyCode  =  e . getKeyCode ();
                 if   ( keyChar  >=   '0'   &&  keyChar  <=   '9' )
                 {
                    digitKeyPressed ( keyChar  -   '0' );
                    e . consume ();
                 }
                 else
                 {
                     switch   ( keyCode )
                     {
                         case   KeyEvent . VK_ENTER :
                        
                            enterKeyPressed ();
                             break ;
                            
                         case   KeyEvent . VK_CLEAR :
                        
                            clearKeyPressed ();
                             break ;
                            
                         case   KeyEvent . VK_CANCEL :
                         case   KeyEvent . VK_ESCAPE :
                        
                            cancelKeyPressed ();
                             break ;
                     }
                    e . consume ();
                 }
             }
         });

         // Initialze mode and input buffer
        
        currentInput  =   new   StringBuffer ();
        mode  =  IDLE_MODE ;
     }
    
     /** Read input from the keyboard
     *
     *   @param  mode the input mode to use - one of the constants defined below.
     *   @param  maxValue the maximum acceptable value (used in MENU_MODE only)
     *   @return  the line that was entered - null if user pressed CANCEL.
     */
     synchronized   String  readInput ( int  mode ,   int  maxValue )
     {
         this . mode  =  mode ;
         this . maxValue  =  maxValue ;
        currentInput . setLength ( 0 );
        cancelled  =   false ;
         if   ( mode  ==  AMOUNT_MODE )
            setEcho ( "0.00" );
         else
            setEcho ( "" );
        requestFocus ();
        
         try
         {
            wait ();
         }
         catch ( InterruptedException  e )
         {   }
        
         this . mode  =  IDLE_MODE ;
        
         if   ( cancelled )
             return   null ;
         else
             return  currentInput . toString ();
     }
    
     /** Handle a digit key
     *
     *   @param  digit the value on the key
     */
     private   synchronized   void  digitKeyPressed ( int  digit )
     {
         switch   ( mode )
         {
             case  IDLE_MODE :
            
                 break ;
                
             case  PIN_MODE :
             {
                currentInput . append ( digit );
                 StringBuffer  echoString  =   new   StringBuffer ();
                 for   ( int  i  =   0 ;  i  <  currentInput . length ();  i  ++ )
                    echoString . append ( '*' );
                setEcho ( echoString . toString ());
                 break ;
             }
                
             case  AMOUNT_MODE :
             {            
                currentInput . append ( digit );
                 String  input  =  currentInput . toString ();
                 if   ( input . length ()   ==   1 )
                    setEcho ( "0.0"   +  input );
                 else   if   ( input . length ()   ==   2 )
                    setEcho ( "0."   +  input );
                 else
                    setEcho ( input . substring ( 0 ,  input . length ()   -   2 )   +   "."   +
                        input . substring ( input . length ()   -   2 ));
                 break ;
             }
            
             case  MENU_MODE :
             {
                 if   ( digit  >   0   &&  digit  <=  maxValue )
                 {
                    currentInput . append ( digit );
                    notify ();
                 }
                 else
                    getToolkit (). beep ();
                 break ;
             }                
         }
     }
    
     /** Handle the ENTER key
     */
     private   synchronized   void  enterKeyPressed ()
     {
         switch ( mode )
         {
             case  IDLE_MODE :
            
                 break ;
                
             case  PIN_MODE :
             case  AMOUNT_MODE :
            
                 if   ( currentInput . length ()   >   0 )
                    notify ();
                 else
                    getToolkit (). beep ();
                 break ;
                    
             case  MENU_MODE :
            
                getToolkit (). beep ();
                 break ;
         }
     }            
                
     /** Handle the CLEAR key
     */
     private   synchronized   void  clearKeyPressed ()
     {
         switch ( mode )
         {
             case  IDLE_MODE :
            
                 break ;
                
             case  PIN_MODE :
            
                currentInput . setLength ( 0 );
                setEcho ( "" );
                 break ;
                
             case  AMOUNT_MODE :
            
                currentInput . setLength ( 0 );
                setEcho ( "0.00" );
                 break ;
                
             case  MENU_MODE :
            
                getToolkit (). beep ();
                 break ;
         }
     }            
                
     /** Handle the CANCEL KEY
     */
     private   synchronized   void  cancelKeyPressed ()
     {
         switch ( mode )
         {
             case  IDLE_MODE :
            
                 // It is possible to press the cancel key when requested
                 // to insert an envelope - so notify the envelope acceptor
                 // of this fact (notification is ignored if acceptor is
                 // not waiting for an envelope)
                
                 synchronized ( envelopeAcceptor )
                 {
                    envelopeAcceptor . notify ();
                 }
                
             case  PIN_MODE :
             case  AMOUNT_MODE :
             case  MENU_MODE :
            
                cancelled  =   true ;
                notify ();
         }
     }            
    
     /** Set the echo string displayed on the display
     *
     *   @param  echo the text to set the echo to (the whole line)
     */
     private   void  setEcho ( String  echo )
     {
        display . setEcho ( echo );
     }
    
     /** The display onto which to echo input
     */
     private   SimDisplay  display ;
    
     /** The envelope acceptor to notify if CANCEL is pressed while not awaiting
     *  customer input
     */
     private   SimEnvelopeAcceptor  envelopeAcceptor ;
    
     /** Current input mode - one of the values defined below
     */
     private   int  mode ;
    
     /** Not currently reading input - ignore keys (except CANCEL)
     */
     private   static   final   int  IDLE_MODE  =   0 ;
    
     /** Read input in PIN mode - allow user to enter several characters,
     *  and to clear the line if the user wishes; echo as asterisks
     */
     private   static   final   int  PIN_MODE  =   Simulation . PIN_MODE ;
    
     /** Read input in amount mode - allow user to enter several characters,
     *  and to clear the line if the user wishes; echo what use types
     */
     private   static   final   int  AMOUNT_MODE  =   Simulation . AMOUNT_MODE ;
    
     /** Read input in menu choice mode - wait for one digit key to be pressed,
     *  and return value immediately.
     */
     private   static   final   int  MENU_MODE  =   Simulation . MENU_MODE ;
    
     /** Current partial line of input
     */
     private   StringBuffer  currentInput ;
    
     /** Cancellation flag - set to true if user cancels
     */
     private   boolean  cancelled ;
    
     /** Maximum valid value - used in MENU_MODE only
     */
     private   int  maxValue ;
}                                
    
    

ATM/src/simulation/SimOperatorPanel.java

ATM/src/simulation/SimOperatorPanel.java

/*
 * ATM Example system - file SimOperatorPanel.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  atm . ATM ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the operator panel
 */
class   SimOperatorPanel   extends   Panel
{
     /** Constructor
     *
     *   @param  simulation the overall simulation object
     */
     SimOperatorPanel ( final   Simulation  simulation )
     {
        setLayout ( new   BorderLayout ( 10 ,   0 ));
        setBackground ( new   Color ( 128 , 128 , 255 ));
        add ( new   Label ( "     Operator Panel" ),   BorderLayout . WEST );
         final   Label  message  =   new   Label ( "Click button to turn ATM on" ,   Label . CENTER );
        add ( message ,   BorderLayout . CENTER );
         final   Button  button  =   new   Button ( " ON " );
        button . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                 if   ( button . getLabel (). equals ( "OFF" ))      // ATM is currently on
                 {
                    message . setText ( "Click button to turn ATM on  " );
                    button . setLabel ( " ON " );
                    
                    simulation . switchChanged ( false );
                 }
                 else                                      // ATM is currently off
                 {
                    message . setText ( "Click button to turn ATM off" );
                    button . setLabel ( "OFF" );
                    
                    simulation . switchChanged ( true );
                 }
             }
         });
         Panel  buttonPanel  =   new   Panel ();
        buttonPanel . add ( button );
        add ( buttonPanel ,   BorderLayout . EAST );
        
         // Use a thread to blink the "Click button to turn ATM on" message when
         // the ATM is off.  This will also make the message invisible when the
         // button is not enabled.
        
         new   Thread ()   {
             public   void  run ()
             {
                 while ( true )
                 {
                     try
                     {
                        sleep ( 1000 );
                     }
                     catch ( InterruptedException  e )
                     {   }
                    
                     if   ( message . isVisible ()   &&   !  button . getLabel (). equals ( "OFF" )
                             ||   !   SimOperatorPanel . this . isEnabled ()   )
                        message . setVisible ( false );
                     else
                        message . setVisible ( true );
                 }
             }
         }. start ();
     }
}                                
    
    

ATM/src/simulation/SimReceiptPrinter.java

ATM/src/simulation/SimReceiptPrinter.java

/*
 * ATM Example system - file SimReceiptPrinter.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  java . awt . * ;
import  java . awt . event . * ;

/** Simulate the receipt printer
 */
class   SimReceiptPrinter   extends   Panel
{
     /** Constructor
     */
     SimReceiptPrinter ()
     {
        setLayout ( new   BorderLayout ( 5 ,   5 ));
        
         // The actual area where receipt prints
        
        printArea  =  
             new   TextArea ( "" ,   ATMPanel . PRINTABLE_LINES ,   ATMPanel . PRINTABLE_CHARS ,
                          TextArea . SCROLLBARS_VERTICAL_ONLY );
        printArea . setBackground ( Color . white );
        printArea . setForeground ( Color . black );
        printArea . setFont ( new   Font ( "Monospaced" ,   Font . PLAIN ,   12 ));
        printArea . setEditable ( false );
        add ( printArea ,   BorderLayout . SOUTH );
             
         // Give user a button to click to take receipt - only visible when a
         // receipt has been printed. We put the button in a panel with a
         // GridLayout to ensure it gets space, even when invisible
        
         Panel  buttonPanel  =   new   Panel ();
        buttonPanel . setLayout ( new   GridLayout ( 1 , 1 ));
        take  =   new   Button ( "Take receipt" );
        buttonPanel . add ( take );
        add ( buttonPanel ,   BorderLayout . NORTH );
        take . addActionListener ( new   ActionListener ()   {
             public   void  actionPerformed ( ActionEvent  e )
             {
                printArea . setText ( "" );
                take . setVisible ( false );
             }
         });
        
        take . setVisible ( false );
     }
    
     /** Print line to receipt
     *
     *   @param  text the line to print
     */
     void  println ( String  text )
     {
        printArea . append ( text  +   '\n' );
         try
         {  
             Thread . sleep ( 1   *   1000 );
         }
         catch   ( InterruptedException  e )
         {   }

       take . setVisible ( true );
     }         

     /** Simulated printout of receipt
     */
     private   TextArea  printArea ;
    
     /** Button to allow the user to take the receipt
     */
     private   Button  take ;
}                                
    
    

ATM/src/simulation/SimulatedBank.java

ATM/src/simulation/SimulatedBank.java

/*
 * ATM Example system - file SimulatedBank.java 
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;
import  banking . AccountInformation ;
import  banking . Balances ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;

/** Simulation of the bank.  A set of simulated accounts is initalized at startup.
 */
public   class   SimulatedBank
{
     /** Simulate the handling of a message
     *
     *   @param  message the message to send
     *   @param  balances (out) balances in customer's account as reported
     *         by bank
     *   @return  status code returned by bank
     */
     public   Status  handleMessage ( Message  message ,   Balances  balances )
     {        
         int  cardNumber  =  message . getCard (). getNumber ();  
         if   ( cardNumber  <   1   ||  cardNumber  >  PIN . length )
             return   new   Failure ( "Invalid card" );
    
         if   ( message . getPIN ()   !=  PIN  [  cardNumber  ]   )
             return   new   InvalidPIN ();
    
         switch ( message . getMessageCode ())
         {
             case   Message . WITHDRAWAL :
            
                 return  withdrawal ( message ,  balances );
                            
             case   Message . INITIATE_DEPOSIT :
            
                 return  initiateDeposit ( message );
            
             case   Message . COMPLETE_DEPOSIT :
            
                 return  completeDeposit ( message ,  balances );
            
             case   Message . TRANSFER :
            
                 return  transfer ( message ,  balances );
            
             case   Message . INQUIRY :
            
                 return  inquiry ( message ,  balances );
         }
        
         // Need to keep compiler happy
        
         return   null ;
     }

     /** Simulate processing of a withdrawal
     *
     *   @param  message the message describing the withdrawal requested
     *   @param  balances (out) balances in account after withdrawal
     *   @return  status code derived from current values
     */
     private   Status  withdrawal ( Message  message ,   Balances  balances )
     {
         int  cardNumber  =  message . getCard (). getNumber ();
        
         int  accountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getFromAccount ()   ];
         if   ( accountNumber  ==   0 )
             return   new   Failure ( "Invalid account type" );
    
         Money  amount  =  message . getAmount ();
        
         Money  limitRemaining  =   new   Money ( DAILY_WITHDRAWAL_LIMIT );
        limitRemaining . subtract ( WITHDRAWALS_TODAY [  cardNumber  ]);
         if   ( !  amount . lessEqual ( limitRemaining ))
             return   new   Failure ( "Daily withdrawal limit exceeded" );

         if   ( !  amount . lessEqual ( AVAILABLE_BALANCE  [  accountNumber  ]))
              return   new   Failure ( "Insufficient available balance" );

         // Update withdrawals today and account balances once we know everything is
         // OK
            
        WITHDRAWALS_TODAY  [  cardNumber  ]. add ( amount );
        BALANCE  [  accountNumber  ]. subtract ( amount );
        AVAILABLE_BALANCE  [  accountNumber  ]. subtract ( amount );
        
         // Return updated balances
        
        balances . setBalances ( BALANCE  [  accountNumber  ],  
                             AVAILABLE_BALANCE  [  accountNumber  ]);
        
         return   new   Success ();
     }  
    
     /** Simulate initiation of a deposit. At this point, the bank only approves
     *  the validity of the deposit - no changes to the records are made until
     *  the envelope is actually inserted 
     *
     *   @param  message the message describing the deposit requested
     *   @return  status code derived from current values
     */
     private   Status  initiateDeposit ( Message  message )
     {
         int  cardNumber  =  message . getCard (). getNumber ();  
    
         int  accountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getToAccount ()   ];
         if   ( accountNumber  ==   0 )
             return   new   Failure ( "Invalid account type" );
            
         // Don't update anything yet
            
         return   new   Success ();
     }     
    
     /** Simulate completion of a deposit
     *
     *   @param  message the message describing the deposit requested
     *   @param  balances (out) balances (not updated until completed)
     *   @return  status code - must always be success in this case
     */
     private   Status  completeDeposit ( Message  message ,   Balances  balances )
     {
         int  cardNumber  =  message . getCard (). getNumber ();  
        
         int  accountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getToAccount ()   ];
         if   ( accountNumber  ==   0 )
             return   new   Failure ( "Invalid account type" );
            
         // Now we can update the balance
        
         Money  amount  =  message . getAmount ();
        BALANCE  [  accountNumber  ]. add ( amount );
        
         // Return updated balances
        
        balances . setBalances ( BALANCE  [  accountNumber  ],  
                             AVAILABLE_BALANCE  [  accountNumber  ]);
        
         return   new   Success ();
     }     
    
     /** Simulate processing of a transfer
     *
     *   @param  message the message describing the transfer requested
     *   @param  balances (out) balances in "to" account after transfer
     *   @return  status code derived from current values
     */
     private   Status  transfer ( Message  message ,   Balances  balances )
     {
         int  cardNumber  =  message . getCard (). getNumber ();  
    
         int  fromAccountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getFromAccount ()   ];
         if   ( fromAccountNumber  ==   0 )
             return   new   Failure ( "Invalid from account type" );
    
         int  toAccountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getToAccount ()   ];
         if   ( toAccountNumber  ==   0 )
             return   new   Failure ( "Invalid to account type" );
         if   ( fromAccountNumber  ==  toAccountNumber )
             return   new   Failure ( "Can't transfer money from\n"   +
                     "an account to itself" );
    
         Money  amount  =  message . getAmount ();
        
         if   ( !  amount . lessEqual ( AVAILABLE_BALANCE  [  fromAccountNumber  ]))
              return   new   Failure ( "Insufficient available balance" );

         // Update account balances once we know everything is OK
            
        BALANCE  [  fromAccountNumber  ]. subtract ( amount );
        AVAILABLE_BALANCE  [  fromAccountNumber  ]. subtract ( amount );
        BALANCE  [  toAccountNumber  ]. add ( amount );
        AVAILABLE_BALANCE  [  toAccountNumber  ]. add ( amount );
        
         // Return updated balances
        
        balances . setBalances ( BALANCE  [  toAccountNumber  ],  
                             AVAILABLE_BALANCE  [  toAccountNumber  ]);
        
         return   new   Success ();
     }  
    
     /** Simulate processing of an inquiry
     *
     *   @param  message the message describing the inquiry requested
     *   @param  balances (out) balances in account
     *   @return  status code derived from current values
     */
     private   Status  inquiry ( Message  message ,   Balances  balances )
     {
         int  cardNumber  =  message . getCard (). getNumber ();  

         int  accountNumber  =  ACCOUNT_NUMBER  [  cardNumber  ]   [  message . getFromAccount ()   ];
         if   ( accountNumber  ==   0 )
             return   new   Failure ( "Invalid account type" );
        
         // Return requested balances
        
        balances . setBalances ( BALANCE  [  accountNumber  ],  
                             AVAILABLE_BALANCE  [  accountNumber  ]);
        
         return   new   Success ();
     }
     
     /** Representation for status of a transaction that succeeded
     */
     private   static   class   Success   extends   Status
     {
         public   boolean  isSuccess ()
         {
             return   true ;
         }
        
         public   boolean  isInvalidPIN ()
         {
             return   false ;
         }
        
         public   String  getMessage ()
         {
             return   null ;
         }
     }
    
     /** Representation for status of a transaction that failed (for reason other than
     *  invalid PIN)
     */
     private   static   class   Failure   extends   Status
     {
         /** Constructor
         *
         *   @param  message description of the failure
         */
         public   Failure ( String  message )
         {
             this . message  =  message ;
         }
        
         public   boolean  isSuccess ()
         {
             return   false ;
         }
        
         public   boolean  isInvalidPIN ()
         {
             return   false ;
         }
        
         public   String  getMessage ()
         {
             return  message ;
         }
        
         private   String  message ;
     }

     /** Representation for status of a transaction that failed due to an invalid PIN
     */
     private   static   class   InvalidPIN   extends   Failure
     {
         /** Constructor
         *
         *   @param  message description of the failure
         */
         public   InvalidPIN ()
         {
             super ( "Invalid PIN" );
         }
        
         public   boolean  isInvalidPIN ()
         {
             return   true ;
         }
     }
    
     /** PIN for each card.  (Valid card numbers start with 1)
     */
     private   static   final   int  PIN  []   =
     {  
         0 ,    // dummy for nonexistent card 0
         42 ,  
         1234  
     };

     /** Array of account numbers associated with each card.  For each card,
     *  there can be three different types of account, which correspond to
     *  the names in class AccountInformation.  0 means no account of this
     *  type.   (Valid card numbers start with 1)
     */
     private   static   final   int  ACCOUNT_NUMBER  []   []   =
     {  
         {   0 ,   0 ,   0   },      // dummies for nonexistent card 0
         {   1 ,   2 ,   0   },
         {   1 ,   0 ,   3   }
     };

     /** Withdrawals so far today on each card.   (Valid card numbers start with 1)
     */  
     private   static   Money  WITHDRAWALS_TODAY  []   =
     {
         new   Money ( 0 ),     // dummy for nonexistent card 0
         new   Money ( 0 ),
         new   Money ( 0 )
     };
    
     /** Maximum daily withdrawal limit for any one card.  
     */
     private   static   final   Money  DAILY_WITHDRAWAL_LIMIT  =   new   Money ( 300 );
    
     /** Balance for each account (will change as program runs, hence not a
     *  static final.
     */
     private   Money  BALANCE  []   =
     {
         new   Money ( 0 ),     // dummy for nonexistent account 0
         new   Money ( 100 ),  
         new   Money ( 1000 ),
         new   Money ( 5000 )  
     };  
    
     /** Available alance for each account (will change as program runs, hence
     *  not a static final.
     */
     private   Money  AVAILABLE_BALANCE  []   =
     {  
         new   Money ( 0 ),     // dummy for nonexistent account 0
         new   Money ( 100 ),  
         new   Money ( 1000 ),
         new   Money ( 5000 )  
     };
}     

ATM/src/simulation/Simulation.java

ATM/src/simulation/Simulation.java

/*
 * ATM Example system - file Simulation.java
 *
 * copyright (c) 2001 - Russell C. Bjork
 *
 */
 
package  simulation ;

import  atm . ATM ;
import  banking . Balances ;
import  banking . Card ;
import  banking . Message ;
import  banking . Money ;
import  banking . Status ;

/** Simulation of the physical components of the ATM, including its network 
 *  connection to the bank.  An instance is created at startup by either the
 *  application's main() program or the applet's init() method.
 *
 *  The individual components are displayed in a panel belonging to class GUI.
 *  The bank is simulated by an object belonging to class SimulatedBank.  The
 *  constructor for this class creates one instance of each.
 *
 *  The static method getInstance() allows components of the ATM to access the one
 *  and only instance of this class in order to simulate various operations.  The
 *  remaining methods simulate specific operations of the ATM, and are forwarded
 *  to either the GUI panel or the simulated bank to actually carry them out.
 */
public   class   Simulation
{
     public   Simulation ( ATM atm )
     {
         this . atm  =  atm ;
        
         // Create the simulated individual components of the ATM's GUI
        
        operatorPanel  =   new   SimOperatorPanel ( this );
        cardReader  =   new   SimCardReader ( this );
        display  =   new   SimDisplay ();
        cashDispenser  =   new   SimCashDispenser ();
        envelopeAcceptor  =   new   SimEnvelopeAcceptor ();
        receiptPrinter  =   new   SimReceiptPrinter ();
        keyboard  =   new   SimKeyboard ( display ,  envelopeAcceptor );
        
         // Create the GUI containing the above
        
        gui  =   new  GUI ( operatorPanel ,  cardReader ,  display ,  keyboard ,
                      cashDispenser ,  envelopeAcceptor ,  receiptPrinter );
        
         // Create the simulation of the bank
        
        simulatedBank  =   new   SimulatedBank ();
        
        theInstance  =   this ;
     }
    
     /** Accessor for the one and only instance of this class
     *
     *   @return  the instance of this class
     */
     public   static   Simulation  getInstance ()
     {
         return  theInstance ;
     }
    
     /** Simulated getting initial amount of cash from operator
     *
     *   @return  value of initial cash entered
     */
     public   Money  getInitialCash ()
     {
         return  gui . getInitialCash ();
     }
    
     /** Simulate reading of a card
     *
     *
     *   @return  Card object representing information on the card if read
     *          successfully, null if not read successfully
     */
     public   Card  readCard ()
     {
         // Machine can't be turned off while there is a card in it
        operatorPanel . setEnabled ( false );

        cardReader . animateInsertion ();
        
         // Since we don't have a magnetic stripe reader, we'll simulate by
         // having customer type the card number in
        
         return  gui . readCard ();
     }
    
     /** Simulate ejecting a card 
     */
     public   void  ejectCard ()
     {
        cardReader . animateEjection ();

         // Re-enable on-off switch
        operatorPanel . setEnabled ( true );
     }
    
     /** Simulate retaining a card
     */
     public   void  retainCard ()
     {
        cardReader . animateRetention ();

         // Re-enable on-off switch
        operatorPanel . setEnabled ( true );
     }
    
     /** Clear the simulated display
     */
     public   void  clearDisplay ()
     {
        display . clearDisplay ();
     }
    
     /** Write one or more lines to the display - beginning just after the
     *  last line written
     *
     *   @param  text the text to display
     */
     public   void  display ( String  text )
     {
        display . display ( text );
     }
     
     /** Simulate reading input from the keyboard
     *
     *   @param  mode the input mode to use - one of the constants defined below.
     *   @param  maxValue the maximum acceptable value (used in MENU_MODE only)
     *   @return  the line that was entered - null if user pressed CANCEL.
     */
     public   String  readInput ( int  mode ,   int  maxValue )
     {
         return  keyboard . readInput ( mode ,  maxValue );
     }
    
     /** Simulate dispensing cash to a customer
     *
     *   @param  amount the amount of cash to dispense
     *
     *  Precondition: amount is <= cash on hand
     */
     public   void  dispenseCash ( Money  amount )
     {
        cashDispenser . animateDispensingCash ( amount );
     }

     /** Simulate accepting an envelope from customer.
     *
     *  return true if an envelope was received within the prescribed time,
     *         else false
     */
     public   boolean  acceptEnvelope ()
     {
         return  envelopeAcceptor . acceptEnvelope ();
     }

     /** Simulate printing one line of a receipt
     *
     *   @param  text the line to print
     */
     public   void  printReceiptLine ( String  text )
     {
        receiptPrinter . println ( text );
     }
    
     /** Simulate printing a line to the log
     *
     *   @param  text the line to print
     */
     public   void  printLogLine ( String  text )
     {
        gui . printLogLine ( text );
     }
    
     /** Simulate sending a message to bank
     *
     *   @param  message the message to send
     *   @param  balances (out) balances in customer's account as reported
     *         by bank
     *   @return  status code returned by bank
     */
     public   Status  sendMessage ( Message  message ,   Balances  balances )
     {
         // Simulate time taken to send message over network
        
         try
         {
             Thread . sleep ( 2   *   1000 );
         }
         catch ( InterruptedException  e )
         {   }
        
         return  simulatedBank . handleMessage ( message ,  balances );
     }

     /** Notify the ATM that the state of the on-off switch has been changed
     *
     *   @param  on true if state is now "on", false if it is "off"
     */
     void  switchChanged ( boolean  on )
     {
         // The card reader is only enabled when the switch is on
        
        cardReader . setVisible ( on );
        
         if   ( on )
            atm . switchOn ();
         else
            atm . switchOff ();
     }
    
     /** Notify ATM that a card has been inserted
     */
     void  cardInserted ()
     {
        atm . cardInserted ();
     }
    
     /** Accessor for GUI Panel that simulates the ATM
     *
     *   @return  the GUI Panel
     */
     public  GUI getGUI ()
     {
         return  gui ;
     }
    
     /** Accessor for simulated bank
     *
     *   @return  simulated bank
     */
     public   SimulatedBank  getSimulatedBank ()
     {
         return  simulatedBank ;
     }

     /* Possible values for mode parameter to readInput() */
    
     /** Read input in PIN mode - allow user to enter several characters,
     *  and to clear the line if the user wishes; echo as asterisks
     */
     public   static   final   int  PIN_MODE  =   1 ;
    
     /** Read input in amount mode - allow user to enter several characters,
     *  and to clear the line if the user wishes; echo what use types
     */
     public   static   final   int  AMOUNT_MODE  =   2 ;
    
     /** Read input in menu choice mode - wait for one digit key to be pressed,
     *  and return value immediately.
     */
     public   static   final   int  MENU_MODE  =   3 ;
    
     /** The ATM object for the ATM being simulated
     */
     private  ATM atm ;
    
     /** The simulated operator panel
     */
     private   SimOperatorPanel  operatorPanel ;
    
     /** The simulated card reader
     */
     private   SimCardReader  cardReader ;
    
     /** The simulated display
     */
     private   SimDisplay  display ;
    
     /** The simulated keyboard
     */
     private   SimKeyboard  keyboard ;
    
     /** The simulated cash dispenser
     */
     private   SimCashDispenser  cashDispenser ;
    
     /** The simulated envelope acceptor
     */
     private   SimEnvelopeAcceptor  envelopeAcceptor ;
    
     /** The simulated receipt printer
     */
     private   SimReceiptPrinter  receiptPrinter ;
    
     /** Panel containing the GUI that simulates the ATM
     */
     private  GUI gui ;
    
     /** Simulated bank
     */
     private   SimulatedBank  simulatedBank ;
    
     /** The one and only instance of this class
     */
     private   static   Simulation  theInstance ;
}