Game Event Listener Manager

You might also like

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 2

public class GameEventListenerManager {

private final Lock lock = new ReentrantLock();

private Map<GameEventType, List<GameEventListener>> listenerByEventType = new


HashMap<>();

/**
* Register a listener for a given event type
* @param eventType the type of the event the listener must be register to
* @param listener the listener to register
*/
public void register(GameEventType eventType, GameEventListener listener) {
lock.lock();
try {
final Map<GameEventType, List<GameEventListener>> copy =
duplicateAListenerMap(listenerByEventType);
listenerByEventType = addListenerToAListenerMap(copy, eventType,
listener);
} finally {
lock.unlock();
}
}

/**
* Remove a listener of a given event type
* @param eventType the type of the event the listener is register to
* @param listener the listener to unregister
*/
public void unregister(GameEventType eventType, GameEventListener listener) {
lock.lock();
try {
if (this.isListenerNotInCurrentListenerMap(eventType,listener)) {
throw new IllegalArgumentException("Trying to unregister a non-
registered listener");
}
final Map<GameEventType, List<GameEventListener>> copy =
duplicateAListenerMap(listenerByEventType);
listenerByEventType = removeListenerFromAListenerMap(copy, eventType,
listener);
} finally {
lock.unlock();
}
}

/**
* @param eventType an event type
* @return a stream of all listeners registered to the given event type
*/
public Stream<GameEventListener> getEventListeners(GameEventType eventType) {
return
this.listenerByEventType.getOrDefault(eventType,Collections.emptyList()).stream();
}

/**
* Check if a listener is not register for the provided event type in the
current listener map
* @return true if not the listener is not register for the given event type
*/
private boolean isListenerNotInCurrentListenerMap(GameEventType type,
GameEventListener listener) {
return !listenerByEventType.getOrDefault(type,
Collections.emptyList()).contains(listener);
}

/**
* @return a deep copy of the provide map
*/
private static Map<GameEventType, List<GameEventListener>>
duplicateAListenerMap(Map<GameEventType, List<GameEventListener>> mapToDuplicate) {
return mapToDuplicate.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> new
ArrayList<>(e.getValue())));
}

/**
* @return add a listener for a given event type to the provided map and
returns it
*/
private static Map<GameEventType, List<GameEventListener>>
addListenerToAListenerMap(Map<GameEventType, List<GameEventListener>> mapToAddTo,
GameEventType eventType, GameEventListener listener) {
mapToAddTo.computeIfAbsent(eventType, t -> new
ArrayList<>()).add(listener);
return mapToAddTo;
}

/**
* @return remove a listener for a given event type to the provided map and
returns it
*/
private static Map<GameEventType, List<GameEventListener>>
removeListenerFromAListenerMap(Map<GameEventType, List<GameEventListener>>
mapToRemoveFrom, GameEventType eventType, GameEventListener listener) {
mapToRemoveFrom.computeIfPresent(eventType, (t,l) -> {
l.remove(listener);
return l.isEmpty()?null:l;
});
return mapToRemoveFrom;
}
}

You might also like