diff --git a/pom.xml b/pom.xml
index bf35cbb..0b5487d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
com.github.informatik-ag-ngl
envoy-common
- e5c67b8
+ develop-SNAPSHOT
diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java
index 4885a92..935669f 100644
--- a/src/main/java/envoy/client/Client.java
+++ b/src/main/java/envoy/client/Client.java
@@ -11,6 +11,7 @@ import javax.naming.TimeLimitExceededException;
import envoy.client.util.EnvoyLog;
import envoy.data.*;
+import envoy.event.IdGeneratorRequest;
import envoy.util.SerializationUtils;
/**
@@ -45,11 +46,13 @@ public class Client implements Closeable {
* an exception is thrown.
*
* @param credentials the login credentials of the user
+ * @param localDB the local database used to persist the current
+ * {@link IdGenerator}
* @throws Exception if the online mode could not be entered or the request
* failed for some other reason
* @since Envoy v0.2-alpha
*/
- public void onlineInit(LoginCredentials credentials) throws Exception {
+ public void onlineInit(LoginCredentials credentials, LocalDB localDB) throws Exception {
// Establish TCP connection
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
socket = new Socket(config.getServer(), config.getPort());
@@ -84,21 +87,38 @@ public class Client implements Closeable {
// Register processors for message and status handling
receiver.registerProcessor(Message.class, new ReceivedMessageProcessor());
+ // TODO: Status handling
+
+ // Process message ID generation
+ receiver.registerProcessor(IdGenerator.class, localDB::setIdGenerator);
+
+ // Request a generator if none is present
+ if (!localDB.hasIdGenerator() || !localDB.getIdGenerator().hasNext()) requestIdGenerator();
}
/**
* Sends a message to the server.
- *
+ *
* @param message the message to send
* @throws IOException if the message does not reach the server
* @since Envoy v0.3-alpha
*/
public void sendMessage(Message message) throws IOException {
- checkOnline();
- SerializationUtils.writeBytesWithLength(message, socket.getOutputStream());
+ writeObject(message);
message.nextStatus();
}
+ /**
+ * Requests a new {@link IdGenerator} from the server.
+ *
+ * @throws IOException if the request does not reach the server
+ * @since Envoy v0.3-alpha
+ */
+ public void requestIdGenerator() throws IOException {
+ logger.info("Requesting new id generator...");
+ writeObject(new IdGeneratorRequest());
+ }
+
/**
* @return a {@code Map} of all users on the server with their
* user names as keys
@@ -114,6 +134,11 @@ public class Client implements Closeable {
@Override
public void close() throws IOException { if (online) socket.close(); }
+ private void writeObject(Object obj) throws IOException {
+ checkOnline();
+ SerializationUtils.writeBytesWithLength(obj, socket.getOutputStream());
+ }
+
private void checkOnline() { if (!online) throw new IllegalStateException("Client is not online"); }
/**
diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java
index 2c40e65..7511d41 100644
--- a/src/main/java/envoy/client/LocalDB.java
+++ b/src/main/java/envoy/client/LocalDB.java
@@ -4,10 +4,15 @@ import java.io.File;
import java.io.IOException;
import java.util.*;
+import envoy.data.IdGenerator;
import envoy.data.User;
import envoy.util.SerializationUtils;
/**
+ * Stored information about the current {@link User} and their {@link Chat}s.
+ * For message ID generation a {@link IdGenerator} is stored as well.
+ * These object are persisted inside a folder of the local file system.
+ *
* Project: envoy-client
* File: LocalDB.java
* Created: 27.10.2019
@@ -18,10 +23,11 @@ import envoy.util.SerializationUtils;
*/
public class LocalDB {
- private File localDBDir, localDBFile, usersFile;
+ private File localDBDir, localDBFile, usersFile, idGeneratorFile;
private User user;
private Map users = new HashMap<>();
private List chats = new ArrayList<>();
+ private IdGenerator idGenerator;
/**
* Constructs an empty local database. To serialize any chats to the file
@@ -37,7 +43,8 @@ public class LocalDB {
// Initialize local database directory
if (localDBDir.exists() && !localDBDir.isDirectory())
throw new IOException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath()));
- usersFile = new File(localDBDir, "users.db");
+ usersFile = new File(localDBDir, "users.db");
+ idGeneratorFile = new File(localDBDir, "id_generator.db");
}
/**
@@ -53,7 +60,8 @@ public class LocalDB {
/**
* Stores all users to the local database. If the client user is specified, the
- * chats related to this user are stored as well.
+ * chats related to this user are stored as well. The message id generator will
+ * also be saved if present.
*
* @throws IOException if something went wrong during saving
* @since Envoy v0.1-alpha
@@ -63,12 +71,15 @@ public class LocalDB {
SerializationUtils.write(usersFile, users);
// Save chats
- SerializationUtils.write(localDBFile, chats);
+ if (user != null) SerializationUtils.write(localDBFile, chats);
+
+ // Save id generator
+ if (hasIdGenerator()) SerializationUtils.write(idGeneratorFile, idGenerator);
}
/**
* Loads all users that are stored in the local database.
- *
+ *
* @throws IOException if the loading process failed
* @throws ClassNotFoundException if the loading process failed
* @since Envoy v0.2-alpha
@@ -77,13 +88,25 @@ public class LocalDB {
/**
* Loads all chats saved by Envoy for the client user.
- *
+ *
* @throws IOException if the loading process failed
* @throws ClassNotFoundException if the loading process failed
* @since Envoy v0.1-alpha
*/
public void loadChats() throws ClassNotFoundException, IOException { chats = SerializationUtils.read(localDBFile, ArrayList.class); }
+ /**
+ * Loads the message ID generator that is stored in the local database. If the
+ * file is not found, the exception is ignored.
+ *
+ * @since Envoy v0.3-alpha
+ */
+ public void loadIdGenerator() {
+ try {
+ idGenerator = SerializationUtils.read(idGeneratorFile, IdGenerator.class);
+ } catch (ClassNotFoundException | IOException e) {}
+ }
+
/**
* @return a {@code Map} of all users stored locally with their
* user names as keys
@@ -119,4 +142,22 @@ public class LocalDB {
* @since Envoy v0.2-alpha
*/
public void setUser(User user) { this.user = user; }
+
+ /**
+ * @return the message ID generator
+ * @since Envoy v0.3-alpha
+ */
+ public IdGenerator getIdGenerator() { return idGenerator; }
+
+ /**
+ * @param idGenerator the message ID generator to set
+ * @since Envoy v0.3-alpha
+ */
+ public void setIdGenerator(IdGenerator idGenerator) { this.idGenerator = idGenerator; }
+
+ /**
+ * @return {@code true} if an {@link IdGenerator} is present
+ * @since Envoy v0.3-alpha
+ */
+ public boolean hasIdGenerator() { return idGenerator != null; }
}
\ No newline at end of file
diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java
index 3c4cdee..51c7d7f 100644
--- a/src/main/java/envoy/client/ui/ChatWindow.java
+++ b/src/main/java/envoy/client/ui/ChatWindow.java
@@ -10,6 +10,7 @@ import javax.swing.*;
import javax.swing.border.EmptyBorder;
import envoy.client.*;
+import envoy.client.event.MessageCreationEvent;
import envoy.client.event.ThemeChangeEvent;
import envoy.client.ui.list.ComponentList;
import envoy.client.ui.settings.SettingsScreen;
@@ -175,7 +176,9 @@ public class ChatWindow extends JFrame {
messageList.setModel(currentChat.getModel());
scrollPane.setChatOpened(true);
- contentPane.revalidate();
+
+ revalidate();
+ repaint();
}
});
@@ -194,13 +197,20 @@ public class ChatWindow extends JFrame {
contentPane.add(userList, gbc_userList);
contentPane.revalidate();
+ // Listen to theme changes
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme((Theme) evt.get()));
+ // Listen to received messages
+ EventBus.getInstance().register(MessageCreationEvent.class, (evt) -> {
+ Message message = ((MessageCreationEvent) evt).get();
+ localDB.getChats().stream().filter(c -> c.getRecipient().getId() == message.getRecipientId()).findFirst().get().appendMessage(message);
+ });
+
contentPane.revalidate();
}
/**
- * Used to immediately reload the ChatWindow when settings were changed.
+ * Used to immediately reload the {@link ChatWindow} when settings were changed.
*
* @param theme the theme to change colors into
* @since Envoy v0.2-alpha
@@ -247,7 +257,7 @@ public class ChatWindow extends JFrame {
if (!messageEnterTextArea.getText().isEmpty()) try {
// Create message
- final Message message = new MessageBuilder(localDB.getUser().getId(), currentChat.getRecipient().getId())
+ final Message message = new MessageBuilder(localDB.getUser().getId(), currentChat.getRecipient().getId(), localDB.getIdGenerator())
.setText(messageEnterTextArea.getText())
.build();
@@ -262,12 +272,17 @@ public class ChatWindow extends JFrame {
// Clear text field
messageEnterTextArea.setText("");
+ // Update UI
revalidate();
repaint();
+
+ // Request a new id generator if all ids were used
+ if (!localDB.getIdGenerator().hasNext()) client.requestIdGenerator();
+
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
- "An exception occured while sending a message. See the log for more details.",
- "Exception occured",
+ "Error sending message:\n" + e.toString(),
+ "Message sending error",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java
index 3e4692d..2fb9a3a 100644
--- a/src/main/java/envoy/client/ui/Startup.java
+++ b/src/main/java/envoy/client/ui/Startup.java
@@ -62,7 +62,7 @@ public class Startup {
if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined");
} catch (Exception e) {
JOptionPane
- .showMessageDialog(null, "Error loading configuration values: \n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE);
+ .showMessageDialog(null, "Error loading configuration values:\n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
e.printStackTrace();
}
@@ -97,7 +97,8 @@ public class Startup {
Client client = new Client();
try {
// Try entering online mode first
- client.onlineInit(credentials);
+ localDB.loadIdGenerator();
+ client.onlineInit(credentials, localDB);
} catch (Exception e1) {
logger.warning("Could not connect to server. Trying offline mode...");
e1.printStackTrace();