Merge pull request #96 from informatik-ag-ngl/f/id_generation
Implemented ID generation on the client
This commit is contained in:
		
							
								
								
									
										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
 | 
				
			||||||
@@ -38,6 +44,7 @@ public class LocalDB {
 | 
				
			|||||||
		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();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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