2021-02-09 09:52:26 +01:00
|
|
|
package dev.kske.eventbus.core;
|
2020-09-02 16:15:31 +02:00
|
|
|
|
|
|
|
import java.lang.reflect.*;
|
|
|
|
|
2021-02-09 09:52:26 +01:00
|
|
|
import dev.kske.eventbus.core.Event.USE_PARAMETER;
|
2020-09-08 19:47:21 +02:00
|
|
|
|
2020-09-02 16:15:31 +02:00
|
|
|
/**
|
|
|
|
* Internal representation of an event handling method.
|
|
|
|
*
|
|
|
|
* @author Kai S. K. Engelbart
|
|
|
|
* @since 0.0.1
|
|
|
|
* @see EventBus
|
|
|
|
*/
|
|
|
|
final class EventHandler implements Comparable<EventHandler> {
|
|
|
|
|
2021-02-15 12:06:33 +01:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
|
2021-02-15 10:55:30 +01:00
|
|
|
private final EventListener listener;
|
|
|
|
private final Method method;
|
|
|
|
private final Event annotation;
|
|
|
|
private final Class<? extends IEvent> eventType;
|
|
|
|
private final boolean polymorphic;
|
2021-02-15 12:06:33 +01:00
|
|
|
private final int priority;
|
2020-09-02 16:15:31 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs an event handler.
|
|
|
|
*
|
|
|
|
* @param listener the listener containing the handler
|
|
|
|
* @param method the handler method
|
|
|
|
* @param annotation the event annotation
|
2020-09-08 19:47:21 +02:00
|
|
|
* @throws EventBusException if the method or the annotation do not comply with the
|
|
|
|
* specification
|
2020-09-02 16:15:31 +02:00
|
|
|
* @since 0.0.1
|
|
|
|
*/
|
2020-09-08 19:47:21 +02:00
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
EventHandler(EventListener listener, Method method, Event annotation) throws EventBusException {
|
2021-02-15 10:55:30 +01:00
|
|
|
this.listener = listener;
|
|
|
|
this.method = method;
|
|
|
|
this.annotation = annotation;
|
2020-09-08 19:47:21 +02:00
|
|
|
|
|
|
|
// Check for correct method signature and return type
|
|
|
|
if (method.getParameterCount() == 0 && annotation.eventType().equals(USE_PARAMETER.class))
|
|
|
|
throw new EventBusException(method + " does not define an event type!");
|
|
|
|
|
|
|
|
if (method.getParameterCount() == 1 && !annotation.eventType().equals(USE_PARAMETER.class))
|
|
|
|
throw new EventBusException(method + " defines an ambiguous event type!");
|
|
|
|
|
|
|
|
if (method.getParameterCount() > 1)
|
|
|
|
throw new EventBusException(method + " defines more than one parameter!");
|
|
|
|
|
|
|
|
if (!method.getReturnType().equals(void.class))
|
|
|
|
throw new EventBusException(method + " does not have a return type of void!");
|
|
|
|
|
|
|
|
// Determine the event type
|
|
|
|
Class<? extends IEvent> eventType = annotation.eventType();
|
|
|
|
if (eventType.equals(USE_PARAMETER.class)) {
|
|
|
|
var param = method.getParameterTypes()[0];
|
|
|
|
if (!IEvent.class.isAssignableFrom(param))
|
|
|
|
throw new EventBusException(param + " is not of type IEvent!");
|
|
|
|
eventType = (Class<? extends IEvent>) param;
|
|
|
|
}
|
2021-02-15 10:55:30 +01:00
|
|
|
this.eventType = eventType;
|
|
|
|
polymorphic = method.isAnnotationPresent(Polymorphic.class);
|
2021-02-15 12:06:33 +01:00
|
|
|
priority = method.isAnnotationPresent(Priority.class)
|
|
|
|
? method.getAnnotation(Priority.class).value()
|
|
|
|
: DEFAULT_PRIORITY;
|
2020-09-08 19:47:21 +02:00
|
|
|
|
|
|
|
// Allow access if the method is non-public
|
2020-09-07 10:38:38 +02:00
|
|
|
method.setAccessible(true);
|
2020-09-02 16:15:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-02-15 12:06:33 +01:00
|
|
|
* Compares this to another event handler based on priority. In case of equal priority a
|
|
|
|
* non-zero value based on hash codes is returned.
|
2020-09-03 09:52:00 +02:00
|
|
|
* <p>
|
2021-02-15 10:55:30 +01:00
|
|
|
* This is used to retrieve event handlers in order of descending priority from a tree set.
|
2020-09-02 16:15:31 +02:00
|
|
|
*
|
|
|
|
* @since 0.0.1
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public int compareTo(EventHandler other) {
|
2021-02-15 12:06:33 +01:00
|
|
|
int priority = other.priority - this.priority;
|
2020-09-02 16:15:31 +02:00
|
|
|
if (priority == 0)
|
|
|
|
priority = listener.hashCode() - other.listener.hashCode();
|
|
|
|
return priority == 0 ? hashCode() - other.hashCode() : priority;
|
|
|
|
}
|
|
|
|
|
2020-09-20 15:27:51 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
2021-02-15 12:06:33 +01:00
|
|
|
return String.format("EventHandler[method=%s, eventType=%s, polymorphic=%b, priority=%d]",
|
|
|
|
method, annotation.eventType(), polymorphic, priority);
|
2020-09-20 15:27:51 +02:00
|
|
|
}
|
|
|
|
|
2020-09-02 16:15:31 +02:00
|
|
|
/**
|
|
|
|
* Executes the event handler.
|
|
|
|
*
|
|
|
|
* @param event the event used as the method parameter
|
|
|
|
* @throws EventBusException if the handler throws an exception
|
|
|
|
* @since 0.0.1
|
|
|
|
*/
|
|
|
|
void execute(IEvent event) throws EventBusException {
|
|
|
|
try {
|
2021-02-15 10:55:30 +01:00
|
|
|
if (annotation.eventType() == USE_PARAMETER.class)
|
2020-09-08 19:47:21 +02:00
|
|
|
method.invoke(listener, event);
|
|
|
|
else
|
|
|
|
method.invoke(listener);
|
2021-02-15 10:55:30 +01:00
|
|
|
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
2020-09-02 16:15:31 +02:00
|
|
|
throw new EventBusException("Failed to invoke event handler!", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the listener containing this handler
|
|
|
|
* @since 0.0.1
|
|
|
|
*/
|
|
|
|
EventListener getListener() { return listener; }
|
|
|
|
|
|
|
|
/**
|
2021-02-15 12:06:33 +01:00
|
|
|
* @return the event type this handler listens to
|
|
|
|
* @since 0.0.3
|
2020-09-02 16:15:31 +02:00
|
|
|
*/
|
2021-02-15 12:06:33 +01:00
|
|
|
Class<? extends IEvent> getEventType() { return eventType; }
|
2020-09-02 16:15:31 +02:00
|
|
|
|
|
|
|
/**
|
2021-02-15 12:06:33 +01:00
|
|
|
* @return the priority of this handler
|
2020-09-02 16:15:31 +02:00
|
|
|
* @since 0.0.1
|
2021-02-15 12:06:33 +01:00
|
|
|
* @see Priority
|
2020-09-02 16:15:31 +02:00
|
|
|
*/
|
2021-02-15 12:06:33 +01:00
|
|
|
int getPriority() { return priority; }
|
2020-09-08 19:47:21 +02:00
|
|
|
|
2020-09-20 12:20:29 +02:00
|
|
|
/**
|
2021-02-15 10:55:30 +01:00
|
|
|
* @return whether this handler is polymorphic
|
|
|
|
* @since 1.0.0
|
|
|
|
* @see Polymorphic
|
2020-09-20 12:20:29 +02:00
|
|
|
*/
|
2021-02-15 10:55:30 +01:00
|
|
|
boolean isPolymorphic() { return polymorphic; }
|
2020-09-02 16:15:31 +02:00
|
|
|
}
|