Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Java implementation of class Statement, MonthlyStatement, QuarterlyStatement, HalfYearlyStatement, FullYearStatement, and MultiYearStatement( Composite Java Design Pattern ). Question: The bank like to provide statements to the

Java implementation of class "Statement", "MonthlyStatement", "QuarterlyStatement", "HalfYearlyStatement", "FullYearStatement", and MultiYearStatement"(Composite Java Design Pattern).

Question: The bank like to provide statements to the customer. These could be monthly, quarterly, half-yealry, full year or multi-year statements. Each higher level statement woudl recursively include its component statements.

Expected output:

-- Testing Monthly Statement by itself --

**Monthly Statement for January, 2022

-- Testing Quartely Statement --

** Combo Statement of Quartely Statement for Q1 2022

** Monthly Statement for January, 2022

** Monthly Statement for February, 2022

** Monthly Statement for March, 2022

-- Testing Quartely Statement --

** Combo Statement of Quartely Statement for Q2 2022

** Monthly Statement for April, 2022

** Monthly Statement for May, 2022

** Monthly Statement for June, 2022

-- Testing Half yearly Statement --

** Combo Statement of First Half yearly Statement for Q2 2022

** Monthly Statement for April, 2022

** Monthly Statement for May, 2022

** Monthly Statement for June, 2022

** Combo Statement of Quartely Statement for Q1 2022

** Monthly Statement for January, 2022

** Monthly Statement for February, 2022

** Monthly Statement for March, 2022

-- Testing Quartely Statement --

** Combo Statement of Quartely Statement for Q2 2022

** Monthly Statement for April, 2022

** Monthly Statement for May, 2022

** Monthly Statement for June, 2022

---------------------------------------------------------------------------------------------------

public class CompositePatternTest {

public static void main(String[] args) {

//

}

}

