Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapped event #5

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/de/cyklon/jevent/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ public String getEventName() {

@Override
public String toString() {
return Event.class + "(" + getEventName() + ")";
return Event.class.getName() + "(" + getEventName() + ")";
}
}
46 changes: 46 additions & 0 deletions src/main/java/de/cyklon/jevent/EventManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,52 @@ default <T extends Event> void registerHandler(@NotNull Class<T> event, Consumer
registerHandler(event, handler, EventHandler.NORMAL, false);
}

/**
* registers a listener for a specific event, with a consumer instead of a method
*
* @param event the event for which the listener is to be registered
* @param handler The consumer to be executed when the event is called
* @param priority the event {@link EventHandler#priority() priority}
* @param ignoreCancelled if true, the handler is not called for {@link EventHandler#ignoreCancelled() canceled events}
* @param <T> the event type
*/
<T> void registerWrappedHandler(@NotNull Class<T> event, Consumer<T> handler, byte priority, boolean ignoreCancelled);

/**
* registers a listener for a specific event, with a consumer instead of a method
*
* @param event the event for which the listener is to be registered
* @param handler The consumer to be executed when the event is called
* @param priority the event {@link EventHandler#priority() priority}
* @param <T> the event type
*/
default <T> void registerWrappedHandler(@NotNull Class<T> event, Consumer<T> handler, byte priority) {
registerWrappedHandler(event, handler, priority, false);
}

/**
* registers a listener for a specific event, with a consumer instead of a method
*
* @param event the event for which the listener is to be registered
* @param handler The consumer to be executed when the event is called
* @param ignoreCancelled if true, the handler is not called for {@link EventHandler#ignoreCancelled() canceled events}
* @param <T> the event type
*/
default <T> void registerWrappedHandler(@NotNull Class<T> event, Consumer<T> handler, boolean ignoreCancelled) {
registerWrappedHandler(event, handler, EventHandler.NORMAL, ignoreCancelled);
}

/**
* registers a listener for a specific event, with a consumer instead of a method
*
* @param event the event for which the listener is to be registered
* @param handler The consumer to be executed when the event is called
* @param <T> the event type
*/
default <T> void registerWrappedHandler(@NotNull Class<T> event, Consumer<T> handler) {
registerWrappedHandler(event, handler, EventHandler.NORMAL, false);
}

