From a453916341d57fe1fe473537d6ff87bbeb52f931 Mon Sep 17 00:00:00 2001
From: "ds.731" <122613372+ds731@users.noreply.github.com>
Date: Thu, 2 Jan 2025 14:10:20 -0600
Subject: [PATCH] Phase I
---
.vscode/settings.json | 7 ++
README.md | 92 ++++++++++++++++++++++++
bin/bankAcctApp/BankAcctApp.class | Bin 0 -> 2246 bytes
bin/bankAcctApp/Customer.class | Bin 0 -> 2328 bytes
bin/bankAcctApp/DataEntry.class | Bin 0 -> 3783 bytes
src/bankAcctApp/BankAcctApp.java | 40 +++++++++++
src/bankAcctApp/Customer.java | 95 ++++++++++++++++++++++++
src/bankAcctApp/DataEntry.java | 116 ++++++++++++++++++++++++++++++
8 files changed, 350 insertions(+)
create mode 100644 .vscode/settings.json
create mode 100644 README.md
create mode 100644 bin/bankAcctApp/BankAcctApp.class
create mode 100644 bin/bankAcctApp/Customer.class
create mode 100644 bin/bankAcctApp/DataEntry.class
create mode 100644 src/bankAcctApp/BankAcctApp.java
create mode 100644 src/bankAcctApp/Customer.java
create mode 100644 src/bankAcctApp/DataEntry.java
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..e112a70
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+ "java.project.sourcePaths": ["src"],
+ "java.project.outputPath": "bin",
+ "java.project.referencedLibraries": [
+ "lib/**/*.jar"
+ ]
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..af20200
--- /dev/null
+++ b/README.md
@@ -0,0 +1,92 @@
+# Banking Application with GUI Frontend in Java
+
+
+# Table of Contents
+
+- [Banking Application with GUI Frontend in Java](#banking-application-with-gui-frontend-in-java)
+- [Table of Contents](#table-of-contents)
+- [Introduction](#introduction)
+- [Scenario:](#scenario)
+- [Application Architecture \& Components](#application-architecture--components)
+- [Functionality \& Rationale](#functionality--rationale)
+- [Running Application Screenshots \& Demo](#running-application-screenshots--demo)
+- [Potential for Scalability \& Future Enhancements](#potential-for-scalability--future-enhancements)
+- [Project Issues \& Lessons Learned](#project-issues--lessons-learned)
+
+
+
+# Introduction
+
+The **Banking Application with GUI Frontend** is a four-phase project designed to create a simple yet functional banking application. Users can make deposits and withdrawals from checking and savings accounts, with transactions displayed in real-time.
+
+This project incorporates core object-oriented programming principles, such as inheritance and polymorphism, by utilizing an abstract superclass to manage account types. Encapsulated data ensures sensitive information remains private and secure, while **try/catch exception blocks** and **static methods** provide robust input validation.
+
+During the first three phases, the application employs console-based input and output. In Phase IV, the project is enhanced with a graphical user interface (GUI) frontend to improve usability and user experience.
+
+
+
+# Scenario:
+
+- ## Phase I: Creating the Initial Classes
+ The initial phase of this project provides the capability to manually input data for new bank customers.The application uses a **sentinel-controlled loop** in the test class to create instances of the **Customer class**. Static methods from the **DataEntry class** are used to collect and validate user input before assigning to the Customer class **instance variables** by way of **setter methods**. Once all customer data has been collected, validated, and assigned to instantiated variables, the **corresponding getter methods** are called by the **BankAccountApp test class** to display the collected data in a formatted report.
+
+- ## Phase II: Adding an Abstract Superclass & Input Data Validation
+ Phase II in the project focuses on adding the capability to create generic bank accounts (e.g., checking and savings), and enhancing the validation of the manually input data. A new class, **Account**, is added to the application (which will be converted to an abstract superclass in Phase III). Input validation is further enhanced in this phase by adding **try/catch blocks** for **exception handling** from improperly formatted or incorrectly entered data.
+
+- ## Phase III: Adding & Implementing Subclasses
+ Expanding on the functionalities of the previous two phases, Phase III adds the capability for creating both **checking** and *savings** accounts for customers. The Account class is converted to an **abstract class**, and two **subclasses** are created: **CheckingAccount** and **SavingsAccount**. Also, since different withdrawal and deposit rules exist for each account type, the **AccountInterface interface** will provide abstract methods for transactions and balance checking. Lastly, logic is added to ensure that all transactional and account input is properly validated before being stored by the appropriate subclass.
+
+- ## Phase IV: Adding a GUI Frontend
+ The final phase of the project, Phase IV, creates a **graphical user interface (GUI)** to replace the console interface. The GUI is created using **Swing classes** to include **JFrames**, **JPanels**, and other GUI components. This GUI uses a combination of **BorderLayout**, **GridBagLayout**, and **FlowLayout** to manage the GUI's layout design.
+
+
+
+# Application Architecture & Components
+The application follows a modular design to provide clearly-defined separation of concerns, as well as to promote code reusability. Each component is designed to handle a specific responsibility, making the application more maintainable and scalable. This approach improves readability, security through encapsulation, and flexibility for future enhancements.
+
+- ## DataEntry Class
+ The **DataEntry class** provides static methods for collecting user input (such as customer and account information, transactional data) and validating it. In Phases I - III, the test class (BankAcctApp) passe arguments to the DataEntry class when calling a specified method. The method uses those arguments as the user prompt and values the user's input is matched against. The method then compares the input against **strict validation rules**. If the input is invalid, **do-while loops** provide an error, prompting the user to correct the input and try again.
+ In Phase IV, with the addition of the GUI, additional validation methods were implemented. While the CLI version's validation methods remained in the DataEntry class, the GUI utilized **Regular Expression (Regex) patterns** was incorporated, enhancing the **validation engine** and making it more robust.
+
+- ## Customer Class
+ The **Customer class** is responsible for securely storing customer information and providing access through **getter and setter methods**. **Private instance variables** are populated with data passed by the BankAcctApp or BankAcctAppGUI classes. The class also **overrides** the inherited **toString()** method to return a formatted string representation of the customer’s details. This formatted data is used for generating reports in the CLI or displaying information in the GUI.
+
+- ## BankAcctApp Class
+ The **BankAcctApp class** serves as the application's primary orchestrator. It creates instances of the **Customer** and **Account** classes, assigns data to their instance variables, and stores them in an **ArrayList** for efficient management. This design allows the application **to handle multiple customers and accounts dynamically**. The class interacts with the Customer and Account classes through setter methods, **ensuring encapsulated data integrity** while enabling features like report generation and transaction handling.
+
+- ## Account Abstract Superclass
+ In **Phases II**, the **Account class** provides the **getter** and **setter** methods for storing and retrieving account information. The functionality of this class is enhanced in **Phase III**, however, when it is converted into an **Abstract Class** and the **CheckingAccount and SavingsAccount subclasses** are added. The (now) abstract Account class provides inheritance to the subclasses and serves as a blueprint for shared functionality and structure. It defines common properties and behaviors for all account types, such as account number, balance, and transaction methods, while leaving the implementation of specific behaviors, like withdrawal rules or interest calculations, to the subclasses. This approach ensures code reuse and enforces a consistent structure across all account types.
+
+- ## CheckingAccount & Savings Account Subclasses
+ The CheckingAccount and SavingsAccount subclasses inherit from the Account abstract class and implement specific transaction rules and fees. Both subclasses handle deposits and withdrawals while sharing safeguards to prevent overdrafts and incorrect interest application.
+
+ - Transaction Fees: Each subclass charges a fee for every transaction, including deposits and withdrawals. The fees vary based on account type, with CheckingAccount having lower fees to support frequent transactions and SavingsAccount charging higher fees to promote saving.
+ - Shared Rules: Logic is implemented to prevent overdrafting savings accounts and to ensure no interest is applied to account balances of $0 or less.
+
+ These subclasses provide distinct account management features while adhering to shared principles of financial security and error handling.
+- ## AccountInterface Interface
+ The **AccountInterface** serves three key purposes:
+ **1. Enforce encapsulation** by defining a consistent interface for interacting with account objects.
+ **2. Promote flexibility** by allowing for the addition of new transaction types (e.g., transfers between accounts, fee deductions) and integration with other components.
+ **3. Enhance modularity** by providing a standardized set of methods for all account types, improving code reusability."
+ These are discussed in greater detail in the [Potential for Scalability & Future Enhancements](#potential-for-scalability--future-enhancements) section.
+
+- ## BankAcctAppGUI Class
+ The **BankAcctAppGUI class** is responsible for implementing the **graphical user interface (GUI)** introduced in **Phase IV**. It utilizes **Java's Swing library**, incorporating **JFrame** for the main application window and **JPanel** for creating distinct sections within the interface. **FlowLayout**, **BorderLayout**, and **GridBagLayout** are implemented to position GUI components in an intuitive manner. The GUI leverages the **enhanced data validation engine** from the **DataEntry class** to ensure data integrity and security. This class facilitates user interaction with the application through a more visually appealing and user-friendly interface. More details and screenshots are provided in the [Functionality & Rationale](#functionality--rationale) and [Running Application Screenshots & Demo](#running-application-screenshots--demo) sections below.
+
+
+# Functionality & Rationale
+
+
+
+# Running Application Screenshots & Demo
+
+
+
+# Potential for Scalability & Future Enhancements
+
+
+
+# Project Issues & Lessons Learned
+
+
diff --git a/bin/bankAcctApp/BankAcctApp.class b/bin/bankAcctApp/BankAcctApp.class
new file mode 100644
index 0000000000000000000000000000000000000000..413bba5e7e022298f7fdc2e5615060bdca8aeca0
GIT binary patch
literal 2246
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
literal 0
HcmV?d00001
diff --git a/src/bankAcctApp/BankAcctApp.java b/src/bankAcctApp/BankAcctApp.java
new file mode 100644
index 0000000..ff211fa
--- /dev/null
+++ b/src/bankAcctApp/BankAcctApp.java
@@ -0,0 +1,40 @@
+package bankAcctApp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BankAcctApp {
+
+ public static void main(String[] args) {
+ ArrayList customers = new ArrayList<>();
+ boolean moreCustomers = true;
+
+ while (moreCustomers) {
+ Customer customer = new Customer();
+ System.out.println("Enter details for new customer:\n");
+
+ customer.setID(DataEntry.inputStringWithLimit("Customer ID (max 5 chars): ", 5));
+ customer.setSSN(DataEntry.inputNumericString("SSN (9 numeric chars): ", 9));
+ customer.setLastName(DataEntry.inputStringWithLimit("Last Name (max 20 chars): ", 20));
+ customer.setFirstName(DataEntry.inputStringWithLimit("First Name (max 15 chars): ", 15));
+ customer.setStreet(DataEntry.inputStringWithLimit("Street (max 20 chars): ", 20));
+ customer.setCity(DataEntry.inputStringWithLimit("City (max 20 chars): ", 20));
+ customer.setState(DataEntry.inputStringWithLimit("State (2 chars): ", 2));
+ customer.setZip(DataEntry.inputNumericString("Zip (5 numeric chars): ", 5));
+ customer.setPhone(DataEntry.inputNumericString("Phone (10 numeric chars): ", 10));
+
+ customers.add(customer);
+
+ String more = DataEntry.inputStringWithLimit("\nAdd another customer? (y/n): ", 1);
+ if (!more.equalsIgnoreCase("y")) {
+ moreCustomers = false;
+ }
+ }
+
+ System.out.println("\nCustomer Information:");
+ System.out.println("========================================");
+ for (Customer c : customers) {
+ System.out.println(c);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bankAcctApp/Customer.java b/src/bankAcctApp/Customer.java
new file mode 100644
index 0000000..76f5776
--- /dev/null
+++ b/src/bankAcctApp/Customer.java
@@ -0,0 +1,95 @@
+package bankAcctApp;
+public class Customer {
+ private String id;
+ private String ssn;
+ private String lastName;
+ private String firstName;
+ private String street;
+ private String city;
+ private String state;
+ private String zip;
+ private String phone;
+
+// Getter and Setter for Customer ID info.
+ public String getID() {
+ return id;
+ }
+ public void setID(String id) {
+ this.id = id;
+ }
+
+// Getter and Setter for Customer SSN info.
+ public String getSSN() {
+ return ssn;
+ }
+ public void setSSN(String ssn) {
+ this.ssn = ssn;
+ }
+
+// Getter and Setter for Customer Last Name.
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+// Getter and Setter for Customer First Name.
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+// Getter and Setter for Customer Street Address.
+ public String getStreet() {
+ return street;
+ }
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+// Getter and Setter for Customer City.
+ public String getCity() {
+ return city;
+ }
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+
+// Getter and Setter for Customer State.
+ public String getState() {
+ return state;
+ }
+ public void setState(String state) {
+ this.state = state;
+ }
+
+// Getter and Setter for Customer ZIP.
+ public String getZip() {
+ return zip;
+ }
+ public void setZip(String zip) {
+ this.zip = zip;
+ }
+
+// Getter and Setter for Customer Phone Number.
+ public String getPhone() {
+ return phone;
+ }
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+// Override the toString() method that is inherited by default from Java's Object class.
+// Then use the custom-written toString() method to return Customer Info
+ @Override
+ public String toString() {
+ return String.format(
+ "ID: %s, SSN: %s, Name: %s %s, Address: %s, %s, %s %s, Phone: %s",
+ id, ssn, firstName, lastName, street, city, state, zip, phone
+ );
+ }
+}
diff --git a/src/bankAcctApp/DataEntry.java b/src/bankAcctApp/DataEntry.java
new file mode 100644
index 0000000..525b8e6
--- /dev/null
+++ b/src/bankAcctApp/DataEntry.java
@@ -0,0 +1,116 @@
+package bankAcctApp;
+
+import java.util.Scanner;
+import java.util.regex.*;
+
+public class DataEntry {
+ private static Scanner in = new Scanner(System.in);
+
+// Static method to validate a string without a limit.
+ public static String inputString(String prompt) {
+ System.out.print(prompt);
+ return in.nextLine();
+ }
+
+// Static method to validate a string with a limit.
+ public static String inputStringWithLimit(String prompt, int maxLength) {
+ String input;
+ do {
+ System.out.print(prompt);
+ input = in.nextLine();
+ if (input == "" || input.length() > maxLength) {
+ System.out.println("Invalid input. Must be non-blank and up to "
+ + maxLength + " characters.");
+ }
+ } while (input == "" || input.length() > maxLength);
+ return input;
+ }
+
+// Static method to validate a numeric-only string without a limit.
+ public static String inputNumericString(String prompt, int length) {
+ String input;
+ do {
+ System.out.print(prompt);
+ input = in.nextLine();
+ if (!input.matches("\\d+")) {
+ System.out.println("Invalid input. Must only be numeric characters.");
+ }
+ } while (!input.matches("\\d+"));
+ return input;
+ }
+
+// Static method to validate Integers.
+ public static int inputInteger(String prompt) {
+ int input = 0;
+ boolean isValid = false;
+ System.out.print(prompt);
+ do {
+ if (in.hasNextInt()) {
+ input = in.nextInt();
+ isValid = true;
+ } else {
+ System.out.print("Invalid entry. Try again: ");
+ in.nextLine();
+ }
+ } while (!isValid);
+ return input;
+ }
+
+// Static method to validate Integers within a range.
+ public static int inputIntegerInRange(String prompt, int min, int max) {
+ int input = (min - 1);
+ do {
+ input = inputInteger(prompt);
+ if (input < min || input > max) {
+ System.out.print("Invalid input. Try again: ");
+ }
+ } while (input < min || input > max);
+ return input;
+ }
+
+// Static method to validate decimals.
+ public static double inputDecimal(String prompt) {
+ boolean isValid = false;
+ double decimalValue = 0.0;
+ System.out.print(prompt);
+ do {
+ if (in.hasNextDouble()) {
+ decimalValue = in.nextDouble();
+ isValid = true;
+ } else{
+ System.out.println("Invalid input. Please enter a valid decimal number.");
+ in.next();
+ }
+ } while (!isValid);
+ return decimalValue;
+ }
+
+// Static method to validate decimals within a range.
+ public static double inputDecimalInRange(String prompt, double min, double max) {
+ double value;
+ do {
+ value = inputDecimal(prompt);
+ if (value < min || value > max) {
+ System.out.println("Invalid input. Must be between "
+ + min + " and " + max + ".");
+ }
+ } while (value < min || value > max);
+ return value;
+ }
+
+// Static method to validate a date in MM/DD/YYYY format.
+ public static String inputDate(String prompt) {
+ Pattern patternDate = Pattern.compile("^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/(\\d{4})$");
+ String date = "";
+ System.out.print(prompt);
+ do {
+ String input = in.nextLine();
+ if (patternDate.matcher(input).matches()) {
+ return input;
+ } else {
+ System.out.print("Invalid date. Please try again: ");
+ }
+ } while (date == "");
+ return date;
+ }
+}