diff --git a/.idea/IntelliLang.xml b/.idea/IntelliLang.xml new file mode 100644 index 0000000..b223a1b --- /dev/null +++ b/.idea/IntelliLang.xml @@ -0,0 +1,151 @@ + + + + + AsyncQueryRunner (org.apache.commons.dbutils) + + + + + + + + + + + + + + + + + + Jodd (jodd.db) + + + + + + + + MyBatis @Select/@Delete/@Insert/@Update + + + + + + + + QueryRunner (org.apache.commons.dbutils) + + + + + + + + + + + + + + + + + + R2DBC (io.r2dbc) + + + + + + Reactiverse Postgres Client (io.reactiverse) + + + + + + + + + + + + + SmallRye Axle SqlClient (io.vertx.axle.sqlclient) + + + + + + SmallRye Mutiny SqlClient (io.vertx.mutiny.sqlclient) + + + + + + SmallRye Mutiny SqlConnection (io.vertx.mutiny.sqlclient) + + + + + + + + Vert.x SQL Extensions (io.vertx.ext.sql) + + + + + + + Vert.x SQL Reactive Extensions (io.vertx.reactivex.ext.sql) + + + + + + + + + + Vert.x SqlClient (io.vertx.sqlclient) + + + + + + + + + + + Vert.x SqlClient RxJava2 (io.vertx.reactivex.sqlclient) + + + + + + + + + + + + jOOQ (org.jooq.DSLContext) + + + + + + + + rxjava2-jdbc (org.davidmoten.rx.jdbc) + + + + + + + \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/BankAccount.java b/src/Lecture4_interfaces_abstract_classes/BankAccount.java index 28d0d07..c935271 100644 --- a/src/Lecture4_interfaces_abstract_classes/BankAccount.java +++ b/src/Lecture4_interfaces_abstract_classes/BankAccount.java @@ -1,7 +1,9 @@ package Lecture4_interfaces_abstract_classes; public class BankAccount { + private double balance; + public BankAccount(double balance) { this.balance = balance; } @@ -13,4 +15,4 @@ public double getBalance() { public void setBalance(double balance) { this.balance = balance; } -} +} \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java b/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java index ed81eb8..0602c16 100644 --- a/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java +++ b/src/Lecture4_interfaces_abstract_classes/BaseTransaction.java @@ -1,51 +1,45 @@ package Lecture4_interfaces_abstract_classes; -import org.jetbrains.annotations.NotNull; - import java.util.Calendar; public abstract class BaseTransaction implements TransactionInterface { + private final int amount; private final Calendar date; private final String transactionID; - /** - * Lecture1_adt.TransactionInterface Constructor - * @param amount in an integer - * @param date: Not null, and must be a Calendar object - * @return void - * Instialises the field, attributes of a transaction - * Creates a object of this - */ - public BaseTransaction(int amount, @NotNull Calendar date) { + public BaseTransaction(int amount, Calendar date) { this.amount = amount; this.date = (Calendar) date.clone(); - int uniq = (int) Math.random()*10000; - transactionID = date.toString()+uniq; + int uniq = (int) (Math.random() * 10000); + this.transactionID = date.getTimeInMillis() + "-" + uniq; } - /** - * getAmount() - * @return integer - */ + @Override public double getAmount() { - return amount; // Because we are dealing with Value types we need not worry about what we return + return amount; } - /** - * getDate() - * @return Calendar Object - */ + @Override 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(); + } + + @Override + public String getTransactionID() { + return transactionID; + } + + @Override + public void printTransactionDetails() { + System.out.println("--- Transaction Details ---"); + System.out.println("Transaction ID: " + transactionID); + System.out.println("Date: " + date.getTime()); + System.out.println("Amount: " + amount); } - // Method to get a unique identifier for the transaction - public String getTransactionID(){ - return transactionID; + @Override + public void apply(BankAccount ba) throws InsufficientFundsException { + System.out.println("Base transaction executed."); } - // Method to print a transaction receipt or details - public abstract void printTransactionDetails(); - public abstract void apply(BankAccount ba); -} +} \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java b/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java index 81afab5..f8c0442 100644 --- a/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java +++ b/src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java @@ -1,30 +1,36 @@ 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; + return false; } else{ - return true; + return true; } } - // Method to print a transaction receipt or details + @Override public void printTransactionDetails(){ - System.out.println("Deposit Trasaction: "+this.toString()); + System.out.println("--- Deposit Transaction ---"); + System.out.println("Transaction ID: " + getTransactionID()); + System.out.println("Date: " + getDate().getTime()); + System.out.println("Amount Deposited: " + getAmount()); } - public void apply(BankAccount ba){ + // Added 'throws InsufficientFundsException' to maintain signature compatibility + @Override + public void apply(BankAccount ba) throws InsufficientFundsException { double curr_balance = ba.getBalance(); double new_balance = curr_balance + getAmount(); ba.setBalance(new_balance); } -} +} \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java new file mode 100644 index 0000000..cf48eef --- /dev/null +++ b/src/Lecture4_interfaces_abstract_classes/InsufficientFundsException.java @@ -0,0 +1,20 @@ +package Lecture4_interfaces_abstract_classes; + +public class InsufficientFundsException extends Exception { + + private double deficitAmount; + + public InsufficientFundsException(String message, double deficit) { + super(message); + this.deficitAmount = deficit; + } + + public InsufficientFundsException(String message) { + super(message); + this.deficitAmount = 0.0; + } + + public double getDeficitAmount() { + return deficitAmount; + } +} \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/TransactionInterface.java b/src/Lecture4_interfaces_abstract_classes/TransactionInterface.java index 5902713..7bdeaf0 100644 --- a/src/Lecture4_interfaces_abstract_classes/TransactionInterface.java +++ b/src/Lecture4_interfaces_abstract_classes/TransactionInterface.java @@ -1,21 +1,16 @@ package Lecture4_interfaces_abstract_classes; + import java.util.Calendar; -/** - * Interface for Transactions - * Any class that defines a transaction is expected to implement this Interface - */ public interface TransactionInterface { - // Method to get the transaction amount double getAmount(); - // Method to get the transaction date Calendar getDate(); - // Method to get a unique identifier for the transaction String getTransactionID(); -} - + void apply(BankAccount ba) throws InsufficientFundsException; + void printTransactionDetails(); +} \ No newline at end of file diff --git a/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java b/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java index face5b6..7406cba 100644 --- a/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java +++ b/src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java @@ -1,10 +1,13 @@ package Lecture4_interfaces_abstract_classes; import org.jetbrains.annotations.NotNull; - import java.util.Calendar; public class WithdrawalTransaction extends BaseTransaction { + private BankAccount appliedAccount = null; + private boolean isApplied = false; + private double shortfallRecord = 0.0; + public WithdrawalTransaction(int amount, @NotNull Calendar date) { super(amount, date); } @@ -17,29 +20,73 @@ private boolean checkDepositAmount(int amt) { } } - // Method to reverse the transaction + // Question 2: Reversal logic restores the account balance to its original amount public boolean reverse() { - return true; - } // return true if reversal was successful + if (isApplied && appliedAccount != null) { + double currentBalance = appliedAccount.getBalance(); + // Restore original amount (current balance + what was successfully withdrawn) + double restoredBalance = currentBalance + (getAmount() - shortfallRecord); + appliedAccount.setBalance(restoredBalance); + isApplied = false; // Reset state + System.out.println("Withdrawal transaction reversed successfully."); + return true; + } + System.out.println("Reversal failed: Transaction has not been applied yet."); + return false; + } // Method to print a transaction receipt or details + @Override public void printTransactionDetails() { - System.out.println("Deposit Trasaction: " + this.toString()); + System.out.println("--- Withdrawal Transaction ---"); + System.out.println("Transaction ID: " + getTransactionID()); + System.out.println("Date: " + getDate().getTime()); + System.out.println("Amount Requested: " + getAmount()); + if (shortfallRecord > 0) { + System.out.println("Shortfall (Not Withdrawn): " + shortfallRecord); + } } - /* - Oportunity for assignment: implementing different form of withdrawal - */ - public void apply(BankAccount ba) { + // Question 3: Standard apply using the throws keyword + @Override + public void apply(BankAccount ba) throws InsufficientFundsException { double curr_balance = ba.getBalance(); - if (curr_balance > getAmount()) { + if (curr_balance >= getAmount()) { double new_balance = curr_balance - getAmount(); ba.setBalance(new_balance); + this.appliedAccount = ba; + this.isApplied = true; + this.shortfallRecord = 0.0; + } else { + throw new InsufficientFundsException("Insufficient funds to complete the withdrawal of " + getAmount()); } } - /* - Assignment 1 Q3: Write the Reverse method - a method unique to the WithdrawalTransaction Class - */ -} - + // Question 3: Overloaded apply handling 0 < balance < withdrawal amount using try...catch...finally + public void apply(BankAccount ba, boolean partialWithdrawalAllowed) { + try { + double curr_balance = ba.getBalance(); + if (curr_balance < getAmount()) { + // Check if balance is greater than 0 for partial withdrawal + if (curr_balance > 0) { + shortfallRecord = getAmount() - curr_balance; + ba.setBalance(0.0); // Withdraw all available balance + this.appliedAccount = ba; + this.isApplied = true; + System.out.println("Partial withdrawal executed. Balance set to 0. Shortfall: " + shortfallRecord); + } else { + // Trigger exception block manually if balance is 0 or less + throw new InsufficientFundsException("Account balance is zero or negative. Cannot withdraw."); + } + } else { + // If funds are completely sufficient, proceed normally via standard apply + apply(ba); + } + } catch (InsufficientFundsException e) { + System.out.println("Caught Exception inside overloaded apply: " + e.getMessage()); + this.isApplied = false; + } finally { + System.out.println("Transaction processing attempt finished for Transaction ID: " + getTransactionID()); + } + } +} \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index 584a048..9d3b022 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,4 +1,5 @@ import Lecture1_adt.*; // Import all classes from Lecture1_adt package to be used in this client code +import Lecture4_interfaces_abstract_classes.*; // Import Lecture 4 assignment files import java.util.Calendar; import java.util.GregorianCalendar; @@ -8,7 +9,7 @@ //TIP To Run code, press or // click the icon in the gutter. /* -* Client Code for accessing the Lecture1_adt.TransactionInterface.java module + * Client Code for accessing the Lecture1_adt.TransactionInterface.java module */ public class Main { @@ -56,8 +57,8 @@ public static void testTransaction2() { 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 + * 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 */ } @@ -143,14 +144,75 @@ public static void testTransaction4() { // Please Take a look at all the 12 transaction now and compare with the outputs of the Transaction3 class } + /** + * Question 4: Client Code to test Assignment 1 functionality + */ + public static void testAssignmentOne() { + System.out.println("========== RUNNING ASSIGNMENT 1 TEST CODE =========="); + + // 1. Setup account and common date object + BankAccount account = new BankAccount(5000.0); + Calendar now = new GregorianCalendar(); + + System.out.println("Initial Bank Account Balance: " + account.getBalance()); + + // 2. Instantiate Subclass Objects + DepositTrasaction deposit = new DepositTrasaction(2000, now); + WithdrawalTransaction withdrawal1 = new WithdrawalTransaction(3000, now); + WithdrawalTransaction withdrawal2 = new WithdrawalTransaction(6000, now); // Will cause exception + WithdrawalTransaction partialWithdrawal = new WithdrawalTransaction(8000, now); // For overloaded test + + // 3. Type casting / Mapping subtype objects to the base type object (Upcasting) + BaseTransaction baseDeposit = (BaseTransaction) deposit; + BaseTransaction baseWithdrawal1 = (BaseTransaction) withdrawal1; + BaseTransaction baseWithdrawal2 = (BaseTransaction) withdrawal2; + + try { + // 4. Apply Deposit via Base type mapping + System.out.println("\n--- Executing Deposit ---"); + baseDeposit.apply(account); + baseDeposit.printTransactionDetails(); + System.out.println("Balance after Deposit: " + account.getBalance()); + + // 5. Apply valid Withdrawal via Base type mapping + System.out.println("\n--- Executing Valid Withdrawal ---"); + baseWithdrawal1.apply(account); + baseWithdrawal1.printTransactionDetails(); + System.out.println("Balance after Withdrawal 1: " + account.getBalance()); + + // 6. Test Reversal on the successful withdrawal + System.out.println("\n--- Testing Reversal on Withdrawal 1 ---"); + withdrawal1.reverse(); + System.out.println("Balance after Reversal: " + account.getBalance()); + + // 7. Apply invalid Withdrawal (Should throw InsufficientFundsException) + System.out.println("\n--- Executing Invalid Withdrawal (Expect Exception) ---"); + baseWithdrawal2.apply(account); // This line will jump to the catch block + + } catch (InsufficientFundsException e) { + System.out.println("Successfully caught handled exception: " + e.getMessage()); + } - 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 + // 8. Test Overloaded apply method (Partial withdrawal scenario) + System.out.println("\n--- Executing Overloaded Apply (Partial Withdrawal Option) ---"); + System.out.println("Current Account Balance before partial: " + account.getBalance()); + + // Attempting to withdraw 8000 when balance is less than that but greater than 0 + partialWithdrawal.apply(account, true); + partialWithdrawal.printTransactionDetails(); + System.out.println("Final Account Balance after partial withdrawal loop: " + account.getBalance()); - // testTransaction1() - // testTransaction2() - // testTransaction3() - // testTransaction4() + System.out.println("===================================================="); + } + + public static void main(String[] args) { + // Run assignment test execution + testAssignmentOne(); + + // Uncomment the following lines to run historical lecture tests if needed + // testTransaction1(); + // testTransaction2(); + // testTransaction3(); + // testTransaction4(); } } \ No newline at end of file