diff --git a/src/main/java/com/example/AccountRepository.java b/src/main/java/com/example/AccountRepository.java index 674ea30..94907d6 100644 --- a/src/main/java/com/example/AccountRepository.java +++ b/src/main/java/com/example/AccountRepository.java @@ -3,8 +3,42 @@ import java.sql.SQLException; public interface AccountRepository { - boolean findByNameAndPassword(String username, String password) throws SQLException; - int create(String firstName, String lastName, String ssn, String password, String username) throws SQLException; - int updatePassword(long userId, String newPassword) throws SQLException; - int delete(long userId) throws SQLException; -} + /** + * Checks whether an account exists that matches the given username and password. + * + * @param username the account's username to look up + * @param password the account's password to validate + * @return `true` if an account with the provided username and password exists, `false` otherwise + * @throws SQLException if a database access error occurs + */ +boolean findByNameAndPassword(String username, String password) throws SQLException; + /** + * Creates a new account record using the provided personal and credential details. + * + * @param firstName the account holder's given name + * @param lastName the account holder's family name + * @param ssn the account holder's social security number + * @param password the account password + * @param username the desired account username + * @return the generated primary key for the new account when available; otherwise an implementation-specific integer status or affected-row count + * @throws SQLException if a database access error occurs + */ +int create(String firstName, String lastName, String ssn, String password, String username) throws SQLException; + /** + * Update the password for the account identified by the given user ID. + * + * @param userId identifier of the user whose password will be changed + * @param newPassword the new password to set for the account + * @return an integer result representing the outcome of the update (for example, number of rows affected or a status code) + * @throws SQLException if a database access error occurs while performing the update + */ +int updatePassword(long userId, String newPassword) throws SQLException; + /** + * Delete the account associated with the given user identifier. + * + * @param userId the identifier of the user to delete + * @return an integer result code (for example, the number of rows deleted or a status code) + * @throws SQLException if a database access error occurs + */ +int delete(long userId) throws SQLException; +} \ No newline at end of file diff --git a/src/main/java/com/example/DataSource.java b/src/main/java/com/example/DataSource.java index 3f2e44d..eeae93d 100644 --- a/src/main/java/com/example/DataSource.java +++ b/src/main/java/com/example/DataSource.java @@ -4,5 +4,11 @@ import java.sql.SQLException; public interface DataSource { - Connection getConnection() throws SQLException; -} + /** + * Obtain a database connection. + * + * @return a {@link java.sql.Connection} instance + * @throws SQLException if a database access error occurs + */ +Connection getConnection() throws SQLException; +} \ No newline at end of file diff --git a/src/main/java/com/example/JdbcAccountRepository.java b/src/main/java/com/example/JdbcAccountRepository.java index 210e6f2..47e8929 100644 --- a/src/main/java/com/example/JdbcAccountRepository.java +++ b/src/main/java/com/example/JdbcAccountRepository.java @@ -9,10 +9,21 @@ public class JdbcAccountRepository implements AccountRepository { private final DataSource dataSource; + /** + * Creates a JdbcAccountRepository backed by the provided DataSource. + */ public JdbcAccountRepository(DataSource dataSource) { this.dataSource = dataSource; } + /** + * Checks whether an account exists for the given username and password. + * + * @param username the account name to authenticate + * @param password the password to match for the account + * @return `true` if an account with the specified credentials exists, `false` otherwise + * @throws SQLException if a database access error occurs + */ @Override public boolean findByNameAndPassword(String username, String password) throws SQLException { String sql = "SELECT user_id FROM account WHERE name = ? AND password = ?"; @@ -27,6 +38,17 @@ public boolean findByNameAndPassword(String username, String password) throws SQ } } + /** + * Inserts a new account record with the provided personal and credential fields. + * + * @param firstName the account holder's first name + * @param lastName the account holder's last name + * @param ssn the account holder's social security number + * @param password the account password to store + * @param username the account username + * @return the number of rows inserted (1 if the account was created, 0 otherwise) + * @throws SQLException if a database access error occurs + */ @Override public int create(String firstName, String lastName, String ssn, String password, String username) throws SQLException { String sql = "INSERT INTO account (first_name, last_name, ssn, password, name) VALUES (?, ?, ?, ?, ?)"; @@ -42,6 +64,14 @@ public int create(String firstName, String lastName, String ssn, String password } } + /** + * Update the password for the account with the given user ID. + * + * @param userId the ID of the user whose password will be updated + * @param newPassword the new password value to set + * @return the number of rows affected by the update + * @throws SQLException if a database access error occurs + */ @Override public int updatePassword(long userId, String newPassword) throws SQLException { String sql = "UPDATE account SET password = ? WHERE user_id = ?"; @@ -54,6 +84,13 @@ public int updatePassword(long userId, String newPassword) throws SQLException { } } + /** + * Deletes the account with the given user ID. + * + * @param userId the identifier of the account to delete + * @return the number of rows deleted (0 if no matching account was found) + * @throws SQLException if a database access error occurs + */ @Override public int delete(long userId) throws SQLException { String sql = "DELETE FROM account WHERE user_id = ?"; @@ -64,4 +101,4 @@ public int delete(long userId) throws SQLException { return stmt.executeUpdate(); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/JdbcMoonMissionRepository.java b/src/main/java/com/example/JdbcMoonMissionRepository.java index 0e7ce9c..886fd92 100644 --- a/src/main/java/com/example/JdbcMoonMissionRepository.java +++ b/src/main/java/com/example/JdbcMoonMissionRepository.java @@ -12,10 +12,21 @@ public class JdbcMoonMissionRepository implements MoonMissionRepository { private final DataSource dataSource; + /** + * Creates a repository backed by the given DataSource. + * + * @param dataSource the DataSource used to obtain database connections for repository operations + */ public JdbcMoonMissionRepository(DataSource dataSource) { this.dataSource = dataSource; } + /** + * Retrieve all spacecraft names stored in the `moon_mission` table. + * + * @return a list of spacecraft names from the `moon_mission` table; the list is empty if no rows are found + * @throws SQLException if a database access error occurs + */ @Override public List findAllSpacecraftNames() throws SQLException { List names = new ArrayList<>(); @@ -31,6 +42,16 @@ public List findAllSpacecraftNames() throws SQLException { } + /** + * Fetches the database row for the mission with the specified mission ID. + * + * @param missionId the primary key of the mission to retrieve + * @param connection JDBC connection used to create and execute the query; this method does not close it + * @return a ResultSet positioned before the first row containing the matching mission (empty if no match) + * @throws SQLException if a database access error occurs + * + * Note: the returned ResultSet is produced by a PreparedStatement created inside this method; the caller is responsible for closing both the ResultSet and its originating PreparedStatement. + */ @Override public ResultSet findMissionById(long missionId, Connection connection) throws SQLException { String sql = "SELECT * FROM moon_mission WHERE mission_id = ?"; @@ -39,6 +60,13 @@ public ResultSet findMissionById(long missionId, Connection connection) throws S return stmt.executeQuery(); } + /** + * Count moon missions whose launch_date falls in the specified year. + * + * @param year the launch year to count missions for + * @return the number of missions launched in the specified year + * @throws SQLException if a database access error occurs + */ @Override public int countMissionsByYear(int year) throws SQLException { String sql = "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date) = ?"; @@ -53,4 +81,4 @@ public int countMissionsByYear(int year) throws SQLException { } } } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index db318b8..bc5b5a2 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -11,7 +11,11 @@ public class Main { private final Scanner scanner = new Scanner(System.in); private AccountRepository accountRepository; private MoonMissionRepository moonMissionRepository; - private DataSource dataSource; // Behålls för att hantera anslutning i getMoonMissionById + private DataSource dataSource; /** + * Starts the application: initializes a development database when dev mode is detected and runs the interactive Main flow. + * + * Uses system properties, environment variables, and command-line arguments to determine dev mode before constructing and running the Main instance. + */ public static void main(String[] args) { if (isDevMode(args)) { @@ -20,6 +24,11 @@ public static void main(String[] args) { new Main().run(); } + /** + * Initializes application resources, verifies database configuration and connectivity, then starts the interactive login and main menu flow. + * + *

Specifically, this method resolves JDBC configuration, initializes the data source and repositories, tests a database connection, and proceeds to prompt for user login. If login succeeds it enters the main menu loop; otherwise it handles an invalid login. If required configuration is missing the method prints an error and exits early.

+ */ public void run() { String JDBC_URL = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL"); @@ -58,7 +67,12 @@ public void run() { // eftersom varje Repository-metod hanterar sin egen Connection. } - // --- Inloggning --- + /** + * Prompts the user for a username and password and authenticates them using the account repository. + * + * @return `true` if authentication succeeds, `false` otherwise. + * @throws SQLException if a database access error occurs while validating credentials. + */ private boolean login() throws SQLException { System.out.print("Username: "); @@ -71,6 +85,11 @@ private boolean login() throws SQLException { } + /** + * Shows an invalid-credentials message and waits for the user to confirm exit by entering "0". + * + * Prints a prompt and consumes input lines until the user types exactly "0". + */ private void handleInvalidLogin() { System.out.println("Invalid username or password. Press 0 to exit."); while (true) { @@ -82,7 +101,15 @@ private void handleInvalidLogin() { } } - // --- Menyhantering --- + /** + * Present the interactive main menu, read user choices, and invoke the corresponding actions. + * + * Repeatedly displays the menu and processes selections until the user chooses 0 to exit. + * Supported choices: + * 1 — list moon missions; 2 — get moon mission by ID; 3 — count missions by year; + * 4 — create an account; 5 — update an account password; 6 — delete an account. + * Handles non-numeric input by prompting the user and reports database operation errors to stderr. + */ private void mainMenu() { // ... (mainMenu och printMenu förblir oförändrade, förutom anropen nedan) ... @@ -128,6 +155,11 @@ private void mainMenu() { } } + /** + * Displays the main interactive menu options to the user. + * + * The menu lists available numeric commands used by the application's main loop. + */ private void printMenu() { System.out.println("\n--- Menu ---"); System.out.println("1) List moon missions (spacecraft names)"); @@ -141,7 +173,14 @@ private void printMenu() { } - // 1) List moon missions + /** + * Prints the spacecraft names of all moon missions to standard output. + * + * Prints a header line ("--- Moon Missions ---") followed by each spacecraft name + * on its own line, prefixed with " - ". + * + * @throws SQLException if a database access error occurs while retrieving missions + */ private void listMoonMissions() throws SQLException { // Använder MoonMissionRepository List spacecrafts = moonMissionRepository.findAllSpacecraftNames(); @@ -151,7 +190,14 @@ private void listMoonMissions() throws SQLException { } } - // 2) Get a moon mission by mission_id + /** + * Prompts the user for a mission ID and displays that mission's details if a record exists. + * + * If the entered mission ID is not a valid number, the method prints a warning and returns + * without querying the database. + * + * @throws SQLException if a database access error occurs while retrieving the mission + */ private void getMoonMissionById() throws SQLException { System.out.print("Enter mission_id: "); long missionId; @@ -177,7 +223,11 @@ private void getMoonMissionById() throws SQLException { } } - // 3) Count missions for a given year + /** + * Prompts for a year, queries the repository for the number of moon missions launched that year, and prints the result. + * + * @throws SQLException if a database error occurs while counting missions + */ private void countMissionsByYear() throws SQLException { System.out.print("Enter year: "); int year = scanner.nextInt(); @@ -188,7 +238,16 @@ private void countMissionsByYear() throws SQLException { System.out.println("Found " + count + " missions launched in " + year + "."); } - // 4) Create an account + /** + * Creates a new account by prompting the user for first name, last name, SSN and password, + * generates a username from up to the first three characters of the first and last names, + * and persists the account via the AccountRepository. + * + * If the generated username is empty (both names empty) the method prints an error and returns + * without creating an account. + * + * @throws SQLException if the repository fails to perform the database operation + */ private void createAccount() throws SQLException { System.out.print("Enter first name: "); String firstName = scanner.nextLine(); @@ -217,7 +276,11 @@ private void createAccount() throws SQLException { } } - // 5) Update an account password + /** + * Prompts for a user ID and a new password, updates that account's password, and reports success or absence. + * + * @throws SQLException if the database update fails + */ private void updateAccountPassword() throws SQLException { System.out.print("Enter user_id to update: "); long userId = scanner.nextLong(); @@ -234,7 +297,12 @@ private void updateAccountPassword() throws SQLException { } } - // 6) Delete an account + /** + * Prompts for a user ID, deletes the corresponding account via the account repository, + * and prints whether the deletion succeeded or no matching account was found. + * + * @throws SQLException if a database access error occurs during the delete operation + */ private void deleteAccount() throws SQLException { System.out.print("Enter user_id to delete: "); long userId = scanner.nextLong(); @@ -251,6 +319,14 @@ private void deleteAccount() throws SQLException { } + /** + * Detects whether the application should run in development mode. + * + * @param args the command-line arguments; the presence of the `--dev` flag enables dev mode + * @return `true` if development mode is enabled via the `devMode` JVM system property (e.g. `-DdevMode=true`), + * the `DEV_MODE` environment variable (case-insensitive), or the `--dev` command-line flag; + * `false` otherwise + */ private static boolean isDevMode(String[] args) { if (Boolean.getBoolean("devMode")) //Add VM option -DdevMode=true return true; diff --git a/src/main/java/com/example/MoonMissionRepository.java b/src/main/java/com/example/MoonMissionRepository.java index bcb0a36..12acd5f 100644 --- a/src/main/java/com/example/MoonMissionRepository.java +++ b/src/main/java/com/example/MoonMissionRepository.java @@ -6,7 +6,27 @@ import java.util.List; public interface MoonMissionRepository { - List findAllSpacecraftNames() throws SQLException; - ResultSet findMissionById(long missionId, Connection connection) throws SQLException; - int countMissionsByYear(int year) throws SQLException; -} + /** + * Retrieve the names of all spacecraft recorded in the repository. + * + * @return a list of spacecraft names; empty if no spacecraft are recorded. + * @throws SQLException if a database access error occurs. + */ +List findAllSpacecraftNames() throws SQLException; + /** + * Retrieve the database result set containing the mission record for the specified mission ID. + * + * @param missionId the identifier of the mission to look up + * @return a ResultSet containing the mission row(s) for the given ID; may be empty if no match + * @throws SQLException if a database access error occurs while executing the query + */ +ResultSet findMissionById(long missionId, Connection connection) throws SQLException; + /** + * Counts moon missions that occurred in the specified calendar year. + * + * @param year the calendar year (e.g., 1969) for which to count missions + * @return the number of missions that took place in the given year + * @throws SQLException if a database access error occurs + */ +int countMissionsByYear(int year) throws SQLException; +} \ No newline at end of file diff --git a/src/main/java/com/example/SimpleDriverManagerDataSource.java b/src/main/java/com/example/SimpleDriverManagerDataSource.java index 80f7e06..00f9d8b 100644 --- a/src/main/java/com/example/SimpleDriverManagerDataSource.java +++ b/src/main/java/com/example/SimpleDriverManagerDataSource.java @@ -9,16 +9,29 @@ public class SimpleDriverManagerDataSource implements DataSource { private final String user; private final String password; + /** + * Creates a new SimpleDriverManagerDataSource with the given JDBC URL and credentials. + * + * @param url the JDBC connection URL + * @param user the database username + * @param password the database password + */ public SimpleDriverManagerDataSource(String url, String user, String password) { this.url = url; this.user = user; this.password = password; } + /** + * Obtain a new JDBC Connection configured with the instance's URL, user, and password. + * + * @return a new {@link java.sql.Connection} to the configured database + * @throws SQLException if a database access error occurs or the connection cannot be established + */ @Override public Connection getConnection() throws SQLException { // Skapar en ny Connection varje gång den anropas. return DriverManager.getConnection(url, user, password); } -} +} \ No newline at end of file