Split @Event Parameters Into @Polymorphic and @Property, Remove Marker Interfaces #5
22
README.md
22
README.md
@ -73,20 +73,18 @@ private void onSimpleEvent(SimpleEvent event) { ... }
|
||||
|
||||
## Event Handler Execution Order
|
||||
|
||||
Sometimes when using multiple handlers for one event, it might be useful to know in which order they will be executed.
|
||||
Event Bus provides a mechanism to ensure the correct propagation of events: the `priority`.
|
||||
Sometimes when using multiple handlers for one event, it might be useful to define in which order they will be executed.
|
||||
Event Bus assigns a priority to every handler, which is `100` by default, but can be explicitly set using the `@Priority` annotation in addition to `@Event`:
|
||||
|
||||
Priority can be set on the `@Event` annotation like that:
|
||||
```java
|
||||
@Event(priority=100)
|
||||
@Event
|
||||
@Priority(250)
|
||||
private void onSimpleEvent(SimpleEvent event) { ... }
|
||||
```
|
||||
|
||||
The default priority for events is `100`.
|
||||
|
||||
**Important:**
|
||||
Events are dispatched top-down, meaning the event handler with the highest priority will be executed first.
|
||||
|
||||
If no priority is set or multiple handlers have the same priority, the order of execution is undefined.
|
||||
Events are dispatched to handlers in descending order of their priority.
|
||||
The execution order is undefined for handlers with the same priority.
|
||||
|
||||
## Parameter-Less Event Handlers
|
||||
|
||||
@ -108,12 +106,14 @@ In some cases it might be useful to stop the propagation of an event.
|
||||
Event Bus makes this possible with event consumption:
|
||||
|
||||
```java
|
||||
@Event(eventType = SimpleEvent.class, priority=100)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(100)
|
||||
private void onSimpleEvent() {
|
||||
EventBus.getInstance().cancel();
|
||||
}
|
||||
|
||||
@Event(eventType = SimpleEvent.class, priority=50)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(50)
|
||||
private void onSimpleEvent2() {
|
||||
System.out.println("Will not be printed!");
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class EventProcessor extends AbstractProcessor {
|
||||
if (declaredElement.getKind() == ElementKind.INTERFACE
|
||||
|| declaredElement.getModifiers().contains(Modifier.ABSTRACT))
|
||||
warning(paramElement,
|
||||
"Parameter should be instantiable or handler should include subtypes");
|
||||
"Parameter should be instantiable or handler should use @Polymorphic");
|
||||
}
|
||||
|
||||
// Check listener for interface implementation
|
||||
|
@ -22,23 +22,13 @@ import java.lang.annotation.*;
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 0.0.1
|
||||
* @see Polymorphic
|
||||
* @see Priority
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface Event {
|
||||
|
||||
/**
|
||||
* Defines the priority of the event handler. Handlers are executed in descending order of their
|
||||
* priority.
|
||||
* <p>
|
||||
* The execution order of handlers with the same priority is undefined.
|
||||
*
|
||||
* @return the priority of the event handler
|
||||
* @since 0.0.1
|
||||
*/
|
||||
int priority() default 100;
|
||||
|
||||
/**
|
||||
* Defines the event type the handler listens to. If this value is set, the handler is not
|
||||
* allowed to declare parameters.
|
||||
|
@ -13,11 +13,20 @@ import dev.kske.eventbus.core.Event.USE_PARAMETER;
|
||||
*/
|
||||
final class EventHandler implements Comparable<EventHandler> {
|
||||
|
||||
/**
|
||||
* The priority assigned to every event handler without an explicitly defined priority.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @see Priority
|
||||
*/
|
||||
public static final int DEFAULT_PRIORITY = 100;
|
||||
|
||||
private final EventListener listener;
|
||||
private final Method method;
|
||||
private final Event annotation;
|
||||
private final Class<? extends IEvent> eventType;
|
||||
private final boolean polymorphic;
|
||||
private final int priority;
|
||||
|
||||
/**
|
||||
* Constructs an event handler.
|
||||
@ -58,14 +67,17 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
}
|
||||
this.eventType = eventType;
|
||||
polymorphic = method.isAnnotationPresent(Polymorphic.class);
|
||||
priority = method.isAnnotationPresent(Priority.class)
|
||||
? method.getAnnotation(Priority.class).value()
|
||||
: DEFAULT_PRIORITY;
|
||||
|
||||
// Allow access if the method is non-public
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this to another event handler based on {@link Event#priority()}. In case of equal
|
||||
* priority a non-zero value based on hash codes is returned.
|
||||
* Compares this to another event handler based on priority. In case of equal priority a
|
||||
* non-zero value based on hash codes is returned.
|
||||
kske marked this conversation as resolved
|
||||
* <p>
|
||||
* This is used to retrieve event handlers in order of descending priority from a tree set.
|
||||
*
|
||||
@ -73,7 +85,7 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(EventHandler other) {
|
||||
int priority = other.annotation.priority() - annotation.priority();
|
||||
int priority = other.priority - this.priority;
|
||||
if (priority == 0)
|
||||
priority = listener.hashCode() - other.listener.hashCode();
|
||||
return priority == 0 ? hashCode() - other.hashCode() : priority;
|
||||
@ -81,7 +93,8 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("EventHandler[method=%s, annotation=%s]", method, annotation);
|
||||
return String.format("EventHandler[method=%s, eventType=%s, polymorphic=%b, priority=%d]",
|
||||
method, annotation.eventType(), polymorphic, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
kske marked this conversation as resolved
Outdated
delvh
commented
Why is that now an object instead of an event? Why is that now an object instead of an event?
kske
commented
Because I got rid of the Because I got rid of the `IEvent` interface so that every object can be used as an event.
|
||||
@ -109,16 +122,17 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
EventListener getListener() { return listener; }
|
||||
|
||||
/**
|
||||
* @return the event annotation
|
||||
* @since 0.0.1
|
||||
* @return the event type this handler listens to
|
||||
* @since 0.0.3
|
||||
*/
|
||||
Event getAnnotation() { return annotation; }
|
||||
Class<? extends IEvent> getEventType() { return eventType; }
|
||||
|
||||
/**
|
||||
* @return the priority of the event annotation
|
||||
* @return the priority of this handler
|
||||
* @since 0.0.1
|
||||
* @see Priority
|
||||
*/
|
||||
int getPriority() { return annotation.priority(); }
|
||||
int getPriority() { return priority; }
|
||||
|
||||
/**
|
||||
* @return whether this handler is polymorphic
|
||||
@ -126,10 +140,4 @@ final class EventHandler implements Comparable<EventHandler> {
|
||||
* @see Polymorphic
|
||||
*/
|
||||
boolean isPolymorphic() { return polymorphic; }
|
||||
|
||||
/**
|
||||
* @return the event type this handler listens to
|
||||
* @since 0.0.3
|
||||
*/
|
||||
Class<? extends IEvent> getEventType() { return eventType; }
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package dev.kske.eventbus.core;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Defines the priority of an event handler. Handlers are executed in descending order of their
|
||||
* priority.
|
||||
* <p>
|
||||
* Handlers without this annotation have the default priority of 100.
|
||||
* <p>
|
||||
* The execution order of handlers with the same priority is undefined.
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since 1.0.0
|
||||
* @see Event
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(METHOD)
|
||||
public @interface Priority {
|
||||
|
||||
/**
|
||||
* @return the priority of the event handler
|
||||
* @since 1.0.0
|
||||
*/
|
||||
int value();
|
||||
}
|
@ -39,13 +39,15 @@ class CancelTest implements EventListener {
|
||||
assertEquals(1, hits);
|
||||
}
|
||||
|
||||
@Event(eventType = SimpleEvent.class, priority = 100)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(100)
|
||||
void onSimpleFirst() {
|
||||
++hits;
|
||||
bus.cancel();
|
||||
}
|
||||
|
||||
@Event(eventType = SimpleEvent.class, priority = 50)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(50)
|
||||
void onSimpleSecond() {
|
||||
++hits;
|
||||
}
|
||||
|
@ -38,20 +38,22 @@ class DispatchTest implements EventListener {
|
||||
bus.dispatch(new SimpleEvent());
|
||||
}
|
||||
|
||||
@Event(eventType = SimpleEvent.class, priority = 200)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(200)
|
||||
@Polymorphic
|
||||
void onSimpleEventFirst() {
|
||||
++hits;
|
||||
assertTrue(hits == 1 || hits == 2);
|
||||
}
|
||||
|
||||
@Event(eventType = SimpleEvent.class, priority = 150)
|
||||
@Event(eventType = SimpleEvent.class)
|
||||
@Priority(150)
|
||||
static void onSimpleEventSecond() {
|
||||
++hits;
|
||||
assertEquals(3, hits);
|
||||
}
|
||||
|
||||
@Event(priority = 100)
|
||||
@Event
|
||||
void onSimpleEventThird(SimpleEvent event) {
|
||||
++hits;
|
||||
assertEquals(4, hits);
|
||||
|
Loading…
Reference in New Issue
Block a user
What about using
Integer.compare(this.priority, other.priority)
?Or is that too much overhead? 😉
Actually, yes I think so.
Integer.compare
callsInteger.valueOf
two times, generating two objects in the process just to execute a statement similar to the one I wrote.But, to your credit, I didn't even consider the possibility, to thanks for the suggestion :)