package tc.oc.commons.bukkit.event; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Optional; import javax.annotation.Nullable; import com.google.common.base.Throwables; import tc.oc.commons.core.util.ThrowingConsumer; import tc.oc.minecraft.api.event.Listener; /** * Describes an event handler method independent from any particular annotation. */ public class EventHandlerInfo<E> implements EventSubscriber<E> { private final EventKey<E> key; private final Method method; private final boolean ignoreCancelled; private @Nullable MethodHandle methodHandle; public EventHandlerInfo(EventKey<E> key, Method method, boolean ignoreCancelled) { this.key = key; this.method = method; this.ignoreCancelled = ignoreCancelled; this.method.setAccessible(true); } @Override public Class<Listener> listener() { return (Class<Listener>) method.getDeclaringClass(); } @Override public EventKey key() { return key; } @Override public boolean ignoreCancelled() { return ignoreCancelled; } @Override public Optional<AnnotatedElement> element() { return Optional.of(method()); } public Method method() { return method; } public MethodHandle methodHandle() { if(methodHandle == null) { try { methodHandle = MethodHandles.lookup().unreflect(method()); } catch(IllegalAccessException e) { // Should never happen, since we called setAccessible Throwables.propagate(e); } } return methodHandle; } @Override public ThrowingConsumer<E, Throwable> bindTo(Listener listener) { return methodHandle().bindTo(listener)::invokeWithArguments; } }