Module 06: Course Project
Development Phase:
Program Finalized
COP3805C Section 01 Advanced Java Programming
Robert Kumar
Kevin McMahon
12-11-2024
:
Simple IC: Project Overview
Simple IC is a practical and flexible inventory management solution designed to simplify stock
tracking for businesses. The system provides two convenient ways to interact: a Command-Line Interface
(CLI) for those who prefer a straightforward, text-based approach, and a Graphical User Interface (GUI) for
users who favor a more visual, interactive experience.
The CLI offers a menu driven system that lets users quickly add, update, delete, search, or view
inventory. It’s intuitive and efficient, guiding users step-by-step through each task. The GUI complements
this with a simple, yet user friendly design featuring input fields, buttons, and a dynamic table that displays
inventory data in real time. A standout feature of the GUI is the ability to enter database credentials directly,
enabling users to connect securely to a MySQL database and ensure their data is always up to date. As well as
being able to select products to edit and delete from the database view directly.
At its core, Simple IC connects seamlessly to the database, ensuring inventory data is securely saved
and easily accessible. Users can manage stock, search for products, and generate comprehensive reports,
including exporting data to a CSV file for sharing or record-keeping and extensive logging.
By combining robust functionality with ease of use, Simple IC meets all requirements, offering a
reliable tool for managing inventory through either a text based or visual interface. Whether used for day to
day operations or generating detailed reports, Simple IC makes inventory control effortless and easily
updated.
GUI SCREENSHOTS:
CLI Screenshots:
Code:
InventoryControlSystemGUI.java
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.sql.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import src.Logger;
public class InventoryControlSystemGUI extends JFrame {
private JTextField hostField, usernameField;
private JPasswordField passwordField;
private JTextField nameField, descriptionField, quantityField, priceField, searchField;
private JTable productsTable;
private DefaultTableModel tableModel;
private int selectedProductId = -1;
public InventoryControlSystemGUI() {
setTitle("Simple IC: Inventory Control System");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setLocationRelativeTo(null);
// Database Connection Panel
JPanel connectionPanel = new JPanel(new GridLayout(3, 2, 10, 10));
connectionPanel.setBorder(BorderFactory.createTitledBorder("Database Connection"));
JLabel hostLabel = new JLabel("Host:");
hostField = new JTextField("localhost:3306");
JLabel usernameLabel = new JLabel("Username:");
usernameField = new JTextField("root");
JLabel passwordLabel = new JLabel("Password:");
passwordField = new JPasswordField("Dani973$");
connectionPanel.add(hostLabel);
connectionPanel.add(hostField);
connectionPanel.add(usernameLabel);
connectionPanel.add(usernameField);
connectionPanel.add(passwordLabel);
connectionPanel.add(passwordField);
// Product Details Panel
JPanel productPanel = new JPanel(new GridLayout(4, 2, 10, 10));
productPanel.setBorder(BorderFactory.createTitledBorder("Product Details"));
JLabel nameLabel = new JLabel("Name:");
nameField = new JTextField();
JLabel descriptionLabel = new JLabel("Description:");
descriptionField = new JTextField();
JLabel quantityLabel = new JLabel("Quantity:");
quantityField = new JTextField();
JLabel priceLabel = new JLabel("Price:");
priceField = new JTextField();
productPanel.add(nameLabel);
productPanel.add(nameField);
productPanel.add(descriptionLabel);
productPanel.add(descriptionField);
productPanel.add(quantityLabel);
productPanel.add(quantityField);
productPanel.add(priceLabel);
productPanel.add(priceField);
// Search Panel
JPanel searchPanel = new JPanel(new GridLayout(1, 2, 10, 10));
searchPanel.setBorder(BorderFactory.createTitledBorder("Search Products"));
JLabel searchLabel = new JLabel("Search Term:");
searchField = new JTextField();
searchField.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
searchProducts();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
searchPanel.add(searchLabel);
searchPanel.add(searchField);
// Inventory Table Panel
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.setBorder(BorderFactory.createTitledBorder("Inventory"));
productsTable = new JTable();
tableModel = new DefaultTableModel(new Object[]{"ID", "Name", "Description", "Quantity",
"Price"}, 0);
productsTable.setModel(tableModel);
productsTable.getSelectionModel().addListSelectionListener(event -> {
if (!event.getValueIsAdjusting()) {
int selectedRow = productsTable.getSelectedRow();
if (selectedRow != -1) {
selectedProductId = (int) productsTable.getValueAt(selectedRow, 0);
nameField.setText((String) productsTable.getValueAt(selectedRow, 1));
descriptionField.setText((String) productsTable.getValueAt(selectedRow, 2));
quantityField.setText(String.valueOf((int) productsTable.getValueAt(selectedRow, 3)));
priceField.setText(String.valueOf((double) productsTable.getValueAt(selectedRow, 4)));
} else {
selectedProductId = -1;
clearProductFields();
}
}
});
JScrollPane scrollPane = new JScrollPane(productsTable);
tablePanel.add(scrollPane, BorderLayout.CENTER);
// Button Panel
JPanel buttonPanel = new JPanel(new GridLayout(2, 3, 10, 10));
JButton connectButton = new JButton("Connect to DB");
connectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
connectToDatabase();
}
});
JButton addProductButton = new JButton("Add Product");
addProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addProduct();
}
});
JButton editProductButton = new JButton("Edit Product");
editProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editProduct();
}
});
JButton deleteProductButton = new JButton("Delete Product");
deleteProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteProduct();
}
});
JButton searchProductsButton = new JButton("Search Products");
searchProductsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchProducts();
}
});
JButton exportToCSVButton = new JButton("Export Inventory Report As CSV");
exportToCSVButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
exportInventoryToCSV();
}
});
buttonPanel.add(connectButton);
buttonPanel.add(addProductButton);
buttonPanel.add(editProductButton);
buttonPanel.add(deleteProductButton);
buttonPanel.add(searchProductsButton);
buttonPanel.add(exportToCSVButton);
setLayout(new BorderLayout(10, 10));
add(connectionPanel, BorderLayout.NORTH);
add(productPanel, BorderLayout.WEST);
add(searchPanel, BorderLayout.EAST);
add(tablePanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
}
private void connectToDatabase() {
String host = hostField.getText();
String username = usernameField.getText();
String password = new String(passwordField.getPassword());
try (Connection connection = DriverManager.getConnection("jdbc:mysql://" + host +
"/simple_ic", username, password)) {
// Check if the necessary tables exist, and create them if they don't
Operations.createTablesIfNotExist(connection);
JOptionPane.showMessageDialog(this, "Connected to the database successfully!", "Connection
Successful", JOptionPane.INFORMATION_MESSAGE);
Logger.logInfo("Connected to the database successfully.");
viewProducts();
} catch (SQLException e) {
JOptionPane.showMessageDialog(this, "Error connecting to the database: " + e.getMessage(),
"Connection Error", JOptionPane.ERROR_MESSAGE);
Logger.logSevere("Error connecting to the database: " + e.getMessage());
}
}
private void addProduct() {
String name = nameField.getText();
String description = descriptionField.getText();
int quantity = Integer.parseInt(quantityField.getText());
double price = Double.parseDouble(priceField.getText());
Operations.addProduct(name, description, quantity, price);
clearProductFields();
viewProducts();
}
private void editProduct() {
if (selectedProductId != -1) {
String name = nameField.getText();
String description = descriptionField.getText();
int quantity = Integer.parseInt(quantityField.getText());
double price = Double.parseDouble(priceField.getText());
Operations.updateProduct(selectedProductId, name, description, quantity, price);
clearProductFields();
viewProducts();
} else {
JOptionPane.showMessageDialog(this, "Please select a product to edit.", "No Product
Selected", JOptionPane.WARNING_MESSAGE);
}
}
private void deleteProduct() {
if (selectedProductId != -1) {
Operations.deleteProduct(selectedProductId);
clearProductFields();
viewProducts();
} else {
JOptionPane.showMessageDialog(this, "Please select a product to delete.", "No Product
Selected", JOptionPane.WARNING_MESSAGE);
}
}
private void searchProducts() {
String searchTerm = searchField.getText();
tableModel.setRowCount(0);
Operations.searchProducts(searchTerm);
viewProducts();
}
private void exportInventoryToCSV() {
Operations.exportInventoryToCSV();
}
private void clearProductFields() {
nameField.setText("");
descriptionField.setText("");
quantityField.setText("");
priceField.setText("");
}
private void viewProducts() {
// Clear existing rows in the table
tableModel.setRowCount(0);
try (Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/simple_ic", "root", "Dani973$")) {
String query = "SELECT * FROM products";
try (PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
tableModel.addRow(new Object[]{
resultSet.getInt("id"),
resultSet.getString("name"),
resultSet.getString("description"),
resultSet.getInt("quantity"),
resultSet.getDouble("price")
});
}
if (tableModel.getRowCount() == 0) {
JOptionPane.showMessageDialog(this, "No products found in the database.", "Empty
Inventory", JOptionPane.INFORMATION_MESSAGE);
}
Logger.logInfo("Successfully retrieved " + tableModel.getRowCount() + " products from the
database.");
} catch (SQLException e) {
Logger.logSevere("Error fetching products: " + e.getMessage());
JOptionPane.showMessageDialog(this, "Error fetching products: " + e.getMessage(),
"Database Error", JOptionPane.ERROR_MESSAGE);
}
} catch (SQLException e) {
Logger.logSevere("Error connecting to the database: " + e.getMessage());
JOptionPane.showMessageDialog(this, "Error connecting to the database: " + e.getMessage(),
"Connection Error", JOptionPane.ERROR_MESSAGE);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new InventoryControlSystemGUI().setVisible(true);
}
});
}
}
InventoryControlSystem.java
import java.util.Scanner;
import src.Logger;
public class InventoryControlSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
char choice;
// Log application start
Logger.logInfo("Application started."); //Logger
Operations.test();
Logger.logInfo("Operations class test completed."); //Logger
do {
// Display the menu options
System.out.println("=================================");
System.out.println("Welcome to Simple IC: Inventory Control System");
System.out.println("a. Add new item to inventory");
System.out.println("v. View current stock levels");
System.out.println("s. Search for a product");
System.out.println("u. Update item details");
System.out.println("d. Delete an item from inventory");
System.out.println("e. Export inventory to CSV");
System.out.println("q. Quit");
System.out.println("=================================");
// Read the user's choice
choice = scanner.next().charAt(0);
Logger.logInfo("User selected menu option: " + choice); //Logger
switch (choice) {
case 'a': // Add a new product
System.out.print("Enter product name: ");
String name = scanner.next();
scanner.nextLine();
System.out.print("Enter description: ");
String description = scanner.nextLine();
int quantity = 0;
boolean validInput = false;
while (!validInput) {
System.out.print("Enter quantity: ");
if (scanner.hasNextInt()) {
quantity = scanner.nextInt();
validInput = true; // Exit the loop if input is valid
} else {
System.out.println("Invalid input. Please enter an integer value.");
Logger.logWarning("Invalid input for quantity."); //Logger
scanner.next(); // Clear the invalid input
}
}
System.out.print("Enter price: ");
double price = scanner.nextDouble();
Logger.logInfo("Adding product: Name=" + name + ", Description=" + description + ",
Quantity=" + quantity + ", Price=" + price); //Logger
Operations.addProduct(name, description, quantity, price);
Logger.logInfo("Product added successfully."); //Logger
break;
case 'v': // View all products
Logger.logInfo("Fetching all products from the database."); //Logger
Operations.viewProducts();
Logger.logInfo("All products fetched successfully."); //Logger
break;
case 's': // Search for a product
System.out.print("Enter search term (name or description): ");
scanner.nextLine(); // Consume the leftover newline
String searchTerm = scanner.nextLine();
Operations.searchProducts(searchTerm);
break;
case 'u': // Update a product
System.out.print("Enter product ID to update: ");
int productId = scanner.nextInt();
scanner.nextLine(); // Consume the leftover newline character
System.out.print("Enter new product name: ");
String newName = scanner.nextLine();
System.out.print("Enter new description: ");
String newDescription = scanner.nextLine();
System.out.print("Enter new quantity: ");
int newQuantity = scanner.nextInt();
scanner.nextLine(); // Consume the leftover newline character
System.out.print("Enter new price: ");
double newPrice = scanner.nextDouble();
scanner.nextLine(); // Consume the leftover newline character
Logger.logInfo("Updating product ID=" + productId + " with new values: Name=" +
newName + ", Description=" + newDescription + ", Quantity=" + newQuantity + ", Price=" +
newPrice); //Logger
Operations.updateProduct(productId, newName, newDescription, newQuantity, newPrice);
Logger.logInfo("Product updated successfully."); //Logger
break;
case 'd': // Delete a product
System.out.print("Enter product ID to delete: ");
int deleteId = scanner.nextInt();
Logger.logInfo("Attempting to delete product with ID=" + deleteId); //Logger
Operations.deleteProduct(deleteId);
Logger.logInfo("Product deleted successfully."); //Logger
break;
case 'e': // Export inventory to CSV
Operations.exportInventoryToCSV();
break;
case 'q': // Quit the program
Logger.logInfo("User exited the system."); //Logger
System.out.println("Exiting the system. Thank you!");
break;
default: // Handle invalid input
Logger.logWarning("Invalid menu option selected: " + choice); //Logger
System.out.println("Invalid choice. Please try again.");
}
System.out.println();
} while (choice != 'q'); // Repeat until the user chooses to quit
// Log application shutdown
Logger.logInfo("Application shut down."); //Logger
}
}
Logger.java
package src;
import java.io.IOException;
import java.util.logging.*;
public class Logger {
private static final java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(Logger.class.getName());
private static Handler fileHandler;
static {
try {
// Configure FileHandler with a single log file
fileHandler = new FileHandler("Logger.log", true); // Appends to the same file on subsequent
runs
fileHandler.setFormatter(new SimpleFormatter()); // Optional: Use SimpleFormatter or a
custom one
logger.addHandler(fileHandler);
// Optional: Add ConsoleHandler for console output
logger.addHandler(new ConsoleHandler());
// Set the logger level
logger.setLevel(Level.ALL);
} catch (IOException e) {
System.err.println("Failed to initialize logger: " + e.getMessage());
}
}
public static void logInfo(String message) {
logger.log(Level.INFO, message);
}
public static void logWarning(String message) {
logger.log(Level.WARNING, message);
}
public static void logSevere(String message) {
logger.log(Level.SEVERE, message);
}
public static void logConfig(String message) {
logger.log(Level.CONFIG, message);
}
public static void closeLogger() {
// Close the file handler to release resources
if (fileHandler != null) {
fileHandler.close();
}
}
}
Operations.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.FileWriter;
import java.io.IOException;
import src.Logger;
public class Operations {
// Test method for debugging
public static void test() {
System.out.println("Operations class is accessible!");
}
// Method to add a product to the database
public static void addProduct(String name, String description, int quantity, double price) {
String query = "INSERT INTO products (name, description, quantity, price) VALUES
(?, ?, ?, ?)";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, name);
statement.setString(2, description);
statement.setInt(3, quantity);
statement.setDouble(4, price);
statement.executeUpdate();
System.out.println("Product added successfully!");
Logger.logInfo("Product added: " + name);
} catch (SQLException e) {
Logger.logSevere("Error adding product: " + e.getMessage());
System.err.println("Error adding product: " + e.getMessage());
}
}
// Method to view all products
public static void viewProducts() {
Logger.logInfo("Fetching all products from the database."); // Logger
String query = "SELECT * FROM products";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
System.out.println("ID: " + resultSet.getInt("id") +
", Name: " + resultSet.getString("name") +
", Description: " + resultSet.getString("description") +
", Quantity: " + resultSet.getInt("quantity") +
", Price: " + resultSet.getDouble("price"));
}
} catch (SQLException e) {
System.err.println("Error fetching products: " + e.getMessage());
}
}
//Method to search inventory
public static void searchProducts(String searchTerm) {
String query = "SELECT * FROM products WHERE name LIKE ? OR description LIKE ?";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, "%" + searchTerm + "%");
statement.setString(2, "%" + searchTerm + "%");
ResultSet resultSet = statement.executeQuery();
boolean found = false;
while (resultSet.next()) {
System.out.println("ID: " + resultSet.getInt("id") +
", Name: " + resultSet.getString("name") +
", Description: " + resultSet.getString("description") +
", Quantity: " + resultSet.getInt("quantity") +
", Price: " + resultSet.getDouble("price"));
found = true;
}
if (!found) {
System.out.println("No products found matching the search term.");
}
} catch (SQLException e) {
Logger.logSevere("Error searching products: " + e.getMessage()); // Logger
System.err.println("Error searching products: " + e.getMessage());
}
}
// Method to delete a product
public static void deleteProduct(int productId) {
String deleteQuery = "DELETE FROM simple_ic.products WHERE id = ?";
String logQuery = "SELECT message FROM deletion_logs WHERE product_id = ?";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement deleteStatement = connection.prepareStatement(deleteQuery);
PreparedStatement logStatement = connection.prepareStatement(logQuery)) {
// Delete the product
deleteStatement.setInt(1, productId);
deleteStatement.executeUpdate();
Logger.logInfo("Deleting product with ID: " + productId); // Logger
// Retrieve the deletion log
logStatement.setInt(1, productId);
ResultSet rs = logStatement.executeQuery();
if (rs.next()) {
String logMessage = rs.getString("message");
Logger.logInfo(logMessage); // Log the deletion message
}
} catch (SQLException e) {
Logger.logSevere("Error deleting product: " + e.getMessage()); // Logger
}
}
// Method to update a product
public static void updateProduct(int productId, String name, String description, int quantity, double
price) {
String query = "UPDATE products SET name = ?, description = ?, quantity = ?, price = ?
WHERE id = ?";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, name);
statement.setString(2, description);
statement.setInt(3, quantity);
statement.setDouble(4, price);
statement.setInt(5, productId);
Logger.logInfo("Updating product with ID: " + productId + " to new values."); // Logger
statement.executeUpdate();
System.out.println("Product updated successfully!");
} catch (SQLException e) {
System.err.println("Error updating product: " + e.getMessage());
}
}
// Method to generate a report of all products
public static void exportInventoryToCSV() {
String query = "SELECT * FROM products";
try (Connection connection = DatabaseConnector.connect();
PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery();
FileWriter writer = new FileWriter("inventory.csv")) {
// Write CSV Header
writer.write("ID,Name,Description,Quantity,Price\n");
// Write data rows
while (resultSet.next()) {
writer.write(resultSet.getInt("id") + "," +
resultSet.getString("name") + "," +
resultSet.getString("description") + "," +
resultSet.getInt("quantity") + "," +
resultSet.getDouble("price") + "\n");
}
System.out.println("Inventory exported successfully to inventory.csv.");
Logger.logInfo("Inventory exported successfully to inventory.csv"); // Logger
} catch (SQLException | IOException e) {
Logger.logSevere("Error exporting inventory: " + e.getMessage()); // Logger
System.err.println("Error exporting inventory: " + e.getMessage());
}
}
// Method to create necessary database tables if they do not exist
public static void createTablesIfNotExist(Connection connection) {
try {
// Create products table
String createProductsTableQuery = "CREATE TABLE IF NOT EXISTS products (" +
"id INT AUTO_INCREMENT PRIMARY KEY, " +
"name VARCHAR(255) NOT NULL, " +
"description TEXT, " +
"quantity INT NOT NULL, " +
"price DECIMAL(10, 2) NOT NULL" +
")";
// Create deletion_logs table
String createDeletionLogsTableQuery = "CREATE TABLE IF NOT EXISTS deletion_logs (" +
"id INT AUTO_INCREMENT PRIMARY KEY, " +
"product_id INT, " +
"message VARCHAR(255), " +
"deletion_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP" +
")";
try (PreparedStatement productsStatement =
connection.prepareStatement(createProductsTableQuery);
PreparedStatement logsStatement =
connection.prepareStatement(createDeletionLogsTableQuery)) {
productsStatement.execute();
logsStatement.execute();
System.out.println("Tables created successfully (if they didn't already exist)");
Logger.logInfo("Database tables verified/created successfully");
}
} catch (SQLException e) {
System.err.println("Error creating tables: " + e.getMessage());
Logger.logSevere("Error creating database tables: " + e.getMessage());
}
}
}
DatabaseConnector.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnector {
private static final String URL = "jdbc:mysql://localhost:3306/simple_ic";
private static final String USERNAME = "root";
private static final String PASSWORD = "Dani973$";
public static Connection connect() throws SQLException {
try {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
System.err.println("Database connection failed: " + e.getMessage());
throw e;
}
}
}
mylogging.properties
handlers= java.util.logging.ConsoleHandler, java.util.logging.FileHandler
.level= INFO
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = INFO
java.util.logging.FileHandler.pattern = logger.log
java.util.logging.FileHandler.limit = 2000
java.util.logging.FileHandler.count = 5
java.util.logging.FileHandler.formatter = src.MyFormatter
GitHub Link https://github.com/KevinGMcMahon/SimpleIC/tree/main
GitHub Screenshots
Source
Files
Jar
(Should create necessary tables upon connecting to DB)