Remove EventListener and IEvent marker interfaces
This allows Event Bus to interface with existing classes without modification.
This commit is contained in:
parent
cd2e7ad023
commit
002180ed3b
13
README.md
13
README.md
@ -3,7 +3,7 @@
|
||||
## Introduction
|
||||
|
||||
This library allows passing events between different objects without them having a direct reference to each other.
|
||||
Any class can be made an event by implementing the `IEvent` interface.
|
||||
Any object can serve as an event.
|
||||
|
||||
Using an instance of the `EventBus` class, an instant of the event class can be dispatched.
|
||||
This means that it will be forwarded to all listeners registered for it at the event bus.
|
||||
@ -13,16 +13,13 @@ In addition, a singleton instance of the event bus is provided by the `EventBus#
|
||||
To listen to events, register event handling methods using the `Event` annotation.
|
||||
For this to work, the method must have a return type of `void` and declare a single parameter of the desired event type.
|
||||
Alternatively, a parameter-less event handler can be declared as shown [below](#parameter-less-event-handlers).
|
||||
Additionally, the class containing the method must implement the `EventListener` interface.
|
||||
|
||||
## A Simple Example
|
||||
|
||||
Lets look at a simple example: we declare the empty class `SimpleEvent` that implements `IEvent` and can thus be used as an event.
|
||||
Lets look at a simple example: we declare the empty class `SimpleEvent` whose objects can be used as events.
|
||||
|
||||
```java
|
||||
import dev.kske.eventbus.core.IEvent;
|
||||
|
||||
public class SimpleEvent implements IEvent {}
|
||||
public class SimpleEvent {}
|
||||
```
|
||||
|
||||
Next, an event listener for the `SimpleEvent` is declared:
|
||||
@ -30,7 +27,7 @@ Next, an event listener for the `SimpleEvent` is declared:
|
||||
```java
|
||||
import dev.kske.eventbus.core.*;
|
||||
|
||||
public class SimpleEventListener implements EventListener {
|
||||
public class SimpleEventListener {
|
||||
|
||||
public SimpleEventListener() {
|
||||
|
||||
@ -165,7 +162,7 @@ opens my.module to dev.kske.eventbus.core;
|
||||
To assist you with writing event listeners, the Event Bus AP (Annotation Processor) module enforces correct usage of the `@Event` annotation during compile time.
|
||||
This reduces difficult-to-debug bugs that occur during runtime to compile-time errors which can be easily fixed.
|
||||
|
||||
The event annotation processor detects invalid event handlers, missing `EventListener` implementations, event type issues with more to come in future versions.
|
||||
The event annotation processor detects invalid event handlers and event type issues with more to come in future versions.
|
||||
|
||||
When using Maven, it can be registered using the Maven Compiler Plugin:
|
||||
|
||||
|
@ -34,8 +34,7 @@ public class EventProcessor extends AbstractProcessor {
|
||||
|
||||
private void processRound(Set<ExecutableElement> eventHandlers) {
|
||||
for (ExecutableElement eventHandler : eventHandlers) {
|
||||
TypeElement eventListener = (TypeElement) eventHandler.getEnclosingElement();
|
||||
Event eventAnnotation = eventHandler.getAnnotation(Event.class);
|
||||
Event eventAnnotation = eventHandler.getAnnotation(Event.class);
|
||||
|
||||
// Determine how the event type is defined
|
||||
boolean useParameter;
|
||||
@ -68,11 +67,6 @@ public class EventProcessor extends AbstractProcessor {
|
||||
var paramElement = eventHandler.getParameters().get(0);
|
||||
var paramType = paramElement.asType();
|
||||
|
||||
// Check for valid event type
|
||||
if (useParameter && !processingEnv.getTypeUtils().isAssignable(paramType,
|
||||
getTypeMirror(IEvent.class)))
|
||||
error(paramElement, "Parameter must implement IEvent");
|
||||
|
||||
// Check for handlers for abstract types that aren't polymorphic
|
||||
if (eventHandler.getAnnotation(Polymorphic.class) == null
|
||||
&& paramType.getKind() == TypeKind.DECLARED) {
|
||||
@ -82,11 +76,6 @@ public class EventProcessor extends AbstractProcessor {
|
||||
warning(paramElement,
|
||||
"Parameter should be instantiable or handler should use @Polymorphic");
|
||||
}
|
||||
|
||||
// Check listener for interface implementation
|
||||
if (!eventListener.getInterfaces().contains(getTypeMirror(EventListener.class)))
|
||||
warning(eventHandler.getEnclosingElement(),
|
||||
"Class should implement EventListener interface");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,9 @@ import java.lang.annotation.*;
|
||||
* Indicates that a method is an event handler. To be successfully used as such, the method has to
|
||||
* comply with the following specifications:
|
||||
* <ul>
|
||||
* <li>Declared inside a class that implements {@link EventListener}</li>
|
||||
* <li>Specifying an event type by either
|
||||
* <ul>
|
||||
* <li>Declaring one parameter of a type that implements {@link IEvent}</li>
|
||||
* <li>Declaring one object parameter</li>
|
||||
* <li>Defining the class of the event using the annotation value</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
@ -38,7 +37,7 @@ public @interface Event {
|
||||
* @return the event type accepted by the handler
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Class<? extends IEvent> value() default USE_PARAMETER.class;
|
||||
Class<?> value() default USE_PARAMETER.class;
|
||||
|
||||
/**
|
||||
* Signifies that the event type the handler listens to is determined by the type of its only
|
||||
@ -46,5 +45,5 @@ public @interface Event {
|
||||
*
|
||||
* @since 0.0.3
|
||||
*/
|
||||
static final class USE_PARAMETER implements IEvent {}
|
||||
static final class USE_PARAMETER {}
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ public final class EventBus {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final Map<Class<? extends IEvent>, TreeSet<EventHandler>> bindings =
|
||||
private final Map<Class<?>, TreeSet<EventHandler>> bindings =
|
||||
new ConcurrentHashMap<>();
|
||||
private final Set<EventListener> registeredListeners =
|
||||
private final Set<Object> registeredListeners =
|
||||
ConcurrentHashMap.newKeySet();
|
||||
private final ThreadLocal<DispatchState> dispatchState =
|
||||
private final ThreadLocal<DispatchState> dispatchState =
|
||||
ThreadLocal.withInitial(DispatchState::new);
|
||||
|
||||
/**
|
||||
@ -65,7 +65,7 @@ public final class EventBus {
|
||||
* @param event the event to dispatch
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public void dispatch(IEvent event) {
|
||||
public void dispatch(Object event) {
|
||||
Objects.requireNonNull(event);
|
||||
logger.log(Level.INFO, "Dispatching event {0}", event);
|
||||
|
||||
@ -95,7 +95,7 @@ public final class EventBus {
|
||||
* @return all event handlers registered for the event class
|
||||
* @since 0.0.1
|
||||
*/
|
||||
private List<EventHandler> getHandlersFor(Class<? extends IEvent> eventClass) {
|
||||
private List<EventHandler> getHandlersFor(Class<?> eventClass) {
|
||||
|
||||
// Get handlers defined for the event class
|
||||
Set<EventHandler> handlers = bindings.getOrDefault(eventClass, new TreeSet<>());
|
||||
@ -133,7 +133,7 @@ public final class EventBus {
|
||||
* @since 0.0.1
|
||||
* @see Event
|
||||
*/
|
||||
public void registerListener(EventListener listener) throws EventBusException {
|
||||
public void registerListener(Object listener) throws EventBusException {
|
||||
Objects.requireNonNull(listener);
|
||||
if (registeredListeners.contains(listener))
|
||||
throw new EventBusException(listener + " already registered!");
|
||||
@ -170,7 +170,7 @@ public final class EventBus {
|
||||
* @param listener the listener to remove
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public void removeListener(EventListener listener) {
|
||||
public void removeListener(Object listener) {
|
||||
Objects.requireNonNull(listener);
|
||||
logger.log(Level.INFO, "Removing event listener {0}", listener.getClass().getName());
|
||||
|
||||
@ -204,7 +204,7 @@ public final class EventBus {
|
||||
* @return all registered event listeners
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public Set<EventListener> getRegisteredListeners() {
|
||||
public Set<Object> getRegisteredListeners() {
|
||||
return Collections.unmodifiableSet(registeredListeners);
|
||||
}
|
||||
}
|
||||
|
@ -21,12 +21,12 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
*/
|
||||
public static final int DEFAULT_PRIORITY = 100;
|
||||
|
||||
private final EventListener listener;
|
||||
private final Method method;
|
||||
private final Class<? extends IEvent> eventType;
|
||||
private final boolean useParameter;
|
||||
private final boolean polymorphic;
|
||||
private final int priority;
|
||||
private final Object listener;
|
||||
private final Method method;
|
||||
private final Class<?> eventType;
|
||||
private final boolean useParameter;
|
||||
private final boolean polymorphic;
|
||||
private final int priority;
|
||||
|
||||
/**
|
||||
* Constructs an event handler.
|
||||
@ -38,8 +38,7 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
* specification
|
||||
* @since 0.0.1
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
EventHandler(EventListener listener, Method method, Event annotation) throws EventBusException {
|
||||
EventHandler(Object listener, Method method, Event annotation) throws EventBusException {
|
||||
this.listener = listener;
|
||||
this.method = method;
|
||||
useParameter = annotation.value() == USE_PARAMETER.class;
|
||||
@ -57,17 +56,8 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
if (!method.getReturnType().equals(void.class))
|
||||
throw new EventBusException(method + " does not have a return type of void!");
|
||||
|
||||
// Determine the event type
|
||||
if (useParameter) {
|
||||
var param = method.getParameterTypes()[0];
|
||||
if (!IEvent.class.isAssignableFrom(param))
|
||||
throw new EventBusException(param + " is not of type IEvent!");
|
||||
eventType = (Class<? extends IEvent>) param;
|
||||
} else {
|
||||
eventType = annotation.value();
|
||||
}
|
||||
|
||||
// Determine additional handler properties
|
||||
// Determine handler properties
|
||||
eventType = useParameter ? method.getParameterTypes()[0] : annotation.value();
|
||||
polymorphic = method.isAnnotationPresent(Polymorphic.class);
|
||||
priority = method.isAnnotationPresent(Priority.class)
|
||||
? method.getAnnotation(Priority.class).value()
|
||||
@ -107,7 +97,7 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
* @throws EventBusException if the handler throws an exception
|
||||
* @since 0.0.1
|
||||
*/
|
||||
void execute(IEvent event) throws EventBusException {
|
||||
void execute(Object event) throws EventBusException {
|
||||
try {
|
||||
if (useParameter)
|
||||
method.invoke(listener, event);
|
||||
@ -122,13 +112,13 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
* @return the listener containing this handler
|
||||
* @since 0.0.1
|
||||
*/
|
||||
EventListener getListener() { return listener; }
|
||||
Object getListener() { return listener; }
|
||||
|
||||
/**
|
||||
* @return the event type this handler listens for
|
||||
* @since 0.0.3
|
||||
*/
|
||||
Class<? extends IEvent> getEventType() { return eventType; }
|
||||
Class<?> getEventType() { return eventType; }
|
||||
|
||||
/**
|
||||
* @return the priority of this handler
|
||||
|
@ -1,12 +0,0 @@
|
||||
package dev.kske.eventbus.core;
|
||||
|
||||
/**
|
||||
* Marker interface for event listeners. Event listeners can contain event handling methods to which
|
||||
* events can be dispatched.
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 0.0.1
|
||||
* @see Event
|
||||
* @see EventBus
|
||||
*/
|
||||
public interface EventListener {}
|
@ -1,12 +0,0 @@
|
||||
package dev.kske.eventbus.core;
|
||||
|
||||
/**
|
||||
* Marker interface for event objects. Event objects can be used as event handler parameters and
|
||||
* thus can be dispatched to the event bus.
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 0.0.1
|
||||
* @see Event
|
||||
* @see EventBus
|
||||
*/
|
||||
public interface IEvent {}
|
@ -11,7 +11,7 @@ import org.junit.jupiter.api.*;
|
||||
* @author Leon Hofmeister
|
||||
* @since 0.1.0
|
||||
*/
|
||||
class CancelTest implements EventListener {
|
||||
class CancelTest {
|
||||
|
||||
EventBus bus;
|
||||
int hits;
|
||||
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 0.0.1
|
||||
*/
|
||||
class DispatchTest implements EventListener {
|
||||
class DispatchTest {
|
||||
|
||||
EventBus bus;
|
||||
static int hits;
|
||||
@ -27,7 +27,7 @@ class DispatchTest implements EventListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link EventBus#dispatch(IEvent)} with multiple handler priorities, a subtype handler
|
||||
* Tests {@link EventBus#dispatch(Object)} with multiple handler priorities, a subtype handler
|
||||
* and a static handler.
|
||||
*
|
||||
* @since 0.0.1
|
||||
|
@ -6,4 +6,4 @@ package dev.kske.eventbus.core;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 0.0.1
|
||||
*/
|
||||
public class SimpleEvent implements IEvent {}
|
||||
public class SimpleEvent {}
|
||||
|
Loading…
Reference in New Issue
Block a user