Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
cc5c07079a | |||
8fae4f6d76 | |||
2d276a1d74 | |||
8609c6a90c | |||
ee9d08b2b8 | |||
5468bddb35 | |||
a8d858e8c7 | |||
6ee4e11161 | |||
8615a0e021 | |||
3aef7d5bcb | |||
36ed55fd71 | |||
999a172e72 | |||
722bf2b999 | |||
7fb633d69f | |||
c5607d12ae | |||
a8810c497f | |||
ebb2191f4a | |||
09d251a02a | |||
27d14a844d | |||
adbcc64e94 | |||
84ae42b44f | |||
e53f356c54 | |||
d649f377b7 | |||
897f1a20f3 |
41
Jenkinsfile
vendored
Normal file
41
Jenkinsfile
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
options {
|
||||||
|
ansiColor('xterm')
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh 'mvn -DskipTests clean package'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Test') {
|
||||||
|
steps {
|
||||||
|
sh 'mvn test'
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
junit '*/target/surefire-reports/*.xml'
|
||||||
|
publishCoverage adapters: [jacocoAdapter(mergeToOneReport: true, path: '*/target/site/jacoco/jacoco.xml')]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('SonarQube Analysis') {
|
||||||
|
when {
|
||||||
|
branch 'develop'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
withSonarQubeEnv('KSKE SonarQube') {
|
||||||
|
sh 'mvn sonar:sonar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
success {
|
||||||
|
archiveArtifacts artifacts: '*/target/event-bus-*.jar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
README.md
36
README.md
@ -183,14 +183,37 @@ private void onDeadEvent(DeadEvent deadEvent) { ... }
|
|||||||
### Detecting Exceptions Thrown by Event Handlers
|
### Detecting Exceptions Thrown by Event Handlers
|
||||||
|
|
||||||
When an event handler throws an exception, an exception event is dispatched that wraps the original event.
|
When an event handler throws an exception, an exception event is dispatched that wraps the original event.
|
||||||
A exception handler is declared as follows:
|
An exception handler is declared as follows:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
private void onExceptionEvent(ExceptionEvent ExceptionEvent) { ... }
|
private void onExceptionEvent(ExceptionEvent ExceptionEvent) { ... }
|
||||||
```
|
```
|
||||||
|
|
||||||
Both system events reference the event bus that caused them and a warning is logged if they are unhandled.
|
Both system events reference the event bus that caused them and a warning is logged if they are unhandled.
|
||||||
|
|
||||||
|
#### Yeeting Exceptions Out of an Event Handler
|
||||||
|
|
||||||
|
In some cases, a warning about an `Exception` that was thrown in an event handler is not enough, stays unnoticed, or an exception should be catched explicitly.
|
||||||
|
Event Bus explicitly dispatches no `ExceptionEvent` when an `ExceptionWrapper` exception is thrown and instead simply rethrows it.
|
||||||
|
`ExceptionWrapper` is an unchecked exception that (as the name says) simply wraps an exception that caused it.
|
||||||
|
This means the following is possible and results in a normal program exit:
|
||||||
|
```java
|
||||||
|
@Event(String.class)
|
||||||
|
void onString() {
|
||||||
|
throw new ExceptionWrapper(new RuntimeException("I failed!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void helloStackTrace() {
|
||||||
|
EventBus.getInstance().registerListener(this);
|
||||||
|
try {
|
||||||
|
EventBus.getInstance().dispatch("A string!");
|
||||||
|
System.exit(-1);
|
||||||
|
} catch(ExceptionWrapper e) {
|
||||||
|
e.getCause().printStackTrace();
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### What About Endless Recursion Caused By Dead Events and Exception Events?
|
### What About Endless Recursion Caused By Dead Events and Exception Events?
|
||||||
|
|
||||||
As one might imagine, an unhandled dead event would theoretically lead to an endless recursion.
|
As one might imagine, an unhandled dead event would theoretically lead to an endless recursion.
|
||||||
@ -198,6 +221,15 @@ The same applies when an exception event handler throws an exception.
|
|||||||
|
|
||||||
To avoid this, system events never cause system events and instead just issue a warning to the logger.
|
To avoid this, system events never cause system events and instead just issue a warning to the logger.
|
||||||
|
|
||||||
|
## Inheritance
|
||||||
|
|
||||||
|
When a superclass or an interface of an event listener defines event handlers, they will be detected and registered by Event Bus, even if they are `private`.
|
||||||
|
If an event handler is overridden by the listener, the `@Event` annotation of the overridden method is automatically considered present on the overriding method.
|
||||||
|
If the overridden method already contains an implementation in the superclass, the superclass implementation is ignored as expected.
|
||||||
|
|
||||||
|
The `@Priority` and `@Polymorphic` annotations are inherited both on a class and on a method level.
|
||||||
|
If the priority or polymorphism has to be redefined on an inherited handler, the `@Event` annotation has to be added explicitly.
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
In more complex setups, taking a look at the event handler execution order can be helpful for debugging.
|
In more complex setups, taking a look at the event handler execution order can be helpful for debugging.
|
||||||
|
66
core/pom.xml
Normal file
66
core/pom.xml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>event-bus-core</artifactId>
|
||||||
|
<name>Event Bus Core</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>dev.kske</groupId>
|
||||||
|
<artifactId>event-bus</artifactId>
|
||||||
|
<version>1.2.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>5.8.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<!-- Disable resource folder -->
|
||||||
|
<resources />
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<!-- Run unit tests -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>3.0.0-M5</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>
|
||||||
|
${argLine}
|
||||||
|
--add-opens dev.kske.eventbus.core/dev.kske.eventbus.core=ALL-UNNAMED
|
||||||
|
--add-opens dev.kske.eventbus.core/dev.kske.eventbus.core.handler=ALL-UNNAMED
|
||||||
|
</argLine>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Generate coverage report -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>0.8.7</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>report</id>
|
||||||
|
<phase>test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -30,13 +30,5 @@ public @interface Event {
|
|||||||
* @return the event type accepted by the handler
|
* @return the event type accepted by the handler
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
Class<?> value() default USE_PARAMETER.class;
|
Class<?> value() default void.class;
|
||||||
|
|
||||||
/**
|
|
||||||
* Signifies that the event type the handler listens to is determined by the type of its only
|
|
||||||
* parameter.
|
|
||||||
*
|
|
||||||
* @since 0.0.3
|
|
||||||
*/
|
|
||||||
static final class USE_PARAMETER {}
|
|
||||||
}
|
}
|
@ -2,7 +2,8 @@ package dev.kske.eventbus.core;
|
|||||||
|
|
||||||
import java.lang.System.Logger;
|
import java.lang.System.Logger;
|
||||||
import java.lang.System.Logger.Level;
|
import java.lang.System.Logger.Level;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -14,9 +15,8 @@ import dev.kske.eventbus.core.handler.*;
|
|||||||
* <p>
|
* <p>
|
||||||
* A singleton instance of this class can be lazily created and acquired using the
|
* A singleton instance of this class can be lazily created and acquired using the
|
||||||
* {@link EventBus#getInstance()} method.
|
* {@link EventBus#getInstance()} method.
|
||||||
* <p>
|
|
||||||
* This is a thread-safe implementation.
|
|
||||||
*
|
*
|
||||||
|
* @implNote This is a thread-safe implementation.
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
* @see Event
|
* @see Event
|
||||||
@ -90,6 +90,16 @@ public final class EventBus {
|
|||||||
*/
|
*/
|
||||||
private final Map<Class<?>, TreeSet<EventHandler>> bindings = new ConcurrentHashMap<>();
|
private final Map<Class<?>, TreeSet<EventHandler>> bindings = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cache mapping an event class to all handlers the event should be dispatched to. This
|
||||||
|
* includes polymorphic handlers that don't reference the event class explicitly. If an event
|
||||||
|
* class is not contained inside this cache, the {@link #bindings} have to be traversed manually
|
||||||
|
* in search of applicable handlers.
|
||||||
|
*
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
private final Map<Class<?>, TreeSet<EventHandler>> bindingCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores all registered event listeners (which declare event handlers) and prevents them from
|
* Stores all registered event listeners (which declare event handlers) and prevents them from
|
||||||
* being garbage collected.
|
* being garbage collected.
|
||||||
@ -112,10 +122,11 @@ public final class EventBus {
|
|||||||
*
|
*
|
||||||
* @param event the event to dispatch
|
* @param event the event to dispatch
|
||||||
* @throws EventBusException if an event handler isn't accessible or has an invalid signature
|
* @throws EventBusException if an event handler isn't accessible or has an invalid signature
|
||||||
|
* @throws ExceptionWrapper if it is thrown by an event handler
|
||||||
* @throws NullPointerException if the specified event is {@code null}
|
* @throws NullPointerException if the specified event is {@code null}
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public void dispatch(Object event) throws EventBusException {
|
public void dispatch(Object event) {
|
||||||
Objects.requireNonNull(event);
|
Objects.requireNonNull(event);
|
||||||
logger.log(Level.INFO, "Dispatching event {0}", event);
|
logger.log(Level.INFO, "Dispatching event {0}", event);
|
||||||
|
|
||||||
@ -140,6 +151,10 @@ public final class EventBus {
|
|||||||
|
|
||||||
// Transparently pass error to the caller
|
// Transparently pass error to the caller
|
||||||
throw (Error) e.getCause();
|
throw (Error) e.getCause();
|
||||||
|
else if (e.getCause() instanceof ExceptionWrapper)
|
||||||
|
|
||||||
|
// Transparently pass exception wrapper to the caller
|
||||||
|
throw (ExceptionWrapper) e.getCause();
|
||||||
else if (event instanceof DeadEvent || event instanceof ExceptionEvent)
|
else if (event instanceof DeadEvent || event instanceof ExceptionEvent)
|
||||||
|
|
||||||
// Warn about system event not being handled
|
// Warn about system event not being handled
|
||||||
@ -170,24 +185,29 @@ public final class EventBus {
|
|||||||
* Searches for the event handlers bound to an event class. This includes polymorphic handlers
|
* Searches for the event handlers bound to an event class. This includes polymorphic handlers
|
||||||
* that are bound to a supertype of the event class.
|
* that are bound to a supertype of the event class.
|
||||||
*
|
*
|
||||||
|
* @implNote If the given event type was requested in the past, the handlers are retrieved from
|
||||||
|
* the {@link #bindingCache}. If not, the entire {@link #bindings} are traversed in
|
||||||
|
* search of polymorphic handlers compatible with the event type.
|
||||||
* @param eventType the event type to use for the search
|
* @param eventType the event type to use for the search
|
||||||
* @return a navigable set containing the applicable handlers in descending order of priority
|
* @return a navigable set containing the applicable handlers in descending order of priority
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
private NavigableSet<EventHandler> getHandlersFor(Class<?> eventType) {
|
private NavigableSet<EventHandler> getHandlersFor(Class<?> eventType) {
|
||||||
|
return bindingCache.computeIfAbsent(eventType, k -> {
|
||||||
|
|
||||||
// Get handlers defined for the event class
|
// Get handlers defined for the event class
|
||||||
TreeSet<EventHandler> handlers =
|
TreeSet<EventHandler> handlers =
|
||||||
bindings.getOrDefault(eventType, new TreeSet<>(byPriority));
|
bindings.getOrDefault(eventType, new TreeSet<>(byPriority));
|
||||||
|
|
||||||
// Get polymorphic handlers
|
// Get polymorphic handlers
|
||||||
for (var binding : bindings.entrySet())
|
for (var binding : bindings.entrySet())
|
||||||
if (binding.getKey().isAssignableFrom(eventType))
|
if (binding.getKey().isAssignableFrom(eventType))
|
||||||
for (var handler : binding.getValue())
|
for (var handler : binding.getValue())
|
||||||
if (handler.isPolymorphic())
|
if (handler.isPolymorphic())
|
||||||
handlers.add(handler);
|
handlers.add(handler);
|
||||||
|
|
||||||
return handlers;
|
return handlers;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,7 +234,7 @@ public final class EventBus {
|
|||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
* @see Event
|
* @see Event
|
||||||
*/
|
*/
|
||||||
public void registerListener(Object listener) throws EventBusException {
|
public void registerListener(Object listener) {
|
||||||
Objects.requireNonNull(listener);
|
Objects.requireNonNull(listener);
|
||||||
if (registeredListeners.contains(listener))
|
if (registeredListeners.contains(listener))
|
||||||
throw new EventBusException(listener + " already registered!");
|
throw new EventBusException(listener + " already registered!");
|
||||||
@ -232,7 +252,7 @@ public final class EventBus {
|
|||||||
priority = listener.getClass().getAnnotation(Priority.class).value();
|
priority = listener.getClass().getAnnotation(Priority.class).value();
|
||||||
|
|
||||||
registeredListeners.add(listener);
|
registeredListeners.add(listener);
|
||||||
for (var method : listener.getClass().getDeclaredMethods()) {
|
for (var method : getHandlerMethods(listener.getClass())) {
|
||||||
Event annotation = method.getAnnotation(Event.class);
|
Event annotation = method.getAnnotation(Event.class);
|
||||||
|
|
||||||
// Skip methods without annotations
|
// Skip methods without annotations
|
||||||
@ -252,6 +272,49 @@ public final class EventBus {
|
|||||||
listener.getClass().getName());
|
listener.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for event handling methods declared inside the inheritance hierarchy of an event
|
||||||
|
* listener.
|
||||||
|
*
|
||||||
|
* @param listenerClass the class to inspect
|
||||||
|
* @return all event handling methods defined for the given listener
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
private Set<Method> getHandlerMethods(Class<?> listenerClass) {
|
||||||
|
|
||||||
|
// Get methods declared by the listener
|
||||||
|
Set<Method> methods = getMethodsAnnotatedWith(listenerClass, Event.class);
|
||||||
|
|
||||||
|
// Recursively add superclass handlers
|
||||||
|
Class<?> superClass = listenerClass.getSuperclass();
|
||||||
|
if (superClass != null && superClass != Object.class)
|
||||||
|
methods.addAll(getHandlerMethods(superClass));
|
||||||
|
|
||||||
|
// Recursively add interface handlers
|
||||||
|
for (Class<?> iClass : listenerClass.getInterfaces())
|
||||||
|
methods.addAll(getHandlerMethods(iClass));
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for declared methods with a specific annotation inside a class.
|
||||||
|
*
|
||||||
|
* @param enclosingClass the class to inspect
|
||||||
|
* @param annotationClass the annotation to look for
|
||||||
|
* @return all methods matching the search criteria
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
private Set<Method> getMethodsAnnotatedWith(Class<?> enclosingClass,
|
||||||
|
Class<? extends Annotation> annotationClass) {
|
||||||
|
var methods = new HashSet<Method>();
|
||||||
|
for (var method : enclosingClass.getDeclaredMethods())
|
||||||
|
if (method.isAnnotationPresent(annotationClass))
|
||||||
|
methods.add(method);
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a callback listener, which is a consumer that is invoked when an event occurs. The
|
* Registers a callback listener, which is a consumer that is invoked when an event occurs. The
|
||||||
* listener is not polymorphic and has the {@link #DEFAULT_PRIORITY}.
|
* listener is not polymorphic and has the {@link #DEFAULT_PRIORITY}.
|
||||||
@ -321,15 +384,28 @@ public final class EventBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a new handler into the {@link #bindings} map.
|
* Inserts a new handler into the {@link #bindings} map. Additionally, the handler is placed
|
||||||
|
* inside the {@link #bindingCache} where applicable.
|
||||||
*
|
*
|
||||||
* @param handler the handler to bind
|
* @param handler the handler to bind
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
private void bindHandler(EventHandler handler) {
|
private void bindHandler(EventHandler handler) {
|
||||||
bindings.putIfAbsent(handler.getEventType(), new TreeSet<>(byPriority));
|
|
||||||
|
// Bind handler
|
||||||
logger.log(Level.DEBUG, "Binding event handler {0}", handler);
|
logger.log(Level.DEBUG, "Binding event handler {0}", handler);
|
||||||
bindings.get(handler.getEventType()).add(handler);
|
bindings.computeIfAbsent(handler.getEventType(), k -> new TreeSet<>(byPriority))
|
||||||
|
.add(handler);
|
||||||
|
|
||||||
|
// Insert handler into cache
|
||||||
|
bindingCache.computeIfAbsent(handler.getEventType(), k -> new TreeSet<>(byPriority))
|
||||||
|
.add(handler);
|
||||||
|
|
||||||
|
// Handler is polymorphic => insert where applicable
|
||||||
|
if (handler.isPolymorphic())
|
||||||
|
for (var binding : bindingCache.entrySet())
|
||||||
|
if (binding.getKey().isAssignableFrom(handler.getEventType()))
|
||||||
|
binding.getValue().add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -347,13 +423,25 @@ public final class EventBus {
|
|||||||
var it = binding.iterator();
|
var it = binding.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
var handler = it.next();
|
var handler = it.next();
|
||||||
if (handler.getListener() == listener) {
|
if (handler.getListener().equals(listener)) {
|
||||||
logger.log(Level.DEBUG, "Unbinding event handler {0}", handler);
|
logger.log(Level.DEBUG, "Unbinding event handler {0}", handler);
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove bindings from cache
|
||||||
|
for (var binding : bindingCache.values()) {
|
||||||
|
var it = binding.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
var handler = it.next();
|
||||||
|
if (handler.getListener().equals(listener)) {
|
||||||
|
logger.log(Level.TRACE, "Removing event handler {0} from cache", handler);
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the listener itself
|
// Remove the listener itself
|
||||||
registeredListeners.remove(listener);
|
registeredListeners.remove(listener);
|
||||||
}
|
}
|
||||||
@ -366,6 +454,7 @@ public final class EventBus {
|
|||||||
public void clearListeners() {
|
public void clearListeners() {
|
||||||
logger.log(Level.INFO, "Clearing event listeners");
|
logger.log(Level.INFO, "Clearing event listeners");
|
||||||
bindings.clear();
|
bindings.clear();
|
||||||
|
bindingCache.clear();
|
||||||
registeredListeners.clear();
|
registeredListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -14,13 +14,14 @@ package dev.kske.eventbus.core;
|
|||||||
*/
|
*/
|
||||||
public final class EventBusException extends RuntimeException {
|
public final class EventBusException extends RuntimeException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 7254445250300604449L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new event bus exception.
|
* Creates a new event bus exception.
|
||||||
*
|
*
|
||||||
* @param message the message to display
|
* @param message the message to display
|
||||||
* @param cause the cause of this exception
|
* @param cause the cause of this exception
|
||||||
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public EventBusException(String message, Throwable cause) {
|
public EventBusException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
@ -30,6 +31,7 @@ public final class EventBusException extends RuntimeException {
|
|||||||
* Creates a new event bus exception.
|
* Creates a new event bus exception.
|
||||||
*
|
*
|
||||||
* @param message the message to display
|
* @param message the message to display
|
||||||
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
public EventBusException(String message) {
|
public EventBusException(String message) {
|
||||||
super(message);
|
super(message);
|
@ -0,0 +1,24 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This unchecked exception acts as a wrapper for an arbitrary exception to prevent an
|
||||||
|
* {@link ExceptionEvent} from being dispatched. Instead, the wrapped exception is rethrown by
|
||||||
|
* {@link EventBus#dispatch(Object)}.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
public final class ExceptionWrapper extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -2016681140617308788L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new exception wrapper.
|
||||||
|
*
|
||||||
|
* @param cause the exception to wrap
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
public ExceptionWrapper(Exception cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ import java.lang.annotation.*;
|
|||||||
* @see Event
|
* @see Event
|
||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
|
@Inherited
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@Target({ METHOD, TYPE })
|
@Target({ METHOD, TYPE })
|
||||||
public @interface Polymorphic {
|
public @interface Polymorphic {
|
@ -21,6 +21,7 @@ import java.lang.annotation.*;
|
|||||||
* @see Event
|
* @see Event
|
||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
|
@Inherited
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@Target({ METHOD, TYPE })
|
@Target({ METHOD, TYPE })
|
||||||
public @interface Priority {
|
public @interface Priority {
|
@ -3,7 +3,6 @@ package dev.kske.eventbus.core.handler;
|
|||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
import dev.kske.eventbus.core.*;
|
import dev.kske.eventbus.core.*;
|
||||||
import dev.kske.eventbus.core.Event.USE_PARAMETER;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event handler wrapping a method annotated with {@link Event} and executing it using
|
* An event handler wrapping a method annotated with {@link Event} and executing it using
|
||||||
@ -37,7 +36,7 @@ public final class ReflectiveEventHandler implements EventHandler {
|
|||||||
boolean defPolymorphism, int defPriority) throws EventBusException {
|
boolean defPolymorphism, int defPriority) throws EventBusException {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
useParameter = annotation.value() == USE_PARAMETER.class;
|
useParameter = annotation.value() == void.class;
|
||||||
|
|
||||||
// Check handler signature
|
// Check handler signature
|
||||||
if (method.getParameterCount() == 0 && useParameter)
|
if (method.getParameterCount() == 0 && useParameter)
|
||||||
@ -58,8 +57,9 @@ public final class ReflectiveEventHandler implements EventHandler {
|
|||||||
? method.getAnnotation(Priority.class).value()
|
? method.getAnnotation(Priority.class).value()
|
||||||
: defPriority;
|
: defPriority;
|
||||||
|
|
||||||
// Allow access if the method is non-public
|
// Try to allow access if the method is not accessible
|
||||||
method.setAccessible(true);
|
if (!method.canAccess(Modifier.isStatic(method.getModifiers()) ? null : listener))
|
||||||
|
method.setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -11,7 +11,7 @@ import org.junit.jupiter.api.*;
|
|||||||
* @author Leon Hofmeister
|
* @author Leon Hofmeister
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
public class CancelTest {
|
class CancelTest {
|
||||||
|
|
||||||
EventBus bus;
|
EventBus bus;
|
||||||
int hits;
|
int hits;
|
||||||
@ -22,7 +22,7 @@ public class CancelTest {
|
|||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void registerListener() {
|
void registerListener() {
|
||||||
bus = new EventBus();
|
bus = new EventBus();
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ public class CancelTest {
|
|||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCancellation() {
|
void testCancellation() {
|
||||||
bus.dispatch(new SimpleEvent());
|
bus.dispatch(new SimpleEvent());
|
||||||
assertEquals(1, hits);
|
assertEquals(1, hits);
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class DeadTest {
|
class DeadTest {
|
||||||
|
|
||||||
EventBus bus = new EventBus();
|
EventBus bus = new EventBus();
|
||||||
String event = "This event has no handler";
|
String event = "This event has no handler";
|
||||||
@ -22,7 +22,7 @@ public class DeadTest {
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeadEvent() {
|
void testDeadEvent() {
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
bus.dispatch(event);
|
bus.dispatch(event);
|
||||||
assertTrue(deadEventHandled);
|
assertTrue(deadEventHandled);
|
||||||
@ -36,7 +36,7 @@ public class DeadTest {
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUnhandledDeadEvent() {
|
void testUnhandledDeadEvent() {
|
||||||
bus.dispatch(event);
|
bus.dispatch(event);
|
||||||
}
|
}
|
||||||
|
|
@ -12,10 +12,9 @@ import org.junit.jupiter.api.*;
|
|||||||
*/
|
*/
|
||||||
@Polymorphic
|
@Polymorphic
|
||||||
@Priority(150)
|
@Priority(150)
|
||||||
public class DispatchTest {
|
class DispatchTest {
|
||||||
|
|
||||||
EventBus bus;
|
EventBus bus;
|
||||||
static int hits;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an event bus and registers this test instance as an event listener.
|
* Constructs an event bus and registers this test instance as an event listener.
|
||||||
@ -23,12 +22,12 @@ public class DispatchTest {
|
|||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void registerListener() {
|
void registerListener() {
|
||||||
bus = new EventBus();
|
bus = new EventBus();
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
bus.registerListener(SimpleEvent.class, e -> {
|
bus.registerListener(SimpleEvent.class, e -> {
|
||||||
++hits;
|
e.increment();
|
||||||
assertEquals(4, hits);
|
assertEquals(3, e.getCounter());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ public class DispatchTest {
|
|||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDispatch() {
|
void testDispatch() {
|
||||||
bus.dispatch(new SimpleEventSub());
|
bus.dispatch(new SimpleEventSub());
|
||||||
bus.dispatch(new SimpleEvent());
|
bus.dispatch(new SimpleEvent());
|
||||||
}
|
}
|
||||||
@ -50,30 +49,40 @@ public class DispatchTest {
|
|||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDebugExecutionOrder() {
|
void testDebugExecutionOrder() {
|
||||||
String executionOrder = bus.debugExecutionOrder(SimpleEvent.class);
|
|
||||||
System.out.println(executionOrder);
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Event handler execution order for class dev.kske.eventbus.core.SimpleEvent (3 handler(s)):\n"
|
"Event handler execution order for class dev.kske.eventbus.core.SimpleEvent (3 handler(s)):\n"
|
||||||
+ "==========================================================================================\n"
|
+ "==========================================================================================\n"
|
||||||
+ "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=true, priority=200, method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(), useParameter=false]\n"
|
+ "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=true, priority=200, method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(dev.kske.eventbus.core.SimpleEvent), useParameter=true]\n"
|
||||||
+ "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=150, method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(), useParameter=false]\n"
|
+ "ReflectiveEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=150, method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(dev.kske.eventbus.core.SimpleEvent), useParameter=true]\n"
|
||||||
+ "CallbackEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=100]\n"
|
+ "CallbackEventHandler[eventType=class dev.kske.eventbus.core.SimpleEvent, polymorphic=false, priority=100]\n"
|
||||||
+ "==========================================================================================",
|
+ "==========================================================================================",
|
||||||
executionOrder);
|
bus.debugExecutionOrder(SimpleEvent.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event(SimpleEvent.class)
|
/**
|
||||||
|
* Tests whether the handlers bound to an event type are correct when retrieved from the binding
|
||||||
|
* cache. On the second call of {@link EventBus#debugExecutionOrder(Class)} the cache is used.
|
||||||
|
*
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testBindingCache() {
|
||||||
|
assertEquals(bus.debugExecutionOrder(SimpleEventSub.class),
|
||||||
|
bus.debugExecutionOrder(SimpleEventSub.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Event
|
||||||
@Priority(200)
|
@Priority(200)
|
||||||
void onSimpleEventFirst() {
|
void onSimpleEventFirst(SimpleEvent event) {
|
||||||
++hits;
|
event.increment();
|
||||||
assertTrue(hits == 1 || hits == 2);
|
assertTrue(event.getCounter() == 1 || event.getCounter() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event(SimpleEvent.class)
|
@Event
|
||||||
@Polymorphic(false)
|
@Polymorphic(false)
|
||||||
static void onSimpleEventSecond() {
|
static void onSimpleEventSecond(SimpleEvent event) {
|
||||||
++hits;
|
event.increment();
|
||||||
assertEquals(3, hits);
|
assertEquals(2, event.getCounter());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class ExceptionTest {
|
class ExceptionTest {
|
||||||
|
|
||||||
EventBus bus = new EventBus();
|
EventBus bus = new EventBus();
|
||||||
String event = "This event will cause an exception";
|
String event = "This event will cause an exception";
|
||||||
@ -23,7 +23,7 @@ public class ExceptionTest {
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testExceptionEvent() {
|
void testExceptionEvent() {
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
bus.registerListener(new ExceptionListener());
|
bus.registerListener(new ExceptionListener());
|
||||||
bus.dispatch(event);
|
bus.dispatch(event);
|
||||||
@ -38,7 +38,7 @@ public class ExceptionTest {
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testUnhandledExceptionEvent() {
|
void testUnhandledExceptionEvent() {
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
bus.dispatch(event);
|
bus.dispatch(event);
|
||||||
bus.removeListener(this);
|
bus.removeListener(this);
|
@ -0,0 +1,33 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the behavior of the event bus when an {@link ExceptionWrapper} is thrown.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
class ExceptionWrapperTest {
|
||||||
|
|
||||||
|
EventBus bus = new EventBus();
|
||||||
|
String event = "This event will cause an exception";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests transparent rethrowing of an exception wrapper by {@link EventBus#dispatch(Object)}.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testExceptionWrapper() {
|
||||||
|
bus.registerListener(this);
|
||||||
|
assertThrows(ExceptionWrapper.class, () -> bus.dispatch(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Event(String.class)
|
||||||
|
void onString() {
|
||||||
|
throw new ExceptionWrapper(new RuntimeException("I failed!"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether event handlers correctly work in the context of an inheritance hierarchy. The
|
||||||
|
* effect of handler priorities is also accounted for.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
class InheritanceTest extends SimpleEventListenerBase implements SimpleEventListenerInterface {
|
||||||
|
|
||||||
|
EventBus bus = new EventBus();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test() {
|
||||||
|
bus.registerListener(this);
|
||||||
|
var event = new SimpleEvent();
|
||||||
|
|
||||||
|
bus.dispatch(event);
|
||||||
|
assertSame(3, event.getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onSimpleEventAbstractHandler(SimpleEvent event) {
|
||||||
|
assertSame(1, event.getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSimpleEventInterfaceHandler(SimpleEvent event) {
|
||||||
|
event.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Event
|
||||||
|
@Priority(250)
|
||||||
|
private void onSimpleEventPrivate(SimpleEvent event) {
|
||||||
|
assertSame(0, event.getCounter());
|
||||||
|
event.increment();
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ import org.junit.jupiter.api.*;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class NestedTest {
|
class NestedTest {
|
||||||
|
|
||||||
EventBus bus;
|
EventBus bus;
|
||||||
boolean nestedHit;
|
boolean nestedHit;
|
||||||
@ -21,7 +21,7 @@ public class NestedTest {
|
|||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void registerListener() {
|
void registerListener() {
|
||||||
bus = new EventBus();
|
bus = new EventBus();
|
||||||
bus.registerListener(this);
|
bus.registerListener(this);
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ public class NestedTest {
|
|||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testNestedDispatch() {
|
void testNestedDispatch() {
|
||||||
bus.dispatch(new SimpleEvent());
|
bus.dispatch(new SimpleEvent());
|
||||||
assertTrue(nestedHit);
|
assertTrue(nestedHit);
|
||||||
}
|
}
|
31
core/src/test/java/dev/kske/eventbus/core/SimpleEvent.java
Normal file
31
core/src/test/java/dev/kske/eventbus/core/SimpleEvent.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple event for testing purposes. The event contains a counter that is supposed to be
|
||||||
|
* incremented when the event is processed by a handler. That way it is possible to test whether all
|
||||||
|
* handlers that were supposed to be invoked were in fact invoked.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
class SimpleEvent {
|
||||||
|
|
||||||
|
private int counter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s[%d]", getClass().getSimpleName(), counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment() {
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCounter() {
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class defining a package-private and a private handler for {@link SimpleEvent}.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
@Priority(200)
|
||||||
|
abstract class SimpleEventListenerBase {
|
||||||
|
|
||||||
|
@Event
|
||||||
|
void onSimpleEventAbstractHandler(SimpleEvent event) {
|
||||||
|
fail("This handler should not be invoked");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Event
|
||||||
|
@Priority(150)
|
||||||
|
private void onSimpleEventPrivate(SimpleEvent event) {
|
||||||
|
assertSame(1, event.getCounter());
|
||||||
|
event.increment();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package dev.kske.eventbus.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface defining a single handler for {@link SimpleEvent}.
|
||||||
|
*
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
interface SimpleEventListenerInterface {
|
||||||
|
|
||||||
|
@Priority(120)
|
||||||
|
@Event
|
||||||
|
void onSimpleEventInterfaceHandler(SimpleEvent event);
|
||||||
|
}
|
@ -6,4 +6,4 @@ package dev.kske.eventbus.core;
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 0.0.4
|
* @since 0.0.4
|
||||||
*/
|
*/
|
||||||
public class SimpleEventSub extends SimpleEvent {}
|
class SimpleEventSub extends SimpleEvent {}
|
@ -1,39 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>event-bus-core</artifactId>
|
|
||||||
<name>Event Bus Core</name>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>dev.kske</groupId>
|
|
||||||
<artifactId>event-bus</artifactId>
|
|
||||||
<version>1.2.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
|
||||||
<version>5.8.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
|
|
||||||
<!-- Disable resource folder -->
|
|
||||||
<resources />
|
|
||||||
|
|
||||||
<!-- Run unit tests -->
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>3.0.0-M5</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
|
|
||||||
</build>
|
|
||||||
</project>
|
|
@ -1,9 +0,0 @@
|
|||||||
package dev.kske.eventbus.core;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple event for testing purposes.
|
|
||||||
*
|
|
||||||
* @author Kai S. K. Engelbart
|
|
||||||
* @since 0.0.1
|
|
||||||
*/
|
|
||||||
public class SimpleEvent {}
|
|
4
pom.xml
4
pom.xml
@ -13,8 +13,8 @@
|
|||||||
<url>https://git.kske.dev/kske/event-bus</url>
|
<url>https://git.kske.dev/kske/event-bus</url>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>event-bus-core</module>
|
<module>core</module>
|
||||||
<module>event-bus-proc</module>
|
<module>proc</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
|
@ -16,17 +16,17 @@
|
|||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/test-classes" path="home/kske/git/event-bus/event-bus-ap">
|
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
<attribute name="test" value="true"/>
|
<attribute name="test" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
@ -24,9 +24,6 @@
|
|||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
<!-- Disable test folder -->
|
|
||||||
<testSourceDirectory />
|
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
||||||
<!-- Prevent annotation processing error during compilation -->
|
<!-- Prevent annotation processing error during compilation -->
|
@ -47,13 +47,12 @@ public class EventProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
// Task failed successfully
|
// Task failed successfully
|
||||||
eventType = e.getTypeMirror();
|
eventType = e.getTypeMirror();
|
||||||
useParameter = processingEnv.getTypeUtils().isSameType(eventType,
|
useParameter = eventType.getKind() == TypeKind.VOID;
|
||||||
getTypeMirror(Event.USE_PARAMETER.class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check handler signature
|
// Check handler signature
|
||||||
boolean pass = false;
|
boolean pass = false;
|
||||||
if (useParameter && eventHandler.getParameters().size() == 0)
|
if (useParameter && eventHandler.getParameters().isEmpty())
|
||||||
error(eventHandler, "The method or the annotation must define the event type");
|
error(eventHandler, "The method or the annotation must define the event type");
|
||||||
else if (!useParameter && eventHandler.getParameters().size() == 1)
|
else if (!useParameter && eventHandler.getParameters().size() == 1)
|
||||||
error(eventHandler,
|
error(eventHandler,
|
||||||
@ -100,14 +99,15 @@ public class EventProcessor extends AbstractProcessor {
|
|||||||
boolean hasListenerPriority = listenerPriority != null;
|
boolean hasListenerPriority = listenerPriority != null;
|
||||||
|
|
||||||
// Effective polymorphism
|
// Effective polymorphism
|
||||||
boolean polymorphic =
|
boolean polymorphic =
|
||||||
hasListenerPolymorphic ? listenerPolymorphic.value() : defPolymorphic;
|
hasListenerPolymorphic ? listenerPolymorphic.value() : defPolymorphic;
|
||||||
boolean hasHandlerPolymorphic = eventHandler.getAnnotation(Polymorphic.class) != null;
|
boolean hasHandlerPolymorphic = eventHandler.getAnnotation(Polymorphic.class) != null;
|
||||||
if (hasHandlerPolymorphic)
|
if (hasHandlerPolymorphic)
|
||||||
polymorphic = eventHandler.getAnnotation(Polymorphic.class).value();
|
polymorphic = eventHandler.getAnnotation(Polymorphic.class).value();
|
||||||
|
|
||||||
// Effective priority
|
// Effective priority
|
||||||
int priority = hasListenerPriority ? listenerPriority.value() : defPriority;
|
int priority =
|
||||||
|
hasListenerPriority ? listenerPriority.value() : defPriority;
|
||||||
boolean hasHandlerPriority = eventHandler.getAnnotation(Priority.class) != null;
|
boolean hasHandlerPriority = eventHandler.getAnnotation(Priority.class) != null;
|
||||||
if (hasHandlerPriority)
|
if (hasHandlerPriority)
|
||||||
priority = eventHandler.getAnnotation(Priority.class).value();
|
priority = eventHandler.getAnnotation(Priority.class).value();
|
||||||
@ -137,14 +137,6 @@ public class EventProcessor extends AbstractProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeMirror getTypeMirror(Class<?> clazz) {
|
|
||||||
return getTypeElement(clazz).asType();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TypeElement getTypeElement(Class<?> clazz) {
|
|
||||||
return processingEnv.getElementUtils().getTypeElement(clazz.getCanonicalName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void warning(Element e, String msg, Object... args) {
|
private void warning(Element e, String msg, Object... args) {
|
||||||
processingEnv.getMessager().printMessage(Kind.WARNING, String.format(msg, args), e);
|
processingEnv.getMessager().printMessage(Kind.WARNING, String.format(msg, args), e);
|
||||||
}
|
}
|
@ -5,7 +5,7 @@
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
module dev.kske.eventbus.ap {
|
module dev.kske.eventbus.proc {
|
||||||
|
|
||||||
requires java.compiler;
|
requires java.compiler;
|
||||||
requires dev.kske.eventbus.core;
|
requires dev.kske.eventbus.core;
|
Loading…
Reference in New Issue
Block a user