Merge pull request #96 from informatik-ag-ngl/f/id_generation
Implemented ID generation on the client
This commit is contained in:
commit
9323b0878f
2
pom.xml
2
pom.xml
@ -28,7 +28,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.informatik-ag-ngl</groupId>
|
<groupId>com.github.informatik-ag-ngl</groupId>
|
||||||
<artifactId>envoy-common</artifactId>
|
<artifactId>envoy-common</artifactId>
|
||||||
<version>e5c67b8</version>
|
<version>develop-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import javax.naming.TimeLimitExceededException;
|
|||||||
|
|
||||||
import envoy.client.util.EnvoyLog;
|
import envoy.client.util.EnvoyLog;
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
|
import envoy.event.IdGeneratorRequest;
|
||||||
import envoy.util.SerializationUtils;
|
import envoy.util.SerializationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,11 +46,13 @@ public class Client implements Closeable {
|
|||||||
* an exception is thrown.
|
* an exception is thrown.
|
||||||
*
|
*
|
||||||
* @param credentials the login credentials of the user
|
* @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
|
* @throws Exception if the online mode could not be entered or the request
|
||||||
* failed for some other reason
|
* failed for some other reason
|
||||||
* @since Envoy v0.2-alpha
|
* @since Envoy v0.2-alpha
|
||||||
*/
|
*/
|
||||||
public void onlineInit(LoginCredentials credentials) throws Exception {
|
public void onlineInit(LoginCredentials credentials, LocalDB localDB) throws Exception {
|
||||||
// Establish TCP connection
|
// Establish TCP connection
|
||||||
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
|
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
|
||||||
socket = new Socket(config.getServer(), config.getPort());
|
socket = new Socket(config.getServer(), config.getPort());
|
||||||
@ -84,6 +87,13 @@ public class Client implements Closeable {
|
|||||||
|
|
||||||
// Register processors for message and status handling
|
// Register processors for message and status handling
|
||||||
receiver.registerProcessor(Message.class, new ReceivedMessageProcessor());
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,11 +104,21 @@ public class Client implements Closeable {
|
|||||||
* @since Envoy v0.3-alpha
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public void sendMessage(Message message) throws IOException {
|
public void sendMessage(Message message) throws IOException {
|
||||||
checkOnline();
|
writeObject(message);
|
||||||
SerializationUtils.writeBytesWithLength(message, socket.getOutputStream());
|
|
||||||
message.nextStatus();
|
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<String, User>} of all users on the server with their
|
* @return a {@code Map<String, User>} of all users on the server with their
|
||||||
* user names as keys
|
* user names as keys
|
||||||
@ -114,6 +134,11 @@ public class Client implements Closeable {
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws IOException { if (online) socket.close(); }
|
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"); }
|
private void checkOnline() { if (!online) throw new IllegalStateException("Client is not online"); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,10 +4,15 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import envoy.data.IdGenerator;
|
||||||
import envoy.data.User;
|
import envoy.data.User;
|
||||||
import envoy.util.SerializationUtils;
|
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.<br>
|
||||||
|
* <br>
|
||||||
* Project: <strong>envoy-client</strong><br>
|
* Project: <strong>envoy-client</strong><br>
|
||||||
* File: <strong>LocalDB.java</strong><br>
|
* File: <strong>LocalDB.java</strong><br>
|
||||||
* Created: <strong>27.10.2019</strong><br>
|
* Created: <strong>27.10.2019</strong><br>
|
||||||
@ -18,10 +23,11 @@ import envoy.util.SerializationUtils;
|
|||||||
*/
|
*/
|
||||||
public class LocalDB {
|
public class LocalDB {
|
||||||
|
|
||||||
private File localDBDir, localDBFile, usersFile;
|
private File localDBDir, localDBFile, usersFile, idGeneratorFile;
|
||||||
private User user;
|
private User user;
|
||||||
private Map<String, User> users = new HashMap<>();
|
private Map<String, User> users = new HashMap<>();
|
||||||
private List<Chat> chats = new ArrayList<>();
|
private List<Chat> chats = new ArrayList<>();
|
||||||
|
private IdGenerator idGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an empty local database. To serialize any chats to the file
|
* Constructs an empty local database. To serialize any chats to the file
|
||||||
@ -37,7 +43,8 @@ public class LocalDB {
|
|||||||
// Initialize local database directory
|
// Initialize local database directory
|
||||||
if (localDBDir.exists() && !localDBDir.isDirectory())
|
if (localDBDir.exists() && !localDBDir.isDirectory())
|
||||||
throw new IOException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath()));
|
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
|
* 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
|
* @throws IOException if something went wrong during saving
|
||||||
* @since Envoy v0.1-alpha
|
* @since Envoy v0.1-alpha
|
||||||
@ -63,7 +71,10 @@ public class LocalDB {
|
|||||||
SerializationUtils.write(usersFile, users);
|
SerializationUtils.write(usersFile, users);
|
||||||
|
|
||||||
// Save chats
|
// Save chats
|
||||||
SerializationUtils.write(localDBFile, chats);
|
if (user != null) SerializationUtils.write(localDBFile, chats);
|
||||||
|
|
||||||
|
// Save id generator
|
||||||
|
if (hasIdGenerator()) SerializationUtils.write(idGeneratorFile, idGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +95,18 @@ public class LocalDB {
|
|||||||
*/
|
*/
|
||||||
public void loadChats() throws ClassNotFoundException, IOException { chats = SerializationUtils.read(localDBFile, ArrayList.class); }
|
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<String, User>} of all users stored locally with their
|
* @return a {@code Map<String, User>} of all users stored locally with their
|
||||||
* user names as keys
|
* user names as keys
|
||||||
@ -119,4 +142,22 @@ public class LocalDB {
|
|||||||
* @since Envoy v0.2-alpha
|
* @since Envoy v0.2-alpha
|
||||||
*/
|
*/
|
||||||
public void setUser(User user) { this.user = user; }
|
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; }
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import javax.swing.*;
|
|||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import envoy.client.*;
|
import envoy.client.*;
|
||||||
|
import envoy.client.event.MessageCreationEvent;
|
||||||
import envoy.client.event.ThemeChangeEvent;
|
import envoy.client.event.ThemeChangeEvent;
|
||||||
import envoy.client.ui.list.ComponentList;
|
import envoy.client.ui.list.ComponentList;
|
||||||
import envoy.client.ui.settings.SettingsScreen;
|
import envoy.client.ui.settings.SettingsScreen;
|
||||||
@ -175,7 +176,9 @@ public class ChatWindow extends JFrame {
|
|||||||
|
|
||||||
messageList.setModel(currentChat.getModel());
|
messageList.setModel(currentChat.getModel());
|
||||||
scrollPane.setChatOpened(true);
|
scrollPane.setChatOpened(true);
|
||||||
contentPane.revalidate();
|
|
||||||
|
revalidate();
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -194,13 +197,20 @@ public class ChatWindow extends JFrame {
|
|||||||
contentPane.add(userList, gbc_userList);
|
contentPane.add(userList, gbc_userList);
|
||||||
contentPane.revalidate();
|
contentPane.revalidate();
|
||||||
|
|
||||||
|
// Listen to theme changes
|
||||||
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme((Theme) evt.get()));
|
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();
|
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
|
* @param theme the theme to change colors into
|
||||||
* @since Envoy v0.2-alpha
|
* @since Envoy v0.2-alpha
|
||||||
@ -247,7 +257,7 @@ public class ChatWindow extends JFrame {
|
|||||||
if (!messageEnterTextArea.getText().isEmpty()) try {
|
if (!messageEnterTextArea.getText().isEmpty()) try {
|
||||||
|
|
||||||
// Create message
|
// 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())
|
.setText(messageEnterTextArea.getText())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -262,12 +272,17 @@ public class ChatWindow extends JFrame {
|
|||||||
// Clear text field
|
// Clear text field
|
||||||
messageEnterTextArea.setText("");
|
messageEnterTextArea.setText("");
|
||||||
|
|
||||||
|
// Update UI
|
||||||
revalidate();
|
revalidate();
|
||||||
repaint();
|
repaint();
|
||||||
|
|
||||||
|
// Request a new id generator if all ids were used
|
||||||
|
if (!localDB.getIdGenerator().hasNext()) client.requestIdGenerator();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
JOptionPane.showMessageDialog(this,
|
JOptionPane.showMessageDialog(this,
|
||||||
"An exception occured while sending a message. See the log for more details.",
|
"Error sending message:\n" + e.toString(),
|
||||||
"Exception occured",
|
"Message sending error",
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class Startup {
|
|||||||
if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined");
|
if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
JOptionPane
|
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);
|
System.exit(1);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -97,7 +97,8 @@ public class Startup {
|
|||||||
Client client = new Client();
|
Client client = new Client();
|
||||||
try {
|
try {
|
||||||
// Try entering online mode first
|
// Try entering online mode first
|
||||||
client.onlineInit(credentials);
|
localDB.loadIdGenerator();
|
||||||
|
client.onlineInit(credentials, localDB);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
logger.warning("Could not connect to server. Trying offline mode...");
|
logger.warning("Could not connect to server. Trying offline mode...");
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
|
Reference in New Issue
Block a user