improve database compatibility with UI

This commit is contained in:
Arnaud Vergnet 2021-01-04 20:51:05 +01:00
parent 3d6d1b7a15
commit a3873394be
8 changed files with 165 additions and 56 deletions

View file

@ -53,7 +53,10 @@ public class ChatHistory {
* Loads history from database
*/
public void load() {
db.getChatHistory(new UserInformation(user), new Date(), new Date(), this::onLoaded);
final Date from = new Date();
// Load whole history
from.setTime(0);
db.getChatHistory(new UserInformation(user), from, new Date(), this::onLoaded);
}
/**

View file

@ -1,5 +1,6 @@
package fr.insa.clavardator.chat;
import fr.insa.clavardator.users.CurrentUser;
import fr.insa.clavardator.users.User;
import fr.insa.clavardator.users.UserInformation;
@ -46,6 +47,14 @@ public class Message implements Serializable {
return recipient;
}
public UserInformation getCorrespondent() {
if (CurrentUser.getInstance().isLocalId(sender.id)) {
return recipient;
} else {
return sender;
}
}
public Date getDate() {
return date;
}

View file

@ -2,10 +2,12 @@ package fr.insa.clavardator.db;
import fr.insa.clavardator.chat.FileMessage;
import fr.insa.clavardator.chat.Message;
import fr.insa.clavardator.users.CurrentUser;
import fr.insa.clavardator.users.User;
import fr.insa.clavardator.users.UserInformation;
import fr.insa.clavardator.util.Log;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.Nullable;
import java.sql.*;
import java.util.ArrayList;
@ -31,7 +33,6 @@ public class DatabaseController {
*/
public void connect() {
connectToDatabase("clavardator");
initTables();
}
/**
@ -103,16 +104,19 @@ public class DatabaseController {
Log.v(getClass().getSimpleName(), "Creating table user...");
executeUpdate("CREATE TABLE IF NOT EXISTS user " +
"(id INTEGER UNSIGNED PRIMARY KEY NOT NULL," +
" username TINYTEXT NOT NULL)");
" username TINYTEXT NULLABLE )");
}
/**
* Creates all needed tables if non-existent
*/
private void initTables() {
public void init(@Nullable FinishCallback callback) {
try {
createMessageTable();
createUserTable();
if (callback != null) {
callback.onFinish();
}
} catch (SQLException e) {
e.printStackTrace();
}
@ -153,7 +157,7 @@ public class DatabaseController {
*/
public void resetTables() {
dropTables();
initTables();
init(null);
}
@ -165,7 +169,7 @@ public class DatabaseController {
public void getAllUsers(UsersCallback callback) {
try {
Statement stmt = connection.createStatement();
String sql = "SELECT * FROM user";
String sql = "SELECT * FROM user WHERE id != " + CurrentUser.getInstance().getId();
Log.v(getClass().getSimpleName(), "Fetching users from db... ");
ResultSet res = stmt.executeQuery(sql);
@ -196,7 +200,7 @@ public class DatabaseController {
* @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) {
public void addMessage(Message message, FinishCallback callback) {
try {
// TODO: Handle messages containing files:
// store file in file system and put the path in filePath
@ -208,42 +212,67 @@ public class DatabaseController {
// Insert the new message
Log.v(getClass().getSimpleName(), "Inserting message into db... ");
int recipientId;
int senderId;
if (CurrentUser.getInstance().isLocalId(message.getRecipient().id)) {
recipientId = CurrentUser.getInstance().getId();
senderId = message.getSender().id;
} else {
senderId = CurrentUser.getInstance().getId();
recipientId = message.getRecipient().id;
}
executeUpdate("INSERT INTO message " +
"(timestamp, sender, recipient, text, file_path) " +
"VALUES (" +
message.getDate().getTime() + ", " +
message.getSender().id + ", " +
message.getRecipient().id + ", " +
senderId + ", " +
recipientId + ", " +
"\"" + message.getText() + "\", " +
filePath +
")");
// Insert the sender
Log.v(getClass().getSimpleName(), "Inserting sender into db... ");
addUser(message.getSender());
Log.v(getClass().getSimpleName(), "Inserting correspondent into db... ");
addUser(message.getCorrespondent());
// Insert the recipient
Log.v(getClass().getSimpleName(), "Inserting recipient into db... ");
addUser(message.getRecipient());
if (callback != null) {
callback.onMessageSaved();
callback.onFinish();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void addUser(UserInformation user) {
addUser(user, null);
}
/**
* Inserts the given user if not existing
*
* @param user The user information to store
* @throws SQLException SQL error
*/
private void addUser(UserInformation user) throws SQLException {
public void addUser(UserInformation user, @Nullable FinishCallback callback) {
try {
Log.v(getClass().getSimpleName(), "Adding user to db: " + user.id + " / " + user.getUsername());
if (user.getUsername() != null) {
executeUpdate("INSERT OR IGNORE INTO user " +
"(id, username) " +
"VALUES (" + user.id + ", \"" + user.getUsername() + "\")");
} else {
executeUpdate("INSERT OR IGNORE INTO user " +
"(id) " +
"VALUES (" + user.id + ")");
}
if (callback != null) {
callback.onFinish();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
@ -296,16 +325,51 @@ public class DatabaseController {
}
}
public void updateUsername(UserInformation user) {
try {
executeUpdate("UPDATE user SET " +
"username = '" + user.getUsername() + "' where id = " + user.id);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void getUsername(int id, UsernameCallback callback) {
try {
Statement statement = connection.createStatement();
String sql = "SELECT username from user where id =" + id;
Log.v(getClass().getSimpleName(), "Fetching users from db... ");
ResultSet res = statement.executeQuery(sql);
String username = null;
if (res.next()) {
username = res.getString("username");
}
Log.v(getClass().getSimpleName(), res.getFetchSize() + " rows fetched");
res.close();
statement.close();
if (callback != null) {
callback.onUsernameFetched(username);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public interface UsersCallback {
void onUsersFetched(ArrayList<User> users);
}
public interface UsernameCallback {
void onUsernameFetched(String username);
}
public interface HistoryCallback {
void onHistoryFetched(ArrayList<Message> history);
}
public interface MessageCallback {
void onMessageSaved();
public interface FinishCallback {
void onFinish();
}
}

View file

@ -1,6 +1,7 @@
package fr.insa.clavardator.ui;
import com.jfoenix.controls.JFXSnackbar;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.ui.chat.ChatController;
import fr.insa.clavardator.ui.dialogs.AboutDialogController;
import fr.insa.clavardator.ui.dialogs.EditUsernameDialogController;
@ -64,7 +65,7 @@ public class MainController implements Initializable {
if (historyLoaded) {
if (newState == CurrentUser.State.VALID)
startChat();
else if (newState != CurrentUser.State.NONE) {
else if (newState != CurrentUser.State.UNINITIALIZED) {
final boolean isError = newState == CurrentUser.State.INVALID;
if (isError) {
endChat();
@ -78,7 +79,7 @@ public class MainController implements Initializable {
historyLoaded = true;
final CurrentUser.State userState = CurrentUser.getInstance().getState();
// If the history loaded after the current user, fire the state change event again
if (userState != CurrentUser.State.NONE) {
if (userState != CurrentUser.State.UNINITIALIZED) {
onCurrentUserStateChange(userState);
}
}
@ -191,14 +192,6 @@ public class MainController implements Initializable {
loadingController.show("Initialisation de Clavardator...");
snackbar = new JFXSnackbar(root);
try {
currentUser.init();
Log.v("INIT", "Current user: " + currentUser.getId());
} catch (SocketException e) {
Log.e("INIT", "Could not init user", e);
showError();
}
listController.setUserSelectedListener((user) -> chatController.setRemoteUser(user));
chatController.addAttachmentListener(() -> System.out.println("attach event"));
chatController.addSendErrorListener((e) -> showSnackbarEvent("Erreur: Message non envoyé", SnackbarController.Mode.ERROR));
@ -206,11 +199,24 @@ public class MainController implements Initializable {
toolbarController.addAboutListener(this::openAboutDialog);
}
private void initDb() {
final DatabaseController db = new DatabaseController();
db.init(() -> {
try {
Log.v("INIT", "Current user: " + currentUser.getId());
currentUser.init(() -> userList.retrievedPreviousUsers(this::onHistoryLoaded));
} catch (SocketException e) {
Log.e("INIT", "Could not init user", e);
showError();
}
});
}
public void setUserList(UserList userList) {
this.userList = userList;
userList.retrievedPreviousUsers(this::onHistoryLoaded);
listController.setUserList(userList);
listController.setRefreshUserListener(this::discoverActiveUsers);
editUserDialogController.setUserList(userList);
initDb();
}
}

View file

@ -34,7 +34,7 @@ public class MessageListItemController implements Initializable {
currentMessage = message;
button.setText(message.getText());
timestamp.setText(DateFormat.getTimeInstance().format(message.getDate()));
if (message.getSender().id == CurrentUser.getInstance().getId()) {
if (CurrentUser.getInstance().isLocalId(message.getSender().id)) {
container.setAlignment(Pos.CENTER_RIGHT);
button.getStyleClass().remove("message-other");
button.getStyleClass().add("message-self");

View file

@ -55,12 +55,14 @@ public class UserListController implements Initializable {
}
private void onUserConnected(PeerUser user) {
Platform.runLater(() -> {
if (!peerUserListView.getItems().contains(user)) {
Log.v(this.getClass().getSimpleName(), "Add user to UI");
Platform.runLater(() -> peerUserListView.getItems().add(user));
peerUserListView.getItems().add(user);
} else {
Log.w(this.getClass().getSimpleName(), "User already added to ui, skipping...");
}
});
}
public void setUserList(UserList userList) {

View file

@ -1,14 +1,13 @@
package fr.insa.clavardator.users;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.network.NetUtil;
import fr.insa.clavardator.util.Log;
import javafx.application.Platform;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import static fr.insa.clavardator.network.NetUtil.getIdFromIp;
@ -17,9 +16,12 @@ public class CurrentUser extends User {
private State state;
private ArrayList<Integer> validIds;
private CurrentUser() {
super();
state = State.UNINITIALIZED;
validIds = new ArrayList<>();
}
/**
@ -31,22 +33,33 @@ public class CurrentUser extends User {
return instance;
}
public void init() throws SocketException {
public void init(InitCallback callback) throws SocketException {
final List<InetAddress> addresses = NetUtil.listAllLocalAddresses();
if (addresses.size() > 0) {
id = getIdFromIp(addresses.get(0));
// Save all addresses for this user
validIds = new ArrayList<>();
addresses.forEach(address -> validIds.add(getIdFromIp(address)));
if (validIds.size() > 0) {
// Set the first id as the main one
id = validIds.get(0);
} else {
throw new SocketException();
}
// TODO replace by db username fetching
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
final DatabaseController db = new DatabaseController();
// Make sure the user is in the db then set its username
db.addUser(new UserInformation(this), () -> {
db.getUsername(id, username -> {
if (username != null) {
Log.v(getClass().getSimpleName(), "Last username found : " + username);
setUsername(username);
} else {
Log.v(getClass().getSimpleName(), "No last username found, asking user...");
setState(State.NONE);
t.cancel();
}
}, 500);
if (callback != null) {
callback.onFinish();
}
});
});
}
@Override
@ -68,10 +81,18 @@ public class CurrentUser extends User {
return state;
}
public boolean isLocalId(int id) {
return validIds.contains(id);
}
public enum State {
UNINITIALIZED,
VALID,
INVALID,
NONE
}
public interface InitCallback {
void onFinish();
}
}

View file

@ -1,5 +1,7 @@
package fr.insa.clavardator.users;
import fr.insa.clavardator.db.DatabaseController;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
@ -41,6 +43,8 @@ public class User implements Serializable {
protected void setUsername(String newUsername) {
pcs.firePropertyChange("username", this.username, newUsername);
this.username = newUsername;
final DatabaseController db = new DatabaseController();
db.updateUsername(new UserInformation(this));
}
@Override