Modify the implementations of the classes in the ATM example so that the bank manages a collection of bank accounts and a separate collection of customers. Allow joint accounts in which some accounts can have more than one customer.

Complete the following files:

Bank.java

Customer.java

Use the following files:

ATM.java

/**
   An ATM that accesses a bank.
*/
public class ATM 
{  
   private int state;
   private int customerNumber;
   private Customer currentCustomer;
   private BankAccount currentAccount;
   private Bank theBank;
   
   public static final int START = 1;
   public static final int PIN = 2;
   public static final int ACCOUNT = 3;
   public static final int TRANSACT = 4;

   public static final int CHECKING = 1;
   public static final int SAVINGS = 2;

   /**
      Constructs an ATM for a given bank.
      @param aBank the bank to which this ATM connects
   */    
   public ATM(Bank aBank)
   {
      theBank = aBank;
      reset();
   }

   /**
      Resets the ATM to the initial state.
   */
   public void reset()
   {
      customerNumber = -1;
      currentAccount = null;
      state = START;             
   }

   /** 
      Sets the current customer number 
      and sets state to PIN. 
      (Precondition: state is START)
      @param number the customer number.
   */
   public void setCustomerNumber(int number) 
   {
      assert state == START;
      customerNumber = number;
      state = PIN;
   }

   /** 
      Finds customer in bank.
      If found sets state to ACCOUNT, else to START.
      (Precondition: state is PIN)
      @param pin the PIN of the current customer
   */
   public void selectCustomer(int pin)
   {  
      assert state == PIN;
      currentCustomer 
         = theBank.findCustomer(customerNumber, pin);
      if (currentCustomer == null) 
         state = START;
      else 
         state = ACCOUNT;
   }
   
   /** 
      Sets current account to checking or savings. Sets 
      state to TRANSACT. 
      (Precondition: state is ACCOUNT or TRANSACT)
      @param account one of CHECKING or SAVINGS
   */
   public void selectAccount(int account)
   {
      assert state == ACCOUNT || state == TRANSACT;
      if (account == CHECKING)
         currentAccount = currentCustomer.getCheckingAccount();
      else
         currentAccount = currentCustomer.getSavingsAccount();
      state = TRANSACT;
   }

   /** 
      Withdraws amount from current account. 
      (Precondition: state is TRANSACT)
      @param value the amount to withdraw
   */
   public void withdraw(double value)
   {  
      assert state == TRANSACT;
      currentAccount.withdraw(value);
   }

   /** 
      Deposits amount to current account. 
      (Precondition: state is TRANSACT)
      @param value the amount to deposit
   */
   public void deposit(double value)
   {  
      assert state == TRANSACT;
      currentAccount.deposit(value);
   }

   /** 
      Gets the balance of the current account. 
      (Precondition: state is TRANSACT)
      @return the balance
   */
   public double getBalance()
   {  
      assert state == TRANSACT;
      return currentAccount.getBalance();
   }

   /**
      Moves back to the previous state.
   */
   public void back()
   {
      if (state == TRANSACT)
         state = ACCOUNT;
      else if (state == ACCOUNT)
         state = PIN;
      else if (state == PIN)
         state = START;
   }

   /**
      Gets the current state of this ATM.
      @return the current state
   */
   public int getState()
   {
      return state;
   }
}

ATMSimulator.java

import java.io.IOException;
import java.util.Scanner;

/**
   A text-based simulation of an automatic teller machine.
*/
public class ATMSimulator
{  
   public static void main(String[] args)
   {  
      ATM theATM;
      try
      {  
         Bank theBank = new Bank();
         theBank.readCustomers("customers.txt");
         theATM = new ATM(theBank);
      }
      catch(IOException e)
      {  
         System.out.println("Error opening accounts file.");
         return;
      }

      Scanner in = new Scanner(System.in);

      while (true)
      {
         int state = theATM.getState();
         if (state == ATM.START)
         {
            System.out.print("Enter customer number (0 to quit): ");
            int number = in.nextInt();
            if (number == 0) return;
            theATM.setCustomerNumber(number);            
         }
         else if (state == ATM.PIN)
         {
            System.out.print("Enter PIN: ");
            int pin = in.nextInt();
            theATM.selectCustomer(pin);
         }
         else if (state == ATM.ACCOUNT)
         {
            System.out.print("A=Checking, B=Savings, C=Quit: ");
            String command = in.next();
            if (command.equalsIgnoreCase("A"))
               theATM.selectAccount(ATM.CHECKING);
            else if (command.equalsIgnoreCase("B"))
               theATM.selectAccount(ATM.SAVINGS);
            else if (command.equalsIgnoreCase("C"))
               theATM.reset();
            else
               System.out.println("Illegal input!");                        
         }
         else if (state == ATM.TRANSACT)
         {
            System.out.println("Balance=" + theATM.getBalance());
            System.out.print("A=Deposit, B=Withdrawal, C=Cancel: ");
            String command = in.next();
            if (command.equalsIgnoreCase("A"))
            {
               System.out.print("Amount: ");
               double amount = in.nextDouble();
               theATM.deposit(amount);
               theATM.back();
            }
            else if (command.equalsIgnoreCase("B"))
            {
               System.out.print("Amount: ");
               double amount = in.nextDouble();
               theATM.withdraw(amount);
               theATM.back();
            }
            else if (command.equalsIgnoreCase("C"))
               theATM.back();
            else
               System.out.println("Illegal input!");                                    
         }         
      }
   }
}

BankAccount.java

/**
   A bank account has a balance that can be changed by 
   deposits and withdrawals.
*/
public class BankAccount
{  
   private double balance; 

   /**
      Constructs a bank account with a zero balance.
   */
   public BankAccount()
   {  
      balance = 0;
   }

   /**
      Constructs a bank account with a given balance.
      @param initialBalance the initial balance
   */
   public BankAccount(double initialBalance)
   {  
      balance = initialBalance;
   }
 
   /** 
      Deposits money into the account.
      @param amount the amount of money to withdraw
   */
   public void deposit(double amount) 
   {  
      balance = balance + amount;
   }

   /** 
      Withdraws money from the account.
      @param amount the amount of money to deposit
   */
   public void withdraw(double amount) 
   {  
      balance = balance - amount;
   }

   /** 
      Gets the account balance.
      @return the account balance
   */
   public double getBalance()
   {  
      return balance; 
   }
}