From b760c58298483bb121b8759ebc46848c32d3eca6 Mon Sep 17 00:00:00 2001 From: kske Date: Mon, 1 Nov 2021 21:36:24 +0100 Subject: [PATCH] Add a handler execution order debugging method --- .../java/dev/kske/eventbus/core/EventBus.java | 43 ++++++++++++++++--- .../dev/kske/eventbus/core/DispatchTest.java | 19 ++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java index 44ff01c..b49f353 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java @@ -109,7 +109,7 @@ public final class EventBus { // Increment nesting count (becomes > 1 during nested dispatches) ++state.nestingCount; - Iterator handlers = getHandlersFor(event.getClass()); + Iterator handlers = getHandlersFor(event.getClass()).iterator(); if (handlers.hasNext()) { while (handlers.hasNext()) if (state.isCancelled) { @@ -155,10 +155,10 @@ public final class EventBus { * that are bound to a supertype of the event class. * * @param eventClass the event class to use for the search - * @return an iterator over the applicable handlers in descending order of priority - * @since 0.0.1 + * @return a navigable set containing the applicable handlers in descending order of priority + * @since 1.2.0 */ - private Iterator getHandlersFor(Class eventClass) { + private NavigableSet getHandlersFor(Class eventClass) { // Get handlers defined for the event class TreeSet handlers = bindings.getOrDefault(eventClass, new TreeSet<>()); @@ -170,7 +170,7 @@ public final class EventBus { if (handler.isPolymorphic()) handlers.add(handler); - return handlers.iterator(); + return handlers; } /** @@ -275,6 +275,39 @@ public final class EventBus { registeredListeners.clear(); } + /** + * Generates a string describing the event handlers that would be executed for a specific event + * type, in order and without actually executing them. + * + * @apiNote Using this method is only recommended for debugging purposes, as the output depends + * on implementation internals which may be subject to change. + * @implNote Nested dispatches are not accounted for, as this would require actually executing + * the handlers. + * @param eventType the event type to generate the execution order for + * @return a human-readable event handler list suitable for debugging purposes + * @since 1.2.0 + */ + public String printExecutionOrder(Class eventType) { + var handlers = getHandlersFor(eventType); + var sj = new StringJoiner("\n"); + + // Output header line + sj.add(String.format("Event handler execution order for %s (%d handler(s)):", eventType, + handlers.size())); + sj.add( + "=========================================================================================="); + + // Individual handlers + for (var handler : handlers) + sj.add(handler.toString()); + + // Bottom line + sj.add( + "=========================================================================================="); + + return sj.toString(); + } + /** * Provides an unmodifiable view of the event listeners registered at this event bus. * diff --git a/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java b/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java index 5149ae1..5ba883e 100644 --- a/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java +++ b/event-bus-core/src/test/java/dev/kske/eventbus/core/DispatchTest.java @@ -40,6 +40,25 @@ class DispatchTest { bus.dispatch(new SimpleEvent()); } + /** + * Tests {@link EventBus#printExecutionOrder(Class)} based on the currently registered handlers. + * + * @since 1.2.0 + */ + @Test + void testPrintExecutionOrder() { + String executionOrder = bus.printExecutionOrder(SimpleEvent.class); + System.out.println(executionOrder); + assertEquals( + "Event handler execution order for class dev.kske.eventbus.core.SimpleEvent (3 handler(s)):\n" + + "==========================================================================================\n" + + "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=true, priority=200]\n" + + "EventHandler[method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=false, priority=150]\n" + + "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventThird(dev.kske.eventbus.core.SimpleEvent), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=true, polymorphic=false, priority=100]\n" + + "==========================================================================================", + executionOrder); + } + @Event(SimpleEvent.class) @Priority(200) void onSimpleEventFirst() {