1 // joi/5/bank/Bank.java
2 //
3 //
4 // Copyright 2003 Bill Campbell and Ethan Bolker
5 // Ethan Bolker: modifications Spring 2004 for cs110 hw7
6 // allow banker to open a SavingsAccount
7 // enable banker's newmonth command
8 //
9 // allow customer to close his or her account (answer to hw6)
10 // check cashing is with customer transaction "cash check" or
11 // "check" (just look at first two characters). To close an
12 // account, need the whole word "close" to guard against error.
13
14 import java.util.*;
15
16 /**
17 * A Bank object simulates the behavior of a simple bank/ATM.
18 * It contains a Terminal object and a collection of
19 * BankAccount objects.
20 *
21 * The visit method opens this Bank for business,
22 * prompting the customer for input.
23 *
24 * To create a Bank and open it for business issue the command
25 * java Bank
.
26 *
27 * @see BankAccount
28 * @version 5.1
29 */
30
31 public class Bank
32 {
33 private String bankName; // the name of this Bank
34 private Terminal atm; // for talking with the customer
35 private int balance = 0; // total cash on hand
36 private int transactionCount = 0; // number of Bank transactions
37 private Month month; // the current month.
38
39 private TreeMap accountList; // mapping names to accounts.
40
41 // what the banker can ask of the bank
42
43 private static final String BANKER_COMMANDS =
44 "Banker commands: " +
45 "exit, open, customer, report, newmonth, help.";
46
47 // what the customer can ask of the bank
48
49 private static final String CUSTOMER_TRANSACTIONS =
50 " Customer transactions: " +
51 "deposit, withdraw, transfer, balance, cash check, close, quit, help.";
52
53 /**
54 * Construct a Bank with the given name and Terminal.
55 *
56 * @param bankName the name for this Bank.
57 * @param atm this Bank's Terminal.
58 */
59
60 public Bank( String bankName, Terminal atm )
61 {
62 this.atm = atm;
63 this.bankName = bankName;
64 accountList = new TreeMap();
65 month = new Month();
66 }
67
68 /**
69 * Simulates interaction with a Bank.
70 * Presents the user with an interactive loop, prompting for
71 * banker transactions and in case of the banker transaction
72 * "customer", an account id and further customer
73 * transactions.
74 */
75
76 public void visit()
77 {
78 instructUser();
79
80 String command;
81 while (!(command =
82 atm.readWord("banker command: ")).equals("exit")) {
83
84 if (command.startsWith("h")) {
85 help( BANKER_COMMANDS );
86 }
87 else if (command.startsWith("o")) {
88 openNewAccount();
89 }
90 else if (command.startsWith("r")) {
91 report();
92 }
93 else if (command.startsWith("n")) {
94 newMonth();
95 }
96 else if (command.startsWith( "c" ) ) {
97 BankAccount acct = whichAccount();
98 if ( acct != null )
99 processTransactionsForAccount( acct );
100 }
101 else {
102 // Unrecognized Request
103 atm.println( "unknown command: " + command );
104 }
105 }
106 report();
107 atm.println( "Goodbye from " + bankName );
108 }
109
110
111 // Open a new bank account,
112 // prompting the user for information.
113
114 private void openNewAccount()
115 {
116 String accountName = atm.readWord( "Account name: " );
117 char accountType =
118 atm.readChar( "Checking/Fee/Regular/Savings? (c/f/r/s): " );
119 int startup = atm.readInt( "Initial deposit: " );
120 BankAccount newAccount;
121 switch( accountType ) {
122 case 'c':
123 newAccount = new CheckingAccount( startup, this );
124 break;
125 case 'f':
126 newAccount = new FeeAccount( startup, this );
127 break;
128 case 'r':
129 newAccount = new RegularAccount( startup, this );
130 break;
131 case 's':
132 newAccount = new SavingsAccount( startup, this );
133 break;
134 default:
135 atm.println("invalid account type: " + accountType);
136 return;
137 }
138 accountList.put( accountName, newAccount );
139 atm.println( "opened new account " + accountName
140 + " with $" + startup );
141 }
142
143 // Prompt the customer for transaction to process.
144 // Then send an appropriate message to the account.
145
146 private void processTransactionsForAccount( BankAccount acct )
147 {
148 help( CUSTOMER_TRANSACTIONS );
149
150 String transaction;
151 while (!(transaction =
152 atm.readWord(" transaction: ")).equals("quit")) {
153
154 if ( transaction.startsWith( "h" ) ) {
155 help( CUSTOMER_TRANSACTIONS );
156 }
157 else if ( transaction.startsWith( "d" ) ) {
158 int amount = atm.readInt( " amount: " );
159 atm.println(" deposited " + acct.deposit( amount ));
160 }
161 else if ( transaction.startsWith( "w" ) ) {
162 int amount = atm.readInt( " amount: " );
163 atm.println(" withdrew " + acct.withdraw( amount ));
164 }
165 else if ( transaction.startsWith( "ca" ) ||
166 transaction.startsWith( "ch" ) ) {
167 int amount = atm.readInt( " amount of check: " );
168 atm.println(" cashed check for " +
169 ((CheckingAccount)acct).honorCheck( amount ));
170 }
171 else if (transaction.startsWith("t")) {
172 atm.print( " to ");
173 BankAccount toacct = whichAccount();
174 if (toacct != null) {
175 int amount = atm.readInt(" amount to transfer: ");
176 atm.println(" transfered " +
177 toacct.deposit(acct.withdraw(amount)));
178 }
179 }
180 else if (transaction.startsWith("b")) {
181 atm.println(" current balance " +
182 acct.requestBalance());
183 }
184 else if (transaction.equals("close")) {
185 close(acct);
186 break; // no more transactions for this account!
187 }
188 else {
189 atm.println(" sorry, unknown transaction" );
190 }
191 }
192 atm.println();
193 }
194
195
196 // Close a bank account, inform the user that a check
197 // for the balance of the account will be mailed to them.
198
199 private void close( BankAccount accountToClose )
200 {
201 atm.println(" We will send you a check for $" +
202 accountToClose.getBalance());
203 atm.println(" Thank you for banking with " +
204 bankName);
205
206 //update the bank's balance and transactionCount
207 balance -= accountToClose.getBalance();
208 transactionCount -= accountToClose.getTransactionCount();
209
210 // find key, to remove the account from the accountList
211 Set keys = accountList.keySet();
212 Iterator keyIterator = keys.iterator();
213 while( keyIterator.hasNext() ) {
214 String accountName = (String)keyIterator.next();
215 BankAccount account = (BankAccount)accountList.get(accountName);
216 if ( accountToClose.equals(account) ) {
217 accountList.remove(accountName);
218 break;
219 }
220 }
221 }
222
223 // Prompt for an account name (or number), look it up
224 // in the account list. If it's there, return it;
225 // otherwise report an error and return null.
226
227 private BankAccount whichAccount()
228 {
229 String accountName = atm.readWord( "account name: " );
230 BankAccount account = (BankAccount) accountList.get(accountName);
231 if (account == null) {
232 atm.println("not a valid account");
233 }
234 return account;
235 }
236
237 // Action to take when a new month starts.
238 // Update the month field by sending a next message.
239 // Loop on all accounts, sending each a newMonth message.
240
241 private void newMonth()
242 {
243 month.next();
244 for (Iterator i = accountList.values().iterator();
245 i.hasNext(); ) {
246 BankAccount acct = (BankAccount) i.next();
247 acct.newMonth();
248 }
249 }
250
251 // Report bank activity.
252 // For each BankAccount, print the account name,
253 // account balance and the number of transactions.
254 // Then print Bank totals.
255
256 private void report()
257 {
258 atm.println( bankName + " report for " + month );
259 atm.println( "\nSummaries of individual accounts:" );
260 atm.println( "account balance transaction count" );
261 for (Iterator i = accountList.keySet().iterator();
262 i.hasNext(); ) {
263 String accountName = (String) i.next();
264 BankAccount acct = (BankAccount) accountList.get(accountName);
265 atm.println(accountName + "\t$" + acct.getBalance() + "\t\t" +
266 acct.getTransactionCount());
267 }
268 atm.println( "\nBank totals");
269 atm.println( "open accounts: " + getNumberOfAccounts() );
270 atm.println( "cash on hand: $" + getBalance());
271 atm.println( "transactions: " + getTransactionCount());
272 atm.println();
273 }
274
275
276 // Welcome the user to the bank and instruct her on
277 // her options.
278
279 private void instructUser()
280 {
281 atm.println( "Welcome to " + bankName );
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 /**
295 * Increment bank balance by given amount.
296 *
297 * @param amount the amount increment.
298 */
299
300 public void incrementBalance(int amount)
301 {
302 balance += amount;
303 }
304
305 /**
306 * Increment by one the count of transactions,
307 * for this bank.
308 */
309
310 public void countTransaction()
311 {
312 transactionCount++;
313 }
314
315 /**
316 * Get the number of transactions performed by this bank.
317 *
318 * @return number of transactions performed.
319 */
320
321 public int getTransactionCount( )
322 {
323 return transactionCount ;
324 }
325
326 /**
327 * Get the current bank balance.
328 *
329 * @return current bank balance.
330 */
331
332 public int getBalance()
333 {
334 return balance;
335 }
336
337 /**
338 * Get the current number of open accounts.
339 *
340 * @return number of open accounts.
341 */
342
343 public int getNumberOfAccounts()
344 {
345 return accountList.size();
346 }
347
348 /**
349 * Run the simulation by creating and then visiting a new Bank.
350 *
351 *
352 * A -e argument causes the input to be echoed. 353 * This can be useful for executing the program against 354 * a test script, e.g., 355 *
356 * java Bank -e < Bank.in 357 *358 * 359 * @param args the command line arguments: 360 *
361 * -e echo input. 362 * bankName any other command line argument. 363 *364 */ 365 366 public static void main( String[] args ) 367 { 368 // parse the command line arguments for the echo 369 // flag and the name of the bank 370 371 boolean echo = false; // default does not echo 372 String bankName = "Faithless Trust"; // default bank name 373 374 for (int i = 0; i < args.length; i++ ) { 375 if (args[i].equals("-e")) { 376 echo = true; 377 } 378 else { 379 bankName = args[i]; 380 } 381 } 382 Bank aBank = new Bank( bankName, new Terminal(echo) ); 383 aBank.visit(); 384 } 385 }