Make EventListener an interface

This commit is contained in:
TheMode 2021-06-02 21:14:48 +02:00
parent 4f127b2e0e
commit 2977bb7b66
2 changed files with 46 additions and 33 deletions

View File

@ -7,28 +7,34 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class EventListener<T extends Event> {
public interface EventListener<T extends Event> {
protected final Class<T> type;
protected final Function<T, Result> executor;
@NotNull Class<T> getEventType();
private EventListener(@NotNull Class<T> type, @NotNull Function<T, Result> executor) {
this.type = type;
this.executor = executor;
}
@NotNull Result run(@NotNull T event);
public static <T extends Event> EventListener.Builder<T> builder(@NotNull Class<T> eventType) {
static <T extends Event> EventListener.Builder<T> builder(@NotNull Class<T> eventType) {
return new EventListener.Builder<>(eventType);
}
public static <T extends Event> EventListener<T> of(@NotNull Class<T> eventType, @NotNull Consumer<@NotNull T> listener) {
return EventListener.builder(eventType).handler(listener).build();
static <T extends Event> EventListener<T> of(@NotNull Class<T> eventType, @NotNull Consumer<@NotNull T> listener) {
return new EventListener<>() {
@Override
public @NotNull Class<T> getEventType() {
return eventType;
}
@Override
public @NotNull Result run(@NotNull T event) {
listener.accept(event);
return Result.SUCCESS;
}
};
}
public static class Builder<T extends Event> {
class Builder<T extends Event> {
private final Class<T> eventType;
@ -61,34 +67,41 @@ public class EventListener<T extends Event> {
return this;
}
public EventListener<T> build() {
public @NotNull EventListener<T> build() {
AtomicInteger expirationCount = new AtomicInteger(this.expirationCount);
final boolean hasExpirationCount = expirationCount.get() > 0;
final var filters = new ArrayList<>(this.filters);
final var handler = this.handler;
return new EventListener<>(eventType, event -> {
// Filtering
if (!filters.isEmpty()) {
if (filters.stream().anyMatch(filter -> !filter.test(event))) {
// Cancelled
return Result.INVALID;
return new EventListener<>() {
@Override
public @NotNull Class<T> getEventType() {
return eventType;
}
@Override
public @NotNull Result run(@NotNull T event) {
// Filtering
if (!filters.isEmpty()) {
if (filters.stream().anyMatch(filter -> !filter.test(event))) {
// Cancelled
return Result.INVALID;
}
}
// Handler
if (handler != null) {
handler.accept(event);
}
// Expiration check
if (hasExpirationCount && expirationCount.decrementAndGet() == 0) {
return Result.EXPIRED;
}
return Result.SUCCESS;
}
// Handler
if (handler != null) {
handler.accept(event);
}
// Expiration check
if (hasExpirationCount && expirationCount.decrementAndGet() == 0) {
return Result.EXPIRED;
}
return Result.SUCCESS;
});
};
}
}
enum Result {
SUCCESS,
INVALID,

View File

@ -45,7 +45,7 @@ class EventNodeImpl<T extends Event, H extends EventHandler> implements EventNod
final var listeners = listenerMap.get(event.getClass());
if (listeners != null && !listeners.isEmpty()) {
listeners.forEach(listener -> {
final EventListener.Result result = listener.executor.apply(event);
final EventListener.Result result = listener.run(event);
if (result == EventListener.Result.EXPIRED) {
listeners.remove(listener);
}
@ -66,13 +66,13 @@ class EventNodeImpl<T extends Event, H extends EventHandler> implements EventNod
@Override
public void addListener(@NotNull EventListener<? extends T> listener) {
this.listenerMap.computeIfAbsent(listener.type, aClass -> new CopyOnWriteArrayList<>())
this.listenerMap.computeIfAbsent(listener.getEventType(), aClass -> new CopyOnWriteArrayList<>())
.add((EventListener<T>) listener);
}
@Override
public void removeListener(@NotNull EventListener<? extends T> listener) {
var listeners = listenerMap.get(listener.type);
var listeners = listenerMap.get(listener.getEventType());
if (listeners == null || listeners.isEmpty())
return;
listeners.remove(listener);