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/
|
||||
!src/**/build/
|
||||
|
||||
# Ignore sqlite db files
|
||||
/*.db
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
|
|
|
@ -3,10 +3,12 @@ package fr.insa.clavardator.chat;
|
|||
import fr.insa.clavardator.db.DatabaseController;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import fr.insa.clavardator.util.Log;
|
||||
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 {
|
||||
private final DatabaseController db;
|
||||
|
@ -17,7 +19,7 @@ public class ChatHistory {
|
|||
|
||||
public ChatHistory(PeerUser user) {
|
||||
this.user = user;
|
||||
db = new DatabaseController(user);
|
||||
db = new DatabaseController();
|
||||
this.historyListener = new ArrayList<>();
|
||||
this.messageListener = new ArrayList<>();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package fr.insa.clavardator.chat;
|
||||
|
||||
import fr.insa.clavardator.users.User;
|
||||
import fr.insa.clavardator.users.UserInformation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -13,7 +13,7 @@ public class FileMessage extends Message {
|
|||
private final byte[] rawFile;
|
||||
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);
|
||||
|
||||
File file = new File(filePath);
|
||||
|
|
|
@ -49,4 +49,14 @@ public class Message implements Serializable {
|
|||
public Date getDate() {
|
||||
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;
|
||||
|
||||
import fr.insa.clavardator.chat.FileMessage;
|
||||
import fr.insa.clavardator.chat.Message;
|
||||
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.Date;
|
||||
|
||||
public class DatabaseController {
|
||||
private final User user;
|
||||
|
||||
public DatabaseController(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
private Connection connection;
|
||||
|
||||
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
|
||||
*
|
||||
* @param callback Function called when the request is done
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @param message The message to add to the database
|
||||
* @param callback Function called when the request is done
|
||||
*/
|
||||
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();
|
||||
}
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 to the ending date
|
||||
* @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);
|
||||
this.username = newUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User " + id + '(' + username + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,9 @@ public class UserInformation implements Serializable {
|
|||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserInfo " + id + '(' + username + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,9 +116,9 @@ public class UserList {
|
|||
// Disconnection
|
||||
if (!activeUsers.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 {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class Log {
|
|||
* 3: errors & warnings & debug,
|
||||
* 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) {
|
||||
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