diff --git a/core/src/main/java/mc/core/eventbus/EventBus.java b/core/src/main/java/mc/core/eventbus/EventBus.java index 460f725..08fac05 100644 --- a/core/src/main/java/mc/core/eventbus/EventBus.java +++ b/core/src/main/java/mc/core/eventbus/EventBus.java @@ -4,17 +4,22 @@ import javafx.util.Pair; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.helpers.MessageFormatter; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Stream; +@Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class EventBus { @Getter private static final EventBus insnance = new EventBus(); - private Queue eventQueue; + private Queue eventQueue = new ConcurrentLinkedQueue<>(); private Map, List>> subscribes = new HashMap<>(); private Stream getMethods(Object subscriberObject) { @@ -56,4 +61,29 @@ public class EventBus { } }); } + + public void post(Event event) { + eventQueue.add(event); + } + + public void process() { + Event event; + while ((event = eventQueue.poll()) != null) { + final Class type = event.getClass(); + if (subscribes.containsKey(type)) { + final List> pairs = subscribes.get(type); + for (Pair pair : pairs) { + try { + pair.getValue().invoke(pair.getKey(), event); + } catch (IllegalAccessException | InvocationTargetException e) { + log.error(MessageFormatter.format("Invoke method '{}#{}'", + pair.getKey().getClass().getSimpleName(), + pair.getValue().getName()).getMessage(), + e + ); + } + } + } + } + } } diff --git a/core/src/test/java/mc/core/TestEventBus.java b/core/src/test/java/mc/core/TestEventBus.java index d8ab843..511f9e4 100644 --- a/core/src/test/java/mc/core/TestEventBus.java +++ b/core/src/test/java/mc/core/TestEventBus.java @@ -1,6 +1,8 @@ package mc.core; import javafx.util.Pair; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; import mc.core.eventbus.Event; import mc.core.eventbus.EventBus; import mc.core.eventbus.Subscriber; @@ -9,21 +11,29 @@ import org.junit.jupiter.api.Test; import org.mockito.internal.util.reflection.Whitebox; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Queue; +import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; class TestEventBus { + private List resultList = new ArrayList<>(); @SuppressWarnings("unchecked") private Map, List>> getEventBusFieldSubscribes() { - return (Map, List>>) Whitebox.getInternalState(EventBus.getInsnance(), "subscribes"); + return (Map, List>>) + Whitebox.getInternalState(EventBus.getInsnance(), "subscribes"); } @BeforeEach + @SuppressWarnings("unchecked") void before() { getEventBusFieldSubscribes().clear(); + ((Queue) Whitebox.getInternalState(EventBus.getInsnance(), "eventQueue")).clear(); } @@ -54,12 +64,46 @@ class TestEventBus { assertEquals(0, subscribes.size()); } - private class DumbEvent implements Event { + @Test + @SuppressWarnings("unchecked") + void testPost() { + EventBus.getInsnance().post(new DumbEvent()); + + Queue eventQueue = (Queue) Whitebox.getInternalState(EventBus.getInsnance(), "eventQueue"); + assertEquals(1, eventQueue.size()); } - private class DumbEventHandler { + @Test + void testProcess() { + Stream.of(new DumbEventHandler("D1 "), new DumbEventHandler("D2 ")) + .forEach(handler -> EventBus.getInsnance().registerSubscribes(handler)); + + Stream.of(new DumbEvent("message 1"), new DumbEvent("message 2")) + .forEach(event -> EventBus.getInsnance().post(event)); + + EventBus.getInsnance().process(); + + assertEquals(4, resultList.size()); + assertEquals("D1 message 1", resultList.get(0)); + assertEquals("D2 message 1", resultList.get(1)); + assertEquals("D1 message 2", resultList.get(2)); + assertEquals("D2 message 2", resultList.get(3)); + } + + @AllArgsConstructor + @NoArgsConstructor + private class DumbEvent implements Event { + String message; + } + + @AllArgsConstructor + @NoArgsConstructor + public class DumbEventHandler { + private String prefix = ""; + @Subscriber public void corectSubscribe(DumbEvent event) { + resultList.add(prefix + event.message); } @Subscriber