Simplify cache storage with a CacheMap class
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/main/java/envoy/client/data/CacheMap.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/java/envoy/client/data/CacheMap.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
package envoy.client.data;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Stores a heterogeneous map of {@link Cache} objects with different type
 | 
			
		||||
 * parameters.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Project: <strong>envoy-client</strong><br>
 | 
			
		||||
 * File: <strong>CacheMap.java</strong><br>
 | 
			
		||||
 * Created: <strong>09.07.2020</strong><br>
 | 
			
		||||
 * 
 | 
			
		||||
 * @author Kai S. K. Engelbart
 | 
			
		||||
 * @since Envoy Client v0.1-beta
 | 
			
		||||
 */
 | 
			
		||||
public final class CacheMap {
 | 
			
		||||
 | 
			
		||||
	private final Map<Class<?>, Cache<?>> map = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Adds a cache to the map.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param <T>   the type accepted by the cache
 | 
			
		||||
	 * @param key   the class that maps to the cache
 | 
			
		||||
	 * @param cache the cache to store
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public <T> void put(Class<T> key, Cache<T> cache) { map.put(key, cache); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Returns a cache mapped by a class.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param <T> the type accepted by the cache
 | 
			
		||||
	 * @param key the class that maps to the cache
 | 
			
		||||
	 * @return the cache
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public <T> Cache<T> get(Class<T> key) { return (Cache<T>) map.get(key); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @return the map in which the caches are stored
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public Map<Class<?>, Cache<?>> getMap() { return map; }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,13 +3,11 @@ package envoy.client.net;
 | 
			
		||||
import java.io.Closeable;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.Socket;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.TimeoutException;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
import envoy.client.data.Cache;
 | 
			
		||||
import envoy.client.data.CacheMap;
 | 
			
		||||
import envoy.client.data.ClientConfig;
 | 
			
		||||
import envoy.client.data.LocalDB;
 | 
			
		||||
import envoy.client.event.SendEvent;
 | 
			
		||||
@@ -40,8 +38,6 @@ public class Client implements Closeable {
 | 
			
		||||
	private Receiver	receiver;
 | 
			
		||||
	private boolean		online;
 | 
			
		||||
 | 
			
		||||
	private Map<Class<?>, Cache<?>> cacheMap;
 | 
			
		||||
 | 
			
		||||
	// Asynchronously initialized during handshake
 | 
			
		||||
	private volatile User		sender;
 | 
			
		||||
	private volatile boolean	rejected;
 | 
			
		||||
@@ -64,7 +60,8 @@ public class Client implements Closeable {
 | 
			
		||||
	 * @throws InterruptedException if the current thread is interrupted while
 | 
			
		||||
	 *                              waiting for the handshake response
 | 
			
		||||
	 */
 | 
			
		||||
	public void performHandshake(LoginCredentials credentials, Map<Class<?>, Cache<?>> cacheMap)
 | 
			
		||||
	public void performHandshake(LoginCredentials credentials,
 | 
			
		||||
			CacheMap cacheMap)
 | 
			
		||||
			throws TimeoutException, IOException, InterruptedException {
 | 
			
		||||
		if (online) throw new IllegalStateException("Handshake has already been performed successfully");
 | 
			
		||||
 | 
			
		||||
@@ -78,7 +75,7 @@ public class Client implements Closeable {
 | 
			
		||||
 | 
			
		||||
		// Register user creation processor, contact list processor and message cache
 | 
			
		||||
		receiver.registerProcessor(User.class, sender -> this.sender = sender);
 | 
			
		||||
		cacheMap.forEach((inputclass, cache) -> receiver.registerProcessor(inputclass, cache));
 | 
			
		||||
		receiver.registerProcessors(cacheMap.getMap());
 | 
			
		||||
		receiver.registerProcessor(HandshakeRejection.class, evt -> { rejected = true; eventBus.dispatch(evt); });
 | 
			
		||||
 | 
			
		||||
		rejected = false;
 | 
			
		||||
@@ -124,7 +121,7 @@ public class Client implements Closeable {
 | 
			
		||||
	 *                     requested from the server
 | 
			
		||||
	 * @since Envoy Client v0.2-alpha
 | 
			
		||||
	 */
 | 
			
		||||
	public void initReceiver(LocalDB localDB, Map<Class<?>, Cache<?>> cacheMap) throws IOException {
 | 
			
		||||
	public void initReceiver(LocalDB localDB, CacheMap cacheMap) throws IOException {
 | 
			
		||||
		checkOnline();
 | 
			
		||||
 | 
			
		||||
		// Process incoming messages
 | 
			
		||||
@@ -134,18 +131,17 @@ public class Client implements Closeable {
 | 
			
		||||
		final GroupMessageStatusChangeProcessor	groupMessageStatusChangeProcessor	= new GroupMessageStatusChangeProcessor();
 | 
			
		||||
 | 
			
		||||
		receiver.registerProcessor(GroupMessage.class, receivedGroupMessageProcessor);
 | 
			
		||||
 | 
			
		||||
		receiver.registerProcessor(Message.class, receivedMessageProcessor);
 | 
			
		||||
 | 
			
		||||
		receiver.registerProcessor(MessageStatusChange.class, messageStatusChangeProcessor);
 | 
			
		||||
 | 
			
		||||
		receiver.registerProcessor(GroupMessageStatusChange.class, groupMessageStatusChangeProcessor);
 | 
			
		||||
 | 
			
		||||
		// Relay cached unread messages and unread groupMessages
 | 
			
		||||
		cacheMap.get(Message.class).setProcessor((Consumer<?>) receivedMessageProcessor);
 | 
			
		||||
		cacheMap.get(GroupMessage.class).setProcessor((Consumer<?>) receivedGroupMessageProcessor);
 | 
			
		||||
		// Process message status changes
 | 
			
		||||
		cacheMap.get(MessageStatusChange.class).setProcessor((Consumer<?>) messageStatusChangeProcessor);
 | 
			
		||||
		cacheMap.get(GroupMessageStatusChange.class).setProcessor((Consumer<?>) groupMessageStatusChangeProcessor);
 | 
			
		||||
		cacheMap.get(Message.class).setProcessor(receivedMessageProcessor);
 | 
			
		||||
		cacheMap.get(GroupMessage.class).setProcessor(receivedGroupMessageProcessor);
 | 
			
		||||
 | 
			
		||||
		// Relay cached status changes
 | 
			
		||||
		cacheMap.get(MessageStatusChange.class).setProcessor(messageStatusChangeProcessor);
 | 
			
		||||
		cacheMap.get(GroupMessageStatusChange.class).setProcessor(groupMessageStatusChangeProcessor);
 | 
			
		||||
 | 
			
		||||
		// Process user status changes
 | 
			
		||||
		receiver.registerProcessor(UserStatusChange.class, eventBus::dispatch);
 | 
			
		||||
 
 | 
			
		||||
@@ -79,9 +79,7 @@ public class Receiver extends Thread {
 | 
			
		||||
					@SuppressWarnings("rawtypes")
 | 
			
		||||
					final Consumer processor = processors.get(obj.getClass());
 | 
			
		||||
					if (processor == null)
 | 
			
		||||
						logger.log(Level.WARNING, String.format(
 | 
			
		||||
										"The received object has the %s for which no processor is defined.",
 | 
			
		||||
										obj.getClass()));
 | 
			
		||||
						logger.log(Level.WARNING, String.format("The received object has the %s for which no processor is defined.", obj.getClass()));
 | 
			
		||||
					else processor.accept(obj);
 | 
			
		||||
				}
 | 
			
		||||
			} catch (final SocketException e) {
 | 
			
		||||
@@ -103,6 +101,14 @@ public class Receiver extends Thread {
 | 
			
		||||
	 */
 | 
			
		||||
	public <T> void registerProcessor(Class<T> processorClass, Consumer<T> processor) { processors.put(processorClass, processor); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Adds a map of object processors to this {@link Receiver}.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param processors the processors to add the processors to add
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public void registerProcessors(Map<Class<?>, ? extends Consumer<?>> processors) { this.processors.putAll(processors); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Removes all object processors registered at this {@link Receiver}.
 | 
			
		||||
	 *
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ package envoy.client.ui;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Properties;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
@@ -100,7 +99,7 @@ public final class Startup extends Application {
 | 
			
		||||
		// Initialize client and unread message cache
 | 
			
		||||
		client = new Client();
 | 
			
		||||
 | 
			
		||||
		final var cacheMap = new HashMap<Class<?>, Cache<?>>();
 | 
			
		||||
		final var cacheMap = new CacheMap();
 | 
			
		||||
		cacheMap.put(Message.class, new Cache<Message>());
 | 
			
		||||
		cacheMap.put(GroupMessage.class, new Cache<GroupMessage>());
 | 
			
		||||
		cacheMap.put(MessageStatusChange.class, new Cache<MessageStatusChange>());
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ package envoy.client.ui.controller;
 | 
			
		||||
 | 
			
		||||
import java.io.FileNotFoundException;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.TimeoutException;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
@@ -55,10 +54,10 @@ public final class LoginScene {
 | 
			
		||||
	@FXML
 | 
			
		||||
	private Label connectionLabel;
 | 
			
		||||
 | 
			
		||||
	private Client					client;
 | 
			
		||||
	private LocalDB					localDB;
 | 
			
		||||
	private Map<Class<?>, Cache<?>>	cacheMap;
 | 
			
		||||
	private SceneContext			sceneContext;
 | 
			
		||||
	private Client			client;
 | 
			
		||||
	private LocalDB			localDB;
 | 
			
		||||
	private CacheMap		cacheMap;
 | 
			
		||||
	private SceneContext	sceneContext;
 | 
			
		||||
 | 
			
		||||
	private static final Logger			logger		= EnvoyLog.getLogger(LoginScene.class);
 | 
			
		||||
	private static final EventBus		eventBus	= EventBus.getInstance();
 | 
			
		||||
@@ -81,7 +80,7 @@ public final class LoginScene {
 | 
			
		||||
	 * @param sceneContext the scene context used to initialize the chat scene
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public void initializeData(Client client, LocalDB localDB, Map<Class<?>, Cache<?>> cacheMap, SceneContext sceneContext) {
 | 
			
		||||
	public void initializeData(Client client, LocalDB localDB, CacheMap cacheMap, SceneContext sceneContext) {
 | 
			
		||||
		this.client			= client;
 | 
			
		||||
		this.localDB		= localDB;
 | 
			
		||||
		this.cacheMap		= cacheMap;
 | 
			
		||||
@@ -198,6 +197,6 @@ public final class LoginScene {
 | 
			
		||||
		sceneContext.<ChatScene>getController().initializeData(sceneContext, localDB, client, writeProxy);
 | 
			
		||||
 | 
			
		||||
		// Relay unread messages from cache
 | 
			
		||||
		if (client.isOnline()) cacheMap.values().forEach(cache -> { if (cache != null) cache.relay(); });
 | 
			
		||||
		if (client.isOnline()) cacheMap.getMap().values().forEach(cache -> { if (cache != null) cache.relay(); });
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user