diff --git a/pom.xml b/pom.xml
index 002ff66..5bd8e26 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,6 +51,11 @@
mysql
1.21.3
+
+ org.slf4j
+ slf4j-nop
+ 2.0.17
+
diff --git a/src/main/java/com/example/AccountRepository.java b/src/main/java/com/example/AccountRepository.java
new file mode 100644
index 0000000..674ea30
--- /dev/null
+++ b/src/main/java/com/example/AccountRepository.java
@@ -0,0 +1,10 @@
+package com.example;
+
+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;
+}
diff --git a/src/main/java/com/example/DataSource.java b/src/main/java/com/example/DataSource.java
new file mode 100644
index 0000000..3f2e44d
--- /dev/null
+++ b/src/main/java/com/example/DataSource.java
@@ -0,0 +1,8 @@
+package com.example;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+public interface DataSource {
+ Connection getConnection() throws SQLException;
+}
diff --git a/src/main/java/com/example/JdbcAccountRepository.java b/src/main/java/com/example/JdbcAccountRepository.java
new file mode 100644
index 0000000..210e6f2
--- /dev/null
+++ b/src/main/java/com/example/JdbcAccountRepository.java
@@ -0,0 +1,67 @@
+package com.example;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class JdbcAccountRepository implements AccountRepository {
+
+ private final DataSource dataSource;
+
+ public JdbcAccountRepository(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Override
+ public boolean findByNameAndPassword(String username, String password) throws SQLException {
+ String sql = "SELECT user_id FROM account WHERE name = ? AND password = ?";
+ // Använder try-with-resources för att säkerställa att Connection stängs
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement stmt = connection.prepareStatement(sql)) {
+ stmt.setString(1, username);
+ stmt.setString(2, password);
+ try (ResultSet rs = stmt.executeQuery()) {
+ return rs.next();
+ }
+ }
+ }
+
+ @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 (?, ?, ?, ?, ?)";
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement stmt = connection.prepareStatement(sql)) {
+ stmt.setString(1, firstName);
+ stmt.setString(2, lastName);
+ stmt.setString(3, ssn);
+ stmt.setString(4, password);
+ stmt.setString(5, username);
+
+ return stmt.executeUpdate();
+ }
+ }
+
+ @Override
+ public int updatePassword(long userId, String newPassword) throws SQLException {
+ String sql = "UPDATE account SET password = ? WHERE user_id = ?";
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement stmt = connection.prepareStatement(sql)) {
+ stmt.setString(1, newPassword);
+ stmt.setLong(2, userId);
+
+ return stmt.executeUpdate();
+ }
+ }
+
+ @Override
+ public int delete(long userId) throws SQLException {
+ String sql = "DELETE FROM account WHERE user_id = ?";
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement stmt = connection.prepareStatement(sql)) {
+ stmt.setLong(1, userId);
+
+ return stmt.executeUpdate();
+ }
+ }
+}
diff --git a/src/main/java/com/example/JdbcMoonMissionRepository.java b/src/main/java/com/example/JdbcMoonMissionRepository.java
new file mode 100644
index 0000000..0e7ce9c
--- /dev/null
+++ b/src/main/java/com/example/JdbcMoonMissionRepository.java
@@ -0,0 +1,56 @@
+package com.example;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+public class JdbcMoonMissionRepository implements MoonMissionRepository {
+
+ private final DataSource dataSource;
+
+ public JdbcMoonMissionRepository(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Override
+ public List findAllSpacecraftNames() throws SQLException {
+ List names = new ArrayList<>();
+ String sql = "SELECT spacecraft FROM moon_mission";
+ try (Connection connection = dataSource.getConnection();
+ Statement stmt = connection.createStatement();
+ ResultSet rs = stmt.executeQuery(sql)) {
+ while (rs.next()) {
+ names.add(rs.getString("spacecraft"));
+ }
+ }
+ return names;
+ }
+
+
+ @Override
+ public ResultSet findMissionById(long missionId, Connection connection) throws SQLException {
+ String sql = "SELECT * FROM moon_mission WHERE mission_id = ?";
+ PreparedStatement stmt = connection.prepareStatement(sql);
+ stmt.setLong(1, missionId);
+ return stmt.executeQuery();
+ }
+
+ @Override
+ public int countMissionsByYear(int year) throws SQLException {
+ String sql = "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date) = ?";
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement stmt = connection.prepareStatement(sql)) {
+ stmt.setInt(1, year);
+ try (ResultSet rs = stmt.executeQuery()) {
+ if (rs.next()) {
+ return rs.getInt(1);
+ }
+ return 0;
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java
index 6dc6fbd..db318b8 100644
--- a/src/main/java/com/example/Main.java
+++ b/src/main/java/com/example/Main.java
@@ -1,13 +1,19 @@
package com.example;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
+import java.sql.*;
import java.util.Arrays;
+import java.util.InputMismatchException;
+import java.util.List;
+import java.util.Scanner;
public class Main {
- static void main(String[] args) {
+ 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
+
+ public static void main(String[] args) {
if (isDevMode(args)) {
DevDatabaseInitializer.start();
}
@@ -15,31 +21,236 @@ static void main(String[] args) {
}
public void run() {
- // Resolve DB settings with precedence: System properties -> Environment variables
- String jdbcUrl = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL");
- String dbUser = resolveConfig("APP_DB_USER", "APP_DB_USER");
- String dbPass = resolveConfig("APP_DB_PASS", "APP_DB_PASS");
- if (jdbcUrl == null || dbUser == null || dbPass == null) {
- throw new IllegalStateException(
- "Missing DB configuration. Provide APP_JDBC_URL, APP_DB_USER, APP_DB_PASS " +
- "as system properties (-Dkey=value) or environment variables.");
+ String JDBC_URL = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL");
+ String DB_USER = resolveConfig("APP_DB_USER", "APP_DB_USER");
+ String DB_PASS = resolveConfig("APP_DB_PASS", "APP_DB_PASS");
+
+ if (JDBC_URL == null || DB_USER == null || DB_PASS == null) {
+ System.err.println("Database configuration environment variables not set.");
+ return;
}
- try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) {
+ // --- Konfigurera Repository Pattern ---
+ dataSource = new SimpleDriverManagerDataSource(JDBC_URL, DB_USER, DB_PASS);
+ accountRepository = new JdbcAccountRepository(dataSource);
+ moonMissionRepository = new JdbcMoonMissionRepository(dataSource);
+ // --- Slut Konfiguration ---
+
+ System.out.println("Application initialized.");
+
+ try {
+ // Vi använder dataSource.getConnection() här för att testa uppkopplingen
+ // och bekräfta att den fungerar.
+ try (Connection testConnection = dataSource.getConnection()) {
+ System.out.println("Database connection established.");
+ }
+
+ if (login()) {
+ mainMenu();
+ } else {
+ handleInvalidLogin();
+ }
} catch (SQLException e) {
- throw new RuntimeException(e);
+ System.err.println("Database error: " + e.getMessage());
}
- //Todo: Starting point for your code
+ // Vi behöver inte stänga en global 'connection' längre,
+ // eftersom varje Repository-metod hanterar sin egen Connection.
}
- /**
- * Determines if the application is running in development mode based on system properties,
- * environment variables, or command-line arguments.
- *
- * @param args an array of command-line arguments
- * @return {@code true} if the application is in development mode; {@code false} otherwise
- */
+ // --- Inloggning ---
+
+ private boolean login() throws SQLException {
+ System.out.print("Username: ");
+ String username = scanner.nextLine();
+ System.out.print("Password: ");
+ String password = scanner.nextLine();
+
+ // Använder AccountRepository
+ return accountRepository.findByNameAndPassword(username, password);
+ }
+
+
+ private void handleInvalidLogin() {
+ System.out.println("Invalid username or password. Press 0 to exit.");
+ while (true) {
+ System.out.print("Choice: ");
+ String choice = scanner.nextLine().trim();
+ if ("0".equals(choice)) {
+ break;
+ }
+ }
+ }
+
+ // --- Menyhantering ---
+
+ private void mainMenu() {
+ // ... (mainMenu och printMenu förblir oförändrade, förutom anropen nedan) ...
+ int choice = -1;
+ while (choice != 0) {
+ printMenu();
+ try {
+ System.out.print("Choice: ");
+ choice = scanner.nextInt();
+ scanner.nextLine();
+
+ switch (choice) {
+ case 1:
+ listMoonMissions();
+ break;
+ case 2:
+ getMoonMissionById();
+ break;
+ case 3:
+ countMissionsByYear();
+ break;
+ case 4:
+ createAccount();
+ break;
+ case 5:
+ updateAccountPassword();
+ break;
+ case 6:
+ deleteAccount();
+ break;
+ case 0:
+ System.out.println("Exiting application.");
+ break;
+ default:
+ System.out.println("Invalid choice. Try again.");
+ }
+ } catch (InputMismatchException e) {
+ System.out.println("Invalid input. Please enter a number.");
+ scanner.nextLine();
+ } catch (SQLException e) {
+ System.err.println("Database operation failed: " + e.getMessage());
+ }
+ }
+ }
+
+ private void printMenu() {
+ System.out.println("\n--- Menu ---");
+ System.out.println("1) List moon missions (spacecraft names)");
+ System.out.println("2) Get a moon mission by mission_id (details)");
+ System.out.println("3) Count missions for a given year");
+ System.out.println("4) Create an account (first name, last name, ssn, password)");
+ System.out.println("5) Update an account password (user_id, new password)");
+ System.out.println("6) Delete an account (user_id)");
+ System.out.println("0) Exit");
+ System.out.println("------------");
+ }
+
+
+ // 1) List moon missions
+ private void listMoonMissions() throws SQLException {
+ // Använder MoonMissionRepository
+ List spacecrafts = moonMissionRepository.findAllSpacecraftNames();
+ System.out.println("--- Moon Missions ---");
+ for (String name : spacecrafts) {
+ System.out.println(" - " + name);
+ }
+ }
+
+ // 2) Get a moon mission by mission_id
+ private void getMoonMissionById() throws SQLException {
+ System.out.print("Enter mission_id: ");
+ long missionId;
+ try {
+ missionId = scanner.nextLong();
+ scanner.nextLine();
+ }catch (InputMismatchException e){
+ System.out.println("Please enter a number");
+ return;
+ }
+
+ try (Connection connection = dataSource.getConnection();
+ ResultSet rs = moonMissionRepository.findMissionById(missionId, connection)) {
+
+ if (rs.next()) {
+ System.out.println("--- Mission Details (ID: " + missionId + ") ---");
+ System.out.println("Spacecraft: " + rs.getString("spacecraft"));
+ System.out.println("Launch Date: " + rs.getDate("launch_date"));
+ System.out.println("Outcome: " + rs.getString("outcome"));
+ } else {
+ System.out.println("Mission with ID " + missionId + " not found.");
+ }
+ }
+ }
+
+ // 3) Count missions for a given year
+ private void countMissionsByYear() throws SQLException {
+ System.out.print("Enter year: ");
+ int year = scanner.nextInt();
+ scanner.nextLine();
+
+ // Använder MoonMissionRepository
+ int count = moonMissionRepository.countMissionsByYear(year);
+ System.out.println("Found " + count + " missions launched in " + year + ".");
+ }
+
+ // 4) Create an account
+ private void createAccount() throws SQLException {
+ System.out.print("Enter first name: ");
+ String firstName = scanner.nextLine();
+ System.out.print("Enter last name: ");
+ String lastName = scanner.nextLine();
+ System.out.print("Enter ssn: ");
+ String ssn = scanner.nextLine();
+ System.out.print("Enter password: ");
+ String password = scanner.nextLine();
+
+ String username = firstName.substring(0, Math.min(firstName.length(), 3))
+ + lastName.substring(0, Math.min(lastName.length(), 3));
+
+ if (username.isEmpty()) {
+ System.out.println("Cannot create account: first name and last name cannot both be empty.");
+ return;
+ }
+
+ // Använder AccountRepository
+ int rowsAffected = accountRepository.create(firstName, lastName, ssn, password, username);
+
+ if (rowsAffected > 0) {
+ System.out.println("Account created successfully. Username is " + username + ".");
+ } else {
+ System.out.println("Failed to create account.");
+ }
+ }
+
+ // 5) Update an account password
+ private void updateAccountPassword() throws SQLException {
+ System.out.print("Enter user_id to update: ");
+ long userId = scanner.nextLong();
+ scanner.nextLine();
+ System.out.print("Enter new password: ");
+ String newPassword = scanner.nextLine();
+
+ // Använder AccountRepository
+ int rowsAffected = accountRepository.updatePassword(userId, newPassword);
+ if (rowsAffected > 0) {
+ System.out.println("Account password updated successfully for user_id " + userId + ".");
+ } else {
+ System.out.println("No account found with user_id " + userId + " to update.");
+ }
+ }
+
+ // 6) Delete an account
+ private void deleteAccount() throws SQLException {
+ System.out.print("Enter user_id to delete: ");
+ long userId = scanner.nextLong();
+ scanner.nextLine();
+
+ // Använder AccountRepository
+ int rowsAffected = accountRepository.delete(userId);
+
+ if (rowsAffected > 0) {
+ System.out.println("Account deleted successfully for user_id " + userId + ".");
+ } else {
+ System.out.println("No account found with user_id " + userId + " to delete.");
+ }
+ }
+
+
private static boolean isDevMode(String[] args) {
if (Boolean.getBoolean("devMode")) //Add VM option -DdevMode=true
return true;
@@ -59,4 +270,4 @@ private static String resolveConfig(String propertyKey, String envKey) {
}
return (v == null || v.trim().isEmpty()) ? null : v.trim();
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/MoonMissionRepository.java b/src/main/java/com/example/MoonMissionRepository.java
new file mode 100644
index 0000000..bcb0a36
--- /dev/null
+++ b/src/main/java/com/example/MoonMissionRepository.java
@@ -0,0 +1,12 @@
+package com.example;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+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;
+}
diff --git a/src/main/java/com/example/SimpleDriverManagerDataSource.java b/src/main/java/com/example/SimpleDriverManagerDataSource.java
new file mode 100644
index 0000000..80f7e06
--- /dev/null
+++ b/src/main/java/com/example/SimpleDriverManagerDataSource.java
@@ -0,0 +1,24 @@
+package com.example;
+
+import java.sql.DriverManager;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+public class SimpleDriverManagerDataSource implements DataSource {
+ private final String url;
+ private final String user;
+ private final String password;
+
+ public SimpleDriverManagerDataSource(String url, String user, String password) {
+ this.url = url;
+ this.user = user;
+ this.password = password;
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ // Skapar en ny Connection varje gång den anropas.
+
+ return DriverManager.getConnection(url, user, password);
+ }
+}