From 02fbe15651586859713678c284f6ffb1272999d1 Mon Sep 17 00:00:00 2001 From: AdrianBalunan Date: Sun, 12 Apr 2026 19:28:40 +0200 Subject: [PATCH] Fix: Futher refined methods to avoid n+1 threading and splitted it for more accessibiliy --- .../systemutvikling/team6/HmHApplication.java | 11 +- .../AvailableOrganizationController.java | 4 +- .../team6/controller/FrontpageController.java | 11 +- .../team6/database/APIToDatabaseService.java | 139 ++++ .../team6/database/DatabaseManager.java | 745 ------------------ .../team6/database/DatabaseSetup.java | 284 +++++++ .../team6/database/Readers/CharitySelect.java | 126 +++ .../database/Readers/DonationSelect.java | 68 ++ .../team6/database/Readers/UserSelect.java | 201 +++++ .../team6/models/Feedback.java | 2 +- .../team6/scraper/APICharityData.java | 4 +- .../team6/DAO/DonationDAOTest.java | 4 +- .../team6/database/DatabaseManagerTest.java | 5 +- 13 files changed, 839 insertions(+), 765 deletions(-) create mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/APIToDatabaseService.java delete mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java create mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java create mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java create mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java create mode 100644 helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java index 74bb73c..da9cebb 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java @@ -3,14 +3,11 @@ import static javafx.application.Application.launch; import java.net.http.HttpClient; -import java.util.Objects; + import javafx.application.Application; -import javafx.fxml.FXMLLoader; -import javafx.scene.Scene; -import javafx.scene.image.Image; import javafx.stage.Stage; import ntnu.systemutvikling.team6.database.DatabaseConnection; -import ntnu.systemutvikling.team6.database.DatabaseManager; +import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.CharityRegistry; import ntnu.systemutvikling.team6.scraper.APICharityScraper; @@ -42,7 +39,7 @@ public void init() { /* Test and create tables to MySQL if ain't any */ try { DatabaseConnection conn = new DatabaseConnection(); - DatabaseManager db = new DatabaseManager(conn); + DatabaseSetup db = new DatabaseSetup(conn); db.testConnection(); db.createTables(); } catch (Exception e) { @@ -53,7 +50,7 @@ public void init() { HttpClient https = HttpClient.newHttpClient(); APICharityScraper scraper = new APICharityScraper(https); DatabaseConnection conn = new DatabaseConnection(); - DatabaseManager db = new DatabaseManager(conn); + DatabaseSetup db = new DatabaseSetup(conn); if (scraper.checkConnection()) { CharityRegistry charityRegistry = scraper.parseJSON(scraper.getJSONData()); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java index 1d74e24..139a5d2 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/AvailableOrganizationController.java @@ -10,7 +10,7 @@ import javafx.scene.control.TextField; import javafx.scene.layout.FlowPane; import ntnu.systemutvikling.team6.database.DatabaseConnection; -import ntnu.systemutvikling.team6.database.DatabaseManager; +import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.CharityRegistry; @@ -40,7 +40,7 @@ public class AvailableOrganizationController { @FXML public void initialize() { DatabaseConnection conn = new DatabaseConnection(); - DatabaseManager db = new DatabaseManager(conn); + DatabaseSetup db = new DatabaseSetup(conn); CharityRegistry charities = db.getCharitiesFromDB(); allCharities = charities.getAllCharities(); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java index 1cad4eb..9ce1e2e 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java @@ -13,7 +13,9 @@ import javafx.scene.control.TextField; import javafx.scene.layout.FlowPane; import ntnu.systemutvikling.team6.database.DatabaseConnection; -import ntnu.systemutvikling.team6.database.DatabaseManager; +import ntnu.systemutvikling.team6.database.DatabaseSetup; +import ntnu.systemutvikling.team6.database.Readers.CharitySelect; +import ntnu.systemutvikling.team6.database.Readers.DonationSelect; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.CharityRegistry; import ntnu.systemutvikling.team6.models.Donation; @@ -54,9 +56,10 @@ public class FrontpageController { public void initialize() { try { DatabaseConnection conn = new DatabaseConnection(); - DatabaseManager db = new DatabaseManager(conn); - CharityRegistry charities = db.getCharitiesFromDB(); - DonationRegistry donations = db.getDonationFromDB(); + CharitySelect cdb = new CharitySelect(conn); + DonationSelect ddb = new DonationSelect(conn); + CharityRegistry charities = cdb.getCharitiesFromDB(); + DonationRegistry donations = ddb.getDonationFromDB(); allCharities = new ArrayList<>(charities.getAllCharities()); displayCharities(allCharities); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/APIToDatabaseService.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/APIToDatabaseService.java new file mode 100644 index 0000000..0bbaa47 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/APIToDatabaseService.java @@ -0,0 +1,139 @@ +package ntnu.systemutvikling.team6.database; + +import ntnu.systemutvikling.team6.models.Charity; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.UUID; + +public class APIToDatabaseService { + private final DatabaseConnection connection; + /** + * Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection + * credentials. + * + * @param connection + */ + public APIToDatabaseService(DatabaseConnection connection) { + this.connection = connection; + } + + /** + * This method is used to verify the integrity of the data in the {@code charities} table and to + * update it based on the data retrieved from the IK API. The param charities are retrieved from + * the IK API through the APICharityData class. Called in initialize method in + * HmHApplication.java, which is the main class of the application, to ensure that the data is up + * to date when the application starts. Uses a a temp table to ensure that the data in the + * database is consistent with the data from the API. + * + * @param charities + */ + public void addAPIDataToTable(List charities) { + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + conn.setAutoCommit(false); + String sql_query = + """ + INSERT INTO Charities (UUID_charities, org_number, charity_name, charity_description, charity_link, pre_approved, status) + VALUES (?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + charity_name = VALUES(charity_name), + charity_link = VALUES(charity_link), + pre_approved = VALUES(pre_approved), + status = VALUES(status) + """; + + try (PreparedStatement ps = conn.prepareStatement(sql_query)) { + for (Charity charity : charities) { + if (charity.getUUID() == null) { + ps.setString(1, UUID.randomUUID().toString()); + } else { + ps.setString(1, charity.getUUID().toString()); + } + + ps.setString(2, charity.getOrg_number().replaceAll("\\s", "")); + ps.setString(3, charity.getName()); + ps.setString(4, "Blank until webscraber works"); + ps.setString(5, charity.getDescription()); + ps.setBoolean(6, charity.getPreApproved()); // Description is the link + ps.setString(7, charity.getStatus()); + + ps.addBatch(); + } + ps.executeBatch(); + } + + // -- Intergerty Check: + String createTemp = + """ + CREATE TEMPORARY TABLE temp_api_charities ( + org_number VARCHAR(255) PRIMARY KEY + ) + """; + + try (PreparedStatement ps = conn.prepareStatement(createTemp)) { + ps.execute(); + } + + String insertTemp = "INSERT IGNORE INTO temp_api_charities (org_number) VALUES (?)"; + + try (PreparedStatement ps = conn.prepareStatement(insertTemp)) { + + for (Charity charity : charities) { + ps.setString(1, charity.getOrg_number().replaceAll("\\s", "")); + ps.addBatch(); + } + + ps.executeBatch(); + } + + String deleteSql = + """ + DELETE FROM Charities c + WHERE NOT EXISTS ( + SELECT 1 FROM temp_api_charities t + WHERE t.org_number = c.org_number + ) + AND NOT EXISTS ( + SELECT 1 FROM Donations d WHERE d.charity_id = c.UUID_charities + ) + AND NOT EXISTS ( + SELECT 1 FROM Feedback f WHERE f.charity_id = c.UUID_charities + ) + AND NOT EXISTS ( + SELECT 1 FROM CharityUsers cu WHERE cu.Charities_UUID_charities = c.UUID_charities + ); + """; + + try (PreparedStatement ps = conn.prepareStatement(deleteSql)) { + ps.executeUpdate(); + } + + conn.commit(); + + } catch (SQLException e) { + if (conn != null) { + try { + conn.rollback(); + } catch (SQLException ex) { + ex.printStackTrace(); + } + } + e.printStackTrace(); + + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } finally { + if (conn != null) { + try { + conn.setAutoCommit(true); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java deleted file mode 100644 index b414fde..0000000 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java +++ /dev/null @@ -1,745 +0,0 @@ -package ntnu.systemutvikling.team6.database; - -import java.sql.*; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import ntnu.systemutvikling.team6.models.*; -import ntnu.systemutvikling.team6.models.user.*; -import ntnu.systemutvikling.team6.scraper.APICharityData; - -/** - * Manages the Database with MySQL tables and JDBC. - * - *

This class is responsible for creating the tables needed for the application, if not done - * already and maintaining the {@code charities} table based on data retrieved from the IK API. It - * is also responsible for retrieving the data from the database and sending it to the application - * through the CharityRegistry and DonationRegistry. It is used by the FrontpageController to - * retrieve the data needed to display the charities - */ -public class DatabaseManager { - private final DatabaseConnection connection; - - /** - * Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection - * credentials. - */ - public DatabaseManager(DatabaseConnection connection) { - this.connection = connection; - } - - /** - * Connection test for the Database. Does a simple SELECT SQL query and returns either true og and - * Exception if failed - * - * @return true if Sucsedd or SQLExepction if failed - */ - public boolean testConnection() { - try (Connection conn = connection.getMySqlConnection(); - Statement stmt = conn.createStatement()) { - - ResultSet rs = stmt.executeQuery("SELECT 1"); - - if (rs.next()) { - System.out.println("Database connection verified."); - return true; - } - - } catch (SQLException e) { - System.out.println("Database connection failed."); - e.printStackTrace(); - } - - return false; - } - - /** - * Creates the {@code Charities} and {@code Donations} tables if they do not already exist. - * - *

The table structure for Charities is based on fields from {@link APICharityData}. - * - * @throws RuntimeException if a {@link SQLException} occurs while creating the table - */ - public void createTables() { - String charitiesTable = - """ - -- ----------------------------------------------------- - -- Table `HelpMeHelp`.`Charities` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Charities` ( - `UUID_charities` CHAR(36) NOT NULL, - `org_number` VARCHAR(255) NOT NULL, - `charity_name` VARCHAR(255) NOT NULL, - `charity_description` VARCHAR(255) NOT NULL, - `charity_link` VARCHAR(255) NOT NULL, - `pre_approved` TINYINT NOT NULL, - `status` VARCHAR(255) NOT NULL, - PRIMARY KEY (`UUID_charities`), - UNIQUE INDEX `org_number_UNIQUE` (`org_number` ASC) VISIBLE) - ENGINE = InnoDB; - - """; - String donationsTable = - """ - -- ----------------------------------------------------- - -- Table `HelpMeHelp`.`Donations` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Donations` ( - `UUID_Donations` CHAR(36) NOT NULL, - `amount` DECIMAL NOT NULL, - `date` DATE NOT NULL, - `charity_id` CHAR(36) NOT NULL, - `user_id` CHAR(36) NOT NULL, - PRIMARY KEY (`UUID_Donations`), - INDEX `fk_Donations_Charities_idx` (`charity_id` ASC) VISIBLE, - INDEX `fk_Donations_User1_idx` (`user_id` ASC) VISIBLE, - CONSTRAINT `fk_Donations_Charities` - FOREIGN KEY (`charity_id`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Donations_User1` - FOREIGN KEY (`user_id`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - String userTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`User` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`User` ( - `UUID_User` CHAR(36) NOT NULL, - `user_displayname` VARCHAR(255) NOT NULL, - `user_name` VARCHAR(255) NOT NULL, - `user_email` VARCHAR(255) NOT NULL, - `user_password` VARCHAR(255) NOT NULL, - `role` VARCHAR(45) NOT NULL, - PRIMARY KEY (`UUID_User`)) - ENGINE = InnoDB; - """; - - String settingsTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`Settings` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Settings` ( - `User_UUID_User` CHAR(36) NOT NULL, - `isAnonymous` TINYINT NOT NULL, - `language` VARCHAR(45) NOT NULL, - `lightmode` TINYINT NOT NULL, - PRIMARY KEY (`User_UUID_User`), - INDEX `fk_Settings_User1_idx` (`User_UUID_User` ASC) VISIBLE, - CONSTRAINT `fk_Settings_User1` - FOREIGN KEY (`User_UUID_User`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - - String messagesTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`Messages` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Messages` ( - `UUID_message` CHAR(36) NOT NULL, - `message_title` VARCHAR(255) NOT NULL, - `message_content` VARCHAR(255) NOT NULL, - `message_date` DATE NOT NULL, - `sender_user_id` CHAR(36) NULL, - `sender_charity_id` CHAR(36) NULL, - `user_id` CHAR(36) NOT NULL, - PRIMARY KEY (`UUID_message`), - INDEX `fk_Messages_User1_idx` (`sender_user_id` ASC) VISIBLE, - INDEX `fk_Messages_Charities1_idx` (`sender_charity_id` ASC) VISIBLE, - INDEX `fk_Messages_User2_idx` (`user_id` ASC) VISIBLE, - CONSTRAINT `fk_Messages_User1` - FOREIGN KEY (`sender_user_id`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Messages_Charities1` - FOREIGN KEY (`sender_charity_id`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Messages_User2` - FOREIGN KEY (`user_id`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - - String feedbackTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`Feedback` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Feedback` ( - `UUID_feedback` CHAR(36) NOT NULL, - `feedback_comment` VARCHAR(255) NOT NULL, - `feedback_date` DATE NOT NULL, - `isAnonymous` TINYINT NOT NULL, - `charity_id` CHAR(36) NOT NULL, - `user_id` CHAR(36) NOT NULL, - PRIMARY KEY (`UUID_feedback`), - INDEX `fk_Feedback_Charities1_idx` (`charity_id` ASC) VISIBLE, - INDEX `fk_Feedback_User1_idx` (`user_id` ASC) VISIBLE, - CONSTRAINT `fk_Feedback_Charities1` - FOREIGN KEY (`charity_id`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Feedback_User1` - FOREIGN KEY (`user_id`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - String categoriesTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`Categories` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Categories` ( - `category_id` INT NOT NULL AUTO_INCREMENT, - `category` VARCHAR(255) NOT NULL, - PRIMARY KEY (`category_id`)) - ENGINE = InnoDB; - """; - - String charityCategoriesTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`Charity_Categories` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Charity_Categories` ( - `Categories_category_id` INT NOT NULL, - `Charities_UUID_charities` CHAR(36) NOT NULL, - PRIMARY KEY (`Categories_category_id`, `Charities_UUID_charities`), - INDEX `fk_Categories_has_Charities_Charities1_idx` (`Charities_UUID_charities` ASC) VISIBLE, - INDEX `fk_Categories_has_Charities_Categories1_idx` (`Categories_category_id` ASC) VISIBLE, - CONSTRAINT `fk_Categories_has_Charities_Categories1` - FOREIGN KEY (`Categories_category_id`) - REFERENCES `apbaluna`.`Categories` (`category_id`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Categories_has_Charities_Charities1` - FOREIGN KEY (`Charities_UUID_charities`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - - String charityUserTable = - """ - -- ----------------------------------------------------- - -- Table `apbaluna`.`CharityUsers` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`CharityUsers` ( - `Charities_UUID_charities` CHAR(36) NOT NULL, - `User_UUID_User` CHAR(36) NOT NULL, - PRIMARY KEY (`Charities_UUID_charities`, `User_UUID_User`), - INDEX `fk_Charities_has_User_User1_idx` (`User_UUID_User` ASC) VISIBLE, - INDEX `fk_Charities_has_User_Charities1_idx` (`Charities_UUID_charities` ASC) VISIBLE, - CONSTRAINT `fk_Charities_has_User_Charities1` - FOREIGN KEY (`Charities_UUID_charities`) - REFERENCES `apbaluna`.`Charities` (`UUID_charities`) - ON DELETE NO ACTION - ON UPDATE NO ACTION, - CONSTRAINT `fk_Charities_has_User_User1` - FOREIGN KEY (`User_UUID_User`) - REFERENCES `apbaluna`.`User` (`UUID_User`) - ON DELETE NO ACTION - ON UPDATE NO ACTION) - ENGINE = InnoDB; - """; - - try (Connection conn = connection.getMySqlConnection(); - Statement s = conn.createStatement()) { - - s.execute(charitiesTable); - s.execute(userTable); - s.execute(donationsTable); - s.execute(settingsTable); - s.execute(messagesTable); - s.execute(feedbackTable); - s.execute(categoriesTable); - s.execute(charityCategoriesTable); - s.execute(charityUserTable); - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("Error creating table."); - } - } - - /** - * This method is used to verify the integrity of the data in the {@code charities} table and to - * update it based on the data retrieved from the IK API. The param charities are retrieved from - * the IK API through the APICharityData class. Called in initialize method in - * HmHApplication.java, which is the main class of the application, to ensure that the data is up - * to date when the application starts. Uses a a temp table to ensure that the data in the - * database is consistent with the data from the API. - * - * @param charities - */ - public void addAPIDataToTable(List charities) { - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - conn.setAutoCommit(false); - String sql_query = - """ - INSERT INTO Charities (UUID_charities, org_number, charity_name, charity_description, charity_link, pre_approved, status) - VALUES (?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE - charity_name = VALUES(charity_name), - charity_link = VALUES(charity_link), - pre_approved = VALUES(pre_approved), - status = VALUES(status) - """; - - try (PreparedStatement ps = conn.prepareStatement(sql_query)) { - for (Charity charity : charities) { - if (charity.getUUID() == null) { - ps.setString(1, UUID.randomUUID().toString()); - } else { - ps.setString(1, charity.getUUID().toString()); - } - - ps.setString(2, charity.getOrg_number().replaceAll("\\s", "")); - ps.setString(3, charity.getName()); - ps.setString(4, "Blank until webscraber works"); - ps.setString(5, charity.getDescription()); - ps.setBoolean(6, charity.getPreApproved()); // Description is the link - ps.setString(7, charity.getStatus()); - - ps.addBatch(); - } - ps.executeBatch(); - } - - // -- Intergerty Check: - String createTemp = - """ - CREATE TEMPORARY TABLE temp_api_charities ( - org_number VARCHAR(255) PRIMARY KEY - ) - """; - - try (PreparedStatement ps = conn.prepareStatement(createTemp)) { - ps.execute(); - } - - String insertTemp = "INSERT IGNORE INTO temp_api_charities (org_number) VALUES (?)"; - - try (PreparedStatement ps = conn.prepareStatement(insertTemp)) { - - for (Charity charity : charities) { - ps.setString(1, charity.getOrg_number().replaceAll("\\s", "")); - ps.addBatch(); - } - - ps.executeBatch(); - } - - String deleteSql = - """ - DELETE FROM Charities c - WHERE NOT EXISTS ( - SELECT 1 FROM temp_api_charities t - WHERE t.org_number = c.org_number - ) - AND NOT EXISTS ( - SELECT 1 FROM Donations d WHERE d.charity_id = c.UUID_charities - ) - AND NOT EXISTS ( - SELECT 1 FROM Feedback f WHERE f.charity_id = c.UUID_charities - ) - AND NOT EXISTS ( - SELECT 1 FROM CharityUsers cu WHERE cu.Charities_UUID_charities = c.UUID_charities - ); - """; - - try (PreparedStatement ps = conn.prepareStatement(deleteSql)) { - ps.executeUpdate(); - } - - conn.commit(); - - } catch (SQLException e) { - if (conn != null) { - try { - conn.rollback(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - } - e.printStackTrace(); - - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } finally { - if (conn != null) { - try { - conn.setAutoCommit(true); - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - public CharityRegistry getCharitiesFromDB() { - CharityRegistry registry = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - c.UUID_charities, c.org_number, c.charity_name, c.charity_link, c.pre_approved, c.status, - f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, - u.UUID_user, u.user_name, u.user_email, u.user_password, u.role - FROM Charities c - LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities - LEFT JOIN User u ON f.user_id = u.UUID_user - """; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query); - - Charity currentCharity = null; - String lastCharity = null; - - registry = new CharityRegistry(); - while (rs.next()) { - String currentId = rs.getString("UUID_charities"); - - if (lastCharity == null || !currentId.equals(lastCharity)) { - currentCharity = - new Charity( - rs.getString("UUID_charities"), - rs.getString("org_number"), - rs.getString("charity_link"), - rs.getString("charity_name"), - rs.getBoolean("pre_approved"), - rs.getString("status") - ); - registry.addCharity(currentCharity); - lastCharity = currentId; - } - String feedbackId = rs.getString("UUID_feedback"); - if (feedbackId != null){ - User userWithNoSettingsAndInbox = new User( - rs.getString("UUID_User"), - rs.getString("user_name"), - rs.getString("user_email"), - rs.getString("user_password"), - rs.getString("role") - ); - - Feedback feedback = new Feedback( - rs.getString("UUID_feedback"), - userWithNoSettingsAndInbox, - rs.getString("feedback_comment"), - LocalDate.parse(rs.getString("feedback_date")) - ); - - currentCharity.getFeedbacks().add(feedback); - } - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return registry; - } - public UserRegistry getUsersFromDB(){ - UserRegistry registry = new UserRegistry(); - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, - s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, - m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id - FROM User u - LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user - LEFT JOIN Messages m ON u.UUID_User = m.user_id - """; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query); - - User currentUser = null; - String lastUserid = null; - - while (rs.next()) { - String userId = rs.getString("UUID_User"); - - if (lastUserid == null || !userId.equals(lastUserid)) { - currentUser = new User( - userId, - rs.getString("user_name"), - rs.getString("user_email"), - rs.getString("user_password"), - rs.getString("role") - ); - if (rs.getString("isAnonymous") != null){ - Settings settings = new Settings( - rs.getBoolean("isAnonymous"), - Language.valueOf(rs.getString("language").toUpperCase()), - rs.getBoolean("lightmode") - ); - currentUser.setSettings(settings); - } - currentUser.setInbox(new Inbox()); - registry.addUser(currentUser); - lastUserid = userId; - } - String messageId = rs.getString("UUID_message"); - if (messageId != null) { - Message message = new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date")) - ); - - currentUser.getInbox().addMessage(message); - } - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return registry; - } - - public User getUserFromDBUuid(String user_id){ - User user = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, - s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, - m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id - FROM User u - LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user - LEFT JOIN Messages m ON u.UUID_User = m.user_id - WHERE u.UUID_User = ?; - """; - PreparedStatement stmt = conn.prepareStatement(sql_query); - stmt.setString(1, user_id); - ResultSet rs = stmt.executeQuery(); - - String lastUserid = null; - while (rs.next()) { - String userId = rs.getString("UUID_User"); - if (lastUserid == null || !userId.equals(lastUserid)) { - user = new User( - userId, - rs.getString("user_name"), - rs.getString("user_email"), - rs.getString("user_password"), - rs.getString("role") - ); - if (rs.getString("isAnonymous") != null){ - Settings settings = new Settings( - rs.getBoolean("isAnonymous"), - Language.valueOf(rs.getString("language").toUpperCase()), - rs.getBoolean("lightmode") - ); - user.setSettings(settings); - } - user.setInbox(new Inbox()); - lastUserid = userId; - } - String messageId = rs.getString("UUID_message"); - if (messageId != null) { - Message message = new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_content"), - LocalDate.parse(rs.getString("message_date")) - ); - - user.getInbox().addMessage(message); - } - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return user; - } - - public Settings getSettingsForUser(String user_id){ - Settings settings = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT User_UUID_User, isAnonymous, language, lightmode FROM Settings - WHERE User_UUID_User = ?; - """; - PreparedStatement stmt = conn.prepareStatement(sql_query); - stmt.setString(1, user_id); - stmt.setMaxRows(1); - ResultSet rs = stmt.executeQuery(); - - while (rs.next()) { - settings = new Settings( - rs.getBoolean("isAnonymous"), - Language.valueOf(rs.getString("language").toUpperCase()), - rs.getBoolean("lightmode") - ); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - - return settings; - } - - public Inbox getInboxForUser(String user_id){ - Inbox inbox = new Inbox(); - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT UUID_message, message_title, message_content, message_date, sender_user_id, sender_charity_id, user_id FROM Messages - WHERE user_id = ?; - """; - PreparedStatement stmt = conn.prepareStatement(sql_query); - stmt.setString(1, user_id); - ResultSet rs = stmt.executeQuery(); - - while (rs.next()) { - Message message = new Message( - rs.getString("message_title"), - UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_date"), - LocalDate.parse(rs.getString("message_date")) - ); - inbox.addMessage(message); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - - return inbox; - } - - - public DonationRegistry getDonationFromDB() { - DonationRegistry registry = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - d.UUID_Donations, - d.amount, - d.date, - c.UUID_charities, - c.org_number, - c.charity_name, - c.charity_link, - c.pre_approved, - c.status - FROM Donations d - JOIN Charities c - ON d.Charities_UUID_charities = c.UUID_charities - """; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query); - - registry = new DonationRegistry(); - while (rs.next()) { - Charity charity = - new Charity( - rs.getString("UUID_charities"), - rs.getString("org_number"), - rs.getString("charity_name"), - rs.getString("charity_link"), - rs.getBoolean("pre_approved"), - rs.getString("status")); - - Donation donation = - new Donation( - rs.getString("UUID_Donations"), - rs.getDouble("amount"), - rs.getDate("date").toLocalDate(), - charity); - registry.addDonation(donation); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return registry; - } - - public ArrayList getFeedbackforCharityUUID(String charity_uuid) { - ArrayList Feedbacks = new ArrayList<>(); - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, - u.UUID_user, u.user_name, u.user_email, u.user_password, u.role - FROM Feedback f - LEFT JOIN User u ON f.user_id = u.UUID_user - WHERE f.charity_id = ?; - """; - PreparedStatement stmt = conn.prepareStatement(sql_query); - stmt.setString(1, charity_uuid); - ResultSet rs = stmt.executeQuery(); - - while (rs.next()){ - User userWithNoSettingsAndInbox = new User( - rs.getString("UUID_User"), - rs.getString("user_name"), - rs.getString("user_email"), - rs.getString("user_password"), - rs.getString("role") - ); - Feedback feedback = new Feedback( - rs.getString("UUID_feedback"), - userWithNoSettingsAndInbox, - rs.getString("feedback_comment"), - LocalDate.parse(rs.getString("feedback_date")) - ); - Feedbacks.add(feedback); - } - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } finally { - conn = null; - } - return Feedbacks; - } -} \ No newline at end of file diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java new file mode 100644 index 0000000..421c8bc --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java @@ -0,0 +1,284 @@ +package ntnu.systemutvikling.team6.database; + +import java.sql.*; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.UUID; + +import ntnu.systemutvikling.team6.models.*; +import ntnu.systemutvikling.team6.models.user.*; +import ntnu.systemutvikling.team6.scraper.APICharityData; + +/** + * Manages the Database with MySQL tables and JDBC. + * + *

This class is responsible for creating the tables needed for the application, if not done + * already and maintaining the {@code charities} table based on data retrieved from the IK API. It + * is also responsible for retrieving the data from the database and sending it to the application + * through the CharityRegistry and DonationRegistry. It is used by the FrontpageController to + * retrieve the data needed to display the charities + */ +public class DatabaseSetup { + private final DatabaseConnection connection; + + /** + * Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection + * credentials. + */ + public DatabaseSetup(DatabaseConnection connection) { + this.connection = connection; + } + + /** + * Connection test for the Database. Does a simple SELECT SQL query and returns either true og and + * Exception if failed + * + * @return true if Sucsedd or SQLExepction if failed + */ + public boolean testConnection() { + try (Connection conn = connection.getMySqlConnection(); + Statement stmt = conn.createStatement()) { + + ResultSet rs = stmt.executeQuery("SELECT 1"); + + if (rs.next()) { + System.out.println("Database connection verified."); + return true; + } + + } catch (SQLException e) { + System.out.println("Database connection failed."); + e.printStackTrace(); + } + + return false; + } + + /** + * Creates the {@code Charities} and {@code Donations} tables if they do not already exist. + * + *

The table structure for Charities is based on fields from {@link APICharityData}. + * + * @throws RuntimeException if a {@link SQLException} occurs while creating the table + */ + public void createTables() { + String charitiesTable = + """ + -- ----------------------------------------------------- + -- Table `HelpMeHelp`.`Charities` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Charities` ( + `UUID_charities` CHAR(36) NOT NULL, + `org_number` VARCHAR(255) NOT NULL, + `charity_name` VARCHAR(255) NOT NULL, + `charity_description` VARCHAR(255) NOT NULL, + `charity_link` VARCHAR(255) NOT NULL, + `pre_approved` TINYINT NOT NULL, + `status` VARCHAR(255) NOT NULL, + PRIMARY KEY (`UUID_charities`), + UNIQUE INDEX `org_number_UNIQUE` (`org_number` ASC) VISIBLE) + ENGINE = InnoDB; + + """; + String donationsTable = + """ + -- ----------------------------------------------------- + -- Table `HelpMeHelp`.`Donations` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Donations` ( + `UUID_Donations` CHAR(36) NOT NULL, + `amount` DECIMAL NOT NULL, + `date` DATE NOT NULL, + `charity_id` CHAR(36) NOT NULL, + `user_id` CHAR(36) NOT NULL, + PRIMARY KEY (`UUID_Donations`), + INDEX `fk_Donations_Charities_idx` (`charity_id` ASC) VISIBLE, + INDEX `fk_Donations_User1_idx` (`user_id` ASC) VISIBLE, + CONSTRAINT `fk_Donations_Charities` + FOREIGN KEY (`charity_id`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Donations_User1` + FOREIGN KEY (`user_id`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + String userTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`User` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`User` ( + `UUID_User` CHAR(36) NOT NULL, + `user_displayname` VARCHAR(255) NOT NULL, + `user_name` VARCHAR(255) NOT NULL, + `user_email` VARCHAR(255) NOT NULL, + `user_password` VARCHAR(255) NOT NULL, + `role` VARCHAR(45) NOT NULL, + PRIMARY KEY (`UUID_User`)) + ENGINE = InnoDB; + """; + + String settingsTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`Settings` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Settings` ( + `User_UUID_User` CHAR(36) NOT NULL, + `isAnonymous` TINYINT NOT NULL, + `language` VARCHAR(45) NOT NULL, + `lightmode` TINYINT NOT NULL, + PRIMARY KEY (`User_UUID_User`), + INDEX `fk_Settings_User1_idx` (`User_UUID_User` ASC) VISIBLE, + CONSTRAINT `fk_Settings_User1` + FOREIGN KEY (`User_UUID_User`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + + String messagesTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`Messages` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Messages` ( + `UUID_message` CHAR(36) NOT NULL, + `message_title` VARCHAR(255) NOT NULL, + `message_content` VARCHAR(255) NOT NULL, + `message_date` DATE NOT NULL, + `sender_user_id` CHAR(36) NULL, + `sender_charity_id` CHAR(36) NULL, + `user_id` CHAR(36) NOT NULL, + PRIMARY KEY (`UUID_message`), + INDEX `fk_Messages_User1_idx` (`sender_user_id` ASC) VISIBLE, + INDEX `fk_Messages_Charities1_idx` (`sender_charity_id` ASC) VISIBLE, + INDEX `fk_Messages_User2_idx` (`user_id` ASC) VISIBLE, + CONSTRAINT `fk_Messages_User1` + FOREIGN KEY (`sender_user_id`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Messages_Charities1` + FOREIGN KEY (`sender_charity_id`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Messages_User2` + FOREIGN KEY (`user_id`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + + String feedbackTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`Feedback` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Feedback` ( + `UUID_feedback` CHAR(36) NOT NULL, + `feedback_comment` VARCHAR(255) NOT NULL, + `feedback_date` DATE NOT NULL, + `isAnonymous` TINYINT NOT NULL, + `charity_id` CHAR(36) NOT NULL, + `user_id` CHAR(36) NOT NULL, + PRIMARY KEY (`UUID_feedback`), + INDEX `fk_Feedback_Charities1_idx` (`charity_id` ASC) VISIBLE, + INDEX `fk_Feedback_User1_idx` (`user_id` ASC) VISIBLE, + CONSTRAINT `fk_Feedback_Charities1` + FOREIGN KEY (`charity_id`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Feedback_User1` + FOREIGN KEY (`user_id`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + String categoriesTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`Categories` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Categories` ( + `category_id` INT NOT NULL AUTO_INCREMENT, + `category` VARCHAR(255) NOT NULL, + PRIMARY KEY (`category_id`)) + ENGINE = InnoDB; + """; + + String charityCategoriesTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`Charity_Categories` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`Charity_Categories` ( + `Categories_category_id` INT NOT NULL, + `Charities_UUID_charities` CHAR(36) NOT NULL, + PRIMARY KEY (`Categories_category_id`, `Charities_UUID_charities`), + INDEX `fk_Categories_has_Charities_Charities1_idx` (`Charities_UUID_charities` ASC) VISIBLE, + INDEX `fk_Categories_has_Charities_Categories1_idx` (`Categories_category_id` ASC) VISIBLE, + CONSTRAINT `fk_Categories_has_Charities_Categories1` + FOREIGN KEY (`Categories_category_id`) + REFERENCES `apbaluna`.`Categories` (`category_id`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Categories_has_Charities_Charities1` + FOREIGN KEY (`Charities_UUID_charities`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + + String charityUserTable = + """ + -- ----------------------------------------------------- + -- Table `apbaluna`.`CharityUsers` + -- ----------------------------------------------------- + CREATE TABLE IF NOT EXISTS `apbaluna`.`CharityUsers` ( + `Charities_UUID_charities` CHAR(36) NOT NULL, + `User_UUID_User` CHAR(36) NOT NULL, + PRIMARY KEY (`Charities_UUID_charities`, `User_UUID_User`), + INDEX `fk_Charities_has_User_User1_idx` (`User_UUID_User` ASC) VISIBLE, + INDEX `fk_Charities_has_User_Charities1_idx` (`Charities_UUID_charities` ASC) VISIBLE, + CONSTRAINT `fk_Charities_has_User_Charities1` + FOREIGN KEY (`Charities_UUID_charities`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Charities_has_User_User1` + FOREIGN KEY (`User_UUID_User`) + REFERENCES `apbaluna`.`User` (`UUID_User`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; + + try (Connection conn = connection.getMySqlConnection(); + Statement s = conn.createStatement()) { + + s.execute(charitiesTable); + s.execute(userTable); + s.execute(donationsTable); + s.execute(settingsTable); + s.execute(messagesTable); + s.execute(feedbackTable); + s.execute(categoriesTable); + s.execute(charityCategoriesTable); + s.execute(charityUserTable); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("Error creating table."); + } + } +} \ No newline at end of file diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java new file mode 100644 index 0000000..bdc0432 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java @@ -0,0 +1,126 @@ +package ntnu.systemutvikling.team6.database.Readers; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.CharityRegistry; +import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.user.User; + +import java.sql.*; +import java.time.LocalDate; +import java.util.ArrayList; + +public class CharitySelect { + private final DatabaseConnection connection; + + public CharitySelect(DatabaseConnection connection){ + this.connection = connection; + } + + public CharityRegistry getCharitiesFromDB() { + CharityRegistry registry = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + c.UUID_charities, c.org_number, c.charity_name, c.charity_link, c.pre_approved, c.status, + f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, + u.UUID_user, u.user_name, u.user_email, u.user_password, u.role + FROM Charities c + LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities + LEFT JOIN User u ON f.user_id = u.UUID_user + """; + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql_query); + + Charity currentCharity = null; + String lastCharity = null; + + registry = new CharityRegistry(); + while (rs.next()) { + String currentId = rs.getString("UUID_charities"); + + if (lastCharity == null || !currentId.equals(lastCharity)) { + currentCharity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_link"), + rs.getString("charity_name"), + rs.getBoolean("pre_approved"), + rs.getString("status") + ); + registry.addCharity(currentCharity); + lastCharity = currentId; + } + String feedbackId = rs.getString("UUID_feedback"); + if (feedbackId != null){ + User userWithNoSettingsAndInbox = new User( + rs.getString("UUID_User"), + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role") + ); + + Feedback feedback = new Feedback( + rs.getString("UUID_feedback"), + userWithNoSettingsAndInbox, + rs.getString("feedback_comment"), + LocalDate.parse(rs.getString("feedback_date")) + ); + + currentCharity.getFeedbacks().add(feedback); + } + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return registry; + } + public ArrayList getFeedbackforCharityUUID(String charity_uuid) { + ArrayList Feedbacks = new ArrayList<>(); + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, + u.UUID_user, u.user_name, u.user_email, u.user_password, u.role + FROM Feedback f + LEFT JOIN User u ON f.user_id = u.UUID_user + WHERE f.charity_id = ?; + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, charity_uuid); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()){ + User userWithNoSettingsAndInbox = new User( + rs.getString("UUID_User"), + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role") + ); + Feedback feedback = new Feedback( + rs.getString("UUID_feedback"), + userWithNoSettingsAndInbox, + rs.getString("feedback_comment"), + LocalDate.parse(rs.getString("feedback_date")) + ); + Feedbacks.add(feedback); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + conn = null; + } + return Feedbacks; + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java new file mode 100644 index 0000000..97bc639 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java @@ -0,0 +1,68 @@ +package ntnu.systemutvikling.team6.database.Readers; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.DonationRegistry; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class DonationSelect { + private final DatabaseConnection connection; + + public DonationSelect (DatabaseConnection connection){ + this.connection = connection; + } + public DonationRegistry getDonationFromDB() { + DonationRegistry registry = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + d.UUID_Donations, + d.amount, + d.date, + c.UUID_charities, + c.org_number, + c.charity_name, + c.charity_link, + c.pre_approved, + c.status + FROM Donations d + JOIN Charities c + ON d.Charities_UUID_charities = c.UUID_charities + """; + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql_query); + + registry = new DonationRegistry(); + while (rs.next()) { + Charity charity = + new Charity( + rs.getString("UUID_charities"), + rs.getString("org_number"), + rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getBoolean("pre_approved"), + rs.getString("status")); + + Donation donation = + new Donation( + rs.getString("UUID_Donations"), + rs.getDouble("amount"), + rs.getDate("date").toLocalDate(), + charity); + registry.addDonation(donation); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return registry; + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java new file mode 100644 index 0000000..e232d08 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java @@ -0,0 +1,201 @@ +package ntnu.systemutvikling.team6.database.Readers; + +import ntnu.systemutvikling.team6.database.DatabaseConnection; +import ntnu.systemutvikling.team6.models.UserRegistry; +import ntnu.systemutvikling.team6.models.user.*; + +import java.sql.*; +import java.time.LocalDate; +import java.util.UUID; + +public class UserSelect { + private final DatabaseConnection connection; + + public UserSelect(DatabaseConnection connection){ + this.connection = connection; + } + + public User getUserFromDBUuid(String user_id){ + User user = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, + s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id + FROM User u + LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user + LEFT JOIN Messages m ON u.UUID_User = m.user_id + WHERE u.UUID_User = ?; + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, user_id); + ResultSet rs = stmt.executeQuery(); + + String lastUserid = null; + while (rs.next()) { + String userId = rs.getString("UUID_User"); + if (lastUserid == null || !userId.equals(lastUserid)) { + user = new User( + userId, + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role") + ); + if (rs.getString("isAnonymous") != null){ + Settings settings = new Settings( + rs.getBoolean("isAnonymous"), + Language.valueOf(rs.getString("language").toUpperCase()), + rs.getBoolean("lightmode") + ); + user.setSettings(settings); + } + user.setInbox(new Inbox()); + lastUserid = userId; + } + String messageId = rs.getString("UUID_message"); + if (messageId != null) { + Message message = new Message( + rs.getString("message_title"), + UUID.fromString(rs.getString("sender_charity_id")), + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + + user.getInbox().addMessage(message); + } + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return user; + } + + public UserRegistry getUsersFromDB(){ + UserRegistry registry = new UserRegistry(); + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role, + s.User_UUID_User, s.isAnonymous, s.language, s.lightmode, + m.UUID_message, m.message_title, m.message_content, m.message_date, m.sender_user_id, m.sender_charity_id, m.user_id + FROM User u + LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user + LEFT JOIN Messages m ON u.UUID_User = m.user_id + """; + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql_query); + + User currentUser = null; + String lastUserid = null; + + while (rs.next()) { + String userId = rs.getString("UUID_User"); + + if (lastUserid == null || !userId.equals(lastUserid)) { + currentUser = new User( + userId, + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role") + ); + if (rs.getString("isAnonymous") != null){ + Settings settings = new Settings( + rs.getBoolean("isAnonymous"), + Language.valueOf(rs.getString("language").toUpperCase()), + rs.getBoolean("lightmode") + ); + currentUser.setSettings(settings); + } + currentUser.setInbox(new Inbox()); + registry.addUser(currentUser); + lastUserid = userId; + } + String messageId = rs.getString("UUID_message"); + if (messageId != null) { + Message message = new Message( + rs.getString("message_title"), + UUID.fromString(rs.getString("sender_charity_id")), + rs.getString("message_content"), + LocalDate.parse(rs.getString("message_date")) + ); + + currentUser.getInbox().addMessage(message); + } + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return registry; + } + + public Settings getSettingsForUser(String user_id){ + Settings settings = null; + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT User_UUID_User, isAnonymous, language, lightmode FROM Settings + WHERE User_UUID_User = ?; + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, user_id); + stmt.setMaxRows(1); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()) { + settings = new Settings( + rs.getBoolean("isAnonymous"), + Language.valueOf(rs.getString("language").toUpperCase()), + rs.getBoolean("lightmode") + ); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + + return settings; + } + + public Inbox getInboxForUser(String user_id){ + Inbox inbox = new Inbox(); + Connection conn = null; + try { + conn = connection.getMySqlConnection(); + String sql_query = + """ + SELECT UUID_message, message_title, message_content, message_date, sender_user_id, sender_charity_id, user_id FROM Messages + WHERE user_id = ?; + """; + PreparedStatement stmt = conn.prepareStatement(sql_query); + stmt.setString(1, user_id); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()) { + Message message = new Message( + rs.getString("message_title"), + UUID.fromString(rs.getString("sender_charity_id")), + rs.getString("message_date"), + LocalDate.parse(rs.getString("message_date")) + ); + inbox.addMessage(message); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException("ERROR: Something went wrong during updating charities table."); + } + return inbox; + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Feedback.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Feedback.java index 6d071cf..75ce7bd 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Feedback.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Feedback.java @@ -47,7 +47,7 @@ public Feedback(User user, String comment) { public Feedback(String feedback_id, User user, String feedback_comment, LocalDate feedback_date) { this.feedbackId = UUID.fromString(feedback_id); this.user = user; - this.comment = comment; + this.comment = feedback_comment; this.date = feedback_date; this.isAnonymous = user.getSettings().isAnonymous(); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java index 10a489d..0cf6da8 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java @@ -1,6 +1,6 @@ package ntnu.systemutvikling.team6.scraper; -import ntnu.systemutvikling.team6.database.DatabaseManager; +import ntnu.systemutvikling.team6.database.DatabaseSetup; /** * Represents data parsed from the IK API JSON response. Instances are immutable; to update any @@ -9,7 +9,7 @@ *

Receives data directly from {@link APICharityScraper}. * *

{@code org_number} should be a unique number, as it is used as a primary key in {@link - * DatabaseManager}. + * DatabaseSetup}. */ public class APICharityData { private final String org_number; diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java index b0f1acc..988f97e 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java @@ -6,7 +6,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import ntnu.systemutvikling.team6.database.DatabaseConnection; -import ntnu.systemutvikling.team6.database.DatabaseManager; +import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -18,7 +18,7 @@ class DonationDAOTest { @BeforeEach void setUp() { DatabaseConnection conn = new DatabaseConnection(); - DatabaseManager manager = new DatabaseManager(conn); + DatabaseSetup manager = new DatabaseSetup(conn); manager.createTables(); charity = new Charity("123456", "https://test.org", "Test Charity", true, "approved"); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java index 25c214e..689048a 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java @@ -5,18 +5,19 @@ import java.sql.*; import java.util.ArrayList; import java.util.List; + import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.CharityRegistry; import org.junit.jupiter.api.*; class DatabaseManagerTest { - private DatabaseManager dbManager; + private DatabaseSetup dbManager; @BeforeEach public void setUp() throws SQLException { DatabaseConnection conn = new DatabaseConnection(); - this.dbManager = new DatabaseManager(conn); + this.dbManager = new DatabaseSetup(conn); } // Make sure you're connected to the NTNU network for this to work