Put id in User, async create and init ActiveUser, make CurrentUser singleton
This commit is contained in:
parent
2fe0289f9f
commit
0e8ded05c9
13 changed files with 328 additions and 152 deletions
|
@ -1,18 +1,24 @@
|
|||
package fr.insa.clavardator;
|
||||
|
||||
import fr.insa.clavardator.network.ConnectionListener;
|
||||
import fr.insa.clavardator.network.NetDiscoverer;
|
||||
import fr.insa.clavardator.ui.MainController;
|
||||
import fr.insa.clavardator.users.ActiveUser;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
// See here : https://github.com/jfoenixadmin/JFoenix/blob/master/demo/src/main/java/demos/components/DrawerDemo.java
|
||||
|
||||
public class MainApp extends Application {
|
||||
|
||||
NetDiscoverer netDiscoverer;
|
||||
private ConnectionListener connectionListener;
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
|
@ -20,8 +26,9 @@ public class MainApp extends Application {
|
|||
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
// String javaVersion = System.getProperty("java.version");
|
||||
// String javafxVersion = System.getProperty("javafx.version");
|
||||
|
||||
// Find a place to call this init function
|
||||
CurrentUser.initCurrentUser(1, "Moi");
|
||||
|
||||
final FXMLLoader mainLoader = new FXMLLoader(getClass().getResource("ui/scene.fxml"));
|
||||
final MainController main = mainLoader.getController();
|
||||
|
@ -39,15 +46,33 @@ public class MainApp extends Application {
|
|||
netDiscoverer = new NetDiscoverer();
|
||||
|
||||
// Network discovery test
|
||||
netDiscoverer.startDiscoveryListening("Yohan", null, Throwable::printStackTrace);
|
||||
netDiscoverer.discoverActiveUsers("Broadcast",
|
||||
(ipAddr, data) -> System.out.println("User detected at address : " + ipAddr.toString()),
|
||||
Throwable::printStackTrace);
|
||||
netDiscoverer.startDiscoveryListening("Yohan", null, Throwable::printStackTrace);
|
||||
|
||||
// TCP communnication tests
|
||||
connectionListener = new ConnectionListener();
|
||||
connectionListener.acceptConnection(user -> {
|
||||
}, e -> {
|
||||
if (e instanceof java.io.EOFException) {
|
||||
System.out.println("Connexion terminée");
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
ActiveUser.create(InetAddress.getLocalHost(), user -> {
|
||||
System.out.println("Connexion établie !");
|
||||
user.destroy();
|
||||
},
|
||||
Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
netDiscoverer.stopDiscovery();
|
||||
connectionListener.stopAccepting();
|
||||
super.stop();
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ 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.users.UserList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -40,21 +39,19 @@ public class ChatHistory {
|
|||
public void load() {
|
||||
if (history == null) {
|
||||
// TODO remove after tests
|
||||
CurrentUser currentUser = new CurrentUser("Moi", new UserList());
|
||||
CurrentUser currentUser = CurrentUser.getInstance();
|
||||
history = new ArrayList<>();
|
||||
history.add(new Message(user, currentUser, "Coucou toi"));
|
||||
history.add(new Message(currentUser, user, "Coucou " + user.getUsername()));
|
||||
history.add(new Message(user, currentUser, "oui"));
|
||||
history.add(new Message(currentUser, user, "merci"));
|
||||
notifyHistoryLoaded();
|
||||
// db.getChatHistory(new Date(), new Date(), // TODO: put actual date
|
||||
// newHistory -> {
|
||||
// history = newHistory;
|
||||
// notifyHistoryLoaded();
|
||||
// });
|
||||
} else {
|
||||
notifyHistoryLoaded();
|
||||
}
|
||||
notifyHistoryLoaded();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,20 +7,34 @@ import java.io.IOException;
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import static fr.insa.clavardator.network.PeerConnection.TCP_PORT;
|
||||
|
||||
public class ConnectionListener {
|
||||
Acceptor acceptor = null;
|
||||
|
||||
ConnectionListener() {
|
||||
public ConnectionListener() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start accepting incoming connections
|
||||
*
|
||||
* @param callback The function to call when a user connects
|
||||
* @param errorCallback The function to call on errror
|
||||
*/
|
||||
public void acceptConnection(NewConnectionCallback callback, ErrorCallback errorCallback) {
|
||||
if (acceptor != null) {
|
||||
acceptor.stopAccepting();
|
||||
}
|
||||
acceptor = new Acceptor(callback, errorCallback);
|
||||
acceptor.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop accepting incoming connexions.
|
||||
* Must be called before exiting the app.
|
||||
*/
|
||||
public void stopAccepting() {
|
||||
if (acceptor != null)
|
||||
acceptor.stopAccepting();
|
||||
}
|
||||
|
||||
|
@ -39,13 +53,15 @@ public class ConnectionListener {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
server = new ServerSocket(PeerConnection.TCP_PORT);
|
||||
server = new ServerSocket(TCP_PORT);
|
||||
while (!shouldStop) {
|
||||
System.out.println("Accepting...");
|
||||
Socket clientSocket = server.accept();
|
||||
ActiveUser newUser = new ActiveUser(clientSocket);
|
||||
callback.onNewConnection(newUser);
|
||||
System.out.println("New connection from " + clientSocket.getRemoteSocketAddress());
|
||||
ActiveUser.create(clientSocket, callback::onNewConnection, errorCallback);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!shouldStop)
|
||||
errorCallback.onError(e);
|
||||
}
|
||||
|
||||
|
@ -61,7 +77,7 @@ public class ConnectionListener {
|
|||
}
|
||||
|
||||
|
||||
interface NewConnectionCallback {
|
||||
public interface NewConnectionCallback {
|
||||
void onNewConnection(ActiveUser user);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,21 +14,30 @@ import java.net.Socket;
|
|||
public class PeerConnection {
|
||||
public static final short TCP_PORT = 31598;
|
||||
|
||||
Socket socket;
|
||||
private final ObjectOutputStream outputStream;
|
||||
private final ObjectInputStream inputStream;
|
||||
private Socket socket;
|
||||
private ObjectOutputStream outputStream;
|
||||
private ObjectInputStream inputStream;
|
||||
private boolean shouldStop = false;
|
||||
|
||||
public PeerConnection(InetAddress ipAddr) throws IOException {
|
||||
socket = new Socket(ipAddr, TCP_PORT);
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
/**
|
||||
* Creates a new connection, and connects to the peer
|
||||
*
|
||||
* @param ipAddr The IP address of the peer
|
||||
* @param callback The function to call when connected
|
||||
* @param errorCallback The function to call on error
|
||||
*/
|
||||
public PeerConnection(InetAddress ipAddr, SocketConnectedCallback callback, ErrorCallback errorCallback) {
|
||||
Connector connector = new Connector(ipAddr, callback, errorCallback);
|
||||
connector.start();
|
||||
}
|
||||
|
||||
public PeerConnection(Socket socket) throws IOException {
|
||||
/**
|
||||
* Creates a new connection using an already connected socket
|
||||
*
|
||||
* @param socket A socket already connected to the host
|
||||
*/
|
||||
public PeerConnection(Socket socket) {
|
||||
this.socket = socket;
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +47,7 @@ public class PeerConnection {
|
|||
* @param callback The function to call on success
|
||||
* @param errorCallback The function to call on error
|
||||
*/
|
||||
public void send(Serializable message, MessageSentCallback callback, ErrorCallback errorCallback) {
|
||||
public void send(Serializable message, @Nullable MessageSentCallback callback, @Nullable ErrorCallback errorCallback) {
|
||||
Sender sender = new Sender(message, callback, errorCallback);
|
||||
sender.start();
|
||||
}
|
||||
|
@ -50,17 +59,59 @@ public class PeerConnection {
|
|||
* @param errorCallback The function to call on error
|
||||
*/
|
||||
public void receive(MessageReceivedCallback callback, ErrorCallback errorCallback) {
|
||||
Receiver receiver = new Receiver(callback, errorCallback);
|
||||
Receiver receiver = new Receiver(callback, errorCallback, true);
|
||||
receiver.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscibe to all incoming messages from the peer
|
||||
*
|
||||
* @param callback The function to call when a message is received
|
||||
* @param errorCallback The function to call on error
|
||||
*/
|
||||
public void receiveOne(MessageReceivedCallback callback, ErrorCallback errorCallback) {
|
||||
Receiver receiver = new Receiver(callback, errorCallback, false);
|
||||
receiver.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket, and silently cancel all running send and receive operations.
|
||||
*/
|
||||
public void close() {
|
||||
shouldStop = true;
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Connector extends Thread {
|
||||
private final InetAddress ipAddr;
|
||||
private final SocketConnectedCallback callback;
|
||||
private final ErrorCallback errorCallback;
|
||||
|
||||
public Connector(InetAddress ipAddr, SocketConnectedCallback callback, @Nullable ErrorCallback errorCallback) {
|
||||
this.ipAddr = ipAddr;
|
||||
this.callback = callback;
|
||||
this.errorCallback = errorCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (socket != null) {
|
||||
close();
|
||||
}
|
||||
socket = new Socket(ipAddr, TCP_PORT);
|
||||
callback.onSocketConnected(PeerConnection.this);
|
||||
} catch (IOException e) {
|
||||
if (errorCallback != null)
|
||||
errorCallback.onError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class Sender extends Thread {
|
||||
|
@ -84,6 +135,9 @@ public class PeerConnection {
|
|||
@Override
|
||||
synchronized public void run() {
|
||||
try {
|
||||
if (outputStream == null) {
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
}
|
||||
outputStream.writeObject(message);
|
||||
if (callback != null)
|
||||
callback.onMessageSent();
|
||||
|
@ -97,7 +151,7 @@ public class PeerConnection {
|
|||
private class Receiver extends Thread {
|
||||
private final MessageReceivedCallback callback;
|
||||
private final ErrorCallback errorCallback;
|
||||
|
||||
private final boolean loop;
|
||||
|
||||
/**
|
||||
* Constructs a thread that receives a message using the socket of the outer class
|
||||
|
@ -105,17 +159,21 @@ public class PeerConnection {
|
|||
* @param callback The function to call on success
|
||||
* @param errorCallback The function to call on error
|
||||
*/
|
||||
public Receiver(@NotNull MessageReceivedCallback callback, @Nullable ErrorCallback errorCallback) {
|
||||
public Receiver(@NotNull MessageReceivedCallback callback, @Nullable ErrorCallback errorCallback, boolean loop) {
|
||||
this.callback = callback;
|
||||
this.errorCallback = errorCallback;
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while(!shouldStop) {
|
||||
callback.onMessageReceived(inputStream.readObject());
|
||||
if (inputStream == null) {
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
}
|
||||
do {
|
||||
callback.onMessageReceived(inputStream.readObject());
|
||||
} while (!shouldStop && loop);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
if (errorCallback != null && !shouldStop)
|
||||
errorCallback.onError(e);
|
||||
|
@ -124,6 +182,10 @@ public class PeerConnection {
|
|||
}
|
||||
|
||||
|
||||
public interface SocketConnectedCallback {
|
||||
void onSocketConnected(PeerConnection connection);
|
||||
}
|
||||
|
||||
public interface MessageReceivedCallback {
|
||||
void onMessageReceived(Object msg);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package fr.insa.clavardator.ui;
|
|||
import fr.insa.clavardator.ui.chat.ChatController;
|
||||
import fr.insa.clavardator.ui.users.UserListController;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.UserList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
|
||||
|
@ -19,7 +18,7 @@ public class MainController implements Initializable {
|
|||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
chatController.setCurrentUser(new CurrentUser("Moi", new UserList()));
|
||||
chatController.setCurrentUser(CurrentUser.getInstance());
|
||||
userListController.addRefreshUserListener(() -> {
|
||||
System.out.println("refresh event");
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ package fr.insa.clavardator.ui.users;
|
|||
|
||||
import fr.insa.clavardator.ui.ButtonPressEvent;
|
||||
import fr.insa.clavardator.ui.UserSelectedEvent;
|
||||
import fr.insa.clavardator.users.ActiveUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import fr.insa.clavardator.users.User;
|
||||
import javafx.collections.FXCollections;
|
||||
|
@ -11,8 +10,6 @@ import javafx.fxml.FXML;
|
|||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.ListView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -53,24 +50,17 @@ public class UserListController implements Initializable {
|
|||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
ObservableList<PeerUser> activeList = null;
|
||||
try {
|
||||
activeList = FXCollections.observableArrayList(
|
||||
new PeerUser("Dodo0"),
|
||||
new PeerUser("Dodo3"),
|
||||
new PeerUser("Dodo2"),
|
||||
new ActiveUser("Coucou0", InetAddress.getLocalHost()),
|
||||
new ActiveUser("Coucou1", InetAddress.getLocalHost()),
|
||||
new ActiveUser("Coucou3", InetAddress.getLocalHost()),
|
||||
new PeerUser("Dodo1"),
|
||||
new ActiveUser("Coucou2", InetAddress.getLocalHost())
|
||||
ObservableList<PeerUser> activeList = FXCollections.observableArrayList(
|
||||
new PeerUser(1, "Dodo0"),
|
||||
new PeerUser(2, "Dodo3"),
|
||||
new PeerUser(3, "Dodo2"),
|
||||
// new ActiveUser(4, "Coucou0", InetAddress.getLocalHost()),
|
||||
// new ActiveUser(5, "Coucou1", InetAddress.getLocalHost()),
|
||||
// new ActiveUser(6, "Coucou3", InetAddress.getLocalHost()),
|
||||
new PeerUser(7, "Dodo1")
|
||||
// new ActiveUser(8, "Coucou2", InetAddress.getLocalHost())
|
||||
);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (activeList != null) {
|
||||
activeList.sort(null);
|
||||
}
|
||||
userList.setItems(activeList);
|
||||
userList.setCellFactory(listView -> {
|
||||
final UserListItemCell cell = new UserListItemCell();
|
||||
|
|
|
@ -4,7 +4,6 @@ import fr.insa.clavardator.chat.Message;
|
|||
import fr.insa.clavardator.network.PeerConnection;
|
||||
import fr.insa.clavardator.util.ErrorCallback;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
|
@ -13,42 +12,61 @@ public class ActiveUser extends PeerUser {
|
|||
|
||||
private final transient PeerConnection connection;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an active user and connects to him/her
|
||||
* @param username The username of the new user
|
||||
* Asynchronously creates a new ActiveUser by receiving information (id, username)
|
||||
*
|
||||
* @param ipAddr The IP address of the new user
|
||||
* @throws IOException when an error occurs during the connection
|
||||
* @param callback The function to call on success, with the new ActiveUser as parameter
|
||||
* @param errorCallback The function to call on socket error
|
||||
*/
|
||||
public ActiveUser(String username, InetAddress ipAddr) throws IOException {
|
||||
super(username);
|
||||
connection = new PeerConnection(ipAddr);
|
||||
subscibeToMessages();
|
||||
connection.send(new UsernameChange("", "currentUser.username"), null, null); // TODO: get currentUser + error handling
|
||||
public static void create(InetAddress ipAddr, UserCreatedCallback callback, ErrorCallback errorCallback) {
|
||||
// Connect to the peer
|
||||
new PeerConnection(ipAddr, (thisConnection) -> {
|
||||
|
||||
// Send our username
|
||||
String currentUserUsername = CurrentUser.getInstance().getUsername();
|
||||
int currentUserId = CurrentUser.getInstance().getId();
|
||||
thisConnection.send(new UserInformation(currentUserId, currentUserUsername), null, errorCallback);
|
||||
|
||||
// Receive peer's username
|
||||
thisConnection.receiveOne(msg -> {
|
||||
assert msg instanceof UserInformation;
|
||||
UserInformation userInfo = (UserInformation) msg;
|
||||
ActiveUser user = new ActiveUser(userInfo.getId(), userInfo.getUsername(), thisConnection, errorCallback);
|
||||
callback.onUserCreated(user);
|
||||
|
||||
}, errorCallback);
|
||||
}, errorCallback);
|
||||
}
|
||||
|
||||
public ActiveUser(Socket socket) throws IOException {
|
||||
super("");
|
||||
connection = new PeerConnection(socket);
|
||||
subscibeToMessages();
|
||||
}
|
||||
/**
|
||||
* Asynchronously creates a new ActiveUser by receiving information (id, username)
|
||||
*
|
||||
* @param socket A socket already connected to the user
|
||||
* @param callback The function to call on success, with the new ActiveUser as parameter
|
||||
* @param errorCallback The function to call on socket error
|
||||
*/
|
||||
public static void create(Socket socket, UserCreatedCallback callback, ErrorCallback errorCallback) {
|
||||
PeerConnection connection = new PeerConnection(socket);
|
||||
|
||||
private void subscibeToMessages() {
|
||||
connection.receive(
|
||||
msg -> {
|
||||
if (msg.getClass().isInstance(UsernameChange.class)) {
|
||||
setUsername(((UsernameChange)msg).getNewUsername());
|
||||
// Send our username
|
||||
String currentUserUsername = CurrentUser.getInstance().getUsername();
|
||||
int currentUserId = CurrentUser.getInstance().getId();
|
||||
connection.send(new UserInformation(currentUserId, currentUserUsername), null, errorCallback);
|
||||
|
||||
} else if (msg.getClass().isInstance(Message.class)) {
|
||||
// TODO
|
||||
}
|
||||
},
|
||||
error -> {
|
||||
// TODO
|
||||
});
|
||||
// Receive peer's username
|
||||
connection.receiveOne(msg -> {
|
||||
assert msg instanceof UserInformation;
|
||||
UserInformation userInfo = (UserInformation) msg;
|
||||
ActiveUser user = new ActiveUser(userInfo.getId(), userInfo.getUsername(), connection, errorCallback);
|
||||
callback.onUserCreated(user);
|
||||
}, errorCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to this peer
|
||||
*
|
||||
* @param message The message to send
|
||||
* @param callback The function to call when the message is sent
|
||||
* @param errorCallback The function to call on error
|
||||
|
@ -65,4 +83,30 @@ public class ActiveUser extends PeerUser {
|
|||
connection.close();
|
||||
}
|
||||
|
||||
|
||||
private ActiveUser(int id, String username, PeerConnection connection, ErrorCallback errorCallback) {
|
||||
super(id, username);
|
||||
this.connection = connection;
|
||||
subscribeToMessages(errorCallback);
|
||||
}
|
||||
|
||||
private void subscribeToMessages(ErrorCallback errorCallback) {
|
||||
connection.receive(
|
||||
msg -> {
|
||||
if (msg.getClass().isInstance(UserInformation.class)) {
|
||||
assert ((UserInformation) msg).getId() == getId();
|
||||
setUsername(((UserInformation) msg).getUsername());
|
||||
|
||||
} else if (msg.getClass().isInstance(Message.class)) {
|
||||
assert ((Message) msg).getRecipient() != this;
|
||||
history.addMessage((Message) msg);
|
||||
}
|
||||
},
|
||||
errorCallback);
|
||||
}
|
||||
|
||||
public interface UserCreatedCallback {
|
||||
void onUserCreated(ActiveUser user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,30 @@
|
|||
package fr.insa.clavardator.users;
|
||||
|
||||
public class CurrentUser extends User {
|
||||
public CurrentUser(String username, UserList userList) {
|
||||
super(username);
|
||||
private static CurrentUser instance = null;
|
||||
|
||||
private CurrentUser(int uniqueId, String username) {
|
||||
super(uniqueId, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and returns the current user.
|
||||
*
|
||||
* @param uniqueId the unique id of the current user
|
||||
* @param username The username of the current user
|
||||
*/
|
||||
public static CurrentUser initCurrentUser(int uniqueId, String username) {
|
||||
assert (instance == null);
|
||||
instance = new CurrentUser(uniqueId, username);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user or null if it has not been initialized yet.
|
||||
*
|
||||
* @see CurrentUser#initCurrentUser(int uniqueId, String username)
|
||||
*/
|
||||
public static CurrentUser getInstance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@ public class PeerUser extends User {
|
|||
|
||||
protected transient ChatHistory history;
|
||||
|
||||
public PeerUser(String username) {
|
||||
super(username);
|
||||
public PeerUser(int id, String username) {
|
||||
super(id, username);
|
||||
history = new ChatHistory(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value of history
|
||||
*
|
||||
|
|
|
@ -7,7 +7,8 @@ import java.beans.PropertyChangeSupport;
|
|||
import java.io.Serializable;
|
||||
|
||||
public class User implements Serializable, Comparable<User> {
|
||||
protected String username;
|
||||
private String username;
|
||||
public final int id;
|
||||
|
||||
// Make this class observable
|
||||
protected final transient PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
@ -18,11 +19,16 @@ public class User implements Serializable, Comparable<User> {
|
|||
pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public User(String username) {
|
||||
public User(int id, String username) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
|
21
src/main/java/fr/insa/clavardator/users/UserInformation.java
Normal file
21
src/main/java/fr/insa/clavardator/users/UserInformation.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package fr.insa.clavardator.users;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class UserInformation implements Serializable {
|
||||
private final int id;
|
||||
private final String username;
|
||||
|
||||
public UserInformation(int id, String username) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
}
|
|
@ -4,9 +4,6 @@ import fr.insa.clavardator.db.DatabaseController;
|
|||
import fr.insa.clavardator.network.NetDiscoverer;
|
||||
import fr.insa.clavardator.util.ErrorCallback;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
@ -14,19 +11,57 @@ public class UserList {
|
|||
|
||||
private ArrayList<ActiveUser> activeUsers;
|
||||
private ArrayList<PeerUser> inactiveUsers;
|
||||
|
||||
private final ArrayList<UserConnectionCallback> activeUsersObservers = new ArrayList<>();
|
||||
|
||||
private final DatabaseController db = new DatabaseController();
|
||||
private final NetDiscoverer netDiscoverer = new NetDiscoverer();
|
||||
|
||||
// Make this class observable
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
public void addObserver(PropertyChangeListener listener) {
|
||||
pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
public void removeObserver(PropertyChangeListener listener) {
|
||||
pcs.removePropertyChangeListener(listener);
|
||||
public UserList() {
|
||||
}
|
||||
|
||||
public UserList() {
|
||||
/**
|
||||
* Discover all active users over the network. Observers are notified for each user discovered.
|
||||
*
|
||||
* @param errorCallback The function to call on error
|
||||
* @see UserList#addActiveUserConnectedObserver(UserConnectionCallback)
|
||||
*/
|
||||
public void discoverActiveUsers(ErrorCallback errorCallback) {
|
||||
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
||||
ActiveUser.create(ipAddr, user -> {
|
||||
activeUsers.add(user);
|
||||
notifyObservers(user);
|
||||
}, errorCallback);
|
||||
}, errorCallback);
|
||||
}
|
||||
|
||||
public void addActiveUserConnectedObserver(UserConnectionCallback callback) {
|
||||
activeUsersObservers.add(callback);
|
||||
}
|
||||
|
||||
private void notifyObservers(ActiveUser user) {
|
||||
activeUsersObservers.forEach(callback -> callback.onUserConnected(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests locally if a username is available
|
||||
*
|
||||
* @param username The username to test
|
||||
* @return True if the username is available
|
||||
*/
|
||||
public boolean isUsernameAvailable(String username) {
|
||||
Predicate<User> usernameEqual = user -> user.getUsername().equals(username);
|
||||
return activeUsers.stream().noneMatch(usernameEqual) &&
|
||||
inactiveUsers.stream().noneMatch(usernameEqual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell all active users that our username changed
|
||||
*
|
||||
* @param username The new username
|
||||
*/
|
||||
public void propagateUsernameChange(String username) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,38 +76,16 @@ public class UserList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isUsernameAvailable(String username) {
|
||||
Predicate<User> usernameEqual = user -> user.username.equals(username);
|
||||
return activeUsers.stream().noneMatch(usernameEqual) &&
|
||||
inactiveUsers.stream().noneMatch(usernameEqual);
|
||||
public ArrayList<ActiveUser> getActiveUsers() {
|
||||
return activeUsers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param username
|
||||
*/
|
||||
public void propagateUsernameChange(String username) {
|
||||
public ArrayList<PeerUser> getInactiveUsers() {
|
||||
return inactiveUsers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void discoverActiveUsers(ErrorCallback errorCallback) {
|
||||
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
||||
ActiveUser newUser = null;
|
||||
try {
|
||||
newUser = new ActiveUser("", ipAddr); // TODO find username
|
||||
} catch (IOException e) {
|
||||
errorCallback.onError(e);
|
||||
}
|
||||
activeUsers.add(newUser);
|
||||
pcs.firePropertyChange("activeUsers", null, newUser);
|
||||
}, errorCallback);
|
||||
interface UserConnectionCallback {
|
||||
void onUserConnected(ActiveUser user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package fr.insa.clavardator.users;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class UsernameChange implements Serializable {
|
||||
private final String prevUsername; // Not sure if this is useful
|
||||
private final String newUsername;
|
||||
|
||||
public UsernameChange(String previousUsername, String newUsername) {
|
||||
this.prevUsername = previousUsername;
|
||||
this.newUsername = newUsername;
|
||||
}
|
||||
|
||||
public String getPreviousUsername() {
|
||||
return prevUsername;
|
||||
}
|
||||
|
||||
public String getNewUsername() {
|
||||
return newUsername;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue