diff --git a/.gitignore b/.gitignore index a1bc206..5a45940 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.idea/ /target/ /dependency-reduced-pom.xml +/developer-docs/ \ No newline at end of file diff --git a/LICENSE b/LICENSE index f186ace..7a2067d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 7orivorian +Copyright (c) 2021-2024 7orivorian Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4cc101e..df822c6 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Lightweight Java event library created and maintained by [7orivorian](https://gi com.github.7orivorian Wraith - 3.1.0 + 3.2.0 ``` @@ -51,13 +51,13 @@ repositories { ```gradle dependencies { - implementation 'com.github.7orivorian:Wraith:3.1.0' + implementation 'com.github.7orivorian:Wraith:3.2.0' } ``` ### Other -Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/releases/tag/3.1.0) +Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/releases/tag/3.2.0) # Building @@ -66,11 +66,12 @@ Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/rele Packaged file can be found in the `target/` directory. -# Usage +# Quick-Start Guide While the code itself is thoroughly documented, here's a simple guide to help you get started with the latest features. ### Subscribers +
Details... @@ -95,11 +96,13 @@ public class ExampleSubscriber implements ISubscriber { Once you've defined your subscriber, you can subscribe it to an event bus directly within the subscriber's constructor: ```java -public class ExampleSubscriber extends Subscriber { +public class Consts { private static final IEventBus EVENT_BUS = new EventBus(); +} +public class ExampleSubscriber extends Subscriber { public ExampleSubscriber() { - EVENT_BUS.subscribe(this); + Consts.EVENT_BUS.subscribe(this); } } ``` @@ -115,9 +118,11 @@ public class Example { } } ``` +
### Defining Events +
Details... @@ -141,26 +146,10 @@ public class ExampleEvent { } ``` -To create a cancelable event, you can: - -Extend the Cancelable class: - -```java -public class CancelableEvent extends Cancelable { -// ... -} -``` - -Implement the ICancelable interface: - -```java -public class CancelableEvent implements ICancelable { -// ... -} -```
### Listeners +
Details... @@ -175,9 +164,7 @@ public class ExampleListener extends EventListener { @Override public void invoke(ExampleEvent event) { - if (event.getStage() == EventStage.POST) { - event.setMessage("I feel wonderful!"); - } + event.setMessage("Hello world!"); } } ``` @@ -200,22 +187,20 @@ public class ExampleSubscriber extends Subscriber { public ExampleSubscriber() { // Register the listener registerListener( - new LambdaEventListener<>(ExampleEvent.class, event -> { - if (event.getStage() == EventStage.PRE) { - event.setMessage("Hello world!"); - } - }) + new LambdaEventListener<>(ExampleEvent.class, event -> event.setMessage("Hello world!")) ); } } ``` +
### Dispatching Events +
Details... -To dispatch an event to an event bus, simply call one of the `dispatch` methods defined in any `IEventBus` +To dispatch an event to an event bus, call one of the `dispatch` methods defined in any `IEventBus` implementation, passing your event as a parameter: ```java @@ -227,19 +212,18 @@ public class Example { public static void main(String[] args) { - ExampleEvent event = new ExampleEvent("Initial message"); + ExampleEvent event = new ExampleEvent("world greetings"); EVENT_BUS.dispatch(event); - if (!event.isCanceled()) { - System.out.println(event.getMessage()); - } + System.out.println(event.getMessage()); } } ``` +
-Feel free to explore the [example folder](examples/java/me/tori/example) for more Wraith implementations. +Please explore the [example folder](./examples/java/me/tori/example) for _even more_ Wraith implementations! # Contributing @@ -261,7 +245,7 @@ To make a contribution, follow these steps: # License -[Wraith is licensed under MIT](src/main/resources/LICENSE.md) +[Wraith is licensed under MIT](./LICENSE) ### MIT License Summary: diff --git a/SECURITY.md b/SECURITY.md index 6ae715d..4ea3204 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,10 +6,6 @@ |-----------|--------------------| | \>= 3.0.0 | :white_check_mark: | | 2.0.1 | :white_check_mark: | -| 2.0.0 | :x: | -| < 2.0.0 | :x: | +| <= 2.0.0 | :x: | -## Reporting a Vulnerability - -Vulnerabilities can be reported by visiting the 'Security' -tab on this repo and clicking 'Report a vulnerability'. +[Report a vulnerability.](https://github.com/7orivorian/Wraith/security/advisories/new) diff --git a/examples/java/me/tori/example/expanded/ExampleEvent.java b/examples/java/me/tori/example/expanded/ExampleEvent.java index 56f9448..686219f 100644 --- a/examples/java/me/tori/example/expanded/ExampleEvent.java +++ b/examples/java/me/tori/example/expanded/ExampleEvent.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.example.expanded; import me.tori.wraith.event.cancelable.CancelableEvent; diff --git a/examples/java/me/tori/example/expanded/ExampleListener.java b/examples/java/me/tori/example/expanded/ExampleListener.java index a6b952d..c3de8fc 100644 --- a/examples/java/me/tori/example/expanded/ExampleListener.java +++ b/examples/java/me/tori/example/expanded/ExampleListener.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.example.expanded; import me.tori.wraith.event.staged.EventStage; diff --git a/examples/java/me/tori/example/expanded/ExampleMain.java b/examples/java/me/tori/example/expanded/ExampleMain.java index 6156f7e..310be01 100644 --- a/examples/java/me/tori/example/expanded/ExampleMain.java +++ b/examples/java/me/tori/example/expanded/ExampleMain.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.example.expanded; import me.tori.wraith.bus.EventBus; diff --git a/examples/java/me/tori/example/expanded/ExampleSubscriber.java b/examples/java/me/tori/example/expanded/ExampleSubscriber.java index 82ddb4d..a8dae62 100644 --- a/examples/java/me/tori/example/expanded/ExampleSubscriber.java +++ b/examples/java/me/tori/example/expanded/ExampleSubscriber.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.example.expanded; import me.tori.wraith.event.staged.EventStage; diff --git a/examples/java/me/tori/example/persistence/PersistenceExample.java b/examples/java/me/tori/example/persistence/PersistenceExample.java new file mode 100644 index 0000000..b6cbc6f --- /dev/null +++ b/examples/java/me/tori/example/persistence/PersistenceExample.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.example.persistence; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.bus.IEventBus; +import me.tori.wraith.listener.LambdaEventListener; +import me.tori.wraith.subscriber.Subscriber; + +/** + * A simple example of listener persistence. + *

+ * Last updated for version 3.1.0 + * + * @author 7orivorian + * @since 3.2.0 + */ +class PersistenceExample { + + private static final IEventBus EVENT_BUS = new EventBus(); + private static final Subscriber SUBSCRIBER = new Subscriber() {{ + // Register a listener that prints a single + // String event & is then removed from the event bus + registerListener(new LambdaEventListener<>(String.class, null, IEventBus.DEFAULT_PRIORITY, 1, System.out::println)); + }}; + + public static void main(String[] args) { + // Subscribe our subscriber. This will never be removed from the event bus. + EVENT_BUS.subscribe(SUBSCRIBER); + + // After this event is dispatched, and it's listener invoked, + // the listener will be removed since it's set to only persist once. + EVENT_BUS.dispatch("Hello world!"); + + // You can still dispatch events to remaining listeners. + EVENT_BUS.dispatch("I wont be printed :("); + } +} \ No newline at end of file diff --git a/examples/java/me/tori/example/simple/SimpleExample.java b/examples/java/me/tori/example/simple/SimpleExample.java index 6796491..b346f28 100644 --- a/examples/java/me/tori/example/simple/SimpleExample.java +++ b/examples/java/me/tori/example/simple/SimpleExample.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.example.simple; import me.tori.wraith.bus.EventBus; @@ -7,7 +28,8 @@ /** * One-class example - *

Last updated for version 3.1.0 + *

+ * Last updated for version 3.1.0 * * @author 7orivorian */ diff --git a/examples/java/me/tori/example/statusevents/SupressionExample.java b/examples/java/me/tori/example/statusevents/SupressionExample.java new file mode 100644 index 0000000..f62abf0 --- /dev/null +++ b/examples/java/me/tori/example/statusevents/SupressionExample.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.example.statusevents; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.bus.IEventBus; +import me.tori.wraith.event.status.StatusEvent; +import me.tori.wraith.listener.LambdaEventListener; +import me.tori.wraith.subscriber.Subscriber; + +/** + * @author 7orivorian + * @since 3.2.0 + */ +public class SupressionExample { + + private static final IEventBus EVENT_BUS = new EventBus(); + private static final Subscriber SUBSCRIBER = new Subscriber() {{ + registerListeners( + new LambdaEventListener<>(StringEvent.class, 1, event -> { + event.message = "Hello world!"; + event.suppress(); + }), + new LambdaEventListener<>(StringEvent.class, 0, event -> { + event.message = "I do not greet"; + }) + ); + }}; + + public static void main(String[] args) { + EVENT_BUS.subscribe(SUBSCRIBER); + + StringEvent event = new StringEvent(null); + System.out.println(EVENT_BUS.dispatch(event)); // This will print "true" because the event was suppressed + + // Even though the event was suppressed, it was still passed to subsequent listeners + System.out.println(event.message); // This will print "I do not greet" + } + + private static class StringEvent extends StatusEvent { + + public String message; + + public StringEvent(String message) { + this.message = message; + } + } +} \ No newline at end of file diff --git a/examples/java/me/tori/example/statusevents/TerminationExample.java b/examples/java/me/tori/example/statusevents/TerminationExample.java new file mode 100644 index 0000000..5a2a4f1 --- /dev/null +++ b/examples/java/me/tori/example/statusevents/TerminationExample.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.example.statusevents; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.bus.IEventBus; +import me.tori.wraith.event.status.StatusEvent; +import me.tori.wraith.listener.LambdaEventListener; +import me.tori.wraith.subscriber.Subscriber; + +/** + * @author 7orivorian + * @since 3.2.0 + */ +public class TerminationExample { + + private static final IEventBus EVENT_BUS = new EventBus(); + private static final Subscriber SUBSCRIBER = new Subscriber() {{ + registerListeners( + new LambdaEventListener<>(StringEvent.class, 1, event -> { + event.message = "Hello world!"; + event.terminate(); + }), + new LambdaEventListener<>(StringEvent.class, 0, event -> { + event.message = "I do not greet"; + }) + ); + }}; + + public static void main(String[] args) { + EVENT_BUS.subscribe(SUBSCRIBER); + + StringEvent event = new StringEvent(null); + System.out.println(EVENT_BUS.dispatch(event)); // This will print "true" because the event was terminated + + // Terminated events are not handled by subsequent listeners + System.out.println(event.message); // This will print "Hello world!" + } + + private static class StringEvent extends StatusEvent { + + public String message; + + public StringEvent(String message) { + this.message = message; + } + } +} \ No newline at end of file diff --git a/examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java b/examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java new file mode 100644 index 0000000..2c4e9d3 --- /dev/null +++ b/examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.example.taskexecutor; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.task.ScheduledTask; +import me.tori.wraith.task.TaskExecutor; + +/** + * A simple example showing how to use the {@link TaskExecutor} + * + * @author 7orivorian + * @since 3.2.0 + */ +public class TaskExecutorExample { + + private static final EventBus EVENT_BUS = new EventBus(); + + public static void main(final String[] args) { + // Schedule a task to run when the next String event is dispatched + EVENT_BUS.scheduleTask(new ScheduledTask(String.class, 3) { + @Override + public void run() { + System.out.println("Hello World!"); + } + }); + + // This event will trigger the previously scheduled task. + // Note that scheduled tasks will be run before any listeners + // are invoked, regardless of listener priority. + EVENT_BUS.dispatch("just a string event"); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index d5a640a..08a4abd 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,16 @@ RELEASE compile + + org.openjdk.jmh + jmh-core + 1.37 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + 3.1.0 diff --git a/src/main/java/me/tori/wraith/bus/EventBus.java b/src/main/java/me/tori/wraith/bus/EventBus.java index 7100c65..3ef51c9 100644 --- a/src/main/java/me/tori/wraith/bus/EventBus.java +++ b/src/main/java/me/tori/wraith/bus/EventBus.java @@ -1,6 +1,27 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.bus; -import me.tori.wraith.event.cancelable.ICancelableEvent; +import me.tori.wraith.event.status.IStatusEvent; import me.tori.wraith.event.targeted.IClassTargetingEvent; import me.tori.wraith.listener.Listener; import me.tori.wraith.subscriber.ISubscriber; @@ -10,6 +31,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Predicate; /** * Default implementation of {@link IEventBus}, {@link TargetableEventBus}, and {@link InvertableEventBus}. @@ -83,8 +105,13 @@ public static int getInstanceCount() { @Override public void subscribe(ISubscriber subscriber) { Objects.requireNonNull(subscriber, "Cannot subscribe null to event bus " + id + "!"); - for (Listener listener : subscriber.getListeners()) { - register(listener); + Collection> listeners = subscriber.getListeners(); + if (listeners.size() == 1) { + register(listeners.iterator().next()); + } else { + for (Listener listener : listeners) { + register(listener); + } } subscribers.add(subscriber); } @@ -100,8 +127,13 @@ public void subscribe(ISubscriber subscriber) { @Override public void unsubscribe(ISubscriber subscriber) { Objects.requireNonNull(subscriber, "Cannot unsubscribe null from event bus " + id + "!"); - for (Listener listener : subscriber.getListeners()) { - unregister(listener); + Collection> listeners = subscriber.getListeners(); + if (listeners.size() == 1) { + unregister(listeners.iterator().next()); + } else { + for (Listener listener : listeners) { + unregister(listener); + } } subscribers.remove(subscriber); } @@ -143,27 +175,14 @@ public void unregister(Listener listener) { * Dispatches an event to listeners. * * @param event the event to be dispatched - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @Override public boolean dispatch(Object event) { - Objects.requireNonNull(event, "Cannot dispatch a null event to event bus " + id + "!"); - if (isShutdown()) { - throw new UnsupportedOperationException("Dispatcher " + id + " is shutdown!"); - } else { - taskExecutor.onEvent(event); - - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - listeners.forEach(listener -> listener.invoke(event)); - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); - } - } - return false; + return dispatch(event, null); } /** @@ -174,7 +193,8 @@ public boolean dispatch(Object event) { * * @param event the event to be dispatched * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @@ -186,14 +206,15 @@ public boolean dispatch(Object event, Class type) { } else { taskExecutor.onEvent(event); - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - listeners.stream() - .filter(listener -> (listener.getType() == null) || (listener.getType() == type)) - .forEach(listener -> listener.invoke(event)); - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); + dispatchToEachListener( + event, + this.listeners.get(event.getClass()), + listener -> (type == null) || (listener.getType() == null) || (listener.getType() == type), + false + ); + + if (event instanceof IStatusEvent e) { + return e.isSuppressed() || e.isTerminated(); } } return false; @@ -203,29 +224,14 @@ public boolean dispatch(Object event, Class type) { * Dispatches the given event to the target listener class * * @param event the {@linkplain IClassTargetingEvent} to be dispatched - * @return {@code true} if the given event was {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event was {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @Override public boolean dispatchTargeted(IClassTargetingEvent event) { - Objects.requireNonNull(event, "Cannot dispatch a null event to event bus " + id + "!"); - if (isShutdown()) { - throw new UnsupportedOperationException("Dispatcher " + id + " is shutdown!"); - } else { - taskExecutor.onEvent(event); - - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - listeners.stream() - .filter(listener -> listener.getClass().equals(event.getTargetClass())) - .forEach(listener -> listener.invoke(event)); - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); - } - } - return false; + return dispatchTargeted(event, null); } /** @@ -236,7 +242,8 @@ public boolean dispatchTargeted(IClassTargetingEvent event) { * * @param event the {@linkplain IClassTargetingEvent} to be dispatched * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @@ -248,61 +255,47 @@ public boolean dispatchTargeted(IClassTargetingEvent event, Class type) { } else { taskExecutor.onEvent(event); - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - listeners.stream() - .filter(listener -> (listener.getType() == null) || (listener.getType() == type)) - .filter(listener -> listener.getClass().equals(event.getTargetClass())) - .forEach(listener -> listener.invoke(event)); - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); + dispatchToEachListener( + event, + this.listeners.get(event.getClass()), + listener -> ((type == null) || (listener.getType() == null) || (listener.getType() == type)) + && listener.getClass().equals(event.getTargetClass()), + false + ); + + if (event instanceof IStatusEvent e) { + return e.isSuppressed() || e.isTerminated(); } } return false; } /** - * Dispatches an event to listeners in order of inverse-priority. E.g. the lowest priority listeners will be - * invoked before the highest priority listeners. + * Dispatches an event to listeners in order of inverse-priority. + * E.g., the lowest priority listeners will be invoked before the highest priority listeners. * * @param event the event to be dispatched - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @Override public boolean dispatchInverted(Object event) { - Objects.requireNonNull(event, "Cannot dispatch a null event to event bus " + id + "!"); - if (isShutdown()) { - throw new UnsupportedOperationException("Dispatcher " + id + " is shutdown!"); - } else { - taskExecutor.onEvent(event); - - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - ListIterator iterator = listeners.listIterator(listeners.size()); - while (iterator.hasPrevious()) { - iterator.previous().invoke(event); - } - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); - } - } - return false; + return dispatchInverted(event, null); } /** - * Dispatches an event to listeners in order of inverse-priority. E.g. the lowest priority listeners will be - * invoked before the highest priority listeners. + * Dispatches an event to listeners in order of inverse-priority. + * E.g., the lowest priority listeners will be invoked before the highest priority listeners. * *

The {@code type} parameter serves as a filtering mechanism for listeners, enabling you to selectively invoke * listeners based on their type, allowing for more targeted event handling. * * @param event the event to be dispatched * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @throws NullPointerException if the given event is {@code null} * @throws UnsupportedOperationException if this event bus is {@link #shutdown} */ @@ -314,18 +307,15 @@ public boolean dispatchInverted(Object event, Class type) { } else { taskExecutor.onEvent(event); - List listeners = this.listeners.get(event.getClass()); - if (listeners != null) { - ListIterator iterator = listeners.listIterator(listeners.size()); - while (iterator.hasPrevious()) { - Listener listener = iterator.previous(); - if ((listener.getType() == null) || (listener.getType() == type)) { - listener.invoke(event); - } - } - } - if (event instanceof ICancelableEvent cancelable) { - return cancelable.isCanceled(); + dispatchToEachListener( + event, + this.listeners.get(event.getClass()), + listener -> (type == null) || (listener.getType() == null) || (listener.getType() == type), + true + ); + + if (event instanceof IStatusEvent e) { + return e.isSuppressed() || e.isTerminated(); } } return false; @@ -382,6 +372,56 @@ public int getId() { return id; } + /** + * Applies a given action to each {@linkplain Listener} in a list that matches a specified predicate. + * Listeners are processed either in normal order or in reverse order based on the + * {@code invertPriority} flag. + * Listeners that should not persist are removed from the list after the action is applied. + * + * @param event the event to be handled by each listener that satisfies the predicate + * @param listeners the list of listeners to be processed + * @param predicate the condition that each listener must satisfy to have the action applied + * @param invertPriority if {@code true}, listeners are processed in reverse order; otherwise, + * they are processed in normal order + * @since 3.2.0 + */ + @SuppressWarnings("DuplicatedCode") + private void dispatchToEachListener(Object event, List listeners, Predicate predicate, boolean invertPriority) { + if (listeners != null && !listeners.isEmpty()) { + if (invertPriority) { + ListIterator iterator = listeners.listIterator(listeners.size()); + while (iterator.hasPrevious()) { + Listener listener = iterator.previous(); + if (!predicate.test(listener)) { + continue; + } + listener.invoke(event); + if ((event instanceof IStatusEvent e) && e.isTerminated()) { + break; + } + if (!listener.shouldPersist()) { + listeners.remove(listener); + } + } + } else { + Iterator iterator = listeners.listIterator(0); + while (iterator.hasNext()) { + Listener listener = iterator.next(); + if (!predicate.test(listener)) { + continue; + } + listener.invoke(event); + if ((event instanceof IStatusEvent e) && e.isTerminated()) { + break; + } + if (!listener.shouldPersist()) { + listeners.remove(listener); + } + } + } + } + } + /** * Checks if this event bus is equal to another object. *

If the given object is an event bus, it is only considered equal if {@code this.id == that.id}. diff --git a/src/main/java/me/tori/wraith/bus/IEventBus.java b/src/main/java/me/tori/wraith/bus/IEventBus.java index 3a4d404..6e905e4 100644 --- a/src/main/java/me/tori/wraith/bus/IEventBus.java +++ b/src/main/java/me/tori/wraith/bus/IEventBus.java @@ -1,6 +1,27 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.bus; -import me.tori.wraith.event.cancelable.ICancelableEvent; +import me.tori.wraith.event.status.IStatusEvent; import me.tori.wraith.listener.EventListener; import me.tori.wraith.listener.Listener; import me.tori.wraith.subscriber.ISubscriber; @@ -43,14 +64,16 @@ public interface IEventBus { /** * @param event the event to be dispatched - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise */ boolean dispatch(Object event); /** * @param event the event to be dispatched * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise */ boolean dispatch(Object event, Class type); diff --git a/src/main/java/me/tori/wraith/bus/InvertableEventBus.java b/src/main/java/me/tori/wraith/bus/InvertableEventBus.java index 3120c6d..b1e51a2 100644 --- a/src/main/java/me/tori/wraith/bus/InvertableEventBus.java +++ b/src/main/java/me/tori/wraith/bus/InvertableEventBus.java @@ -1,6 +1,27 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.bus; -import me.tori.wraith.event.cancelable.ICancelableEvent; +import me.tori.wraith.event.status.IStatusEvent; /** * @author 7orivorian @@ -10,7 +31,8 @@ public interface InvertableEventBus extends IEventBus { /** * @param event the event to be dispatched - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @see EventBus#dispatchInverted(Object) */ boolean dispatchInverted(Object event); @@ -18,7 +40,8 @@ public interface InvertableEventBus extends IEventBus { /** * @param event the event to be dispatched * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event is {@linkplain ICancelableEvent cancelable} and canceled, {@code false} otherwise + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise * @see EventBus#dispatchInverted(Object, Class) */ boolean dispatchInverted(Object event, Class type); diff --git a/src/main/java/me/tori/wraith/bus/TargetableEventBus.java b/src/main/java/me/tori/wraith/bus/TargetableEventBus.java index 5b6776c..f44517d 100644 --- a/src/main/java/me/tori/wraith/bus/TargetableEventBus.java +++ b/src/main/java/me/tori/wraith/bus/TargetableEventBus.java @@ -1,6 +1,27 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.bus; -import me.tori.wraith.event.cancelable.ICancelableEvent; +import me.tori.wraith.event.status.IStatusEvent; import me.tori.wraith.event.targeted.IClassTargetingEvent; /** @@ -11,7 +32,8 @@ public interface TargetableEventBus extends IEventBus { /** * @param event the {@linkplain IClassTargetingEvent} to dispatch - * @return {@code true} if the given event was {@linkplain ICancelableEvent cancelable} and canceled, {@code false otherwise} + * @return {@code true} if the given event was {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false otherwise} * @see EventBus#dispatchTargeted(IClassTargetingEvent) */ boolean dispatchTargeted(IClassTargetingEvent event); @@ -19,7 +41,8 @@ public interface TargetableEventBus extends IEventBus { /** * @param event the {@linkplain IClassTargetingEvent} to dispatch * @param type the type of listener to invoke (can be {@code null}) - * @return {@code true} if the given event was {@linkplain ICancelableEvent cancelable} and canceled, {@code false otherwise} + * @return {@code true} if the given event was {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false otherwise} * @see EventBus#dispatchTargeted(IClassTargetingEvent, Class) */ boolean dispatchTargeted(IClassTargetingEvent event, Class type); diff --git a/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java b/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java index 1a1798f..ae3f539 100644 --- a/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java +++ b/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java @@ -1,47 +1,44 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.cancelable; +import me.tori.wraith.event.status.StatusEvent; + +import static me.tori.wraith.event.status.IStatusEvent.EventStatus.SUPPRESSED; + /** * Default implementation of the {@link ICancelableEvent} interface. * - *

This class provides a basic implementation of the cancelable event behavior. - * Event classes can extend this class to inherit the cancellation capability. - * * @author 7orivorian * @see ICancelableEvent * @since 1.0.0 */ -public class CancelableEvent implements ICancelableEvent { - - /** - * Indicates the cancellation state of this event. - */ - private boolean canceled = false; - - /** - * Checks whether this event is canceled. - * - * @return {@code true} if this event is canceled, {@code false} otherwise - */ - @Override - public boolean isCanceled() { - return canceled; - } - - /** - * Sets the cancellation state of this event. - * - * @param canceled {@code true} to mark this event as canceled, {@code false} otherwise - * @implNote Passing {@code false} to this method can un-cancel this event if it was previously canceled. - */ - @Override - public void setCanceled(boolean canceled) { - this.canceled = canceled; - } +@Deprecated(forRemoval = true, since = "3.2.0") +public class CancelableEvent extends StatusEvent implements ICancelableEvent { @Override public String toString() { return "Cancelable{" + - "canceled=" + canceled + + "canceled=" + (getEventStatus() == SUPPRESSED) + '}'; } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java b/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java index ddbb4b5..13b14ea 100644 --- a/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java +++ b/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java @@ -1,42 +1,56 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.cancelable; +import me.tori.wraith.event.status.IStatusEvent; + /** - * Represents a cancelable event that can be prevented from further processing. - * - *

This interface allows events to be canceled, indicating that they should not proceed through their - * normal processing flow. This is particularly useful in scenarios where certain conditions require an event - * to be halted from performing its intended action. - * * @author 7orivorian * @see CancelableEvent * @since 1.0.0 + * @deprecated Use {@link IStatusEvent} instead. */ -public interface ICancelableEvent { +@Deprecated(forRemoval = true, since = "3.2.0") +public interface ICancelableEvent extends IStatusEvent { /** - * Checks whether this event is canceled. - * * @return {@code true} if this event is canceled, {@code false} otherwise + * @see #isSuppressed() */ - boolean isCanceled(); + default boolean isCanceled() { + return isSuppressed(); + } /** - * Sets the cancellation state of this event. - * - * @param canceled {@code true} to mark this event as canceled, {@code false} otherwise - * @implNote Passing {@code false} to this method can un-cancel this event if it was previously canceled. + * @see #setSuppressed(boolean) */ - void setCanceled(boolean canceled); + default void setCanceled(boolean canceled) { + setSuppressed(canceled); + } /** - * Convenience method to cancel this event. - * - *

This is a shorthand method equivalent to calling {@code setCanceled(true)}, conveniently - * marking this event as canceled. - * - * @see #setCanceled(boolean) + * @see #suppress() */ default void cancel() { - setCanceled(true); + suppress(); } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/event/staged/EventStage.java b/src/main/java/me/tori/wraith/event/staged/EventStage.java index b8dd23b..10cbdda 100644 --- a/src/main/java/me/tori/wraith/event/staged/EventStage.java +++ b/src/main/java/me/tori/wraith/event/staged/EventStage.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.staged; /** diff --git a/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java b/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java index 9d9a3d4..870843e 100644 --- a/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java +++ b/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.staged; /** diff --git a/src/main/java/me/tori/wraith/event/staged/StagedEvent.java b/src/main/java/me/tori/wraith/event/staged/StagedEvent.java index 958f543..bc332a4 100644 --- a/src/main/java/me/tori/wraith/event/staged/StagedEvent.java +++ b/src/main/java/me/tori/wraith/event/staged/StagedEvent.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.staged; import org.jetbrains.annotations.NotNull; @@ -24,7 +45,6 @@ public class StagedEvent implements IStagedEvent { * @throws NullPointerException If the provided {@code stage} is {@code null}. */ public StagedEvent(@NotNull EventStage stage) { - Objects.requireNonNull(stage); this.stage = stage; } diff --git a/src/main/java/me/tori/wraith/event/status/IStatusEvent.java b/src/main/java/me/tori/wraith/event/status/IStatusEvent.java new file mode 100644 index 0000000..5d17741 --- /dev/null +++ b/src/main/java/me/tori/wraith/event/status/IStatusEvent.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.event.status; + +import org.jetbrains.annotations.NotNull; + +/** + * Represents an event that can be alive, suppressed, or terminated. + *

+ * This interface defines the status of an event and provides methods to + * manipulate and check this status. The possible statuses are defined by {@link EventStatus}.

+ * + * @author 7orivorian + * @see StatusEvent + * @since 3.2.0 + */ +public interface IStatusEvent { + + /** + * Gets the current status of this event. + * + * @return the current {@link EventStatus} of this event. + */ + @NotNull + EventStatus getEventStatus(); + + /** + * Sets the status of this event. + * + * @param status the new {@link EventStatus} to set. + */ + void setEventStatus(@NotNull EventStatus status); + + /** + * Checks whether this event is suppressed. + * + * @return {@code true} if this event is suppressed, {@code false} otherwise. + */ + boolean isSuppressed(); + + /** + * Sets the suppression state of this event. + * + *

If the event is not terminated, this method will update the event's state to either + * suppressed or alive based on the provided boolean parameter ({@code suppressed}).

+ * + * @param suppressed {@code true} to suppress the event, {@code false} to unsuppress it. + * @return {@code true} if the suppression state was successfully updated, {@code false} if the event is terminated. + */ + default boolean setSuppressed(boolean suppressed) { + if (getEventStatus() != EventStatus.TERMINATED) { + if (suppressed) { + setEventStatus(EventStatus.SUPPRESSED); + } else { + setEventStatus(EventStatus.ALIVE); + } + return true; + } + return false; + } + + /** + * Convenience method to suppress this event if it is not currently terminated. + *

+ * This is a shorthand method equivalent to calling {@code setSuppressed(true)}. + * + * @return {@code true} if the event was successfully suppressed, {@code false} if the event is terminated. + * @see #setSuppressed(boolean) + */ + default boolean suppress() { + return setSuppressed(true); + } + + /** + * Checks whether this event is terminated. + * + * @return {@code true} if this event is terminated, {@code false} otherwise. + */ + boolean isTerminated(); + + /** + * Convenience method to terminate this event. + *

+ * This is a shorthand method equivalent to calling {@code setEventStatus(EventStatus.TERMINATED)}. + * + * @see #setEventStatus(EventStatus) + */ + default void terminate() { + setEventStatus(EventStatus.TERMINATED); + } + + /** + * Enum representing the possible statuses of a {@link IStatusEvent}. + */ + enum EventStatus { + /** + * The event is active and not suppressed or terminated. + */ + ALIVE, + /** + * The event is suppressed. A suppressed event may become unsuppressed. + */ + SUPPRESSED, + /** + * The event is terminated and cannot be altered further. + */ + TERMINATED + } +} \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/event/status/StatusEvent.java b/src/main/java/me/tori/wraith/event/status/StatusEvent.java new file mode 100644 index 0000000..86ff702 --- /dev/null +++ b/src/main/java/me/tori/wraith/event/status/StatusEvent.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.event.status; + +import org.jetbrains.annotations.NotNull; + +/** + * Default implementation of {@link IStatusEvent}. + * + * @author 7orivorian + * @see IStatusEvent + * @since 3.2.0 + */ +public class StatusEvent implements IStatusEvent { + + protected EventStatus status = EventStatus.ALIVE; + + /** + * {@inheritDoc} + * + * @return the current {@link EventStatus} of this event. + */ + @NotNull + @Override + public EventStatus getEventStatus() { + return status; + } + + /** + * {@inheritDoc} + * + * @param status the new {@link EventStatus} to set. + */ + @Override + public void setEventStatus(@NotNull EventStatus status) { + this.status = status; + } + + /** + * {@inheritDoc} + * + * @return {@code true} if this event is suppressed, {@code false} otherwise. + */ + @Override + public boolean isSuppressed() { + return status == EventStatus.SUPPRESSED; + } + + /** + * {@inheritDoc} + * + * @return {@code true} if this event is terminated, {@code false} otherwise. + */ + @Override + public boolean isTerminated() { + return status == EventStatus.TERMINATED; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + + StatusEvent that = (StatusEvent) o; + return status == that.status; + } + + @Override + public int hashCode() { + return status.hashCode(); + } + + @Override + public String toString() { + return "StatusEvent{" + + "status=" + status + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/event/targeted/ClassTargetingEvent.java b/src/main/java/me/tori/wraith/event/targeted/ClassTargetingEvent.java index 33d2505..bff8530 100644 --- a/src/main/java/me/tori/wraith/event/targeted/ClassTargetingEvent.java +++ b/src/main/java/me/tori/wraith/event/targeted/ClassTargetingEvent.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.targeted; import me.tori.wraith.listener.Listener; diff --git a/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java b/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java index b69bf5d..5700c91 100644 --- a/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java +++ b/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.event.targeted; import me.tori.wraith.listener.Listener; diff --git a/src/main/java/me/tori/wraith/listener/EventListener.java b/src/main/java/me/tori/wraith/listener/EventListener.java index 1f200fa..3b428a4 100644 --- a/src/main/java/me/tori/wraith/listener/EventListener.java +++ b/src/main/java/me/tori/wraith/listener/EventListener.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.listener; import me.tori.wraith.bus.IEventBus; @@ -18,9 +39,11 @@ */ public abstract class EventListener implements Listener { - protected final int priority; - protected final @Nullable Class type; protected final @NotNull Class target; + protected final @Nullable Class type; + protected final int priority; + protected final boolean indefinitePersistence; + protected int persists; /** * Constructs an event listener with default priority and no specified type. @@ -47,7 +70,7 @@ public EventListener(@NotNull Class target, int priority) { * Constructs an event listener with default priority and a specified type. * * @param target The target class that this listener is designed to handle events for. - * @param type The type of events that this listener can handle. + * @param type The type of events that this listener can handle. Can be {@code null}. * @throws NullPointerException if {@code target} is {@code null}. */ public EventListener(@NotNull Class target, @Nullable Class type) { @@ -59,14 +82,31 @@ public EventListener(@NotNull Class target, @Nullable Class type) * * @param target The target class that this listener is designed to handle events for. * @param priority The priority level of this listener for event handling. - * @param type The type of events that this listener can handle. + * @param type The type of events that this listener can handle. Can be {@code null}. * @throws NullPointerException if {@code target} is {@code null}. */ public EventListener(@NotNull Class target, int priority, @Nullable Class type) { + this(target, type, priority, 0); + } + + /** + * Constructs an event listener with a specified priority and type. + * + * @param target The target class that this listener is designed to handle events for. + * @param type The type of events that this listener can handle. Can be {@code null}. + * @param priority The priority level of this listener for event handling. + * @param persists How many events this listener should handle before being killed. + * A value {@code <= 0} will flag this listener to {@linkplain #indefinitePersistence persist indefinitely}. + * @throws NullPointerException if {@code target} is {@code null}. + * @since 3.2.0 + */ + public EventListener(@NotNull Class target, @Nullable Class type, int priority, int persists) { Objects.requireNonNull(target); this.priority = priority; this.target = target; this.type = type; + this.persists = persists; + this.indefinitePersistence = persists <= 0; } /** @@ -101,6 +141,32 @@ public Class getTarget() { return target; } + /** + * Determines whether this listener should persist after being invoked. + * The listener persists if it is inherently persistent (as determined by {@link #hasIndefinitePersistence()}) + * or if the {@linkplain EventListener#persists internal persistence counter} is greater than zero + * after being decremented. + * + * @return {@code true} if the listener should persist, {@code false} otherwise + * @since 3.2.0 + */ + @Override + public boolean shouldPersist() { + return hasIndefinitePersistence() || ((--persists) > 0); + } + + /** + * Indicates whether this listener is inherently persistent. + * A listener is considered inherently persistent if the {@linkplain #indefinitePersistence} flag is set to {@code true}. + * + * @return {@code true} if the listener is inherently persistent, {@code false} otherwise + * @since 3.2.0 + */ + @Override + public boolean hasIndefinitePersistence() { + return indefinitePersistence; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -114,6 +180,9 @@ public boolean equals(Object o) { if (priority != that.priority) { return false; } + if (indefinitePersistence != that.indefinitePersistence) { + return false; + } if (!Objects.equals(type, that.type)) { return false; } @@ -122,18 +191,22 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = priority; - result = (31 * result) + ((type != null) ? type.hashCode() : 0); - result = (31 * result) + target.hashCode(); + int result = target.hashCode(); + result = 31 * result + Objects.hashCode(type); + result = 31 * result + priority; + result = 31 * result + Boolean.hashCode(indefinitePersistence); + result = 31 * result + persists; return result; } @Override public String toString() { return "EventListener{" + - "priority=" + priority + + "target=" + target + ", type=" + type + - ", target=" + target + + ", priority=" + priority + + ", indefinitePersistence=" + indefinitePersistence + + ", persists=" + persists + '}'; } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/listener/Invokable.java b/src/main/java/me/tori/wraith/listener/Invokable.java index 1d2cb3d..d8594ff 100644 --- a/src/main/java/me/tori/wraith/listener/Invokable.java +++ b/src/main/java/me/tori/wraith/listener/Invokable.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.listener; /** diff --git a/src/main/java/me/tori/wraith/listener/LambdaEventListener.java b/src/main/java/me/tori/wraith/listener/LambdaEventListener.java index 8d2adb0..a6b89ee 100644 --- a/src/main/java/me/tori/wraith/listener/LambdaEventListener.java +++ b/src/main/java/me/tori/wraith/listener/LambdaEventListener.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.listener; import org.jetbrains.annotations.NotNull; @@ -73,6 +94,23 @@ public LambdaEventListener(@NotNull Class target, int priority, @Null this.invokable = invokable; } + /** + * Constructs a new {@code LambdaEventListener} with the given target class, priority, type, and invokable action. + * + * @param target The target class of the event. + * @param type The type of the event. + * @param priority The priority of this listener. + * @param persists How many events this listener should handle before being killed. + * A value {@code <= 0} will flag this listener to {@linkplain #indefinitePersistence persist indefinitely}. + * @param invokable The invokable action to be executed when the event is dispatched. + * @throws NullPointerException if {@code target} is {@code null}. + */ + public LambdaEventListener(@NotNull Class target, @Nullable Class type, int priority, int persists, @NotNull Invokable invokable) { + super(target, type, priority, persists); + Objects.requireNonNull(invokable); + this.invokable = invokable; + } + /** * Invokes the wrapped invokable action with the provided event. * @@ -88,12 +126,13 @@ public boolean equals(Object o) { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if ((o == null) || (getClass() != o.getClass())) { return false; } if (!super.equals(o)) { return false; } + LambdaEventListener that = (LambdaEventListener) o; return invokable.equals(that.invokable); } @@ -101,17 +140,19 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + invokable.hashCode(); + result = (31 * result) + invokable.hashCode(); return result; } @Override public String toString() { return "LambdaEventListener{" + - "invokable=" + invokable + - ", priority=" + priority + + "target=" + target + ", type=" + type + - ", target=" + target + + ", priority=" + priority + + ", indefinitePersistence=" + indefinitePersistence + + ", persists=" + persists + + ", invokable=" + invokable + '}'; } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/listener/Listener.java b/src/main/java/me/tori/wraith/listener/Listener.java index 3ea8909..cfdb508 100644 --- a/src/main/java/me/tori/wraith/listener/Listener.java +++ b/src/main/java/me/tori/wraith/listener/Listener.java @@ -1,5 +1,32 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.listener; +import me.tori.wraith.bus.EventBus; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + /** * An interface representing an event listener with priority, type, and target class information. * @@ -21,7 +48,7 @@ public interface Listener extends Invokable { /** * Gets the type of events that this listener can handle. * - * @return The type of events that this listener can handle, or null if no type is specified. + * @return The type of events that this listener can handle, or {@code null} if no type is specified. */ Class getType(); @@ -31,4 +58,26 @@ public interface Listener extends Invokable { * @return The target class that this listener is designed to handle events for. */ Class getTarget(); + + /** + * Determines whether this listener should persist after being invoked. + * + * @return {@code true} if the listener should persist, {@code false} otherwise + * @see EventBus#forEachListener(List, Predicate, Consumer, boolean) + * @since 3.2.0 + */ + @SuppressWarnings("JavadocReference") + default boolean shouldPersist() { + return hasIndefinitePersistence(); + } + + /** + * Indicates whether this listener is inherently persistent. + * + * @return {@code true} if the listener is inherently persistent, {@code false} otherwise + * @since 3.2.0 + */ + default boolean hasIndefinitePersistence() { + return true; + } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/listener/ListenerBuilder.java b/src/main/java/me/tori/wraith/listener/ListenerBuilder.java new file mode 100644 index 0000000..bf576c0 --- /dev/null +++ b/src/main/java/me/tori/wraith/listener/ListenerBuilder.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.listener; + +import me.tori.wraith.bus.IEventBus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * A builder class for creating instances of {@link EventListener}. + * + *

This builder allows configuring various properties of an {@link EventListener}, + * including the target class, type, priority, persistence, and the invokable action. + * + *

Usage Example: + *

+ * {@code
+ * EventListener listener = new ListenerBuilder()
+ *     .target(MyEvent.class)
+ *     .type(SomeSpecificType.class)
+ *     .priority(5)
+ *     .persists(10)
+ *     .invokable(event -> handleEvent(event))
+ *     .build();
+ * }
+ * 
+ * + * @param the type of event this listener handles + * @author 7orivorian + * @see EventListener + * @since 3.2.0 + */ +public class ListenerBuilder { + + private Class target = null; + private @Nullable Class type = null; + private int priority = IEventBus.DEFAULT_PRIORITY; + private int persists = -1; + private boolean persistent = true; + private Invokable invokable = null; + + /** + * Sets the target class for this listener. + * + * @param target the class of the event this listener will handle + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder target(@NotNull Class target) { + this.target = target; + return this; + } + + /** + * Sets the specific type for this listener. + * + * @param type the specific type of event this listener will handle + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder type(@Nullable Class type) { + this.type = type; + return this; + } + + /** + * Sets the priority for this listener. + * + * @param priority the priority of the listener + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder priority(int priority) { + this.priority = priority; + return this; + } + + /** + * Sets the number of times this listener should persist. + *

+ * Overrides {@link #persistent}. + * + * @param persists the number of events this listener should handle before being removed + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder persists(int persists) { + this.persists = persists; + this.persistent = persists <= 0; + return this; + } + + /** + * Sets whether this listener is inherently persistent. + *

+ * Overrides {@link #persists}. + * + * @param persistent {@code true} if the listener should be persistent, {@code false} otherwise + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder persistent(boolean persistent) { + this.persistent = persistent; + if (persistent) { + return persists(0); + } + return this; + } + + /** + * Sets the invokable action for this listener. + * + * @param invokable the action to be invoked when an event is handled + * @return this {@code ListenerBuilder} instance + */ + public ListenerBuilder invokable(@NotNull Invokable invokable) { + this.invokable = invokable; + return this; + } + + /** + * Builds and returns an {@link EventListener} with the configured properties. + * + * @return a new {@link EventListener} instance + * @throws NullPointerException if the target or invokable is not set + * @throws IllegalArgumentException if there is a mismatch between persistence settings + */ + @NotNull + public EventListener build() { + Objects.requireNonNull(target, "target must not be null"); + Objects.requireNonNull(invokable, "invokable must not be null"); + if ((persistent && (persists > 0)) || (!persistent && (persists <= 0))) { + throw new IllegalArgumentException( + "Persistency missmatch. persistent=" + persistent + " and persists>" + persists + " is not allowed." + ); + } + return new EventListener<>(target, type, priority, persists) { + @Override + public void invoke(T event) { + invokable.invoke(event); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/subscriber/ISubscriber.java b/src/main/java/me/tori/wraith/subscriber/ISubscriber.java index 08b5b4a..1936bd6 100644 --- a/src/main/java/me/tori/wraith/subscriber/ISubscriber.java +++ b/src/main/java/me/tori/wraith/subscriber/ISubscriber.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.subscriber; import me.tori.wraith.listener.Listener; diff --git a/src/main/java/me/tori/wraith/subscriber/Subscriber.java b/src/main/java/me/tori/wraith/subscriber/Subscriber.java index 1c26936..a0faa12 100644 --- a/src/main/java/me/tori/wraith/subscriber/Subscriber.java +++ b/src/main/java/me/tori/wraith/subscriber/Subscriber.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.subscriber; import me.tori.wraith.listener.Listener; diff --git a/src/main/java/me/tori/wraith/task/ScheduledTask.java b/src/main/java/me/tori/wraith/task/ScheduledTask.java index 1198fee..d257077 100644 --- a/src/main/java/me/tori/wraith/task/ScheduledTask.java +++ b/src/main/java/me/tori/wraith/task/ScheduledTask.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.task; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/me/tori/wraith/task/TaskExecutor.java b/src/main/java/me/tori/wraith/task/TaskExecutor.java index 2311015..e2beb99 100644 --- a/src/main/java/me/tori/wraith/task/TaskExecutor.java +++ b/src/main/java/me/tori/wraith/task/TaskExecutor.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.task; import java.util.ArrayList; @@ -34,7 +55,7 @@ public TaskExecutor() { */ public boolean onEvent(Object event) { ArrayList queue = tasks.get(event.getClass()); - if (queue != null) { + if ((queue != null) && !queue.isEmpty()) { boolean executed = false; for (int i = 0; i < queue.size(); ) { ScheduledTask task = queue.get(i); diff --git a/src/main/resources/LICENSE.md b/src/main/resources/LICENSE similarity index 96% rename from src/main/resources/LICENSE.md rename to src/main/resources/LICENSE index f186ace..7a2067d 100644 --- a/src/main/resources/LICENSE.md +++ b/src/main/resources/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 7orivorian +Copyright (c) 2021-2024 7orivorian Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/main/test/me/tori/wraith/benchmarking/MyBenchmark.java b/src/main/test/me/tori/wraith/benchmarking/MyBenchmark.java new file mode 100644 index 0000000..b7d3660 --- /dev/null +++ b/src/main/test/me/tori/wraith/benchmarking/MyBenchmark.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.benchmarking; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.listener.EventListener; +import me.tori.wraith.subscriber.Subscriber; +import org.openjdk.jmh.Main; +import org.openjdk.jmh.annotations.*; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * @author 7orivorian + * @since 3.2.0 + */ +public class MyBenchmark { + + public static void main(String[] args) throws IOException { + Main.main(args); + } + + @State(Scope.Thread) + public static class BenchmarkState { + MyListener myListener; + MySubscriber mySubscriber; + EventBus bus; + + @Setup(Level.Trial) + public void setup() { + bus = new EventBus(); + mySubscriber = new MySubscriber(); + myListener = new MyListener(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + @Warmup(iterations = 1, time = 2) + @Measurement(iterations = 2, time = 2) + @Fork(5) + public void testMethod(BenchmarkState state) { + for (int i = 0; i < 1_000; i++) { + state.bus.register(state.myListener); + } + } + + public static class MySubscriber extends Subscriber { + + public MySubscriber() { + registerListener( + new MyListener() + ); + } + } + + public static class MyListener extends EventListener { + + public MyListener() { + super(MyEvent.class); + } + + @Override + public void invoke(MyEvent event) { + System.out.println(event.content()); + } + + @Override + public boolean shouldPersist() { + return false; + } + } + + public static final class MyEvent { + + private String content; + + public MyEvent(String content) { + this.content = content; + } + + public String content() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @Override + public String toString() { + return "MyEvent[" + + "content=" + content + ']'; + } + } +} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/persistency/PersistencyTest.java b/src/main/test/me/tori/wraith/persistency/PersistencyTest.java new file mode 100644 index 0000000..1fd050e --- /dev/null +++ b/src/main/test/me/tori/wraith/persistency/PersistencyTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.persistency; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.event.cancelable.CancelableEvent; +import me.tori.wraith.listener.EventListener; +import me.tori.wraith.subscriber.Subscriber; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author 7orivorian + * @since 3.2.0 + */ +public class PersistencyTest { + + @Test + public void testEventPersistency() { + final EventBus bus = new EventBus(); + + bus.subscribe(new Subscriber() {{ + registerListener(new MyListener(3)); + }}); + + Assertions.assertTrue(bus.dispatch(new MyEvent())); + Assertions.assertTrue(bus.dispatch(new MyEvent())); + Assertions.assertTrue(bus.dispatch(new MyEvent())); + + Assertions.assertFalse(bus.dispatch(new MyEvent())); + } + + @Test + public void testIndefiniteEvent() { + final EventBus bus = new EventBus(); + + bus.subscribe(new Subscriber() {{ + registerListener(new MyListener(0)); // <= 0 means persist indefinitely + }}); + + for (int i = 0; i < 1_000_000; i++) { + Assertions.assertTrue(bus.dispatch(new MyEvent())); + } + } + + public static class MyListener extends EventListener { + + public MyListener(int persists) { + super(MyEvent.class, null, 0, persists); + } + + @Override + public void invoke(MyEvent event) { + event.cancel(); + } + } + + public static class MyEvent extends CancelableEvent { + + } +} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/statusevent/StatusEventTest.java b/src/main/test/me/tori/wraith/statusevent/StatusEventTest.java new file mode 100644 index 0000000..03cff8e --- /dev/null +++ b/src/main/test/me/tori/wraith/statusevent/StatusEventTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package me.tori.wraith.statusevent; + +import me.tori.wraith.bus.EventBus; +import me.tori.wraith.event.status.StatusEvent; +import me.tori.wraith.listener.LambdaEventListener; +import me.tori.wraith.subscriber.Subscriber; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * @author 7orivorian + * @since 3.2.0 + */ +public class StatusEventTest { + + @Test + public void testSupression() { + final EventBus bus = new EventBus(); + + MySubscriber subscriber = new MySubscriber() {{ + registerListeners( + new LambdaEventListener<>(StatusEvent.class, 1, event -> { + this.counter = 1; + event.suppress(); + }), + new LambdaEventListener<>(StatusEvent.class, 0, event -> { + this.counter++; + }) + ); + }}; + bus.subscribe(subscriber); + + Assertions.assertTrue(bus.dispatch(new StatusEvent())); + Assertions.assertEquals(2, subscriber.counter); + } + + @Test + public void testTermination() { + final EventBus bus = new EventBus(); + + MySubscriber subscriber = new MySubscriber() {{ + registerListeners( + new LambdaEventListener<>(StatusEvent.class, 1, event -> { + this.counter = 1; + event.terminate(); + }), + new LambdaEventListener<>(StatusEvent.class, 0, event -> { + this.counter = 1_000; + }) + ); + }}; + bus.subscribe(subscriber); + + Assertions.assertTrue(bus.dispatch(new StatusEvent())); + Assertions.assertEquals(1, subscriber.counter); + } + + private static class MySubscriber extends Subscriber { + + public int counter = 0; + + public MySubscriber() { + + } + } +} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/InvalidListener.java b/src/main/test/me/tori/wraith/targetedevent/InvalidListener.java deleted file mode 100644 index 04cb61d..0000000 --- a/src/main/test/me/tori/wraith/targetedevent/InvalidListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.tori.wraith.targetedevent; - -import me.tori.wraith.listener.EventListener; - -/** - * @author 7orivorian - */ -public class InvalidListener extends EventListener { - - public InvalidListener() { - super(TestEvent.class); - } - - @Override - public void invoke(TestEvent event) { - event.message = "mwahahahaa >:/"; - event.cancel(); - } -} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java b/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java index 0ed9b61..a7ddbb3 100644 --- a/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java +++ b/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java @@ -1,6 +1,32 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.targetedevent; import me.tori.wraith.bus.EventBus; +import me.tori.wraith.event.cancelable.CancelableEvent; +import me.tori.wraith.event.targeted.IClassTargetingEvent; +import me.tori.wraith.listener.EventListener; +import me.tori.wraith.listener.Listener; +import me.tori.wraith.subscriber.Subscriber; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -14,10 +40,52 @@ public class TargetedEventTest { public void testTargetedEvent() { final EventBus bus = new EventBus(); - TestSubsciber subsciber = new TestSubsciber(); - bus.subscribe(subsciber); + bus.subscribe(new Subscriber() {{ + registerListeners( + new MyListener(), + new OtherListener() + ); + }}); - TestEvent event = new TestEvent("message", ValidListener.class); + TestEvent event = new TestEvent(MyListener.class); assertFalse(bus.dispatchTargeted(event)); } + + public static class MyListener extends EventListener { + + public MyListener() { + super(TestEvent.class); + } + + @Override + public void invoke(TestEvent event) { + + } + } + + public static class OtherListener extends EventListener { + + public OtherListener() { + super(TestEvent.class); + } + + @Override + public void invoke(TestEvent event) { + event.cancel(); + } + } + + public static class TestEvent extends CancelableEvent implements IClassTargetingEvent { + + private final Class> targetClass; + + public TestEvent(Class> target) { + this.targetClass = target; + } + + @Override + public Class> getTargetClass() { + return targetClass; + } + } } \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/TestEvent.java b/src/main/test/me/tori/wraith/targetedevent/TestEvent.java deleted file mode 100644 index 3a074e7..0000000 --- a/src/main/test/me/tori/wraith/targetedevent/TestEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.tori.wraith.targetedevent; - -import me.tori.wraith.event.cancelable.CancelableEvent; -import me.tori.wraith.event.targeted.IClassTargetingEvent; -import me.tori.wraith.listener.Listener; - -/** - * @author 7orivorian - */ -public class TestEvent extends CancelableEvent implements IClassTargetingEvent { - - public String message; - private final Class> targetClass; - - public TestEvent(String message, Class> target) { - this.message = message; - this.targetClass = target; - } - - @Override - public Class> getTargetClass() { - return targetClass; - } -} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/TestSubsciber.java b/src/main/test/me/tori/wraith/targetedevent/TestSubsciber.java deleted file mode 100644 index 59041a9..0000000 --- a/src/main/test/me/tori/wraith/targetedevent/TestSubsciber.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.tori.wraith.targetedevent; - -import me.tori.wraith.subscriber.Subscriber; - -/** - * @author 7orivorian - */ -public class TestSubsciber extends Subscriber { - - public TestSubsciber() { - registerListeners( - new ValidListener(), - new InvalidListener() - ); - } -} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/ValidListener.java b/src/main/test/me/tori/wraith/targetedevent/ValidListener.java deleted file mode 100644 index dd9d401..0000000 --- a/src/main/test/me/tori/wraith/targetedevent/ValidListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package me.tori.wraith.targetedevent; - -import me.tori.wraith.listener.EventListener; - -/** - * @author 7orivorian - */ -public class ValidListener extends EventListener { - - public ValidListener() { - super(TestEvent.class); - } - - @Override - public void invoke(TestEvent event) { - event.message = "hello world :D"; - } -} \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/taskexecutor/TaskExecutorTest.java b/src/main/test/me/tori/wraith/taskexecutor/TaskExecutorTest.java index 8b18593..a735a2d 100644 --- a/src/main/test/me/tori/wraith/taskexecutor/TaskExecutorTest.java +++ b/src/main/test/me/tori/wraith/taskexecutor/TaskExecutorTest.java @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2021-2024 7orivorian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + package me.tori.wraith.taskexecutor; import me.tori.wraith.task.ScheduledTask; @@ -42,28 +63,42 @@ public void run() { @Test public void testDelayedSingleExecution() { TaskExecutor executor = new TaskExecutor(); - executor.schedule(new ScheduledTask(TargetEvent.class, 1) { // Skip 1 event + + // Schedule a task to execute after skipping 1 event + executor.schedule(new ScheduledTask(TargetEvent.class, 1) { @Override public void run() { } }); + // This event should be skipped Assertions.assertFalse(executor.onEvent(new TargetEvent())); + + // Tasks should be executed on this event Assertions.assertTrue(executor.onEvent(new TargetEvent())); + + // This event should be skipped Assertions.assertFalse(executor.onEvent(new TargetEvent())); - executor.schedule(new ScheduledTask(TargetEvent.class, 3) { // Skip 3 events + + // Schedule a task to execute after skipping 3 events + executor.schedule(new ScheduledTask(TargetEvent.class, 3) { @Override public void run() { } }); + // These events should be skipped Assertions.assertFalse(executor.onEvent(new TargetEvent())); Assertions.assertFalse(executor.onEvent(new TargetEvent())); Assertions.assertFalse(executor.onEvent(new TargetEvent())); + + // Tasks should be executed on this event Assertions.assertTrue(executor.onEvent(new TargetEvent())); + + // This event should be skipped Assertions.assertFalse(executor.onEvent(new TargetEvent())); }