diff --git a/README.md b/README.md
index 99b7168..2a724ca 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,215 @@
# Advanced-Programming
A Repository for Programming Exercises and Assignments in Advanced Programming
+# Advanced Programming Assignment 1
+
+**Course:** object oriented programming 2
+**Name:** phillip kimonyi
+regno: SCT212-0057/2024
+**Semester:** Sept–Dec 2024
+
+This project implements a simple **Bank Transaction System** in Java to demonstrate key **Advanced Object-Oriented Programming** concepts including:
+- ADT (Abstract Data Type) Design
+- Interfaces
+- Abstract Classes
+- Inheritance
+- Polymorphism
+- Method Overriding
+- Exception Handling
+- Defensive Programming
+
+The system processes financial transactions such as:
+
+- Deposits
+- Withdrawals
+- Reversible Withdrawals
+
+---
+## Folder Structure
+src/
+│
+├── Lecture1_adt/
+│ Transaction1.java
+│ Transaction2.java
+│ Transaction3.java
+│ Transaction4.java
+│
+├── Lecture2_adt_specification/
+│ Transaction4.java
+│
+├── Lecture4_interfaces_abstract_classes/
+│ TransactionInterface.java
+│ BaseTransaction.java
+│ BankAccount.java
+│ DepositTrasaction.java
+│ WithdrawalTransaction.java
+│ InsufficientFundsException.java
+│
+└── Main.java
+
+## Concepts Implemented
+### 1. Interface Implementation
+
+`TransactionInterface` defines the transaction contract.
+
+Required methods:
+java
+getAmount()
+getDate()
+getTransactionID()
+
+### 2. Abstract Class Design
+
+`BaseTransaction`:
+- Implements `TransactionInterface`
+- Stores common transaction fields:
+ - amount
+ - date
+ - transactionID
+- Defines shared transaction behaviour.
+### 3. Inheritance and Method Overriding
+
+Derived classes:
+
+- `DepositTrasaction`
+- `WithdrawalTransaction`
+
+Override:
+
+```java
+apply()
+printTransactionDetails()
+
+to provide specialized behavior.
+
+### 4. Polymorphism
+
+Demonstrated using superclass references:
+
+```java
+BaseTransaction bt =
+ new DepositTrasaction(250,date);
+```
+
+Late binding ensures the correct subclass implementation of `apply()` executes.
+
+---
+
+### 5. Exception Handling
+
+Custom exception class:
+
+```java
+InsufficientFundsException
+```
+
+Features implemented:
+
+- `throws`
+- `try{ } catch{ } finally{ }`
+
+Used to safely handle withdrawal failures.
+
+---
+
+### 6. Withdrawal Reversal
+
+Unlike deposits, withdrawals are reversible.
+
+Implemented through:
+
+```java
+reverse()
+```
+
+The method restores the original bank account balance.
+
+---
+
+### 7. Partial Withdrawal Mode
+
+Implemented through overloaded method:
+
+```java
+apply(BankAccount ba,
+ boolean availableBalanceMode)
+```
+
+Behavior:
+
+If:
+
+```plaintext
+0 < balance < withdrawal amount
+```
+
+the system:
+
+- withdraws all available funds
+- stores remaining unpaid amount
+- records `amountNotWithdrawn`
+
+---
+
+## Running the Project
+
+Compile:
+
+```bash
+javac Main.java
+```
+
+Run:
+
+```bash
+java Main
+```
+
+---
+
+## Sample Output
+
+```plaintext
+Initial Balance: 1000
+
+Deposit Transaction
+Balance After Deposit: 1500
+
+Withdrawal Transaction
+Balance After Withdrawal: 1200
+
+Withdrawal Reversed: true
+Balance After Reversal: 1500
+
+Exception Test:
+Insufficient account balance.
+
+Partial withdrawal completed.
+Amount not withdrawn: 500
+```
+
+---
+
+## Assignment Requirements Covered
+
+✔ Interface implementation
+
+✔ Abstract class inheritance
+
+✔ Method overriding
+
+✔ Polymorphism
+
+✔ Exception handling
+
+✔ Reversible withdrawals
+
+✔ Overloaded methods
+
+✔ Client code testing
+
+---
+
+## Author
+
+Student Assignment Submission
+Advanced Programming — Assignment One
diff --git a/src/Lecture1_adt/Transaction1.java b/src/Lecture1_adt/Transaction1.java
index 8a46bd5..9a53b6c 100644
--- a/src/Lecture1_adt/Transaction1.java
+++ b/src/Lecture1_adt/Transaction1.java
@@ -10,7 +10,7 @@
public class Transaction1 {
public int amount;
public Calendar date;
-
+ //we need to introduce a method to and make the fields private to prevent external modification
public Transaction1(int amount, Calendar date) {
this.amount = amount;
this.date = (Calendar) date.clone();
diff --git a/src/Lecture4_interfaces_abstract_classes/BankAccount.class b/src/Lecture4_interfaces_abstract_classes/BankAccount.class
new file mode 100644
index 0000000..bc4a552
Binary files /dev/null and b/src/Lecture4_interfaces_abstract_classes/BankAccount.class differ
diff --git a/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java b/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java
index ed81eb8..4a26428 100644
--- a/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java
+++ b/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java
@@ -20,7 +20,7 @@ public abstract class BaseTransaction implements TransactionInterface {
public BaseTransaction(int amount, @NotNull Calendar date) {
this.amount = amount;
this.date = (Calendar) date.clone();
- int uniq = (int) Math.random()*10000;
+ int uniq = (int)(Math.random()*10000);
transactionID = date.toString()+uniq;
}
@@ -37,8 +37,7 @@ public double getAmount() {
* @return Calendar Object
*/
public Calendar getDate() {
-// return date; // Because we are dealing with Reference types we need to judiciously copy what our getters return
- return (Calendar) date.clone(); // Defensive copying or Judicious Copying
+ return (Calendar) date.clone(); // Defensive copying or Judicious Copying
}
// Method to get a unique identifier for the transaction
@@ -46,6 +45,9 @@ public String getTransactionID(){
return transactionID;
}
// Method to print a transaction receipt or details
+ // Abstract method to be implemented by subclasses for specific transaction details
public abstract void printTransactionDetails();
- public abstract void apply(BankAccount ba);
+ // Abstract method to apply the transaction to a BankAccount, to be implemented by subclasses
+ public abstract void apply(BankAccount ba)
+ throws InsufficientFundsException;
}
diff --git a/src/Lecture4_interfaces_abstract_classes/DepositTransaction.java b/src/Lecture4_interfaces_abstract_classes/DepositTransaction.java
new file mode 100644
index 0000000..7efad08
--- /dev/null
+++ b/src/Lecture4_interfaces_abstract_classes/DepositTransaction.java
@@ -0,0 +1,43 @@
+package Lecture4_interfaces_abstract_classes;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Calendar;
+
+public class DepositTransaction extends BaseTransaction {
+ public DepositTransaction(int amount, @NotNull Calendar date){
+ super(amount, date);
+ }
+ private boolean checkDepositAmount(int amt){
+ if (amt < 0){
+ return false;
+ }
+ else{
+ return true;
+ }
+ }
+
+ // Method to print a transaction receipt or details
+ // public void printTransactionDetails(){
+ // System.out.println("Deposit Trasaction: "+this.toString());
+ // }
+ //impoved version of printTransactionDetails
+ public void printTransactionDetails() {
+
+ System.out.println("\nDeposit Transaction");
+ System.out.println("Transaction ID: "
+ + getTransactionID());
+
+ System.out.println("Amount: "
+ + getAmount());
+
+ System.out.println("Date: "
+ + getDate().getTime());
+ }
+
+ public void apply(BankAccount ba){
+ double curr_balance = ba.getBalance();
+ double new_balance = curr_balance + getAmount();
+ ba.setBalance(new_balance);
+ }
+}
diff --git a/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java b/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java
deleted file mode 100644
index 81afab5..0000000
--- a/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package Lecture4_interfaces_abstract_classes;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Calendar;
-
-public class DepositTrasaction extends BaseTransaction {
- public DepositTrasaction(int amount, @NotNull Calendar date){
- super(amount, date);
- }
- private boolean checkDepositAmount(int amt){
- if (amt < 0){
- return false;
- }
- else{
- return true;
- }
- }
-
- // Method to print a transaction receipt or details
- public void printTransactionDetails(){
- System.out.println("Deposit Trasaction: "+this.toString());
- }
-
- public void apply(BankAccount ba){
- double curr_balance = ba.getBalance();
- double new_balance = curr_balance + getAmount();
- ba.setBalance(new_balance);
- }
-}
diff --git a/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.class b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.class
new file mode 100644
index 0000000..22209a2
Binary files /dev/null and b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.class differ
diff --git a/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java
new file mode 100644
index 0000000..0c85803
--- /dev/null
+++ b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java
@@ -0,0 +1,9 @@
+package Lecture4_interfaces_abstract_classes;
+
+public class InsufficientFundsException
+ extends Exception {
+ // Constructor that accepts a message to describe the exception
+ public InsufficientFundsException(String message) {
+ super(message);// Call the constructor of the superclass (Exception) with the provided message
+ }
+}
diff --git a/src/Lecture4_interfaces_abstract_classes/TransactionInterface.class b/src/Lecture4_interfaces_abstract_classes/TransactionInterface.class
new file mode 100644
index 0000000..4b6463c
Binary files /dev/null and b/src/Lecture4_interfaces_abstract_classes/TransactionInterface.class differ
diff --git a/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java b/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java
index face5b6..081e398 100644
--- a/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java
+++ b/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java
@@ -5,41 +5,185 @@
import java.util.Calendar;
public class WithdrawalTransaction extends BaseTransaction {
- public WithdrawalTransaction(int amount, @NotNull Calendar date) {
+
+ // Tracks amount remaining after partial withdrawal
+ private double amountNotWithdrawn = 0;
+
+ // Tracks BankAccount where transaction was applied
+ private BankAccount appliedAccount;
+
+ // Prevents invalid/double reversals
+ private boolean transactionApplied = false;
+
+
+ public WithdrawalTransaction(int amount,
+ @NotNull Calendar date) {
+
super(amount, date);
}
- private boolean checkDepositAmount(int amt) {
- if (amt < 0) {
- return false;
- } else {
+
+ // Checks withdrawal amount validity
+ private boolean checkWithdrawalAmount(int amt) {
+ return amt >= 0;
+ }
+
+
+ /*
+ Assignment Q2:
+ Reverse a withdrawal transaction.
+ Restore original account balance.
+ */
+ public boolean reverse() {
+
+ if(transactionApplied &&
+ appliedAccount != null){
+
+ double currBalance =
+ appliedAccount.getBalance();
+
+ appliedAccount.setBalance(
+ currBalance + getAmount()
+ );
+
+ // mark transaction reversed
+ transactionApplied = false;
+
return true;
}
+
+ return false;
}
- // Method to reverse the transaction
- public boolean reverse() {
- return true;
- } // return true if reversal was successful
- // Method to print a transaction receipt or details
- public void printTransactionDetails() {
- System.out.println("Deposit Trasaction: " + this.toString());
+ /*
+ Print transaction details / receipt
+ */
+ public void printTransactionDetails(){
+
+ System.out.println(
+ "\nWithdrawal Transaction");
+
+ System.out.println(
+ "Transaction ID: "
+ + getTransactionID());
+
+ System.out.println(
+ "Amount: "
+ + getAmount());
+
+ System.out.println(
+ "Date: "
+ + getDate().getTime());
}
+
/*
- Oportunity for assignment: implementing different form of withdrawal
+ Standard withdrawal operation.
+ Uses throws keyword.
*/
- public void apply(BankAccount ba) {
- double curr_balance = ba.getBalance();
- if (curr_balance > getAmount()) {
- double new_balance = curr_balance - getAmount();
- ba.setBalance(new_balance);
+ public void apply(BankAccount ba)
+ throws InsufficientFundsException {
+
+ double curr_balance =
+ ba.getBalance();
+
+ if(!checkWithdrawalAmount(
+ (int)getAmount())){
+
+ throw new
+ InsufficientFundsException(
+ "Invalid withdrawal amount."
+ );
}
+
+ if(curr_balance < getAmount()){
+
+ throw new
+ InsufficientFundsException(
+ "Insufficient account balance."
+ );
+ }
+
+ double new_balance =
+ curr_balance - getAmount();
+
+ ba.setBalance(new_balance);
+
+ appliedAccount = ba;
+
+ transactionApplied = true;
}
+
/*
- Assignment 1 Q3: Write the Reverse method - a method unique to the WithdrawalTransaction Class
+ Assignment Q3: Overloaded apply().
+
+ Available balance withdrawal mode.
+
+ If:
+ 0 < balance < withdrawal amount
+
+ withdraw all available funds and
+ record remaining unpaid amount.
*/
-}
+ public void apply(BankAccount ba,
+ boolean availableBalanceMode){
+
+ try{
+
+ double curr_balance =
+ ba.getBalance();
+
+ if(curr_balance <= 0){
+
+ throw new
+ InsufficientFundsException(
+ "Account balance is zero."
+ );
+ }
+ if(availableBalanceMode &&
+ curr_balance < getAmount()){
+
+ amountNotWithdrawn =
+ getAmount()
+ - curr_balance;
+
+ ba.setBalance(0);
+
+ appliedAccount = ba;
+
+ transactionApplied = true;
+
+ System.out.println(
+ "Partial withdrawal completed."
+ );
+
+ System.out.println(
+ "Amount not withdrawn: "
+ + amountNotWithdrawn
+ );
+ }
+ else{
+
+ apply(ba);
+ }
+
+ }
+ catch(
+ InsufficientFundsException e){
+
+ System.out.println(
+ "ERROR: "
+ + e.getMessage()
+ );
+ }
+ finally{
+
+ System.out.println(
+ "Withdrawal operation finished."
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
index 584a048..3871394 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,156 +1,135 @@
-import Lecture1_adt.*; // Import all classes from Lecture1_adt package to be used in this client code
-
+import Lecture4_interfaces_abstract_classes.*;// Importing all classes from the package
import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.ArrayList;
-import java.util.List;
-
-//TIP To Run code, press or
-// click the icon in the gutter.
-/*
-* Client Code for accessing the Lecture1_adt.TransactionInterface.java module
- */
+import java.util.GregorianCalendar;// Importing necessary classes for date handling
public class Main {
+ public static void main(String[] args) {
- public static void testTransaction1() {
- Calendar d1 = new GregorianCalendar(); // d1 is an Object [Objects are Reference types]
- Lecture1_adt.Transaction1 t1 = new Lecture1_adt.Transaction1(1000, d1); // amount and d1 are arguments
-
- System.out.println(t1.toString());
- System.out.println("Lecture1_adt.TransactionInterface Amount: \t " + t1.amount);
- System.out.println("Lecture1_adt.TransactionInterface Date: \t " + t1.date);
-
- // Please note that the Client Codes can access the data in the class directly through the dot operator
- // This kind of exposure is a threat to both the Representation Independence and Preservation of Invariants
- }
-
-
- /** @return a transaction of same amount as t, one month later
- * This is a PRODUCER of the class Lecture1_adt.Transaction2
- * This code will help demostrate the Design exposures still present in transaction2 class
- * */
-
- public static Transaction2 makeNextPayment(Transaction2 t) {
- Calendar d = t.getDate();
- d.add(Calendar.MONTH, 1);
- return new Transaction2(t.getAmount(), d);
- }
-
- /*
- Testing Transaction2 class
- */
- public static void testTransaction2() {
-
- Calendar d1 = new GregorianCalendar();
-
- Lecture1_adt.Transaction2 t = new Lecture1_adt.Transaction2(1000, d1);
-
- Lecture1_adt.Transaction2 modified_t = makeNextPayment(t);
-
- System.out.println("\n\nState of the Object T1 After Client Code Tried to Change the Amount");
- System.out.println("Lecture1_adt.TransactionInterface Amount: \t "+modified_t.getAmount());
- System.out.println("Lecture1_adt.TransactionInterface Date: \t "+modified_t.getDate().getTime());
-
- System.out.println("\n\nHow does T2 Look Like?????");
- System.out.println("Lecture1_adt.TransactionInterface Amount: \t "+modified_t.getAmount());
- System.out.println("Lecture1_adt.TransactionInterface Date: \t "+modified_t.getDate().getTime());
-
- /* Please note that Although we have solved the problem of Transaction1
- * And client code can no longer use the dot (.) operator to directly access the data
- * There is still some exposure especially if we pass an object of a previous Transaction2 to create a new Transaction2 object
- */
-
- }
-
-
- /** @return a list of 12 monthly payments of identical amounts
- * This code will help demostrate the Design exposures still present in transaction3 class
- * */
- public static List makeYearOfPayments (int amount) throws NullPointerException {
-
- List listOfTransaction3s = new ArrayList();
- Calendar date = new GregorianCalendar(2024, Calendar.JANUARY, 3);
-
+ Calendar date = new GregorianCalendar();
+
+ // Create Bank Account
+ BankAccount account =
+ new BankAccount(1000);
+ // Display Initial Balance
+ System.out.println( "\nInitial Balance: " + account.getBalance()
+ );
+ /*case1 — DepositTransaction----- */
+
+ DepositTransaction deposit = new DepositTransaction(
+ 500,
+ date
+ );
+
+ deposit.apply(account);// Applying the deposit transaction to the account either deposit or withdrawal
+ deposit.printTransactionDetails();
+
+ System.out.println(
+ "Balance After Deposit: "
+ + account.getBalance()
+ );
+ /*
+ case 2 — WithdrawalTransaction---------- */
+ WithdrawalTransaction withdrawal =
+ new WithdrawalTransaction(
+ 300,
+ date
+ );
+ //use try catch block to handle potential InsufficientFundsException when applying the withdrawal transaction to the account
+ try{
+ withdrawal.apply(account);
+ withdrawal.printTransactionDetails();
+ System.out.println(
+ "Balance After Withdrawal: "
+ + account.getBalance()
+ );
- for (int i = 0; i < 12; i++) {
- listOfTransaction3s.add(new Transaction3(amount, date));
- date.add(Calendar.MONTH, 1);
}
- return listOfTransaction3s;
- }
-
- /*
- Testing Transaction3 class
- */
- public static void testTransaction3() {
-
- List allPaymentsIn2024 = makeYearOfPayments(1000);
-
- for (Transaction3 t3 : allPaymentsIn2024) {
-
- // Display all the 12 Transactions
- for (Transaction3 transact : allPaymentsIn2024) {
- System.out.println("\n\n ::::::::::::::::::::::::::::::::::::::::::::\n");
- System.out.println("Lecture1_adt.TransactionInterface Amount: \t "+transact.getAmount());
- System.out.println("Lecture1_adt.TransactionInterface Date: \t "+transact.getDate().getTime());
- }
+ catch(InsufficientFundsException e){
+ System.out.println(
+ "Exception: "
+ + e.getMessage()
+ );
}
-
- /* Please Check all the 12 transactions displayed and hwo their dates look like
- * Note that Although Transaction3 class resolves to an extent the exposure in Transaction2 class
- * There is still some exposure especially if we pass an object of a previous Transaction3 to create a
- * new Transaction3 object
- */
- }
-
-
- /** @return a list of 12 monthly payments of identical amounts
- * This code Show that by judicious copying and defensive programming we eliminate the exposure in Transaction3
- * As defined in the constructor of Transaction4 class
- * */
-
- public static List makeYearOfPaymentsFinal (int amount) throws NullPointerException {
-
- List listOfTransaction4s = new ArrayList();
- Calendar date = new GregorianCalendar(2024, Calendar.JANUARY, 3);
-
-
- for (int i = 0; i < 12; i++) {
- listOfTransaction4s.add(new Transaction4(amount, date));
- date.add(Calendar.MONTH, 1);
+ /*case 3 — Reverse Withdrawal-------- */
+ boolean reversed =
+ withdrawal.reverse();
+ System.out.println(
+ "\nWithdrawal Reversed: " + reversed);
+ //code to Display Balance After Reversal
+ System.out.println(
+ "Balance After Reversal: "
+ + account.getBalance()
+ );
+ /*---- TEST 4 — Exception Handling----------- */
+ WithdrawalTransaction bigWithdrawal =
+ new WithdrawalTransaction(
+ 5000,
+ date
+ );
+ try{
+ bigWithdrawal.apply(account);
}
- return listOfTransaction4s;
- }
+ catch(
+ InsufficientFundsException e){
- /*
- Testing Transaction3 class
- */
- public static void testTransaction4() {
-
- /*
- * Call the function to make all the Twelve transaction in a year of our business
- */
-
- List transactionsIn2024 = makeYearOfPaymentsFinal(1200);
+ System.out.println(
+ "\nException Test: "
+ + e.getMessage()
+ );
+ }
+ /*-------TEST 5 — Overloaded apply() Partial Withdrawal Mode------ */
+
+ WithdrawalTransaction partial = new WithdrawalTransaction(
+ 2000,
+ date
+ );
+
+ partial.apply(account,true);
+ /*------------------------ TEST 6 — Polymorphism Superclass Reference... */
+
+ BaseTransaction bt;
+ bt = new DepositTransaction(
+ 250,
+ date
+ );
+ try{
+ bt.apply(account);
+ }
+ catch(
+ InsufficientFundsException e){
- // Display all the 12 Transactions
- for (Transaction4 transact : transactionsIn2024) {
- System.out.println("\n\n ::::::::::::::::::::::::::::::::::::::::::::\n");
- System.out.println("Lecture1_adt.TransactionInterface Amount: \t "+transact.getAmount());
- System.out.println("Lecture1_adt.TransactionInterface Date: \t "+transact.getDate().getTime());
+ System.out.println(
+ e.getMessage()
+ );
}
- // Please Take a look at all the 12 transaction now and compare with the outputs of the Transaction3 class
- }
+ bt.printTransactionDetails();
+ System.out.println(
+ "\nBalance After Polymorphic Deposit: "
+ + account.getBalance()
+ );
- public static void main(String[] args) {
- // This is the client code
- // Uncomment the following lines to test the class which you would like to test
+ /*-------- TEST 7 — Type Casting------- */
- // testTransaction1()
- // testTransaction2()
- // testTransaction3()
- // testTransaction4()
+ BaseTransaction baseRef =
+ (BaseTransaction)
+ new WithdrawalTransaction(
+ 100,
+ date
+ );
+ try{
+ baseRef.apply(account);
+ }
+ catch(
+ InsufficientFundsException e){
+ System.out.println(
+ e.getMessage()
+ );
+ }
+ baseRef.printTransactionDetails();
+ System.out.println(
+ "Final Balance: "
+ + account.getBalance()
+ );
}
}
\ No newline at end of file