Implement and test DatabaseController functions
This commit is contained in:
parent
aed165108c
commit
34255a98e8
10 changed files with 298 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,6 +2,9 @@
|
||||||
**/build/
|
**/build/
|
||||||
!src/**/build/
|
!src/**/build/
|
||||||
|
|
||||||
|
# Ignore sqlite db files
|
||||||
|
/*.db
|
||||||
|
|
||||||
# Ignore Gradle GUI config
|
# Ignore Gradle GUI config
|
||||||
gradle-app.setting
|
gradle-app.setting
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,12 @@ package fr.insa.clavardator.chat;
|
||||||
import fr.insa.clavardator.db.DatabaseController;
|
import fr.insa.clavardator.db.DatabaseController;
|
||||||
import fr.insa.clavardator.users.CurrentUser;
|
import fr.insa.clavardator.users.CurrentUser;
|
||||||
import fr.insa.clavardator.users.PeerUser;
|
import fr.insa.clavardator.users.PeerUser;
|
||||||
import fr.insa.clavardator.util.Log;
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class ChatHistory {
|
public class ChatHistory {
|
||||||
private final DatabaseController db;
|
private final DatabaseController db;
|
||||||
|
@ -17,7 +19,7 @@ public class ChatHistory {
|
||||||
|
|
||||||
public ChatHistory(PeerUser user) {
|
public ChatHistory(PeerUser user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
db = new DatabaseController(user);
|
db = new DatabaseController();
|
||||||
this.historyListener = new ArrayList<>();
|
this.historyListener = new ArrayList<>();
|
||||||
this.messageListener = new ArrayList<>();
|
this.messageListener = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package fr.insa.clavardator.chat;
|
package fr.insa.clavardator.chat;
|
||||||
|
|
||||||
import fr.insa.clavardator.users.User;
|
import fr.insa.clavardator.users.UserInformation;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -13,7 +13,7 @@ public class FileMessage extends Message {
|
||||||
private final byte[] rawFile;
|
private final byte[] rawFile;
|
||||||
private final String fileName;
|
private final String fileName;
|
||||||
|
|
||||||
public FileMessage(User sender, User recipient, String filePath, Date date, String text) throws IOException {
|
public FileMessage(UserInformation sender, UserInformation recipient, Date date, String text, String filePath) throws IOException {
|
||||||
super(sender, recipient, date, text);
|
super(sender, recipient, date, text);
|
||||||
|
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
|
|
|
@ -49,4 +49,14 @@ public class Message implements Serializable {
|
||||||
public Date getDate() {
|
public Date getDate() {
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Message{" +
|
||||||
|
"text='" + text + '\'' +
|
||||||
|
", date=" + date +
|
||||||
|
", sender=" + sender +
|
||||||
|
", recipient=" + recipient +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,243 @@
|
||||||
package fr.insa.clavardator.db;
|
package fr.insa.clavardator.db;
|
||||||
|
|
||||||
|
import fr.insa.clavardator.chat.FileMessage;
|
||||||
import fr.insa.clavardator.chat.Message;
|
import fr.insa.clavardator.chat.Message;
|
||||||
import fr.insa.clavardator.users.User;
|
import fr.insa.clavardator.users.User;
|
||||||
|
import fr.insa.clavardator.users.UserInformation;
|
||||||
|
import fr.insa.clavardator.util.Log;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class DatabaseController {
|
public class DatabaseController {
|
||||||
private final User user;
|
private Connection connection;
|
||||||
|
|
||||||
public DatabaseController(User user) {
|
|
||||||
this.user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DatabaseController() {
|
public DatabaseController() {
|
||||||
user = null;
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
try {
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
connection = DriverManager.getConnection("jdbc:sqlite:clavardator.db");
|
||||||
|
Log.v(getClass().getSimpleName(), "Opened database successfully");
|
||||||
|
} catch (ClassNotFoundException | SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initTables() {
|
||||||
|
try {
|
||||||
|
Statement stmtMessageTable = connection.createStatement();
|
||||||
|
String messageTableSql =
|
||||||
|
"CREATE TABLE IF NOT EXISTS message " +
|
||||||
|
"(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
|
||||||
|
" timestamp DATETIME NOT NULL, " +
|
||||||
|
" sender INTEGER NOT NULL, " +
|
||||||
|
" recipient INTEGER NOT NULL, " +
|
||||||
|
" text TEXT, " +
|
||||||
|
" file_path TEXT)";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Creating table message...");
|
||||||
|
int rowsModified = stmtMessageTable.executeUpdate(messageTableSql);
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
stmtMessageTable.close();
|
||||||
|
Statement stmtUserTable = connection.createStatement();
|
||||||
|
String userTableSql =
|
||||||
|
"CREATE TABLE IF NOT EXISTS user " +
|
||||||
|
"(id INTEGER PRIMARY KEY NOT NULL," +
|
||||||
|
" username INTEGER NOT NULL)";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Creating table user...");
|
||||||
|
rowsModified = stmtUserTable.executeUpdate(userTableSql);
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
stmtUserTable.close();
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetTables() {
|
||||||
|
try {
|
||||||
|
Statement dropMessage = connection.createStatement();
|
||||||
|
String dropMessageSql = "DROP TABLE message";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Dropping table message...");
|
||||||
|
int rowsModified = dropMessage.executeUpdate(dropMessageSql);
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
dropMessage.close();
|
||||||
|
|
||||||
|
Statement dropUser = connection.createStatement();
|
||||||
|
String dropUserSql = "DROP TABLE user";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Dropping table user...");
|
||||||
|
rowsModified = dropUser.executeUpdate(dropUserSql);
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
dropUser.close();
|
||||||
|
|
||||||
|
initTables();
|
||||||
|
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the list of users for which we already have a chat history
|
* Fetches the list of users for which we already have a chat history
|
||||||
|
*
|
||||||
* @param callback Function called when the request is done
|
* @param callback Function called when the request is done
|
||||||
*/
|
*/
|
||||||
public void getAllUsers(UsersCallback callback) {
|
public void getAllUsers(UsersCallback callback) {
|
||||||
|
try {
|
||||||
|
Statement stmt = connection.createStatement();
|
||||||
|
String sql = "SELECT * FROM user";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Fetching users from db... ");
|
||||||
|
ResultSet res = stmt.executeQuery(sql);
|
||||||
|
Log.v(getClass().getSimpleName(), res.getFetchSize() + " rows fetched");
|
||||||
|
|
||||||
|
ArrayList<User> userList = new ArrayList<>();
|
||||||
|
while (res.next()) {
|
||||||
|
int id = res.getInt("id");
|
||||||
|
String username = res.getString("username");
|
||||||
|
userList.add(new User(id, username));
|
||||||
|
}
|
||||||
|
res.close();
|
||||||
|
stmt.close();
|
||||||
|
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onUsersFetched(userList);
|
||||||
|
}
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a message to the database for this user
|
* Adds a message to the database for this user
|
||||||
|
*
|
||||||
* @param message The message to add to the database
|
* @param message The message to add to the database
|
||||||
* @param callback Function called when the request is done
|
* @param callback Function called when the request is done
|
||||||
*/
|
*/
|
||||||
public void addMessage(Message message, MessageCallback callback) {
|
public void addMessage(Message message, MessageCallback callback) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Insert the new message
|
||||||
|
final String insertMessageSql =
|
||||||
|
"INSERT INTO message " +
|
||||||
|
"(timestamp, sender, recipient, text, file_path) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?)";
|
||||||
|
PreparedStatement insertMsgStmt = connection.prepareStatement(insertMessageSql);
|
||||||
|
insertMsgStmt.setTimestamp(1, new Timestamp(message.getDate().getTime()));
|
||||||
|
insertMsgStmt.setInt(2, message.getSender().id);
|
||||||
|
insertMsgStmt.setInt(3, message.getRecipient().id);
|
||||||
|
insertMsgStmt.setString(4, message.getText());
|
||||||
|
if (insertMsgStmt instanceof FileMessage) {
|
||||||
|
// TODO: store file in file system
|
||||||
|
Log.w(getClass().getSimpleName(), "Functionality not implemented: file has not been saved");
|
||||||
|
// stmt.setString(5, ((FileMessage) stmt).getFileName());
|
||||||
|
} else {
|
||||||
|
insertMsgStmt.setString(5, null);
|
||||||
|
}
|
||||||
|
Log.v(getClass().getSimpleName(), "Inserting message into db... ");
|
||||||
|
int rowsModified = insertMsgStmt.executeUpdate();
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
insertMsgStmt.close();
|
||||||
|
|
||||||
|
// Insert the user if not already existing
|
||||||
|
final String insertUserSql =
|
||||||
|
"INSERT OR IGNORE INTO user" +
|
||||||
|
"(id, username)" +
|
||||||
|
"VALUES (?, ?)";
|
||||||
|
PreparedStatement insertUserStmt = connection.prepareStatement(insertUserSql);
|
||||||
|
// Add sender
|
||||||
|
insertUserStmt.setInt(1, message.getSender().id);
|
||||||
|
insertUserStmt.setString(2, message.getSender().getUsername());
|
||||||
|
Log.v(getClass().getSimpleName(), "Inserting sender into db... ");
|
||||||
|
rowsModified = insertUserStmt.executeUpdate();
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
// Add recipient
|
||||||
|
insertUserStmt.setInt(1, message.getRecipient().id);
|
||||||
|
insertUserStmt.setString(2, message.getRecipient().getUsername());
|
||||||
|
Log.v(getClass().getSimpleName(), "Inserting recipient into db");
|
||||||
|
rowsModified = insertUserStmt.executeUpdate();
|
||||||
|
Log.v(getClass().getSimpleName(), rowsModified + " rows modified");
|
||||||
|
|
||||||
|
|
||||||
|
insertUserStmt.close();
|
||||||
|
|
||||||
|
if (callback != null) {
|
||||||
callback.onMessageSaved();
|
callback.onMessageSaved();
|
||||||
}
|
}
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the chat history for a given time frame
|
* Get the chat history for a given time frame
|
||||||
|
*
|
||||||
|
* @param user the user for which to retrieve the history
|
||||||
* @param from the starting date
|
* @param from the starting date
|
||||||
* @param to the ending date
|
* @param to the ending date
|
||||||
* @param callback Function called when the request is done
|
* @param callback Function called when the request is done
|
||||||
*/
|
*/
|
||||||
public void getChatHistory(Date from, Date to, HistoryCallback callback) {
|
public void getChatHistory(UserInformation user, Date from, Date to, HistoryCallback callback) {
|
||||||
|
try {
|
||||||
|
Statement stmt = connection.createStatement();
|
||||||
|
String sql =
|
||||||
|
"SELECT timestamp, s.id AS sender_id, s.username AS sender_username, " +
|
||||||
|
"r.id AS recipient_id, r.username AS recipient_username, text, file_path " +
|
||||||
|
"FROM message JOIN user AS s ON sender = s.id " +
|
||||||
|
" JOIN user AS r ON recipient = r.id " +
|
||||||
|
"WHERE (s.id = " + user.id + " OR r.id = " + user.id + ") AND " +
|
||||||
|
"timestamp > " + from.getTime() + " AND timestamp < " + to.getTime() +
|
||||||
|
" ORDER BY timestamp";
|
||||||
|
|
||||||
|
Log.v(getClass().getSimpleName(), "Fetching chat history from db... ");
|
||||||
|
ResultSet res = stmt.executeQuery(sql);
|
||||||
|
Log.v(getClass().getSimpleName(), res.getFetchSize() + " rows fetched");
|
||||||
|
|
||||||
|
ArrayList<Message> chatHistory = new ArrayList<>();
|
||||||
|
while (res.next()) {
|
||||||
|
int sId = res.getInt("sender_id");
|
||||||
|
String sUsername = res.getString("sender_username");
|
||||||
|
int rId = res.getInt("recipient_id");
|
||||||
|
String rUsername = res.getString("recipient_username");
|
||||||
|
Date date = new Date(res.getTimestamp("timestamp").getTime());
|
||||||
|
String text = res.getString("text");
|
||||||
|
String filePath = res.getString("file_path");
|
||||||
|
if (filePath == null) {
|
||||||
|
chatHistory.add(new Message(new UserInformation(sId, sUsername), new UserInformation(rId, rUsername), date, text));
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
// chatHistory.add(new FileMessage(new UserInformation(sId, sUsername), new UserInformation(rId, rUsername), date, text, filePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.close();
|
||||||
|
stmt.close();
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onHistoryFetched(chatHistory);
|
||||||
|
}
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,4 +44,9 @@ public class User implements Serializable {
|
||||||
pcs.firePropertyChange("username", this.username, newUsername);
|
pcs.firePropertyChange("username", this.username, newUsername);
|
||||||
this.username = newUsername;
|
this.username = newUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User " + id + '(' + username + ')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,9 @@ public class UserInformation implements Serializable {
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UserInfo " + id + '(' + username + ')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,9 +116,9 @@ public class UserList {
|
||||||
// Disconnection
|
// Disconnection
|
||||||
if (!activeUsers.containsKey(id)) {
|
if (!activeUsers.containsKey(id)) {
|
||||||
if (inactiveUsers.containsKey(id)) {
|
if (inactiveUsers.containsKey(id)) {
|
||||||
Log.e(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an already disconnected user: user id " + id);
|
Log.w(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an already disconnected user: user id " + id);
|
||||||
} else {
|
} else {
|
||||||
Log.e(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an unknown user: user id " + id);
|
Log.w(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an unknown user: user id " + id);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class Log {
|
||||||
* 3: errors & warnings & debug,
|
* 3: errors & warnings & debug,
|
||||||
* 4: all
|
* 4: all
|
||||||
*/
|
*/
|
||||||
public static int verboseLevel = 0;
|
public static int verboseLevel = 4;
|
||||||
|
|
||||||
private static void print(String prefix, String message, String mode, int requiredLevel, @Nullable Exception e) {
|
private static void print(String prefix, String message, String mode, int requiredLevel, @Nullable Exception e) {
|
||||||
if (verboseLevel >= requiredLevel) {
|
if (verboseLevel >= requiredLevel) {
|
||||||
|
|
60
src/test/java/fr/insa/clavardator/DatabaseTest.java
Normal file
60
src/test/java/fr/insa/clavardator/DatabaseTest.java
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package fr.insa.clavardator;
|
||||||
|
|
||||||
|
import fr.insa.clavardator.chat.Message;
|
||||||
|
import fr.insa.clavardator.db.DatabaseController;
|
||||||
|
import fr.insa.clavardator.users.UserInformation;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class DatabaseTest {
|
||||||
|
private final DatabaseController db = new DatabaseController();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDB() {
|
||||||
|
db.connect();
|
||||||
|
db.resetTables();
|
||||||
|
db.getAllUsers(users -> {
|
||||||
|
assertEquals(0, users.size());
|
||||||
|
});
|
||||||
|
|
||||||
|
db.getChatHistory(new UserInformation(1, "Yohan"), new Date(0), new Date(), history -> {
|
||||||
|
assertEquals(history.size(), 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"), new Date(), "Coucou Arnaud !"), null);
|
||||||
|
db.addMessage(new Message(new UserInformation(2, "Arnaud"), new UserInformation(1, "Yohan"), new Date(), "Coucou Yohan !"), null);
|
||||||
|
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"), new Date(), "Ça va ?"), null);
|
||||||
|
db.addMessage(new Message(new UserInformation(2, "Arnaud"), new UserInformation(1, "Yohan"), new Date(), "Ouais et toi ?"), null);
|
||||||
|
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"), new Date(), "Super !"), null);
|
||||||
|
db.getAllUsers(users -> {
|
||||||
|
assertEquals(2, users.size());
|
||||||
|
assertEquals(1, users.get(0).getId());
|
||||||
|
assertEquals(2, users.get(1).getId());
|
||||||
|
assertEquals("Yohan", users.get(0).getUsername());
|
||||||
|
assertEquals("Arnaud", users.get(1).getUsername());
|
||||||
|
});
|
||||||
|
db.getChatHistory(new UserInformation(1, "Yohan"), new Date(0), new Date(), history -> {
|
||||||
|
assertEquals(5, history.size());
|
||||||
|
assertEquals("Coucou Arnaud !", history.get(0).getText());
|
||||||
|
assertEquals(1, history.get(0).getSender().id);
|
||||||
|
assertEquals(2, history.get(0).getRecipient().id);
|
||||||
|
assertEquals("Yohan", history.get(0).getSender().getUsername());
|
||||||
|
assertEquals("Arnaud", history.get(0).getRecipient().getUsername());
|
||||||
|
|
||||||
|
assertEquals("Ouais et toi ?", history.get(3).getText());
|
||||||
|
assertEquals(2, history.get(3).getSender().id);
|
||||||
|
assertEquals(1, history.get(3).getRecipient().id);
|
||||||
|
assertEquals("Arnaud", history.get(3).getSender().getUsername());
|
||||||
|
assertEquals("Yohan", history.get(3).getRecipient().getUsername());
|
||||||
|
});
|
||||||
|
|
||||||
|
db.resetTables();
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue