|
Bank |
|
1 // joi/7/bank/Bank.java 2 // 3 // 4 // Copyright 2003 Bill Campbell and Ethan Bolker 5 6 import java.util.*; 7 8 /** 9 * A Bank object simulates the behavior of a simple bank/ATM. 10 * It contains a Terminal object and a collection of 11 * BankAccount objects. 12 * 13 * The visit method opens this Bank for business, 14 * prompting the customer for input. 15 * 16 * To create a Bank and open it for business issue the command 17 * <code>java Bank</code>. 18 * 19 * @see BankAccount 20 * @version 7 21 */ 22 23 public class Bank 24 { 25 private String bankName; // the name of this Bank 26 private Terminal atm; // for talking with the customer 27 private int balance = 0; // total cash on hand 28 private int transactionCount = 0; // number of Bank transactions 29 private Month month; // the current month. 30 private Map accountList; // mapping names to accounts. 31 32 private int checkFee = 2; // cost for each check 33 private int transactionFee = 1; // fee for each transaction 34 private int monthlyCharge = 5; // monthly charge 35 private double interestRate = 0.05; // annual rate paid on savings 36 private int maxFreeTransactions = 3; // for savings accounts 37 38 // what the banker can ask of the bank 39 40 private static final String BANKER_COMMANDS = 41 "Banker commands: " + 42 "exit, open, customer, nextmonth, report, help."; 43 44 // what the customer can ask of the bank 45 46 private static final String CUSTOMER_TRANSACTIONS = 47 " Customer transactions: " + 48 "deposit, withdraw, transfer, balance, cash check, quit, help."; 49 50 /** 51 * Construct a Bank with the given name and Terminal. 52 * 53 * @param bankName the name for this Bank. 54 * @param atm this Bank's Terminal. 55 */ 56 57 public Bank( String bankName, Terminal atm ) 58 { 59 this.atm = atm; 60 this.bankName = bankName; 61 accountList = new TreeMap(); 62 month = new Month(); 63 } 64 65 /** 66 * Simulates interaction with a Bank. 67 * Presents the user with an interactive loop, prompting for 68 * banker transactions and in the case of the banker 69 * transaction "customer", an account id and further 70 * customer transactions. 71 */ 72 73 public void visit() 74 { 75 instructUser(); 76 77 String command; 78 while (!(command = 79 atm.readWord("banker command: ")).equals("exit")) { 80 81 if (command.startsWith("h")) { 82 help( BANKER_COMMANDS ); 83 } 84 else if (command.startsWith("o")) { 85 openNewAccount(); 86 } 87 else if (command.startsWith("n")) { 88 newMonth(); 89 } 90 else if (command.startsWith("r")) { 91 report(); 92 } 93 else if (command.startsWith( "c" ) ) { 94 BankAccount acct = whichAccount(); 95 if ( acct != null ) { 96 processTransactionsForAccount( acct ); 97 } 98 } 99 else { 100 // Unrecognized Request 101 atm.println( "unknown command: " + command ); 102 } 103 } 104 report(); 105 atm.println( "Goodbye from " + bankName ); 106 } 107 108 109 // Open a new bank account, 110 // prompting the user for information. 111 112 private void openNewAccount() 113 { 114 String accountName = atm.readWord("Account name: "); 115 char accountType = 116 atm.readChar( "Type of account (r/c/f/s): " ); 117 try { 118 int startup = readPosAmt( "Initial deposit: " ); 119 BankAccount newAccount; 120 switch( accountType ) { 121 case 'c': 122 newAccount = new CheckingAccount(startup, this); 123 break; 124 case 'f': 125 newAccount = new FeeAccount(startup, this); 126 break; 127 case 's': 128 newAccount = new SavingsAccount(startup, this); 129 break; 130 case 'r': 131 newAccount = new RegularAccount( startup, this ); 132 break; 133 default: 134 atm.println("invalid account type: " + accountType); 135 return; 136 } 137 accountList.put( accountName, newAccount ); 138 atm.println( "opened new account " + accountName 139 + " with $" + startup ); 140 } // end of try block 141 catch (NegativeAmountException e) { 142 atm.errPrintln( 143 "can't start with a negative balance"); 144 } 145 catch (InsufficientFundsException e) { 146 atm.errPrintln("Initial deposit less than fee"); 147 } 148 } 149 150 // Prompt the customer for transaction to process. 151 // Then send an appropriate message to the account. 152 153 private void processTransactionsForAccount( BankAccount acct ) 154 { 155 help( CUSTOMER_TRANSACTIONS ); 156 157 String transaction; 158 while (!(transaction = 159 atm.readWord(" transaction: ")).equals("quit")) { 160 161 try { 162 if ( transaction.startsWith( "h" ) ) { 163 help( CUSTOMER_TRANSACTIONS ); 164 } 165 else if ( transaction.startsWith( "d" ) ) { 166 int amount = readPosAmt( " amount: " ); 167 atm.println(" deposited " 168 + acct.deposit( amount )); 169 } 170 else if ( transaction.startsWith( "w" ) ) { 171 int amount = readPosAmt( " amount: " ); 172 atm.println(" withdrew " 173 + acct.withdraw( amount )); 174 } 175 else if ( transaction.startsWith( "c" ) ) { 176 int amount = readPosAmt( " amount of check: " ); 177 try { // to cast acct to CheckingAccount ... 178 atm.println(" cashed check for " + 179 ((CheckingAccount) acct).honorCheck( amount )); 180 } 181 catch (ClassCastException e) { 182 // if not a checking account, report error 183 atm.errPrintln( 184 " Sorry, not a checking account." ); 185 } 186 } 187 else if (transaction.startsWith("t")) { 188 atm.print( " to "); 189 BankAccount toacct = whichAccount(); 190 if (toacct != null) { 191 int amount = readPosAmt(" amount to transfer: "); 192 atm.println(" transfered " 193 + toacct.deposit(acct.withdraw(amount))); 194 } 195 } 196 else if (transaction.startsWith("b")) { 197 atm.println(" current balance " 198 + acct.requestBalance()); 199 } 200 else { 201 atm.println(" sorry, unknown transaction" ); 202 } 203 } 204 catch (InsufficientFundsException e) { 205 atm.errPrintln( " Insufficient funds " + 206 e.getMessage() ); 207 } 208 catch (NegativeAmountException e) { 209 atm.errPrintln(" Sorry, negative amounts disallowed." ); 210 } 211 atm.println(); 212 } 213 } 214 215 // Prompt for an account name (or number), look it up 216 // in the account list. If it's there, return it; 217 // otherwise report an error and return null. 218 219 private BankAccount whichAccount() 220 { 221 String accountName = atm.readWord( "account name: " ); 222 BankAccount account = (BankAccount) accountList.get(accountName); 223 if (account == null) { 224 atm.println( "not a valid account" ); 225 } 226 return account; 227 } 228 229 // Action to take when a new month starts. 230 // Update the month field by sending a next message. 231 // Loop on all accounts, sending each a newMonth message. 232 233 private void newMonth() 234 { 235 month.next(); 236 Iterator i = accountList.keySet().iterator(); 237 while ( i.hasNext() ) { 238 String name = (String) i.next(); 239 BankAccount acct = (BankAccount)accountList.get(name); 240 try { 241 acct.newMonth(); 242 } 243 catch (InsufficientFundsException exception) { 244 atm.errPrintln( 245 "Insufficient funds in account \"" + 246 name + "\" for monthly fee" ); 247 } 248 } 249 } 250 251 // Report bank activity. For each BankAccount, 252 // print the customer id (name or number), balance, and 253 // the number of transactions. Then print Bank totals. 254 255 private void report() 256 { 257 atm.println( bankName + " report for " + month ); 258 atm.println( "\nSummaries of individual accounts:" ); 259 atm.println( "account balance transaction count" ); 260 for (Iterator i = accountList.keySet().iterator(); 261 i.hasNext(); ) { 262 String accountName = (String) i.next(); 263 BankAccount acct = (BankAccount) accountList.get(accountName); 264 atm.println(accountName + "\t$" + acct.getBalance() + "\t\t" 265 + acct.getTransactionCount()); 266 } 267 atm.println( "\nBank totals"); 268 atm.println( "open accounts: " + getNumberOfAccounts() ); 269 atm.println( "cash on hand: $" + getBalance()); 270 atm.println( "transactions: " + getTransactionCount()); 271 atm.println(); 272 } 273 274 275 // Welcome the user to the bank and instruct her on 276 // her options. 277 278 private void instructUser() 279 { 280 atm.println( "Welcome to " + bankName ); 281 atm.println( month.toString() ); 282 atm.println( "Open some accounts and work with them." ); 283 help( BANKER_COMMANDS ); 284 } 285 286 // Display a help string. 287 288 private void help( String helpString ) 289 { 290 atm.println( helpString ); 291 atm.println(); 292 } 293 294 // Read amount prompted for from the atm. 295 // Throw a NegativeAmountException if amount < 0 296 297 private int readPosAmt( String prompt ) 298 throws NegativeAmountException 299 { 300 int amount = atm.readInt( prompt ); 301 if (amount < 0) { 302 throw new NegativeAmountException(); 303 } 304 return amount; 305 } 306 307 /** 308 * Increment bank balance by given amount. 309 * 310 * @param amount the amount increment. 311 */ 312 313 public void incrementBalance(int amount) 314 { 315 balance += amount; 316 } 317 318 /** 319 * Increment by one the count of transactions, 320 * for this bank. 321 */ 322 323 public void countTransaction() 324 { 325 transactionCount++; 326 } 327 328 /** 329 * Get the number of transactions performed by this bank. 330 * 331 * @return number of transactions performed. 332 */ 333 334 public int getTransactionCount( ) 335 { 336 return transactionCount ; 337 } 338 339 /** 340 * The charge this bank levies for cashing a check. 341 * 342 * @return check fee 343 */ 344 345 public int getCheckFee( ) 346 { 347 return checkFee ; 348 } 349 350 /** 351 * The charge this bank levies for a transaction. 352 * 353 * @return the transaction fee 354 */ 355 356 public int getTransactionFee( ) 357 { 358 return transactionFee ; 359 } 360 361 /** 362 * The charge this bank levies each month. 363 * 364 * @return the monthly charge 365 */ 366 367 public int getMonthlyCharge( ) 368 { 369 return monthlyCharge; 370 } 371 372 /** 373 * The current interest rate on savings. 374 * 375 * @return the interest rate 376 */ 377 378 public double getInterestRate( ) 379 { 380 return interestRate; 381 } 382 383 /** 384 * The number of free transactions per month. 385 * 386 * @return the number of transactions 387 */ 388 389 public int getMaxFreeTransactions() 390 { 391 return maxFreeTransactions; 392 } 393 394 /** 395 * Get the current bank balance. 396 * 397 * @return current bank balance. 398 */ 399 400 public int getBalance() 401 { 402 return balance; 403 } 404 405 /** 406 * Get the current number of open accounts. 407 * 408 * @return number of open accounts. 409 */ 410 411 public int getNumberOfAccounts() 412 { 413 return accountList.size(); 414 } 415 416 /** 417 * Run the simulation by creating and then visiting a new Bank. 418 * <p> 419 * A -e argument causes the input to be echoed. 420 * This can be useful for executing the program against 421 * a test script, e.g., 422 * <pre> 423 * java Bank -e < Bank.in 424 * </pre> 425 * 426 * @param args the command line arguments: 427 * <pre> 428 * -e echo input. 429 * bankName any other command line argument. 430 * </pre> 431 */ 432 433 public static void main( String[] args ) 434 { 435 // parse the command line arguments for the echo 436 // flag and the name of the bank 437 438 boolean echo = false; // default does not echo 439 String bankName = "River Bank"; // default bank name 440 441 for (int i = 0; i < args.length; i++ ) { 442 if (args[i].equals("-e")) { 443 echo = true; 444 } 445 else { 446 bankName = args[i]; 447 } 448 } 449 Bank aBank = new Bank( bankName, new Terminal(echo) ); 450 aBank.visit(); 451 } 452 } 453
|
Bank |
|