classStatement { public void print() { //... } }

classMonthlyStatementextends Statement { public void print() { //... super.print(); //... } }

classQuarterlyStatementextends Statement { public void print() { //... super.print(); //... } }

classHalfYearlyStatementextends Statement { public void print() { //... super.print(); //... } }

classFullYearlyStatementextends Statement { public void print() { //... super.print(); //... } }

classMultiYearlyStatementextends Statement { public void print() { //... super.print(); //... } }

-----------------------------------------------------------------------------------

import java.text.DateFormat; import java.util.Date; import java.util.UUID;

public abstract class Transaction {

private final Date transactionDate; private final UUID transactionId;

private String description;

private final int transactionAmount;

private final Customer transactionOwner;

private int endingBalance;

public Transaction(Date transactionDate, String description, int transactionAmount, Customer transactionOwner) { this.transactionId = UUID.randomUUID(); this.transactionDate = transactionDate; this.description = description; this.transactionAmount = transactionAmount; this.transactionOwner = transactionOwner; }

public Date getTransactionDate() { return this.transactionDate; }

public int getTransactionAmount() { return this.transactionAmount; }

public Customer getTransactionOwner() { return this.transactionOwner; }

public String getDescription() { return description; }

public void setDescription(String description) { this.description = description; }

public int getEndingBalance() { return endingBalance; }

public void setEndingBalance(int endingBalance) { this.endingBalance = endingBalance; }

public void print(Account account) { if (account != null) { System.out.printf("\t%s Account: %s\t%10s $%-6d\tby %-10s Running Balance $%d ", DateFormat.getDateInstance().format(this.transactionDate), account.getAccountId(), this.description, this.transactionAmount, this.transactionOwner.getName(), this.getEndingBalance()); } else { System.out.printf("\t%s %10s $%-6d\tby %-10s ", DateFormat.getDateInstance().format(this.transactionDate), this.description, this.transactionAmount, this.transactionOwner.getName()); }

}

protected abstract void execute();

}

-------------------------------------------------------------------------------------------

import java.util.Date;

public class DepositTransaction extends Transaction {

public DepositTransaction(Date transactionDate, int amount, Customer transactionOwner, Account toAccount) { super(transactionDate, "Deposit", amount, transactionOwner); if (toAccount != null) toAccount.addTransaction(this); }

public void execute() { System.out.println("Transaction::DepositTransaction"); } }

--------------------------

import java.util.Date;

public class WithdrawTransaction extends Transaction {

public WithdrawTransaction(Date transactionDate, int amount, Customer transactionOwner, Account fromAccount) { super(transactionDate, "Withdraw", amount, transactionOwner); if (fromAccount != null) fromAccount.addTransaction(this); }

public void execute() { System.out.println("Transaction::WithdrawTransaction"); } } ------------------------------------------------------------------

import java.text.DateFormat; import java.util.Date;

public class TransferTransaction extends Transaction {

private final Account fromAccount; private final Account toAccount;

public TransferTransaction(Date transactionDate, int amount, Customer transactionOwner, Account fromAccount, Account toAccount) {

super(transactionDate, "Transfer", amount, transactionOwner); this.fromAccount = fromAccount; this.toAccount = toAccount; this.fromAccount.addTransaction(this);

synchronized (this.fromAccount) { if (amount <= this.fromAccount.getCurrentBalance()) { Transaction t1 = new WithdrawTransaction(transactionDate, amount, transactionOwner, fromAccount); Transaction t2 = new DepositTransaction(transactionDate, amount, transactionOwner, toAccount); } }

}

public Account getFromAccount() { return fromAccount; }

public Account getToAccount() { return toAccount; }

public void execute() { System.out.println("transaction::Transfertransaction"); }

public void print(Account account) {

System.out.printf("\t%s %10s $%-6d\tby %-10s ", DateFormat.getDateInstance().format(this.getTransactionDate()), this.getDescription(), this.getTransactionAmount(), this.getTransactionOwner().getName());

}

} ----------------------------------------------------------------------------------------------------- public class TransactionDecorator extends Transaction{

protected Transaction transaction;

public TransactionDecorator(Transaction transaction){

super(transaction.getTransactionDate(), transaction.getDescription(), transaction.getTransactionAmount(), transaction.getTransactionOwner());

this.transaction = transaction;

}

public void execute(){

this.transaction.execute();

}

}

-----------------------------------------------------------

public class LoggingTransaction extends TransactionDecorator {

public LoggingTransaction(Transaction transaction){

super(transaction);

}

public void execute(){

System.out.println("Logging @" + new Date() + "->Transaction::" + transaction.getDescription());

transaction.execute();

}

}

--------------------------------------------------------------------------------------------------------------------------------

class SecurityTransaction extends TransactionDecorator {

public SecurityTransaction(Transaction transaction){

super(transaction);

}

public void execute(){

System.out.println("Security check @" + new Date() + "->Transaction::" + transaction.getDescription());

transaction.execute();

}

}

--------------------------------------------------------------------------------------------------

class DepositTransaction extends Transaction{

public DepositTransaction(int amount, Customer transactionOwner, Account toAccount){

super(amount, transactionOwner);

if(toAccount != null)

toAccount.addTransaction(this);

}

public void execute(){

System.out.println("Transaction::DepositTransaction");

}

}

-------------------------------------------------------------------------------------------------

class WithdrawTransaction extends Transaction{

public WithdrawTransaction(int amount, Customer transactionOwner, Account fromAccount){

super(amount, transactionOwner);

if(fromAccount != null)

fromAccount.addTransaction(this);

}

public void execute(){

System.out.println("Transaction::WithdrawTransaction");

}

}

----------------------------------------------------------------------

class TransferTransaction extends Transaction{

private Account fromAccount;

private Account toAccount;

public TransferTransaction(int amount, Customer transactionOwner, Account fromAccount, Account toAccount){

super(amount, transactionOwner);

this.fromAccount = fromAccount;

this.toAccount = toAccount;

this.fromAccount.addTransaction(this);

synchronized (this.fromAccount) {

if(amount <= this.fromAccount.getCurrentBalance()) {

Transaction t1 = new WithdrawTransaction(amount, transactionOwner, fromAccount);

Transaction t2 = new DepositTransaction(amount, transactionOwner, toAccount);

}

}

}

public void execute(){

System.out.println("Transaction::TransferTransaction");

}

}

class Customer {

private final String name; private final String customerId; private final Date registrationDate; private final List accountList; public Customer(String name, String customerId, Date registrationDate) { this.name = name; this.customerId = customerId; this.registrationDate = registrationDate; this.accountList = new ArrayList<>(); }

public String getName() { return this.name; }

public String getCustomerId() { return this.customerId; }

public Date getRegistrationDate() { return this.registrationDate; }

public void addAccount(Account account) { accountList.add(account); /* Add the account to the customer's accountList */ }

public void printStatement(Date toDate) {

System.out.println(" BEGIN ACCOUNT STATEMENT - " + this.getName() + " - " + DateFormat.getDateInstance().format(toDate)); for(int i=0; i < accountList.size(); i++) { accountList.get(i).printStatement(toDate); }

System.out.println(" END ACCOUNT STATEMENT "); }

} --------------------------------------------------------------------------

class Account {

private final String accountId; private final Date openDate; private Date closeDate;

private final Customer primaryOwner; private Customer jointOwner;

private AccountStatus accountStatus;

private Date jointOwnershipDate;

private int currentBalance;

private final List transactionList;

public Account(Customer primaryOwner, String accountId, Date openDate) { this.accountId = accountId; this.openDate = openDate; this.accountStatus = AccountStatus.Open; this.currentBalance = 0; this.transactionList = new ArrayList<>(); this.primaryOwner = primaryOwner; primaryOwner.addAccount(this); }

public Customer getPrimaryOwner() { return this.primaryOwner; }

public String getAccountId() { return this.accountId; }

public Date getOpenDate() { return this.openDate; }

public AccountStatus getAccountStatus() { return this.accountStatus; }

public int getCurrentBalance() { return this.currentBalance; }

public void setJointOwner(Customer jointOwner, Date jointOwnershipDate) { this.jointOwner = jointOwner; this.jointOwnershipDate = jointOwnershipDate; jointOwner.addAccount(this); }

public Customer getJointOwner() { return this.jointOwner; }

public Date getJointOwnershipDate() { return this.jointOwnershipDate; }

protected synchronized void addTransaction(Transaction t) {

if (this.accountStatus == AccountStatus.Close) throw new BankException("Account " + this.getAccountId() + "closed... Transaction not allowed");

if (t instanceof DepositTransaction) { deposit(t.getTransactionAmount()); transactionList.add(t); t.setEndingBalance(currentBalance);; /* Update Ending Balance after the Deposit transaction and add transaction details in the Transaction List*/ t.print(this); } else if (t instanceof WithdrawTransaction) { WithdrawTransaction wt = (WithdrawTransaction) t;

if (wt.getTransactionAmount() <= currentBalance){ withdraw(wt.getTransactionAmount()); } else { wt.setDescription("Not enough balance, withdrawl ignored"); } transactionList.add(wt); wt.setEndingBalance(currentBalance); /* Update Ending Balance after the withdraw transaction (Successfull or not successful) and add transaction details in the Transaction List*/ wt.print(this); } else if (t instanceof TransferTransaction) {

TransferTransaction tr = (TransferTransaction) t;

if (tr.getToAccount().accountStatus == AccountStatus.Close) throw new BankException("Account " + this.getAccountId() + " closed... Transaction not allowed");

tr.setDescription("Transfer from " + this.getAccountId() + " to " + tr.getToAccount().getAccountId()); this.transactionList.add(tr); tr.getToAccount().transactionList.add(tr); /* Update Ending Balance of source/destination accounts after the transfer transaction and add transaction details in the Transaction List*/ tr.print(this); }

}

private synchronized void deposit(int amount) { this.currentBalance += amount; }

private synchronized void withdraw(int amount) { this.currentBalance -= amount; }

public synchronized void closeAccount(Date closeDate) { this.accountStatus = AccountStatus.Close; this.closeDate = closeDate; }

public void printStatement(Date toDate) {

System.out.println(" \tTransactions for Account " + this.accountId + " Primary Owner: " + this.primaryOwner.getName() + " ");

for (int i=0; i< transactionList.size();i++) { Transaction t =(Transaction) transactionList.get(i); /* print each transaction from the account holder's Transaction List*/ t.print(this); } }

}

------------------------------------------------------------------------------------

public class Bank {

private final Map customerMap; private final Map accountMap;

private static Bank bankInstance;

private Bank() { customerMap = new HashMap<>(); accountMap = new HashMap<>(); }

public static synchronized Bank getBankInstance() { if (bankInstance == null) { bankInstance = new Bank(); } return bankInstance; }

public synchronized Customer createCustomer(String name, String customerId, Date registrationDate) throws BankException {

if(customerMap.containsKey(customerId)) { throw new BankException ("customerId already exists"); } else { Customer customer = new Customer(name, customerId, registrationDate); customerMap.put(customerId, customer); return customer; } }

public synchronized Customer lookupCustomer(String customerId) throws BankException { Customer customer = customerMap.get(customerId); if(customer == null) { throw new BankException ("customerId does not exist"); } else { return customer; } }

public synchronized Account createAccount(String customerId, AccountType accountType, String accountId, Date openDate, int initialAmount) throws BankException {

if(accountMap.containsKey(accountId)) { throw new BankException ("accountId already exists"); } else { Customer customer = customerMap.get(customerId); Account account = null; switch(accountType) { case Checking -> { account = new CheckingAccount(customer, accountId, openDate, initialAmount); } case Savings -> { account = new SavingsAccount(customer, accountId, openDate, initialAmount); } } accountMap.put(accountId, account); return account; } } public synchronized Account lookupAccount(String accountId) { Account account = accountMap.get(accountId); if (account == null) { new BankException("accountId does not exist"); } else { return account; } return account; }

public synchronized void setJointOwner(String accountId, String primaryOwnerId, String jointOwnerId, Date jointOwnershipDate) {

Account account = this.lookupAccount(accountId); Customer primaryOwner = this.lookupCustomer(primaryOwnerId); Customer jointOwner = this.lookupCustomer(jointOwnerId);

if ((account != null) && (primaryOwner != null) && (jointOwner != null)) { if ( (account.getPrimaryOwner() == primaryOwner) && (account.getJointOwner() == null) ) { account.setJointOwner(jointOwner, jointOwnershipDate); } }

}

public synchronized void createTransaction(TransactionType transactionType, Date date, int amount, String customerId, String sourceAccountId, String destinationAccountId) { switch (transactionType) {

case Deposit -> { makeDeposit(date, amount, customerId, sourceAccountId); break; } case Withdraw -> { makeWithdrawal(date, amount, customerId, sourceAccountId); break; } case Transfer -> { makeTransfer(date, amount, customerId, sourceAccountId, destinationAccountId); } } }

private synchronized void makeDeposit(Date date, int amount, String customerId, String accountId) { Customer customer = this.lookupCustomer(customerId); Account account = this.lookupAccount(accountId); new DepositTransaction(date, amount, customer, account); }

private synchronized void makeWithdrawal(Date date, int amount, String customerId, String accountId) { Customer customer = this.lookupCustomer(customerId); Account account = this.lookupAccount(accountId); if (account != null && ((account.getPrimaryOwner() == customer) || (account.getJointOwner() != null && account.getJointOwner() == customer)) ) { new WithdrawTransaction(date, amount, customer, account); } else new BankException("Customer is not owner or joint owner"); }

private synchronized void makeTransfer(Date date, int amount, String customerId, String fromAccountId, String toAccountId) { Customer customer = this.lookupCustomer(customerId); Account fromAccount = this.lookupAccount(fromAccountId); Account toAccount = this.lookupAccount(toAccountId); if (fromAccount != null && ((fromAccount.getPrimaryOwner() == customer) || (fromAccount.getJointOwner() != null && fromAccount.getJointOwner() == customer)) ){ new TransferTransaction(date, amount, customer, fromAccount, toAccount); } else new BankException("Customer is not owner or joint owner"); }

public synchronized void printStatement(String customerId, Date toDate) { Customer customer = this.lookupCustomer(customerId); if (customer != null) customer.printStatement(toDate); }

}

----------------------------------------------------------------------------------------

import java.util.Date;

class SavingsAccount extends Account {

public SavingsAccount(Customer primaryOwner, String accountId, Date openDate, int initialAmount) { super(primaryOwner, accountId, openDate); Transaction t = new DepositTransaction(openDate, initialAmount, primaryOwner, this);

}

}

import java.util.Date;

class CheckingAccount extends Account {

public CheckingAccount(Customer primaryOwner, String accountId, Date openDate, int initialAmount) { super(primaryOwner, accountId, openDate); Transaction t = new DepositTransaction(openDate, initialAmount, primaryOwner, this); }

}

-------------------------------------------------------------------------

public enum AccountStatus { Open, Close } public enum AccountType { Checking, Savings, CD } public class BankException extends RuntimeException { public BankException(String msg) { super(msg); } }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Introduction To Programming With Java A Problem Solving Approach

Authors: John Dean

3rd International Edition

1260575241, 9781260575248

More Books

Students also viewed these Programming questions