Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions src/main/java/com/example/AccountRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
10 changes: 8 additions & 2 deletions src/main/java/com/example/DataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
39 changes: 38 additions & 1 deletion src/main/java/com/example/JdbcAccountRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ?";
Expand All @@ -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 (?, ?, ?, ?, ?)";
Expand All @@ -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 = ?";
Expand All @@ -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 = ?";
Expand All @@ -64,4 +101,4 @@ public int delete(long userId) throws SQLException {
return stmt.executeUpdate();
}
}
}
}
30 changes: 29 additions & 1 deletion src/main/java/com/example/JdbcMoonMissionRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> findAllSpacecraftNames() throws SQLException {
List<String> names = new ArrayList<>();
Expand All @@ -31,6 +42,16 @@ public List<String> 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 = ?";
Expand All @@ -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) = ?";
Expand All @@ -53,4 +81,4 @@ public int countMissionsByYear(int year) throws SQLException {
}
}
}
}
}
94 changes: 85 additions & 9 deletions src/main/java/com/example/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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.
*
* <p>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.</p>
*/
public void run() {

String JDBC_URL = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL");
Expand Down Expand Up @@ -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: ");
Expand All @@ -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) {
Expand All @@ -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) ...
Expand Down Expand Up @@ -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)");
Expand All @@ -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<String> spacecrafts = moonMissionRepository.findAllSpacecraftNames();
Expand All @@ -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;
Expand All @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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;
Expand Down
Loading