/**
* removes all listeners that have the type of the specified class
*
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/de/cyklon/jevent/Handler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
*/
abstract class Handler<T extends Event> implements Comparable<Handler<T>> {
protected Class<? extends Event> eventType;
protected Class<?> wrappedType;
private final byte priority;
private final boolean ignoreCancelled;

public Handler(Class<T> eventType, byte priority, boolean ignoreCancelled) {
public Handler(Class<T> eventType, Class<?> wrappedType, byte priority, boolean ignoreCancelled) {
this.eventType = eventType;
this.wrappedType = wrappedType;
this.priority = priority;
this.ignoreCancelled = ignoreCancelled;
}

public boolean isSuitableHandler(@NotNull Class<? extends Event> event) {
return eventType.isAssignableFrom(event);
return eventType.isAssignableFrom(event) || (eventType.equals(WrappedEvent.class) && wrappedType!=null && wrappedType.isAssignableFrom(event));
}

@SuppressWarnings("unchecked")
Expand All @@ -35,6 +37,6 @@ public int compareTo(@NotNull Handler o) {

@Override
public String toString() {
return "Handler{eventType: %s, priority: %s, ignoreCancelled: %s, handler: %s}".formatted(eventType, priority, ignoreCancelled, "%s");
return "Handler{eventType: %s, priority: %s, ignoreCancelled: %s, handler: %s}".formatted(eventType.equals(WrappedEvent.class) ? String.format("{%s, %s}", WrappedEvent.class, wrappedType) : eventType, priority, ignoreCancelled, "%s");
}
}
13 changes: 12 additions & 1 deletion src/main/java/de/cyklon/jevent/JEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,22 @@ private void processClass(ReflectClass<?> clazz, boolean includeSubclasses) {

@Override
public <T extends Event> void registerHandler(@NotNull Class<T> event, Consumer<T> handler, byte priority, boolean ignoreCancelled) {
RawHandler<T> rh = new RawHandler<>(event, handler, priority, ignoreCancelled);
RawHandler<T, T> rh = new RawHandler<>(event, event, handler, priority, ignoreCancelled);
debug("register handler " + rh);
handlerSet.add(rh);
}

@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public <T> void registerWrappedHandler(@NotNull Class<T> event, Consumer<T> handler, byte priority, boolean ignoreCancelled) {
if (Event.class.isAssignableFrom(event)) registerHandler((Class<? extends Event>)event, e -> handler.accept((T) e), priority, ignoreCancelled);
else {
RawHandler<WrappedEvent, T> rh = new RawHandler<>(WrappedEvent.class, event, handler, priority, ignoreCancelled);
debug("register wrapped handler " + rh);
handlerSet.add(rh);
}
}

@SuppressWarnings("rawtypes")
public void unregisterListener(@NotNull Class<?> clazz) {
if (handlerSet.removeIf(h -> h instanceof MethodHandler mh && mh.getListener().getClass().isInstance(clazz))) debug("unregistered listener " + clazz);
Expand Down
28 changes: 24 additions & 4 deletions src/main/java/de/cyklon/jevent/MethodHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MethodHandler<D> extends Handler<Event> {

@SuppressWarnings("unchecked")
private MethodHandler(@NotNull D listener, @NotNull ReflectMethod<D, ?> handler, byte priority, boolean ignoreCancelled) {
super(null, priority, ignoreCancelled);
super(null, null, priority, ignoreCancelled);
this.listener = listener;
this.handler = handler;

Expand All @@ -35,7 +35,26 @@ private MethodHandler(@NotNull D listener, @NotNull ReflectMethod<D, ?> handler,
if(eventIndex==-1 && Event.class.isAssignableFrom(c)) {
this.eventType = (Class<? extends Event>) c;
eventIndex = i;
} else {
}
}
if(eventIndex==-1) {
for (int i = 0; i < parameters.size(); i++) {
ReflectParameter<D, ?> parameter = parameters.get(i);
Class<?> c = parameter.getReturnType().getInternal();
if (eventIndex==-1 && !parameter.hasAnnotation(ParameterInstance.class) && !EventManager.class.equals(c)) {
this.eventType = WrappedEvent.class;
this.wrappedType = c;
eventIndex = i;
}
}
}

if (eventIndex==-1) throw new EventException("the method must have an event as a parameter!");

for (int i = 0; i < parameters.size(); i++) {
if (i!=eventIndex) {
ReflectParameter<D, ?> parameter = parameters.get(i);
Class<?> c = parameter.getReturnType().getInternal();
ParameterInstance pi = parameter.getAnnotation(ParameterInstance.class);
if (pi==null) {
if (EventManager.class.equals(c)) pInstances.add(null);
Expand All @@ -44,7 +63,6 @@ private MethodHandler(@NotNull D listener, @NotNull ReflectMethod<D, ?> handler,
else pInstances.add(pi.value());
}
}
if(eventIndex==-1) throw new EventException("the method must have an event as a parameter!");

this.eventIndex = eventIndex;
this.parameterInstances = pInstances.toArray(String[]::new);
Expand All @@ -61,7 +79,9 @@ protected void invokeEvent(@NotNull EventManager manager, @NotNull Event event)
for (int i = 0; i < params.length; i++) {
int i1 = i;
if (i>=eventIndex) i1--;
params[i] = i==eventIndex ? event : parameterInstances[i1]==null ? manager : manager.getParameterInstance(parameterInstances[i1]);
Object eventObj = event;
if (event instanceof WrappedEvent<?> we) eventObj = we.getWrapped();
params[i] = i==eventIndex ? eventObj : parameterInstances[i1]==null ? manager : manager.getParameterInstance(parameterInstances[i1]);
}
handler.invoke(listener, params);
}
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/de/cyklon/jevent/RawHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@
/**
* The RawHandler object represents a single event handler that is represented by a consumer without an additional method or other wrapper
*/
class RawHandler<T extends Event> extends Handler<T> {
class RawHandler<T extends Event, W> extends Handler<T> {

private final long id;
private final Consumer<T> consumer;
private final Consumer<W> consumer;

public RawHandler(Class<T> eventType, Consumer<T> consumer, byte priority, boolean ignoreCancelled) {
super(eventType, priority, ignoreCancelled);
public RawHandler(Class<T> eventType, Class<W> wrappedType, Consumer<W> consumer, byte priority, boolean ignoreCancelled) {
super(eventType, eventType.equals(wrappedType) ? null : wrappedType, priority, ignoreCancelled);
this.id = System.nanoTime();
this.consumer = consumer;
}

@Override
@SuppressWarnings("unchecked")
protected void invokeEvent(@NotNull EventManager manager, @NotNull T event) {
consumer.accept(event);
W eventObj;
if (wrappedType==null) eventObj = (W) event;
else eventObj = ((WrappedEvent<W>) event).getWrapped();
consumer.accept(eventObj);
}

@Override
Expand All @@ -31,7 +35,7 @@ public int hashCode() {

@Override
public boolean equals(Object obj) {
return obj instanceof RawHandler<?> rh && rh.id==this.id;
return obj instanceof RawHandler<?, ?> rh && rh.id==this.id;
}

@Override
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/de/cyklon/jevent/WrappedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.cyklon.jevent;

import org.jetbrains.annotations.NotNull;

public final class WrappedEvent<T> extends Event {

private final T wrapped;

public WrappedEvent(@NotNull T wrapped) {
super(WrappedEvent.class.getSimpleName() + "{" + wrapped.getClass().getName() + "}");
this.wrapped = wrapped;
}

public T getWrapped() {
return wrapped;
}

@Override
public String toString() {
return WrappedEvent.class.getName() + "(" + wrapped.getClass().getName() + ")";
}
}
Loading