123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- package fr.insa.clavardator.client.users;
-
- import fr.insa.clavardator.client.chat.ChatHistory;
- import fr.insa.clavardator.client.db.DatabaseController;
- import fr.insa.clavardator.lib.errors.UsernameTakenException;
- import fr.insa.clavardator.lib.message.FileMessage;
- import fr.insa.clavardator.lib.message.Message;
- import fr.insa.clavardator.lib.network.TcpConnection;
- import fr.insa.clavardator.lib.users.User;
- import fr.insa.clavardator.lib.users.UserInformation;
- import fr.insa.clavardator.lib.util.ErrorCallback;
- import fr.insa.clavardator.lib.util.Log;
- import org.jetbrains.annotations.NotNull;
- import org.jetbrains.annotations.Nullable;
-
- import java.io.EOFException;
- import java.io.File;
- import java.io.IOException;
- import java.util.Date;
-
- public class PeerUser extends User implements Comparable<PeerUser> {
- protected transient ChatHistory history;
- private State state = State.DISCONNECTED;
- private transient TcpConnection connection;
-
- public PeerUser(String id, String username) {
- super(id, username);
- history = new ChatHistory(this);
- }
-
- public PeerUser(String id) {
- super(id);
- history = new ChatHistory(this);
- }
-
- public PeerUser() {
- super();
- history = new ChatHistory(this);
- }
-
-
- /**
- * Sends a basic text message to this user
- *
- * @param msg The text message to send
- * @param errorCallback Callback on error
- */
- public void sendTextMessage(String msg, @Nullable ErrorCallback errorCallback) {
- if (connection != null) {
- Log.v(this.getClass().getSimpleName(),
- "Sending message to " + this.getUsername() + " / " + this.getId() + ": " + msg);
- final Message message = new Message(CurrentUser.getInstance(), this, new Date(), msg);
- connection.send(message, () -> history.addMessage(message, errorCallback), errorCallback);
- } else {
- Log.e(this.getClass().getSimpleName(), "Could not send message: connection is not initialized");
- }
- }
-
- /**
- * Sends a message containing a file to this user
- *
- * @param msg The text message to send
- * @param errorCallback Callback on error
- */
- public void sendFileMessage(String msg, File file, @Nullable ErrorCallback errorCallback) {
- if (connection != null) {
- Log.v(this.getClass().getSimpleName(),
- "Sending file message to " + this.getUsername() + " / " + this.getId() + ": " + msg);
- try {
- final FileMessage message = new FileMessage(CurrentUser.getInstance(), this, new Date(), msg, file.getPath());
- message.storeFile();
- connection.send(message, () -> history.addMessage(message, errorCallback), errorCallback);
- } catch (IOException e) {
- Log.e(this.getClass().getSimpleName(), "Could not send message: error while opening file", e);
- if (errorCallback != null) {
- errorCallback.onError(e);
- }
- }
- } else {
- Log.e(this.getClass().getSimpleName(), "Could not send message: connection is not initialized");
- }
- }
-
- /**
- * Sends current user information to this user
- *
- * @param errorCallback Callback on error
- */
- public void sendCurrentUser(@Nullable ErrorCallback errorCallback) {
- if (connection != null) {
- final String username = CurrentUser.getInstance().getUsername();
- Log.v(this.getClass().getSimpleName(),
- "Sending current user information to " + this.getUsername() + " / " + this.getId() + ": " + username);
- connection.send(
- new UserInformation(CurrentUser.getInstance()),
- null,
- errorCallback);
- } else {
- Log.e(this.getClass().getSimpleName(), "Could not send new username: connection is not initialized");
- }
- }
-
- private void sendUsernameTaken(TcpConnection thisConnection) {
- Log.v(this.getClass().getSimpleName(), "Received username request using current username");
- thisConnection.send(new UsernameTakenException("Username taken", getId()), this::disconnect, null);
- }
-
- public void init(TcpConnection connection, String id, String username, ErrorCallback errorCallback) {
- this.connection = connection;
- this.setId(id);
- setUsername(username);
- setState(State.CONNECTED);
- subscribeToMessages((e) -> {
- disconnect();
- errorCallback.onError(e);
- });
- }
-
- /**
- * Subscribe to this user messages.
- * If receiving new user info, update this user.
- * If receiving text message, store it in the history.
- *
- * @param errorCallback Callback on error
- */
- private void subscribeToMessages(ErrorCallback errorCallback) {
- connection.receive(
- msg -> {
- Log.v(this.getClass().getSimpleName(), "Received message from " + getId());
- if (msg instanceof UserInformation) {
- assert ((UserInformation) msg).id.equals(getId());
- final String receivedUsername = ((UserInformation) msg).getUsername();
- Log.v(this.getClass().getSimpleName(), "Message username: " + receivedUsername);
- if (CurrentUser.getInstance().getUsername().equals(receivedUsername)) {
- sendUsernameTaken(connection);
- } else {
- setUsername(receivedUsername);
- }
- } else if (msg instanceof Message) {
- assert !((Message) msg).getRecipient().id.equals(getId());
-
- Log.v(this.getClass().getSimpleName(), "Message text: " + ((Message) msg).getText());
- if (msg instanceof FileMessage) {
- ((FileMessage) msg).storeFile();
- }
- history.addMessage((Message) msg, errorCallback);
- } else if (msg instanceof UsernameTakenException) {
- disconnect();
- errorCallback.onError(new Exception("Received username already taken message"));
- }
- },
- e -> {
- if (e instanceof EOFException) {
- disconnect();
- } else {
- Log.e(this.getClass().getSimpleName(), "Error receiving message from " + getId(), e);
- errorCallback.onError(e);
- }
- });
- }
-
- /**
- * Close the connection and set state to disconnected
- */
- public void disconnect() {
- Log.v(this.getClass().getSimpleName(), "Disconnecting from user: " + getId());
- closeConnection();
- setState(State.DISCONNECTED);
- }
-
- @Override
- protected void setUsername(String newUsername) {
- super.setUsername(newUsername);
- final DatabaseController db = new DatabaseController();
- db.updateUsername(new UserInformation(this),
- null,
- e -> Log.e(getClass().getSimpleName(), "Unable to update the username", e));
- }
-
- /**
- * Close the connection to this user
- */
- private void closeConnection() {
- if (connection != null && connection.isOpen()) {
- connection.close();
- connection = null;
- }
- }
-
-
- /**
- * Gets the value of history
- *
- * @return the value of history
- */
- public ChatHistory getHistory() {
- return history;
- }
-
- /**
- * Sets this user state
- *
- * @param state The new state
- */
- protected void setState(State state) {
- getPcs().firePropertyChange("state", this.state, state);
- this.state = state;
- }
-
- /**
- * Check if this user is active.
- *
- * @return True id active, false otherwise
- */
- public boolean isActive() {
- return state == State.CONNECTED;
- }
-
- @Override
- public int compareTo(@NotNull PeerUser peerUser) {
- if (peerUser.isActive() && !this.isActive()) {
- return 1;
- } else if (!peerUser.isActive() && this.isActive()) {
- return -1;
- }
- return getUsername().compareTo(peerUser.getUsername());
- }
-
- /**
- * The user connection state
- */
- public enum State {
- CONNECTED,
- DISCONNECTED,
- }
- }
|