diff --git a/.gitignore b/.gitignore
index c563bd9..3f5e349 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,3 @@
-### Wraith Specifics
-developer-docs
-
### Java template
# Compiled class file
*.class
@@ -668,3 +665,6 @@ bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
+
+### Project Specific ###
+developer-docs/
diff --git a/.run/test in Wraith.run.xml b/.run/test in Wraith.run.xml
new file mode 100644
index 0000000..2454a17
--- /dev/null
+++ b/.run/test in Wraith.run.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 83e33ab..bce696f 100644
--- a/README.md
+++ b/README.md
@@ -2,17 +2,31 @@
# Wraith
-![GitHub all releases](https://img.shields.io/github/downloads/7orivorian/Wraith/total?style=flat-square)
-![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/7orivorian/Wraith?style=flat-square)
-[![](https://jitci.com/gh/7orivorian/Wraith/svg)](https://jitci.com/gh/7orivorian/Wraith)
+![GitHub all releases](https://img.shields.io/github/downloads/7orivorian/Wraith/total?style=flat)
+![GitHub Release](https://img.shields.io/github/v/release/7orivorian/Wraith?sort=semver&style=flat&link=https%3A%2F%2Fgithub.com%2F7orivorian%2FWraith%2Freleases%2Flatest)
+![JitPack Release](https://jitpack.io/v/dev.7ori/Wraith.svg?style=flat)
+[![JitCI](https://jitci.com/gh/7orivorian/Wraith/svg)](https://jitci.com/gh/7orivorian/Wraith)
+![GitHub License](https://img.shields.io/github/license/7orivorian/Wraith?color=blue)
-Lightweight Java event library created and maintained by [7orivorian](https://github.com/7orivorian)
+Capable, versatile, and easy to use Java event library.
-# Importing
+## Key Features
-### Maven
+- Easily define your own events, listeners, & event buses.
+- Out-of-the-box support for any scenario.
+- Performant.
+- Fully documented.
-* Include JitPack in your maven build file
+## Usage
+
+Click [here](https://docs.7ori.dev/wraith/importing) to learn how to import Wraith into your own project.
+For more information, please see the Wraith [documentation](https://docs.7ori.dev/wraith/).
+
+## Import with Build Automation
+
+
+Maven
+Include JitPack in your maven build file.
```xml
@@ -24,228 +38,71 @@ Lightweight Java event library created and maintained by [7orivorian](https://gi
```
-* Add Wraith as a dependency
+Add the dependency.
```xml
com.github.7orivorianWraith
- 3.3.0
+ 4.0.0
```
-### Gradle
-
-* Add JitPack to your root `build.gradle` at the end of repositories
+
+
+Gradle
+Add JitPack to your root `build.gradle` at the end of repositories.
-```gradle
+```groovy
repositories {
+ //...
maven {
url 'https://jitpack.io'
}
}
```
-* Add the dependency
+Add the dependency.
-```gradle
+```groovy
dependencies {
- implementation 'com.github.7orivorian:Wraith:3.3.0'
-}
-```
-
-### Other
-
-Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/releases/tag/3.3.0)
-
-# Building
-
-* Clone this repository
-* Run `mvn package`
-
-Packaged file can be found in the `target/` directory.
-
-# 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...
-
-To define a subscriber, you have multiple options:
-
-Extending the Subscriber class:
-
-```java
-public class ExampleSubscriber extends Subscriber {
-// ...
-}
-```
-
-Implementing the ISubscriber interface:
-
-```java
-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 Consts {
- private static final IEventBus EVENT_BUS = new EventBus();
-}
-
-public class ExampleSubscriber extends Subscriber {
-
- public ExampleSubscriber() {
- Consts.EVENT_BUS.subscribe(this);
- }
-}
-```
-
-Alternatively, you can subscribe a subscriber externally:
-
-```java
-public class Example {
- private static final IEventBus EVENT_BUS = new EventBus();
-
- public static void main(String[] args) {
- EVENT_BUS.subscribe(new ExampleSubscriber());
- }
+ implementation 'com.github.7orivorian:Wraith:4.0.0'
}
```
-
-### Defining Events
-
-Details...
+Gradle (Kotlin)
+Add JitPack to your root `build.gradle.kts` at the end of repositories.
-Any class can be used as an event. For instance:
-
-```java
-public class ExampleEvent {
- private String message;
-
- public ExampleEvent(String message) {
- this.message = message;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-}
-```
-
-
-
-### Listeners
-
-
-Details...
-
-For class event listeners, you can define your listeners as follows:
-
-```java
-public class ExampleListener extends EventListener {
-
- public ExampleListener() {
- super(ExampleEvent.class);
- }
-
- @Override
- public void invoke(ExampleEvent event) {
- event.setMessage("Hello world!");
- }
-}
-```
-
-```java
-public class ExampleSubscriber extends Subscriber {
-
- public ExampleSubscriber() {
- // Register the listener
- registerListener(new ExampleListener());
- }
-}
-```
-
-Lambda event listeners provide a more concise way to achieve the same functionality:
-
-```java
-public class ExampleSubscriber extends Subscriber {
-
- public ExampleSubscriber() {
- // Register the listener
- registerListener(
- new LambdaEventListener<>(ExampleEvent.class, event -> event.setMessage("Hello world!"))
- );
+```groovy
+repositories {
+ //...
+ maven {
+ url = uri("https://jitpack.io")
}
}
```
-
-
-### Dispatching Events
-
-
-Details...
-
-To dispatch an event, call one of the `dispatch` methods defined in `EventBus`, passing your event as a parameter:
-
-```java
-import me.tori.wraith.event.staged.EventStage;
-
-public class Example {
-
- private static final IEventBus EVENT_BUS = new EventBus();
+Add the dependency.
- public static void main(String[] args) {
-
- ExampleEvent event = new ExampleEvent("world greetings");
-
- EVENT_BUS.dispatch(event);
-
- System.out.println(event.getMessage());
- }
+```groovy
+dependencies {
+ implementation("com.github.7orivorian:Wraith:4.0.0")
}
```
-Please explore the [example folder](./examples/java/me/tori/example) for _even more_ Wraith implementations!
-
-# Contributing
-
-Contributions are welcome! Feel free to open a pull request.
-
-### Guidelines
-
-* Utilize similar [formatting](.editorconfig) and practises to the rest of the codebase
-* Do not include workspace files (such as an `.idea/` or `target/` directory) in your pull request
-* Include unit tests for any features you add
-
-### How to contribute
-
-To make a contribution, follow these steps:
+## Download a Jar
-1. Fork and clone this repository
-2. Make the changes to your fork
-3. Submit a pull request
+Wraith and its sources can be downloaded
+[here](https://github.com/7orivorian/Wraith/releases/latest).
-# License
+## License
-[Wraith is licensed under MIT](./LICENSE)
+[Wraith is licensed under MIT.](./LICENSE)
### MIT License Summary:
diff --git a/examples/java/me/tori/example/persistence/PersistenceExample.java b/examples/java/dev/tori/example/persistence/PersistenceExample.java
similarity index 84%
rename from examples/java/me/tori/example/persistence/PersistenceExample.java
rename to examples/java/dev/tori/example/persistence/PersistenceExample.java
index b6cbc6f..eec5f97 100644
--- a/examples/java/me/tori/example/persistence/PersistenceExample.java
+++ b/examples/java/dev/tori/example/persistence/PersistenceExample.java
@@ -19,12 +19,13 @@
* THE SOFTWARE.
*/
-package me.tori.example.persistence;
+package dev.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;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.listener.LambdaEventListener;
+import dev.tori.wraith.subscriber.Subscriber;
/**
* A simple example of listener persistence.
@@ -40,7 +41,7 @@ class PersistenceExample {
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));
+ registerListener(new LambdaEventListener(Target.fine(String.class), IEventBus.DEFAULT_PRIORITY, 1, System.out::println));
}};
public static void main(String[] args) {
diff --git a/examples/java/me/tori/example/simple/SimpleExample.java b/examples/java/dev/tori/example/simple/SimpleExample.java
similarity index 77%
rename from examples/java/me/tori/example/simple/SimpleExample.java
rename to examples/java/dev/tori/example/simple/SimpleExample.java
index 3d6fdfa..7e7173c 100644
--- a/examples/java/me/tori/example/simple/SimpleExample.java
+++ b/examples/java/dev/tori/example/simple/SimpleExample.java
@@ -19,12 +19,13 @@
* THE SOFTWARE.
*/
-package me.tori.example.simple;
+package dev.tori.example.simple;
-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 dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.StatusEvent;
+import dev.tori.wraith.listener.LambdaEventListener;
+import dev.tori.wraith.subscriber.Subscriber;
/**
* One-class example.
@@ -44,7 +45,7 @@ public static void main(String[] args) {
bus.subscribe(subscriber);
// Create a simple event
- SimpleEvent event = new SimpleEvent("Pie is delicious <3");
+ StringEvent event = new StringEvent("Pie is delicious <3");
// Dispatch our event
bus.dispatch(event);
@@ -54,16 +55,16 @@ private static final class SimpleSubscriber extends Subscriber {
public SimpleSubscriber() {
registerListener(
- new LambdaEventListener<>(SimpleEvent.class, event -> System.out.println(event.getMessage()))
+ new LambdaEventListener(Target.fine(StringEvent.class), event -> System.out.println(event.getMessage()))
);
}
}
- private static final class SimpleEvent extends StatusEvent {
+ private static final class StringEvent extends StatusEvent {
private final String message;
- public SimpleEvent(String message) {
+ public StringEvent(String message) {
this.message = message;
}
diff --git a/examples/java/me/tori/example/statusevents/SupressionExample.java b/examples/java/dev/tori/example/statusevents/SupressionExample.java
similarity index 81%
rename from examples/java/me/tori/example/statusevents/SupressionExample.java
rename to examples/java/dev/tori/example/statusevents/SupressionExample.java
index f62abf0..512e313 100644
--- a/examples/java/me/tori/example/statusevents/SupressionExample.java
+++ b/examples/java/dev/tori/example/statusevents/SupressionExample.java
@@ -19,13 +19,14 @@
* THE SOFTWARE.
*/
-package me.tori.example.statusevents;
+package dev.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;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.StatusEvent;
+import dev.tori.wraith.listener.LambdaEventListener;
+import dev.tori.wraith.subscriber.Subscriber;
/**
* @author 7orivorian
@@ -36,11 +37,11 @@ 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 -> {
+ new LambdaEventListener(Target.fine(StringEvent.class), 1, event -> {
event.message = "Hello world!";
event.suppress();
}),
- new LambdaEventListener<>(StringEvent.class, 0, event -> {
+ new LambdaEventListener(Target.fine(StringEvent.class), 0, event -> {
event.message = "I do not greet";
})
);
diff --git a/examples/java/me/tori/example/statusevents/TerminationExample.java b/examples/java/dev/tori/example/statusevents/TerminationExample.java
similarity index 81%
rename from examples/java/me/tori/example/statusevents/TerminationExample.java
rename to examples/java/dev/tori/example/statusevents/TerminationExample.java
index 5a2a4f1..aaccd5a 100644
--- a/examples/java/me/tori/example/statusevents/TerminationExample.java
+++ b/examples/java/dev/tori/example/statusevents/TerminationExample.java
@@ -19,13 +19,14 @@
* THE SOFTWARE.
*/
-package me.tori.example.statusevents;
+package dev.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;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.StatusEvent;
+import dev.tori.wraith.listener.LambdaEventListener;
+import dev.tori.wraith.subscriber.Subscriber;
/**
* @author 7orivorian
@@ -36,11 +37,11 @@ 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 -> {
+ new LambdaEventListener(Target.fine(StringEvent.class), 1, event -> {
event.message = "Hello world!";
event.terminate();
}),
- new LambdaEventListener<>(StringEvent.class, 0, event -> {
+ new LambdaEventListener(Target.fine(StringEvent.class), 0, event -> {
event.message = "I do not greet";
})
);
diff --git a/examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java b/examples/java/dev/tori/example/taskexecutor/TaskExecutorExample.java
similarity index 93%
rename from examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java
rename to examples/java/dev/tori/example/taskexecutor/TaskExecutorExample.java
index f94777c..435f040 100644
--- a/examples/java/me/tori/example/taskexecutor/TaskExecutorExample.java
+++ b/examples/java/dev/tori/example/taskexecutor/TaskExecutorExample.java
@@ -19,11 +19,11 @@
* THE SOFTWARE.
*/
-package me.tori.example.taskexecutor;
+package dev.tori.example.taskexecutor;
-import me.tori.wraith.bus.EventBus;
-import me.tori.wraith.task.ScheduledTask;
-import me.tori.wraith.task.TaskExecutor;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.task.ScheduledTask;
+import dev.tori.wraith.task.TaskExecutor;
/**
* A simple example showing how to use the {@link TaskExecutor}
diff --git a/examples/java/me/tori/example/expanded/ExampleEvent.java b/examples/java/me/tori/example/expanded/ExampleEvent.java
deleted file mode 100644
index 3b1a423..0000000
--- a/examples/java/me/tori/example/expanded/ExampleEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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;
-import me.tori.wraith.event.staged.IStagedEvent;
-import me.tori.wraith.event.status.StatusEvent;
-
-/**
- * Example event.
- *
- * @author 7orivorian
- * @since 1.0.0
- */
-class ExampleEvent extends StatusEvent implements IStagedEvent {
-
- private String message;
- private final EventStage stage;
-
- public ExampleEvent(EventStage stage) {
- this.stage = stage;
- this.message = "nothing to say";
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- @Override
- public EventStage getStage() {
- return stage;
- }
-}
\ No newline at end of file
diff --git a/examples/java/me/tori/example/expanded/ExampleMain.java b/examples/java/me/tori/example/expanded/ExampleMain.java
deleted file mode 100644
index 25b663f..0000000
--- a/examples/java/me/tori/example/expanded/ExampleMain.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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;
-import me.tori.wraith.bus.IEventBus;
-import me.tori.wraith.event.staged.EventStage;
-
-/**
- * Example program.
- *
- * @author 7orivorian
- * @since 1.0.0
- */
-class ExampleMain {
-
- private static final IEventBus EVENT_BUS = new EventBus();
-
- private static final ExampleSubscriber EXAMPLE_SUBSCRIBER = new ExampleSubscriber();
-
- public static void main(String[] args) {
- EVENT_BUS.subscribe(EXAMPLE_SUBSCRIBER);
-
- ExampleEvent event1 = new ExampleEvent(EventStage.PRE);
-
- EVENT_BUS.dispatch(event1);
-
- if (!event1.isSuppressed()) {
- System.out.println(event1.getMessage());
- }
-
- ExampleEvent event2 = new ExampleEvent(EventStage.POST);
-
- EVENT_BUS.dispatch(event2);
-
- if (!event2.isSuppressed()) {
- System.out.println(event2.getMessage());
- }
- }
-}
\ No newline at end of file
diff --git a/examples/java/me/tori/example/expanded/ExampleSubscriber.java b/examples/java/me/tori/example/expanded/ExampleSubscriber.java
deleted file mode 100644
index f3cf156..0000000
--- a/examples/java/me/tori/example/expanded/ExampleSubscriber.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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;
-import me.tori.wraith.listener.LambdaEventListener;
-import me.tori.wraith.subscriber.Subscriber;
-
-/**
- * Example subscriber.
- *
- * @author 7orivorian
- * @since 1.0.0
- */
-class ExampleSubscriber extends Subscriber {
-
- public ExampleSubscriber() {
- registerListener(
- new LambdaEventListener<>(ExampleEvent.class, event -> {
- if (event.getStage() == EventStage.PRE) {
- event.setMessage("Hello world!");
- }
- })
- );
- registerListener(new ExampleListener());
- }
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index c829fcb..a761a8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,10 +7,10 @@
Java event libraryhttps://github.com/7orivorian/Wraith
- me.tori
+ dev.7ori.wraithWraithjar
- 3.3.0
+ 4.0.0
@@ -22,7 +22,7 @@
7orivorian
- Tori Vii
+ Torihttps://7ori.dev
@@ -60,6 +60,14 @@
UTF-8
+
+
+ github
+ GitHub 7orivorian Apache Maven Packages
+ https://maven.pkg.github.com/7orivorian/Wraith
+
+
+
diff --git a/src/main/java/dev/tori/wraith/bus/AbstractEventBus.java b/src/main/java/dev/tori/wraith/bus/AbstractEventBus.java
new file mode 100644
index 0000000..0f8d040
--- /dev/null
+++ b/src/main/java/dev/tori/wraith/bus/AbstractEventBus.java
@@ -0,0 +1,360 @@
+/*
+ * 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 dev.tori.wraith.bus;
+
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.IStatusEvent;
+import dev.tori.wraith.listener.Listener;
+import dev.tori.wraith.subscriber.ISubscriber;
+import dev.tori.wraith.task.ScheduledTask;
+import dev.tori.wraith.task.TaskExecutor;
+import dev.tori.wraith.util.IndexedHashSet;
+import org.jetbrains.annotations.Contract;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+
+/**
+ * Abstract implementation of {@link IEventBus}.
+ *
+ * Manages subscription and task scheduling.
+ *
+ * @author 7orivorian
+ * @since 4.0.0
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public abstract class AbstractEventBus implements IEventBus {
+
+ /**
+ * The amount of {@linkplain AbstractEventBus} instances that have been created.
+ */
+ private static int instances = 0;
+
+ /**
+ * This event bus's id.
+ */
+ protected final int id;
+ /**
+ * Indicates whether this event bus is shutdown.
+ *
+ * @apiNote Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException} when
+ * attempting to do so.
+ */
+ protected boolean shutdown;
+ /**
+ * A {@link Set} of this event bus' {@link ISubscriber subscribers}.
+ */
+ protected final Set subscribers;
+ /**
+ * A {@link TaskExecutor} that manages the scheduling and execution of tasks associated with events. It provides
+ * a mechanism to associate event classes with queues of tasks and ensures their orderly execution when the
+ * corresponding events are dispatched.
+ *
+ * @see #scheduleTask(ScheduledTask)
+ */
+ protected final TaskExecutor taskExecutor;
+
+ /**
+ * Creates a new event bus instance.
+ */
+ public AbstractEventBus() {
+ this.id = instances++;
+ this.shutdown = false;
+ this.subscribers = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ this.taskExecutor = new TaskExecutor();
+ }
+
+ /**
+ * @return The amount of {@linkplain AbstractEventBus} instances that have been created.
+ */
+ @Contract(pure = true)
+ public static int getInstanceCount() {
+ return instances;
+ }
+
+ /**
+ * Subscribes a {@link ISubscriber subscriber} to this event bus and registers all the
+ * subscriber's {@link Listener listeners}
+ *
+ * @param subscriber the {@link ISubscriber} to be subscribed
+ * @throws NullPointerException if the given {@link ISubscriber} is {@code null}
+ * @see #register(Listener)
+ */
+ @Override
+ public void subscribe(ISubscriber subscriber) {
+ Objects.requireNonNull(subscriber, "Cannot subscribe null to event bus " + id + ".");
+
+ subscribers.add(subscriber);
+ subscriber.linkToBus(this);
+
+ Collection> listeners = subscriber.getListeners();
+ if (!listeners.isEmpty()) {
+ if (listeners.size() == 1) {
+ register(listeners.iterator().next());
+ } else {
+ for (Listener> listener : listeners) {
+ register(listener);
+ }
+ }
+ }
+ }
+
+ /**
+ * Unsubscribes a {@link ISubscriber subscriber} from this event bus and unregisters all the
+ * subscriber's {@link Listener listeners}.
+ *
+ * @param subscriber the {@link ISubscriber} to be unsubscribed
+ * @throws NullPointerException if the given {@link ISubscriber} is {@code null}
+ * @see #unregister(Listener)
+ */
+ @Override
+ public void unsubscribe(ISubscriber subscriber) {
+ Objects.requireNonNull(subscriber, "Cannot unsubscribe null from event bus " + id + ".");
+
+ subscribers.remove(subscriber);
+ subscriber.unlinkFromBus(this);
+
+ Collection> listeners = subscriber.getListeners();
+ if (!listeners.isEmpty()) {
+ if (listeners.size() == 1) {
+ unregister(listeners.iterator().next());
+ } else {
+ for (Listener> listener : listeners) {
+ unregister(listener);
+ }
+ }
+ }
+ }
+
+ /**
+ * Unsubscribes all {@link ISubscriber subscribers} and unregisters all their
+ * {@link Listener listeners} from this event bus.
+ *
+ * @apiNote Listeners registered directly to this event bus will not be unregistered.
+ */
+ public void unsubscribeAll() {
+ for (ISubscriber subscriber : subscribers) {
+ subscriber.unlinkFromBus(this);
+ }
+ subscribers.clear();
+ }
+
+ /**
+ * Registers a {@link Listener listener} to this event bus
+ *
+ * @param listener the {@link Listener} to be registered
+ * @throws NullPointerException if the given {@link Listener} is {@code null}
+ */
+ @Override
+ public abstract void register(Listener> listener);
+
+ /**
+ * Unregisters a {@link Listener listener} from this event bus. A listener will no longer be invoked by events dispatched by this event bus
+ *
+ * @param listener the {@link Listener} to be unregistered
+ * @throws NullPointerException if the given {@link Listener} is {@code null}
+ */
+ @Override
+ public abstract void unregister(Listener> listener);
+
+ /**
+ * Convenience method to dispatch an event with no {@linkplain Target target listener}, and
+ * normal processing priority.
+ *
+ * @see #dispatch(Object, Target, boolean)
+ */
+ @Override
+ public boolean dispatch(Object event) {
+ return dispatch(event, Target.all(), false);
+ }
+
+ /**
+ * Convenience method to dispatch an event with an optional {@linkplain Target target listener} and
+ * normal processing priority.
+ *
+ * @see #dispatch(Object, Target, boolean)
+ */
+ @Override
+ public boolean dispatch(Object event, Target target) {
+ return dispatch(event, target, false);
+ }
+
+ /**
+ * Convenience method to dispatch an event with a universal {@linkplain Target target listener} and
+ * optional inverted processing priority.
+ *
+ * @see #dispatch(Object, Target, boolean)
+ */
+ @Override
+ public boolean dispatch(Object event, boolean invertPriority) {
+ return dispatch(event, Target.all(), invertPriority);
+ }
+
+ /**
+ * Dispatches the given event to all valid registered 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 target the {@linkplain Target target listener} to invoke.
+ * @param invertPriority flag to dispatch the event in inverse listener priority.
+ * @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 abstract boolean dispatch(Object event, Target target, boolean invertPriority);
+
+ /**
+ * Schedules a task to be executed.
+ *
+ * @param task The task to be executed.
+ * @see TaskExecutor#schedule(ScheduledTask)
+ * @see ScheduledTask
+ */
+ public void scheduleTask(ScheduledTask task) {
+ taskExecutor.schedule(task);
+ }
+
+ /**
+ * Clears all tasks associated with events from the underlying {@link #taskExecutor}, effectively
+ * resetting the task scheduling within this {@link AbstractEventBus}.
+ *
+ * @see TaskExecutor#clear()
+ */
+ public void clearTaskExecutor() {
+ taskExecutor.clear();
+ }
+
+ /**
+ * Logs a warning message and shuts down this event bus, preventing future events from being dispatched.
+ *
+ * @implNote Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException}
+ * when attempting to do so.
+ */
+ @Override
+ public void shutdown() {
+ shutdown = true;
+ }
+
+ /**
+ * @return {@code true} if this event bus is shut down
+ * @implNote Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException}
+ * when attempting to do so.
+ */
+ @Override
+ public boolean isShutdown() {
+ return shutdown;
+ }
+
+ /**
+ * @return the {@code id} of this event bus
+ */
+ 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 order of inverse priority; otherwise,
+ * they are processed in normal order
+ */
+ @SuppressWarnings("DuplicatedCode")
+ protected final void dispatchToEachListener(Object event, IndexedHashSet listeners, Predicate predicate, boolean invertPriority) {
+ if ((listeners != null) && !listeners.isEmpty()) {
+ if (invertPriority) {
+ for (int i = listeners.size() - 1; i >= 0; i--) {
+ Listener listener = listeners.get(i);
+ if (!predicate.test(listener)) {
+ continue;
+ }
+
+ listener.invoke(event);
+
+ if ((event instanceof IStatusEvent e) && e.isTerminated()) {
+ break;
+ }
+ if (!listener.shouldPersist()) {
+ listeners.remove(listener);
+ }
+ }
+ } else {
+ for (int i = 0; i < listeners.size(); i++) {
+ Listener listener = listeners.get(i);
+ 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}.
+ *
+ * @param obj the object to compare with
+ * @return {@code true} if the object is equal to this event bus, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+ AbstractEventBus that = (AbstractEventBus) obj;
+ return id == that.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public abstract String toString();
+}
\ No newline at end of file
diff --git a/src/main/java/dev/tori/wraith/bus/EventBus.java b/src/main/java/dev/tori/wraith/bus/EventBus.java
new file mode 100644
index 0000000..4fa28f5
--- /dev/null
+++ b/src/main/java/dev/tori/wraith/bus/EventBus.java
@@ -0,0 +1,140 @@
+/*
+ * 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 dev.tori.wraith.bus;
+
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.IStatusEvent;
+import dev.tori.wraith.listener.Listener;
+import dev.tori.wraith.util.IndexedHashSet;
+
+import java.util.Comparator;
+import java.util.Objects;
+
+/**
+ * An implementation of {@link AbstractEventBus}.
+ *
+ * Manages listener registration, event dispatching, and task execution.
+ *
+ * @author 7orivorian
+ * @since 4.0.0
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class EventBus extends AbstractEventBus {
+
+ /**
+ * An {@link IndexedHashSet} of {@link Listener listeners} registered to this event bus.
+ */
+ private final IndexedHashSet listeners;
+ private boolean sorted = false;
+
+ /**
+ * Creates a new {@link EventBus} instance
+ */
+ public EventBus() {
+ super();
+ this.listeners = new IndexedHashSet<>();
+ }
+
+ /**
+ * Registers a {@link Listener listener} to this event bus
+ *
+ * @param listener the {@link Listener} to be registered
+ * @throws NullPointerException if the given {@link Listener} is {@code null}
+ */
+ @Override
+ public void register(Listener> listener) {
+ Objects.requireNonNull(listener, "Cannot register null listener to event bus " + id + ".");
+
+ listeners.add(listener);
+ sorted = false;
+ }
+
+ /**
+ * Unregisters a {@link Listener listener} from this event bus. A listener will no longer be invoked by events dispatched by this event bus
+ *
+ * @param listener the {@link Listener} to be unregistered
+ * @throws NullPointerException if the given {@link Listener} is {@code null}
+ */
+ @Override
+ public void unregister(Listener> listener) {
+ Objects.requireNonNull(listener, "Cannot unregister null listener from event bus " + id + ".");
+ listeners.removeIf(l -> l.equals(listener));
+ }
+
+ /**
+ * Dispatches the given event to all valid registered 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 target the {@linkplain Target target listener} to invoke.
+ * @param invertPriority flag to dispatch the event in inverse listener priority.
+ * @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, Target target, boolean invertPriority) {
+ Objects.requireNonNull(event, "Cannot dispatch a null event to event bus " + id + ".");
+ Objects.requireNonNull(target, "Cannot dispatch an event with a null target to event bus " + id + ".");
+ if (isShutdown()) {
+ throw new UnsupportedOperationException("Event bus " + id + " is shutdown!");
+ } else {
+ taskExecutor.onEvent(event);
+
+ if (!sorted) {
+ listeners.sort(Comparator.naturalOrder());
+ sorted = true;
+ }
+
+ dispatchToEachListener(
+ event,
+ listeners,
+ listener -> target.targets(listener.getClass()) && listener.getTarget().targets(event.getClass()),
+ invertPriority
+ );
+
+ if (event instanceof IStatusEvent e) {
+ return e.isSuppressed() || e.isTerminated();
+ }
+ }
+ return false;
+ }
+
+ public IndexedHashSet getListeners() {
+ return listeners;
+ }
+
+ @Override
+ public String toString() {
+ return "EventBus{" +
+ "id=" + id +
+ ", shutdown=" + shutdown +
+ ", listeners=" + listeners +
+ ", sorted=" + sorted +
+ ", subscribers=" + subscribers +
+ ", taskExecutor=" + taskExecutor +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/bus/IEventBus.java b/src/main/java/dev/tori/wraith/bus/IEventBus.java
similarity index 72%
rename from src/main/java/me/tori/wraith/bus/IEventBus.java
rename to src/main/java/dev/tori/wraith/bus/IEventBus.java
index a2167af..aafd5dd 100644
--- a/src/main/java/me/tori/wraith/bus/IEventBus.java
+++ b/src/main/java/dev/tori/wraith/bus/IEventBus.java
@@ -19,31 +19,33 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.bus;
+package dev.tori.wraith.bus;
-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;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.event.status.IStatusEvent;
+import dev.tori.wraith.listener.EventListener;
+import dev.tori.wraith.listener.Listener;
+import dev.tori.wraith.subscriber.ISubscriber;
/**
- * @author 7orivorian
- * @since 1.0.0
+ * An event bus that allows for the subscription, registration, and dispatching of events to listeners.
+ *
+ * @author 7orivorian
+ * @since 1.0.0
*/
public interface IEventBus {
/**
- * Default priority that used when no other priority is specified
+ * Default priority used when no other priority is specified.
*
- * @see EventListener#EventListener(Class)
- * @see EventListener#EventListener(Class, Class)
+ * @see EventListener#EventListener(Target)
*/
int DEFAULT_PRIORITY = 0;
/**
* Subscribes the specified subscriber to this event bus.
*
- * @param subscriber the {@link ISubscriber} to be subscribed
+ * @param subscriber the {@link ISubscriber} to be subscribed.
* @see #register(Listener)
*/
void subscribe(ISubscriber subscriber);
@@ -51,7 +53,7 @@ public interface IEventBus {
/**
* Unsubscribes the specified subscriber from this event bus.
*
- * @param subscriber the {@link ISubscriber} to be unsubscribed
+ * @param subscriber the {@link ISubscriber} to be unsubscribed.
* @see #unregister(Listener)
*/
void unsubscribe(ISubscriber subscriber);
@@ -59,21 +61,21 @@ public interface IEventBus {
/**
* Registers the specified listener to this event bus.
*
- * @param listener the {@link Listener} to be registered
+ * @param listener the {@link Listener} to be registered.
*/
void register(Listener> listener);
/**
* Unregisters the specified listener from this event bus.
*
- * @param listener the {@link Listener} to be unregistered
+ * @param listener the {@link Listener} to be unregistered.
*/
void unregister(Listener> listener);
/**
* Dispatches the specified event to all registered listeners.
*
- * @param event the event to be dispatched
+ * @param event the event to be dispatched.
* @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener,
* {@code false} otherwise.
*/
@@ -82,35 +84,38 @@ public interface IEventBus {
/**
* Dispatches the specified event to all registered listeners of the specified type.
*
- * @param event the event to be dispatched
- * @param type the type of listener to invoke (can be {@code null})
+ * @param event the event to be dispatched.
+ * @param target the {@linkplain Target target class} of listener to invoke.
* @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener,
* {@code false} otherwise.
+ * @since 4.0.0
*/
- boolean dispatch(Object event, Class> type);
+ boolean dispatch(Object event, Target target);
/**
* Dispatches the specified event to all registered listeners, with the option to invert the processing priority.
*
- * @param event the event to be dispatched
+ * @param event the event to be dispatched.
* @param invertPriority if {@code true}, listeners are processed in order of inverse priority; otherwise,
- * they are processed in normal order
+ * they are processed in normal order.
* @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener,
* {@code false} otherwise.
+ * @since 3.3.0
*/
boolean dispatch(Object event, boolean invertPriority);
/**
* Dispatches the specified event to all registered listeners of the specified type, with the option to invert the processing priority.
*
- * @param event the event to be dispatched
- * @param type the type of listener to invoke (can be {@code null})
+ * @param event the event to be dispatched.
+ * @param target the {@linkplain Target target class} of listener to invoke.
* @param invertPriority if {@code true}, listeners are processed in order of inverse priority; otherwise,
- * they are processed in normal order
+ * they are processed in normal order.
* @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener,
* {@code false} otherwise.
+ * @since 4.0.0
*/
- boolean dispatch(Object event, Class> type, boolean invertPriority);
+ boolean dispatch(Object event, Target target, boolean invertPriority);
/**
* Shuts down this event bus, preventing future events from being dispatched.
diff --git a/src/main/java/dev/tori/wraith/event/Target.java b/src/main/java/dev/tori/wraith/event/Target.java
new file mode 100644
index 0000000..0561009
--- /dev/null
+++ b/src/main/java/dev/tori/wraith/event/Target.java
@@ -0,0 +1,199 @@
+/*
+ * 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 dev.tori.wraith.event;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * Represents a class target with a specified {@linkplain TargetingRule targeting rule}.
+ *
+ * This class is used to determine if a given class matches the target class according to the {@linkplain TargetingRule targeting rule}.
+ *
+ * @author 7orivorian
+ * @since 4.0.0
+ */
+public class Target {
+
+ @NotNull
+ private final Class> targetClazz;
+ @NotNull
+ private final TargetingRule rule;
+
+ /**
+ * Constructs a new {@link Target}.
+ *
+ * @param targetClazz the target class.
+ * @param rule the targeting rule.
+ */
+ @Contract(pure = true)
+ private Target(@NotNull Class> targetClazz, @NotNull TargetingRule rule) {
+ this.targetClazz = targetClazz;
+ this.rule = rule;
+ }
+
+ /**
+ * Returns a {@link Target} that matches any class.
+ *
+ * @return a {@link Target} that matches any class.
+ */
+ @NotNull
+ @Contract(value = " -> new", pure = true)
+ public static Target all() {
+ return new Target(Object.class, TargetingRule.CASCADE);
+ }
+
+ /**
+ * Returns a {@link Target} with the specified target and {@link TargetingRule#FINE FINE} targeting.
+ *
+ * @param clazz the target class.
+ * @return a {@link Target} with the specified target and {@link TargetingRule#FINE FINE} targeting.
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ public static Target fine(@NotNull Class> clazz) {
+ return new Target(clazz, TargetingRule.FINE);
+ }
+
+ /**
+ * Returns a {@link Target} with the specified target and {@link TargetingRule#CASCADE CASCADE} targeting.
+ *
+ * @param clazz the target class.
+ * @return a {@link Target} with the specified target and {@link TargetingRule#CASCADE CASCADE} targeting.
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ public static Target cascade(@NotNull Class> clazz) {
+ return new Target(clazz, TargetingRule.CASCADE);
+ }
+
+ /**
+ * Returns a {@link Target} with the specified target and {@link TargetingRule#REVERSE_CASCADE REVERSE_CASCADE} targeting.
+ *
+ * @param clazz the target class.
+ * @return a {@link Target} with the specified target and {@link TargetingRule#REVERSE_CASCADE REVERSE_CASCADE} targeting.
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ public static Target reverseCascade(@NotNull Class> clazz) {
+ return new Target(clazz, TargetingRule.REVERSE_CASCADE);
+ }
+
+ /**
+ * Checks if the target class matches the given class according to the targeting rule.
+ *
+ * @param clazz the class to check.
+ * @return {@code true} if the class matches the target, {@code false} otherwise.
+ */
+ public boolean targets(@NotNull Class> clazz) {
+ if (this.targetClazz == Object.class) {
+ return true;
+ }
+ return rule.classesMatch(clazz, this.targetClazz);
+ }
+
+ /**
+ * Returns the {@linkplain #targetClazz target class}.
+ *
+ * @return the {@linkplain #targetClazz target class}.
+ */
+ @NotNull
+ public Class> clazz() {
+ return targetClazz;
+ }
+
+ /**
+ * Returns the {@linkplain #rule targeting rule}.
+ *
+ * @return the {@linkplain #rule targeting rule}.
+ */
+ @NotNull
+ public TargetingRule rule() {
+ return rule;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+
+ Target target = (Target) obj;
+ return targetClazz.equals(target.targetClazz)
+ && (rule == target.rule);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = targetClazz.hashCode();
+ result = (31 * result) + rule.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Target{" +
+ "clazz=" + targetClazz +
+ ", rule=" + rule +
+ '}';
+ }
+
+ /**
+ * Enumeration of targeting rules.
+ */
+ public enum TargetingRule {
+ /**
+ * The class must exactly equal the target class.
+ */
+ FINE {
+ @Override
+ public boolean classesMatch(Class> clazz, Class> target) {
+ return Objects.equals(clazz, target);
+ }
+ },
+ /**
+ * The class must be a subclass or implementation of the target class.
+ */
+ CASCADE {
+ @Override
+ public boolean classesMatch(Class> clazz, Class> target) {
+ return target.isAssignableFrom(clazz);
+ }
+ },
+ /**
+ * The target class must be a subclass or implementation of the given class.
+ */
+ REVERSE_CASCADE {
+ @Override
+ public boolean classesMatch(Class> clazz, Class> target) {
+ return clazz.isAssignableFrom(target);
+ }
+ };
+
+ public abstract boolean classesMatch(Class> clazz, Class> target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/event/status/IStatusEvent.java b/src/main/java/dev/tori/wraith/event/status/IStatusEvent.java
similarity index 96%
rename from src/main/java/me/tori/wraith/event/status/IStatusEvent.java
rename to src/main/java/dev/tori/wraith/event/status/IStatusEvent.java
index 5d17741..d1a6282 100644
--- a/src/main/java/me/tori/wraith/event/status/IStatusEvent.java
+++ b/src/main/java/dev/tori/wraith/event/status/IStatusEvent.java
@@ -19,7 +19,7 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.event.status;
+package dev.tori.wraith.event.status;
import org.jetbrains.annotations.NotNull;
@@ -45,8 +45,13 @@ public interface IStatusEvent {
/**
* Sets the status of this event.
+ *
+ * Note:
+ * This method should not be called directly.
*
* @param status the new {@link EventStatus} to set.
+ * @see #suppress()
+ * @see #terminate()
*/
void setEventStatus(@NotNull EventStatus status);
diff --git a/src/main/java/me/tori/wraith/event/status/StatusEvent.java b/src/main/java/dev/tori/wraith/event/status/StatusEvent.java
similarity index 92%
rename from src/main/java/me/tori/wraith/event/status/StatusEvent.java
rename to src/main/java/dev/tori/wraith/event/status/StatusEvent.java
index 86ff702..7364c31 100644
--- a/src/main/java/me/tori/wraith/event/status/StatusEvent.java
+++ b/src/main/java/dev/tori/wraith/event/status/StatusEvent.java
@@ -19,7 +19,7 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.event.status;
+package dev.tori.wraith.event.status;
import org.jetbrains.annotations.NotNull;
@@ -32,6 +32,7 @@
*/
public class StatusEvent implements IStatusEvent {
+ @NotNull
protected EventStatus status = EventStatus.ALIVE;
/**
@@ -76,15 +77,15 @@ public boolean isTerminated() {
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if ((o == null) || (getClass() != o.getClass())) {
+ if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
- StatusEvent that = (StatusEvent) o;
+ StatusEvent that = (StatusEvent) obj;
return status == that.status;
}
diff --git a/src/main/java/me/tori/wraith/listener/EventListener.java b/src/main/java/dev/tori/wraith/listener/EventListener.java
similarity index 51%
rename from src/main/java/me/tori/wraith/listener/EventListener.java
rename to src/main/java/dev/tori/wraith/listener/EventListener.java
index 3b428a4..fa426e5 100644
--- a/src/main/java/me/tori/wraith/listener/EventListener.java
+++ b/src/main/java/dev/tori/wraith/listener/EventListener.java
@@ -19,92 +19,71 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.listener;
+package dev.tori.wraith.listener;
-import me.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.event.Target;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* An abstract base class for event listeners that implements the {@link Listener} interface.
- * Event listeners provide event handling logic with specified priorities, target classes, and types.
+ * Event listeners provide event handling logic with specified targets and priorities.
*
* @param The type of event this listener is designed to handle.
- * @author 7orivorian
+ * @author 7orivorian
* @see Listener
* @see Invokable
- * @since 1.0.0
+ * @since 1.0.0
*/
public abstract class EventListener implements Listener {
- protected final @NotNull Class super T> target;
- protected final @Nullable Class> type;
+ @NotNull
+ protected final Target target;
protected final int priority;
protected final boolean indefinitePersistence;
protected int persists;
/**
- * Constructs an event listener with default priority and no specified type.
- *
- * @param target The target class that this listener is designed to handle events for.
- * @throws NullPointerException if {@code target} is {@code null}.
- */
- public EventListener(@NotNull Class super T> target) {
- this(target, IEventBus.DEFAULT_PRIORITY, null);
- }
-
- /**
- * Constructs an event listener with a specified priority and no specified 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.
- * @throws NullPointerException if {@code target} is {@code null}.
- */
- public EventListener(@NotNull Class super T> target, int priority) {
- this(target, priority, null);
- }
-
- /**
- * Constructs an event listener with default priority and a specified type.
+ * Constructs an event listener with default {@linkplain IEventBus#DEFAULT_PRIORITY priority} and {@linkplain #DEFAULT_PERSISTENCE persistence}.
*
- * @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 target This listener's {@linkplain Target target class}.
* @throws NullPointerException if {@code target} is {@code null}.
*/
- public EventListener(@NotNull Class super T> target, @Nullable Class> type) {
- this(target, IEventBus.DEFAULT_PRIORITY, type);
+ @Contract(pure = true)
+ public EventListener(@NotNull Target target) {
+ this(target, IEventBus.DEFAULT_PRIORITY, DEFAULT_PERSISTENCE);
}
/**
- * Constructs an event listener with a specified priority and type.
+ * Constructs an event listener with a specified {@code priority} and {@linkplain #DEFAULT_PERSISTENCE default persistence}.
*
- * @param target The target class that this listener is designed to handle events for.
+ * @param target This listener's {@link Target}.
* @param priority The priority level of this listener for event handling.
- * @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 super T> target, int priority, @Nullable Class> type) {
- this(target, type, priority, 0);
+ @Contract(pure = true)
+ public EventListener(@NotNull Target target, int priority) {
+ this(target, priority, DEFAULT_PERSISTENCE);
}
/**
- * Constructs an event listener with a specified priority and type.
+ * Constructs an event listener with a specified {@code priority} and {@code persists}.
*
- * @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 target This listener's {@link Target}.
* @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}.
+ * A value {@code <= 0} will {@linkplain #indefinitePersistence flag this listener to persist indefinitely}.
* @throws NullPointerException if {@code target} is {@code null}.
* @since 3.2.0
*/
- public EventListener(@NotNull Class super T> target, @Nullable Class> type, int priority, int persists) {
+ @Contract(pure = true)
+ public EventListener(@NotNull Target target, int priority, int persists) {
Objects.requireNonNull(target);
- this.priority = priority;
this.target = target;
- this.type = type;
+ this.priority = priority;
this.persists = persists;
this.indefinitePersistence = persists <= 0;
}
@@ -120,24 +99,13 @@ public int getPriority() {
}
/**
- * Gets the type of events that this listener can handle.
- *
- * @return The type of events that this listener can handle, or {@code null} if no type is specified.
- */
- @Nullable
- @Override
- public Class> getType() {
- return type;
- }
-
- /**
- * Gets the target class that this listener is designed to handle events for.
+ * Gets the {@link Target} of this listener.
*
- * @return The target class that this listener is designed to handle events for.
+ * @return The {@link Target} of this listener.
*/
@NotNull
@Override
- public Class super T> getTarget() {
+ public Target getTarget() {
return target;
}
@@ -147,7 +115,7 @@ public Class super T> getTarget() {
* 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
+ * @return {@code true} if the listener should persist, {@code false} otherwise.
* @since 3.2.0
*/
@Override
@@ -159,7 +127,7 @@ public boolean shouldPersist() {
* 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
+ * @return {@code true} if the listener is inherently persistent, {@code false} otherwise.
* @since 3.2.0
*/
@Override
@@ -168,34 +136,26 @@ public boolean hasIndefinitePersistence() {
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ @Contract(value = "null -> false", pure = true)
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if ((o == null) || (getClass() != o.getClass())) {
+ if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
- EventListener> that = (EventListener>) o;
- if (priority != that.priority) {
- return false;
- }
- if (indefinitePersistence != that.indefinitePersistence) {
- return false;
- }
- if (!Objects.equals(type, that.type)) {
- return false;
- }
- return target.equals(that.target);
+ EventListener> that = (EventListener>) obj;
+ return (priority == that.priority)
+ && (indefinitePersistence == that.indefinitePersistence)
+ && target.equals(that.target);
}
@Override
public int 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;
+ result = (31 * result) + priority;
+ result = (31 * result) + Boolean.hashCode(indefinitePersistence);
return result;
}
@@ -203,7 +163,6 @@ public int hashCode() {
public String toString() {
return "EventListener{" +
"target=" + target +
- ", type=" + type +
", priority=" + priority +
", indefinitePersistence=" + indefinitePersistence +
", persists=" + persists +
diff --git a/src/main/java/me/tori/wraith/listener/Invokable.java b/src/main/java/dev/tori/wraith/listener/Invokable.java
similarity index 98%
rename from src/main/java/me/tori/wraith/listener/Invokable.java
rename to src/main/java/dev/tori/wraith/listener/Invokable.java
index d8594ff..685ceb1 100644
--- a/src/main/java/me/tori/wraith/listener/Invokable.java
+++ b/src/main/java/dev/tori/wraith/listener/Invokable.java
@@ -19,7 +19,7 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.listener;
+package dev.tori.wraith.listener;
/**
* A functional interface representing a callable object that can handle or process an event.
diff --git a/src/main/java/me/tori/wraith/listener/LambdaEventListener.java b/src/main/java/dev/tori/wraith/listener/LambdaEventListener.java
similarity index 55%
rename from src/main/java/me/tori/wraith/listener/LambdaEventListener.java
rename to src/main/java/dev/tori/wraith/listener/LambdaEventListener.java
index a6b89ee..0f1ce8a 100644
--- a/src/main/java/me/tori/wraith/listener/LambdaEventListener.java
+++ b/src/main/java/dev/tori/wraith/listener/LambdaEventListener.java
@@ -19,10 +19,11 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.listener;
+package dev.tori.wraith.listener;
+import dev.tori.wraith.event.Target;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@@ -31,82 +32,53 @@
* This provides a convenient way to create event listeners using lambda expressions.
*
* @param The type of event handled by this listener.
- * @author 7orivorian
- * @since 1.3.0
+ * @author 7orivorian
+ * @since 1.3.0
*/
public class LambdaEventListener extends EventListener {
- protected final @NotNull Invokable invokable;
+ @NotNull
+ protected final Invokable invokable;
/**
- * Constructs a new `LambdaEventListener` with the given target class and invokable action.
+ * Constructs a new {@link LambdaEventListener} with the given target and invokable action.
*
- * @param target The target class of the event.
+ * @param target This listener's {@link Target}.
* @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 super E> target, @NotNull Invokable invokable) {
+ public LambdaEventListener(@NotNull Target target, @NotNull Invokable invokable) {
super(target);
Objects.requireNonNull(invokable);
this.invokable = invokable;
}
/**
- * Constructs a new `LambdaEventListener` with the given target class, priority, and invokable action.
+ * Constructs a new {@link LambdaEventListener} with the given target, priority, and invokable action.
*
- * @param target The target class of the event.
+ * @param target This listener's {@link Target}.
* @param priority The priority of this listener.
* @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 super E> target, int priority, @NotNull Invokable invokable) {
+ public LambdaEventListener(@NotNull Target target, int priority, @NotNull Invokable invokable) {
super(target, priority);
Objects.requireNonNull(invokable);
this.invokable = invokable;
}
/**
- * Constructs a new `LambdaEventListener` with the given target class, type, and invokable action.
+ * Constructs a new {@link LambdaEventListener} with the given target, priority, and invokable action.
*
- * @param target The target class of the event.
- * @param type The type of the event.
- * @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 super E> target, @Nullable Class> type, @NotNull Invokable invokable) {
- super(target, type);
- Objects.requireNonNull(invokable);
- this.invokable = invokable;
- }
-
- /**
- * Constructs a new `LambdaEventListener` with the given target class, priority, type, and invokable action.
- *
- * @param target The target class of the event.
- * @param priority The priority of this listener.
- * @param type The type of the event.
- * @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 super E> target, int priority, @Nullable Class> type, @NotNull Invokable invokable) {
- super(target, priority, type);
- Objects.requireNonNull(invokable);
- 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 target This listener's {@link Target}.
* @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}.
+ * A value of {@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 super E> target, @Nullable Class> type, int priority, int persists, @NotNull Invokable invokable) {
- super(target, type, priority, persists);
+ public LambdaEventListener(@NotNull Target target, int priority, int persists, @NotNull Invokable invokable) {
+ super(target, priority, persists);
Objects.requireNonNull(invokable);
this.invokable = invokable;
}
@@ -122,18 +94,19 @@ public void invoke(E event) {
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ @Contract(value = "null -> false", pure = true)
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if ((o == null) || (getClass() != o.getClass())) {
+ if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
- if (!super.equals(o)) {
+ if (!super.equals(obj)) {
return false;
}
- LambdaEventListener> that = (LambdaEventListener>) o;
+ LambdaEventListener> that = (LambdaEventListener>) obj;
return invokable.equals(that.invokable);
}
@@ -148,7 +121,6 @@ public int hashCode() {
public String toString() {
return "LambdaEventListener{" +
"target=" + target +
- ", type=" + type +
", priority=" + priority +
", indefinitePersistence=" + indefinitePersistence +
", persists=" + persists +
diff --git a/src/main/java/me/tori/wraith/listener/Listener.java b/src/main/java/dev/tori/wraith/listener/Listener.java
similarity index 58%
rename from src/main/java/me/tori/wraith/listener/Listener.java
rename to src/main/java/dev/tori/wraith/listener/Listener.java
index 5cf68d1..b9b6a33 100644
--- a/src/main/java/me/tori/wraith/listener/Listener.java
+++ b/src/main/java/dev/tori/wraith/listener/Listener.java
@@ -19,24 +19,27 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.listener;
+package dev.tori.wraith.listener;
-import me.tori.wraith.bus.EventBus;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.util.IndexedHashSet;
+import org.jetbrains.annotations.NotNull;
-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.
*
* @param The type of event this listener is designed to handle.
- * @author 7orivorian
+ * @author 7orivorian
* @see EventListener
* @see Invokable
- * @since 1.0.0
+ * @since 1.0.0
*/
-public interface Listener extends Invokable {
+public interface Listener extends Invokable, Comparable> {
+
+ int DEFAULT_PERSISTENCE = 0;
/**
* Gets the priority level of this listener for event handling.
@@ -46,24 +49,19 @@ public interface Listener extends Invokable {
int getPriority();
/**
- * Gets the type of events that this listener can handle.
- *
- * @return The type of events that this listener can handle, or {@code null} if no type is specified.
- */
- Class> getType();
-
- /**
- * Gets the target class that this listener is designed to handle events for.
+ * Gets the {@linkplain Target target class} of this listener.
*
- * @return The target class that this listener is designed to handle events for.
+ * @return the {@linkplain Target target class} of this listener.
+ * @since 4.0.0
*/
- Class super T> getTarget();
+ @NotNull
+ Target 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)
+ * @see EventBus#dispatchToEachListener(Object, IndexedHashSet, Predicate, boolean)
* @since 3.2.0
*/
@SuppressWarnings("JavadocReference")
@@ -82,21 +80,12 @@ default boolean hasIndefinitePersistence() {
}
/**
- * Checks if the provided type is acceptable for this listener.
- *
- * This default method evaluates whether the given type is acceptable by comparing it with
- * the type associated with this listener. It returns {@code true} if any of the following conditions are met:
- *
- *
The provided type is {@code null}.
- *
The listener's type is {@code null}.
- *
The provided type is equal to the listener's type.
- *
- *
- * @param type the class type to check for acceptability
- * @return {@code true} if the type is acceptable, {@code false} otherwise.
- * @since 3.3.0
+ * @param listener the listener to be compared.
+ * @apiNote This class has a natural ordering that is inconsistent with equals.
+ * @since 4.0.0
*/
- default boolean isAcceptableType(Class> type) {
- return (type == null) || (getType() == null) || (getType() == type);
+ @Override
+ default int compareTo(@NotNull Listener listener) {
+ return listener.getPriority() - getPriority();
}
}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/listener/ListenerBuilder.java b/src/main/java/dev/tori/wraith/listener/ListenerBuilder.java
similarity index 75%
rename from src/main/java/me/tori/wraith/listener/ListenerBuilder.java
rename to src/main/java/dev/tori/wraith/listener/ListenerBuilder.java
index 2c02670..356dabd 100644
--- a/src/main/java/me/tori/wraith/listener/ListenerBuilder.java
+++ b/src/main/java/dev/tori/wraith/listener/ListenerBuilder.java
@@ -19,11 +19,11 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.listener;
+package dev.tori.wraith.listener;
-import me.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.event.Target;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@@ -37,8 +37,7 @@
*
* {@code
* EventListener listener = new ListenerBuilder<>()
- * .target(MyEvent.class)
- * .type(SomeSpecificType.class)
+ * .target(ClassTarget.fine(MyEvent.class))
* .priority(5)
* .persists(10)
* .invokable(event -> handleEvent(event))
@@ -53,40 +52,28 @@
*/
public class ListenerBuilder {
- private Class super T> target = null;
- private @Nullable Class> type = null;
+ private Target target = 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.
+ * Sets the {@link Target} for this listener.
*
- * @param target the class of the event this listener will handle
- * @return this {@code ListenerBuilder} instance
+ * @param target This listener's {@link Target}.
+ * @return this {@code ListenerBuilder} instance.
*/
- public ListenerBuilder target(@NotNull Class super T> target) {
+ public ListenerBuilder target(@NotNull Target 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 super T> type) {
- this.type = type;
- return this;
- }
-
/**
* Sets the priority for this listener.
*
- * @param priority the priority of the listener
- * @return this {@code ListenerBuilder} instance
+ * @param priority the priority of the listener.
+ * @return this {@code ListenerBuilder} instance.
*/
public ListenerBuilder priority(int priority) {
this.priority = priority;
@@ -98,8 +85,8 @@ public ListenerBuilder priority(int priority) {
*
* Overrides {@link #persistent}.
*
- * @param persists the number of events this listener should handle before being removed
- * @return this {@code ListenerBuilder} instance
+ * @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;
@@ -112,8 +99,8 @@ public ListenerBuilder persists(int persists) {
*
* Overrides {@link #persists}.
*
- * @param persistent {@code true} if the listener should be persistent, {@code false} otherwise
- * @return this {@code ListenerBuilder} instance
+ * @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;
@@ -127,7 +114,7 @@ public ListenerBuilder persistent(boolean persistent) {
* Sets the invokable action for this listener.
*
* @param invokable the action to be invoked when an event is handled
- * @return this {@code ListenerBuilder} instance
+ * @return this {@code ListenerBuilder} instance.
*/
public ListenerBuilder invokable(@NotNull Invokable invokable) {
this.invokable = invokable;
@@ -137,9 +124,9 @@ public ListenerBuilder invokable(@NotNull Invokable invokable) {
/**
* 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
+ * @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() {
@@ -150,7 +137,7 @@ public EventListener build() {
"Persistency missmatch. persistent=" + persistent + " and persists=" + persists + " is not allowed."
);
}
- return new EventListener<>(target, type, priority, persists) {
+ return new EventListener<>(target, priority, persists) {
@Override
public void invoke(T event) {
invokable.invoke(event);
diff --git a/src/main/java/me/tori/wraith/subscriber/ISubscriber.java b/src/main/java/dev/tori/wraith/subscriber/ISubscriber.java
similarity index 55%
rename from src/main/java/me/tori/wraith/subscriber/ISubscriber.java
rename to src/main/java/dev/tori/wraith/subscriber/ISubscriber.java
index 1936bd6..547b03c 100644
--- a/src/main/java/me/tori/wraith/subscriber/ISubscriber.java
+++ b/src/main/java/dev/tori/wraith/subscriber/ISubscriber.java
@@ -19,19 +19,22 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.subscriber;
+package dev.tori.wraith.subscriber;
-import me.tori.wraith.listener.Listener;
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.listener.Listener;
+import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* Represents a subscriber that can register and manage event listeners.
- *
An instance of a class implementing this interface can subscribe to an event bus by registering listeners.
+ *
+ * An instance of a class implementing this interface can subscribe to an event bus by registering listeners.
*
- * @author 7orivorian
+ * @author 7orivorian
* @see Subscriber
- * @since 1.0.0
+ * @since 1.0.0
*/
public interface ISubscriber {
@@ -54,10 +57,46 @@ public interface ISubscriber {
@SuppressWarnings("unchecked")
> T[] registerListeners(T... listeners);
+ /**
+ * Unregisters a single event listener from this subscriber.
+ *
+ * @param listener The event listener to unregister.
+ * @param The type of the listener.
+ * @return {@code true} if this subscriber contained the specified listener, {@code false} otherwise.
+ */
+ > boolean unregisterListener(T listener);
+
+ /**
+ * Unregisters multiple event listeners from this subscriber.
+ *
+ * @param listeners The event listeners to unregister.
+ * @param The type of the listeners.
+ * @return {@code true} if this subscriber was changed as a result of the call, {@code false} otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ > boolean unregisterListeners(T... listeners);
+
/**
* Retrieves a collection of event listeners registered with this subscriber.
*
* @return A collection of registered event listeners.
*/
+ @NotNull
Collection> getListeners();
+
+ /**
+ * Links this subscriber to the specified event bus.
+ *
+ * @param eventBus The event bus to link to this subscriber. Must not be {@code null}.
+ * @throws NullPointerException If the {@code eventBus} is {@code null}.
+ */
+ void linkToBus(IEventBus eventBus);
+
+ /**
+ * Unlinks this subscriber from the specified event bus.
+ *
+ * @param eventBus The event bus to unlink from this subscriber. Must not be {@code null}.
+ * @throws NullPointerException If the {@code eventBus} is {@code null}.
+ */
+ void unlinkFromBus(IEventBus eventBus);
}
\ No newline at end of file
diff --git a/src/main/java/dev/tori/wraith/subscriber/Subscriber.java b/src/main/java/dev/tori/wraith/subscriber/Subscriber.java
new file mode 100644
index 0000000..a5e37a2
--- /dev/null
+++ b/src/main/java/dev/tori/wraith/subscriber/Subscriber.java
@@ -0,0 +1,201 @@
+/*
+ * 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 dev.tori.wraith.subscriber;
+
+import dev.tori.wraith.bus.IEventBus;
+import dev.tori.wraith.listener.Listener;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The default implementation of {@link ISubscriber} that manages event listeners and their registration.
+ *
+ * This class provides methods to register single or multiple event listeners and retrieve registered listeners.
+ *
+ * @author 7orivorian
+ * @see ISubscriber
+ * @since 1.0.0
+ */
+public class Subscriber implements ISubscriber {
+
+ /**
+ * The amount of {@linkplain Subscriber} instances that have been created.
+ */
+ private static int instances = 0;
+
+ private final int id;
+ private final Set<@NotNull IEventBus> linkedBuses = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ private final List<@NotNull Listener>> listeners = new ArrayList<>();
+
+ public Subscriber() {
+ this.id = instances++;
+ }
+
+ /**
+ * Registers a single event listener with this subscriber.
+ *
+ * @param listener The event listener to register.
+ * @param The type of the listener.
+ * @return The registered listener.
+ */
+ @Override
+ public > T registerListener(@NotNull T listener) {
+ listeners.add(listener);
+ if (!linkedBuses.isEmpty()) {
+ linkedBuses.forEach(bus -> bus.register(listener));
+ }
+ return listener;
+ }
+
+ /**
+ * Registers multiple event listeners with this subscriber.
+ *
+ * @param listeners The event listeners to register.
+ * @param The type of the listeners.
+ * @return An array containing the registered listeners.
+ */
+ @Contract("_ -> param1")
+ @SafeVarargs
+ @Override
+ public final > T[] registerListeners(@NotNull T... listeners) {
+ final List<@NotNull T> list = Arrays.asList(listeners);
+ this.listeners.addAll(list);
+ if (!linkedBuses.isEmpty()) {
+ linkedBuses.forEach(bus -> list.forEach(bus::register));
+ }
+ return listeners;
+ }
+
+ /**
+ * Unregisters a single event listener from this subscriber.
+ *
+ * @param listener The event listener to unregister.
+ * @param The type of the listener.
+ * @return {@code true} if this subscriber contained the specified listener, {@code false} otherwise.
+ */
+ @Override
+ public > boolean unregisterListener(@NotNull T listener) {
+ if (!linkedBuses.isEmpty()) {
+ linkedBuses.forEach(bus -> bus.unregister(listener));
+ }
+ return listeners.remove(listener);
+ }
+
+ /**
+ * Unregisters multiple event listeners from this subscriber.
+ *
+ * @param listeners The event listeners to unregister.
+ * @param The type of the listeners.
+ * @return {@code true} if this subscriber was changed as a result of the call, {@code false} otherwise.
+ */
+ @SafeVarargs
+ @Override
+ public final > boolean unregisterListeners(T... listeners) {
+ if (!linkedBuses.isEmpty()) {
+ for (T listener : listeners) {
+ linkedBuses.forEach(bus -> bus.unregister(listener));
+ }
+ }
+ return this.listeners.removeAll(Arrays.asList(listeners));
+ }
+
+ /**
+ * Retrieves a collection of event listeners registered with this subscriber.
+ *
+ * @return A collection of registered event listeners.
+ */
+ @NotNull
+ @Override
+ public Collection> getListeners() {
+ return listeners;
+ }
+
+ /**
+ * Links this subscriber to the specified event bus.
+ *
+ * This method adds the given {@code eventBus} to the {@linkplain #linkedBuses set of event buses that this subscriber is linked to}.
+ * Once linked, the event bus can register the event listeners managed by this subscriber.
+ *
+ * @param eventBus The event bus to link to this subscriber. Must not be {@code null}.
+ * @throws NullPointerException If the {@code eventBus} is {@code null}.
+ * @implNote This method should not be called outside an {@link IEventBus} implementation
+ */
+ @Override
+ public void linkToBus(IEventBus eventBus) {
+ Objects.requireNonNull(eventBus, "Cannot link subscriber to a null event bus");
+ linkedBuses.add(eventBus);
+ }
+
+ /**
+ * Unlinks this subscriber from the specified event bus.
+ *
+ * This method removes the given {@code eventBus} from the {@linkplain #linkedBuses set of event buses that this subscriber is linked to}.
+ * Once unlinked, the event bus will no longer register the event listeners managed by this subscriber.
+ *
+ * @param eventBus The event bus to unlink from this subscriber. Must not be {@code null}.
+ * @throws NullPointerException If the {@code eventBus} is {@code null}.
+ * @implNote This method should not be called outside an {@link IEventBus} implementation
+ */
+ @Override
+ public void unlinkFromBus(IEventBus eventBus) {
+ Objects.requireNonNull(eventBus, "Cannot unlink unsubscriber from a null event bus");
+ linkedBuses.remove(eventBus);
+ }
+
+ /**
+ * Returns this {@linkplain Subscriber}'s {@linkplain #id}.
+ *
+ * @return this {@linkplain Subscriber}'s {@linkplain #id}.
+ */
+ public int getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (getClass() != obj.getClass())) {
+ return false;
+ }
+
+ Subscriber that = (Subscriber) obj;
+ return this.id == that.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "Subscriber{" +
+ "linkedBuses=" + linkedBuses +
+ ", listeners=" + listeners +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/task/ScheduledTask.java b/src/main/java/dev/tori/wraith/task/ScheduledTask.java
similarity index 95%
rename from src/main/java/me/tori/wraith/task/ScheduledTask.java
rename to src/main/java/dev/tori/wraith/task/ScheduledTask.java
index 54e4041..16e11d4 100644
--- a/src/main/java/me/tori/wraith/task/ScheduledTask.java
+++ b/src/main/java/dev/tori/wraith/task/ScheduledTask.java
@@ -19,8 +19,9 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.task;
+package dev.tori.wraith.task;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,7 +38,8 @@
*/
public abstract class ScheduledTask implements Runnable {
- private final @NotNull Class> target;
+ @NotNull
+ private final Class> target;
private int delay;
/**
@@ -45,6 +47,7 @@ public abstract class ScheduledTask implements Runnable {
*
* @param target The target class representing the event that triggers the task's execution.
*/
+ @Contract(pure = true)
public ScheduledTask(@NotNull Class> target) {
this(target, 0);
}
@@ -55,6 +58,7 @@ public ScheduledTask(@NotNull Class> target) {
* @param target The target class representing the event that triggers the task's execution.
* @param delay The delay value, determining the number of event dispatches before execution.
*/
+ @Contract(pure = true)
public ScheduledTask(@NotNull Class> target, int delay) {
this.target = target;
this.delay = delay;
diff --git a/src/main/java/me/tori/wraith/task/TaskExecutor.java b/src/main/java/dev/tori/wraith/task/TaskExecutor.java
similarity index 89%
rename from src/main/java/me/tori/wraith/task/TaskExecutor.java
rename to src/main/java/dev/tori/wraith/task/TaskExecutor.java
index e2beb99..4932c2a 100644
--- a/src/main/java/me/tori/wraith/task/TaskExecutor.java
+++ b/src/main/java/dev/tori/wraith/task/TaskExecutor.java
@@ -19,7 +19,10 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.task;
+package dev.tori.wraith.task;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
@@ -43,6 +46,7 @@ public class TaskExecutor {
/**
* Constructs a new TaskExecutor with an empty task mapping.
*/
+ @Contract(pure = true)
public TaskExecutor() {
this.tasks = new ConcurrentHashMap<>();
}
@@ -53,7 +57,7 @@ public TaskExecutor() {
* @param event The event for which associated tasks should be executed.
* @return {@code true} if any tasks were executed, {@code false} otherwise.
*/
- public boolean onEvent(Object event) {
+ public boolean onEvent(@NotNull Object event) {
ArrayList queue = tasks.get(event.getClass());
if ((queue != null) && !queue.isEmpty()) {
boolean executed = false;
@@ -77,7 +81,7 @@ public boolean onEvent(Object event) {
* @param task The task to be executed.
* @see ScheduledTask
*/
- public void schedule(ScheduledTask task) {
+ public void schedule(@NotNull ScheduledTask task) {
tasks.computeIfAbsent(task.getTarget(), clazz -> new ArrayList<>()).add(task);
}
@@ -87,4 +91,11 @@ public void schedule(ScheduledTask task) {
public void clear() {
tasks.clear();
}
+
+ @Override
+ public String toString() {
+ return "TaskExecutor{" +
+ "tasks=" + tasks +
+ '}';
+ }
}
\ No newline at end of file
diff --git a/src/main/java/dev/tori/wraith/util/IndexedHashSet.java b/src/main/java/dev/tori/wraith/util/IndexedHashSet.java
new file mode 100644
index 0000000..0b34ae8
--- /dev/null
+++ b/src/main/java/dev/tori/wraith/util/IndexedHashSet.java
@@ -0,0 +1,121 @@
+/*
+ * 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 dev.tori.wraith.util;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.function.Predicate;
+
+/**
+ * @author 7orivorian
+ * @since 4.0.0
+ */
+public class IndexedHashSet extends ArrayList {
+
+ private final HashMap map;
+
+ public IndexedHashSet() {
+ this.map = new HashMap<>();
+ }
+
+ @Override
+ public boolean add(E element) {
+ Objects.requireNonNull(element);
+ if (map.put(element, true) == null) {
+ super.add(element);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ Objects.requireNonNull(element);
+ rangeCheckForAdd(index);
+ if (map.put(element, true) == null) {
+ super.add(index, element);
+ }
+ }
+
+ @Override
+ public E remove(int index) {
+ E element = super.remove(index);
+ map.remove(element);
+ return element;
+ }
+
+ @Override
+ public boolean remove(Object element) {
+ if (map.remove(element) != null) {
+ super.remove(element);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeIf(Predicate super E> filter) {
+ Objects.requireNonNull(filter);
+ boolean removed = false;
+ Iterator it = iterator();
+ while (it.hasNext()) {
+ E element = it.next();
+ if (filter.test(element)) {
+ it.remove();
+ map.remove(element);
+ removed = true;
+ }
+ }
+ return removed;
+ }
+
+ @Override
+ @Contract(pure = true)
+ @SuppressWarnings("SuspiciousMethodCalls")
+ public boolean contains(Object element) {
+ return map.containsKey(element);
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ map.clear();
+ }
+
+ public List immutableList() {
+ return Collections.unmodifiableList(this);
+ }
+
+ private void rangeCheckForAdd(int index) {
+ if ((index > size()) || (index < 0)) {
+ throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
+ }
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ private String outOfBoundsMsg(int index) {
+ return "Index: " + index + ", Size: " + size();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/bus/EventBus.java b/src/main/java/me/tori/wraith/bus/EventBus.java
deleted file mode 100644
index 7879c69..0000000
--- a/src/main/java/me/tori/wraith/bus/EventBus.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * 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.status.IStatusEvent;
-import me.tori.wraith.event.targeted.IClassTargetingEvent;
-import me.tori.wraith.listener.Listener;
-import me.tori.wraith.subscriber.ISubscriber;
-import me.tori.wraith.task.ScheduledTask;
-import me.tori.wraith.task.TaskExecutor;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-
-/**
- * Default implementation of {@link IEventBus}, {@link TargetableEventBus}, and {@link InvertableEventBus}.
- *
- *
Manages event subscription, dispatching, and listener registration.
- *
- * @author 7orivorian
- * @since 1.0.0
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class EventBus implements TargetableEventBus, InvertableEventBus {
-
- /**
- * The amount of {@linkplain EventBus} instances that have been created
- */
- private static int instances = 0;
-
- /**
- * This event bus's id
- */
- private final int id;
- /**
- * Indicates whether this event bus is shutdown.
- *
Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException} when
- * attempting to do so
- */
- private boolean shutdown;
- /**
- * A {@link Set} of this event bus' {@link ISubscriber subscribers}
- */
- private final Set subscribers;
- /**
- * A {@link ConcurrentHashMap} of this event bus' {@link Listener listeners}
- */
- private final ConcurrentHashMap, List> listeners;
- /**
- * A {@link TaskExecutor} that manages the scheduling and execution of tasks associated with events. It provides
- * a mechanism to associate event classes with queues of tasks and ensures their orderly execution when the
- * corresponding events are dispatched.
- *
- * @see #scheduleTask(ScheduledTask)
- */
- private final TaskExecutor taskExecutor;
-
- /**
- * Creates a new event bus instance
- */
- public EventBus() {
- this.id = instances++;
- this.shutdown = false;
- this.subscribers = Collections.newSetFromMap(new ConcurrentHashMap<>());
- this.listeners = new ConcurrentHashMap<>();
- this.taskExecutor = new TaskExecutor();
- }
-
- /**
- * @return The amount of {@linkplain EventBus} instances that have been created.
- */
- public static int getInstanceCount() {
- return instances;
- }
-
- /**
- * Subscribes a {@link ISubscriber subscriber} to this event bus and registers all the
- * subscriber's {@link Listener listeners}
- *
- * @param subscriber the {@link ISubscriber} to be subscribed
- * @throws NullPointerException if the given {@link ISubscriber} is {@code null}
- * @see #register(Listener)
- */
- @Override
- public void subscribe(ISubscriber subscriber) {
- Objects.requireNonNull(subscriber, "Cannot subscribe null to event bus " + id + "!");
- Collection> listeners = subscriber.getListeners();
- if (listeners.size() == 1) {
- register(listeners.iterator().next());
- } else {
- for (Listener> listener : listeners) {
- register(listener);
- }
- }
- subscribers.add(subscriber);
- }
-
- /**
- * Unsubscribes a {@link ISubscriber subscriber} from this event bus and unregisters all the
- * subscriber's {@link Listener listeners}
- *
- * @param subscriber the {@link ISubscriber} to be unsubscribed
- * @throws NullPointerException if the given {@link ISubscriber} is {@code null}
- * @see #unregister(Listener)
- */
- @Override
- public void unsubscribe(ISubscriber subscriber) {
- Objects.requireNonNull(subscriber, "Cannot unsubscribe null from event bus " + id + "!");
- Collection> listeners = subscriber.getListeners();
- if (listeners.size() == 1) {
- unregister(listeners.iterator().next());
- } else {
- for (Listener> listener : listeners) {
- unregister(listener);
- }
- }
- subscribers.remove(subscriber);
- }
-
- /**
- * Registers a {@link Listener listener} to this event bus
- *
- * @param listener the {@link Listener} to be registered
- * @throws NullPointerException if the given {@link Listener} is {@code null}
- */
- @Override
- public void register(Listener> listener) {
- Objects.requireNonNull(listener, "Cannot register null listener to event bus " + id + "!");
-
- List listeners = this.listeners.computeIfAbsent(listener.getTarget(), target -> new CopyOnWriteArrayList<>());
- final int size = listeners.size();
- int index = 0;
- for (; index < size; index++) {
- if (listener.getPriority() > listeners.get(index).getPriority()) {
- break;
- }
- }
- listeners.add(index, listener);
- }
-
- /**
- * Unregisters a {@link Listener listener} from this event bus. A listener will no longer be invoked by events dispatched by this event bus
- *
- * @param listener the {@link Listener} to be unregistered
- * @throws NullPointerException if the given {@link Listener} is {@code null}
- */
- @Override
- public void unregister(Listener> listener) {
- Objects.requireNonNull(listener, "Cannot unregister null listener from event bus " + id + "!");
- listeners.get(listener.getTarget()).removeIf(l -> l.equals(listener));
- }
-
- /**
- * Convenience method to dispatch an event with no {@linkplain Listener#getType() listener type} restriction, and
- * normal processing priority.
- *
- * @see #dispatch(Object, Class, boolean)
- * @since 3.3.0
- */
- @Override
- public boolean dispatch(Object event) {
- return dispatch(event, null, false);
- }
-
- /**
- * Convenience method to dispatch an event with an optional {@linkplain Listener#getType() listener type} restriction, and
- * normal processing priority.
- *
- * @see #dispatch(Object, Class, boolean)
- * @since 3.3.0
- */
- @Override
- public boolean dispatch(Object event, Class> type) {
- return dispatch(event, type, false);
- }
-
- /**
- * Convenience method to dispatch an event with no {@linkplain Listener#getType() listener type} restriction, and
- * optional inverted processing priority.
- *
- * @see #dispatch(Object, Class, boolean)
- * @since 3.3.0
- */
- @Override
- public boolean dispatch(Object event, boolean invertPriority) {
- return dispatch(event, null, invertPriority);
- }
-
- /**
- * Dispatches the given event to all valid registered 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 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}
- * @since 3.3.0
- */
- @Override
- public boolean dispatch(Object event, Class> type, boolean invertPriority) {
- 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);
-
- dispatchToEachListener(
- event,
- this.listeners.get(event.getClass()),
- listener -> listener.isAcceptableType(type) && IClassTargetingEvent.isListenerTargetedByEvent(listener, event),
- invertPriority
- );
-
- if (event instanceof IStatusEvent e) {
- return e.isSuppressed() || e.isTerminated();
- }
- }
- return false;
- }
-
- /**
- * 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 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}
- * @deprecated This method's functionality is now built into {@link #dispatch(Object)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- @Override
- public boolean dispatchTargeted(IClassTargetingEvent event) {
- return dispatchTargeted(event, null);
- }
-
- /**
- * Dispatches the given {@link IClassTargetingEvent} to the target listener class.
- *
- *
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 {@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 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}
- * @deprecated This method's functionality is now built into {@link #dispatch(Object, Class)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- @Override
- public boolean dispatchTargeted(IClassTargetingEvent event, Class> type) {
- return dispatch(event, type);
- }
-
- /**
- * 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 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}
- * @deprecated This method's functionality is now built into {@link #dispatch(Object)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- @Override
- public boolean dispatchInverted(Object event) {
- 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.
- *
- *
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 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}
- * @deprecated This method's functionality is now built into {@link #dispatch(Object)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- @Override
- public boolean dispatchInverted(Object event, Class> type) {
- 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);
-
- dispatchToEachListener(
- event,
- this.listeners.get(event.getClass()),
- listener -> listener.isAcceptableType(type) && IClassTargetingEvent.isListenerTargetedByEvent(listener, event),
- true
- );
-
- if (event instanceof IStatusEvent e) {
- return e.isSuppressed() || e.isTerminated();
- }
- }
- return false;
- }
-
- /**
- * Schedules a task to be executed.
- *
- * @param task The task to be executed.
- * @see TaskExecutor#schedule(ScheduledTask)
- * @see ScheduledTask
- */
- public void scheduleTask(ScheduledTask task) {
- taskExecutor.schedule(task);
- }
-
- /**
- * Clears all tasks associated with events from the underlying {@link #taskExecutor}, effectively
- * resetting the task scheduling within this {@link EventBus}.
- *
- * @see TaskExecutor#clear()
- */
- public void clearTaskExecutor() {
- taskExecutor.clear();
- }
-
- /**
- * Logs a warning message and shuts down this event bus, preventing future events from being dispatched.
- *
- * @implNote Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException}
- * when attempting to do so.
- */
- @Override
- public void shutdown() {
- shutdown = true;
- }
-
- /**
- * @return {@code true} if this event bus is shut down
- * @implNote Shut-down event dispatchers cannot dispatch events, and throw {@link UnsupportedOperationException}
- * when attempting to do so.
- */
- @Override
- public boolean isShutdown() {
- return shutdown;
- }
-
- /**
- * @return the {@code id} of this event bus
- * @since 3.1.0
- */
- 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 order of inverse priority; otherwise,
- * they are processed in normal order
- * @since 3.2.0
- */
- private void dispatchToEachListener(Object event, List listeners, Predicate predicate, boolean invertPriority) {
- if (listeners != null && !listeners.isEmpty()) {
- ListIterator iterator;
- Supplier supplier;
- if (invertPriority) {
- iterator = listeners.listIterator(listeners.size());
- supplier = () -> (iterator.hasPrevious() ? iterator.previous() : null);
- } else {
- iterator = listeners.listIterator(0);
- supplier = () -> (iterator.hasNext() ? iterator.next() : null);
- }
- Listener listener;
- while ((listener = supplier.get()) != null) {
- 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}.
- *
- * @param o the object to compare with
- * @return {@code true} if the object is equal to this event bus, {@code false} otherwise
- */
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if ((o == null) || (getClass() != o.getClass())) {
- return false;
- }
- EventBus that = (EventBus) o;
- return id == that.id;
- }
-
- @Override
- public int hashCode() {
- return id;
- }
-
- @Override
- public String toString() {
- return "EventBus{" +
- "id=" + id +
- ", shutdown=" + shutdown +
- ", subscribers=" + subscribers +
- ", listeners=" + listeners +
- '}';
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/bus/InvertableEventBus.java b/src/main/java/me/tori/wraith/bus/InvertableEventBus.java
deleted file mode 100644
index a49ecbc..0000000
--- a/src/main/java/me/tori/wraith/bus/InvertableEventBus.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.status.IStatusEvent;
-
-/**
- * @author 7orivorian
- * @since 3.0.0
- * @deprecated This event bus' functionality is now built into the {@linkplain IEventBus standard event bus}.
- */
-@Deprecated(since = "3.3.0", forRemoval = true)
-public interface InvertableEventBus extends IEventBus {
-
- /**
- * @param event the event to be dispatched
- * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener,
- * {@code false} otherwise
- * @see EventBus#dispatchInverted(Object)
- * @deprecated This method's functionality is now handled by {@link #dispatch(Object, boolean)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- boolean dispatchInverted(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 IStatusEvent suppressed or terminated} by any listener,
- * {@code false} otherwise
- * @see EventBus#dispatchInverted(Object, Class)
- * @deprecated This method's functionality is now handled by {@link #dispatch(Object, Class, boolean)}.
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- boolean dispatchInverted(Object event, Class> type);
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/bus/TargetableEventBus.java b/src/main/java/me/tori/wraith/bus/TargetableEventBus.java
deleted file mode 100644
index 6bc6752..0000000
--- a/src/main/java/me/tori/wraith/bus/TargetableEventBus.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.status.IStatusEvent;
-import me.tori.wraith.event.targeted.IClassTargetingEvent;
-
-/**
- * @author 7orivorian
- * @since 3.0.0
- * @deprecated This event bus' functionality is now built into the {@linkplain IEventBus standard event bus}.
- */
-@Deprecated(since = "3.3.0", forRemoval = true)
-public interface TargetableEventBus extends IEventBus {
-
- /**
- * @param event the {@linkplain IClassTargetingEvent} to dispatch
- * @return {@code true} if the given event was {@linkplain IStatusEvent suppressed or terminated} by any listener,
- * {@code false} otherwise
- * @see EventBus#dispatchTargeted(IClassTargetingEvent)
- * @deprecated This method's functionality is now built into {@link #dispatch(Object)}
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- boolean dispatchTargeted(IClassTargetingEvent event);
-
- /**
- * @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 IStatusEvent suppressed or terminated} by any listener,
- * {@code false} otherwise
- * @see EventBus#dispatchTargeted(IClassTargetingEvent, Class)
- * @deprecated This method's functionality is now built into {@link #dispatch(Object)}
- */
- @Deprecated(since = "3.3.0", forRemoval = true)
- boolean dispatchTargeted(IClassTargetingEvent event, Class> type);
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java b/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java
deleted file mode 100644
index 870843e..0000000
--- a/src/main/java/me/tori/wraith/event/staged/IStagedEvent.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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;
-
-/**
- * An interface representing a staged event, indicating the stage at which the event is occurring.
- *
- *
This interface is implemented by events that have distinct stages of processing. Events can be categorized
- * into different stages such as pre, peri, and post.
- *
- * @author 7orivorian
- * @see EventStage
- * @see StagedEvent
- * @since 3.0.0
- */
-public interface IStagedEvent {
-
- /**
- * Gets the stage at which this event is occurring.
- *
- * @return The {@link EventStage} representing the stage of this event.
- */
- EventStage getStage();
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/event/staged/StagedEvent.java b/src/main/java/me/tori/wraith/event/staged/StagedEvent.java
deleted file mode 100644
index bc332a4..0000000
--- a/src/main/java/me/tori/wraith/event/staged/StagedEvent.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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;
-
-import java.util.Objects;
-
-/**
- * Represents a staged event implementation that specifies the stage at which the event occurs.
- *
- * @author 7orivorian
- * @see IStagedEvent
- * @see EventStage
- * @since 1.0.0
- */
-@SuppressWarnings("ClassCanBeRecord")
-public class StagedEvent implements IStagedEvent {
-
- private final @NotNull EventStage stage;
-
- /**
- * Constructs a {@code StagedEvent} with the specified stage.
- *
- * @param stage The {@link EventStage} representing the stage of the event.
- * @throws NullPointerException If the provided {@code stage} is {@code null}.
- */
- public StagedEvent(@NotNull EventStage stage) {
- this.stage = stage;
- }
-
- /**
- * Gets the stage of this staged event.
- *
- * @return The {@link EventStage} representing the stage of the event.
- */
- @NotNull
- @Override
- public EventStage getStage() {
- return stage;
- }
-
- @Override
- public String toString() {
- return "StagedEvent{" +
- "stage=" + stage +
- '}';
- }
-}
\ 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
deleted file mode 100644
index bff8530..0000000
--- a/src/main/java/me/tori/wraith/event/targeted/ClassTargetingEvent.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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;
-
-/**
- * A basic implementation of the {@link IClassTargetingEvent} interface.
- * This class provides a simple way to specify the target class of listeners for an event.
- *
- * @author 7orivorian
- * @see IClassTargetingEvent
- * @since 3.0.0
- */
-@SuppressWarnings("ClassCanBeRecord")
-public class ClassTargetingEvent implements IClassTargetingEvent {
-
- private final Class extends Listener>> targetClass;
-
- /**
- * Constructs a new {@link ClassTargetingEvent} with the specified target class of listeners.
- *
- * @param targetClass The class representing the type of listeners to be targeted by this event.
- */
- public ClassTargetingEvent(Class extends Listener>> targetClass) {
- this.targetClass = targetClass;
- }
-
- /**
- * Retrieves the target class of listeners for this event.
- *
- * @return The class that represents the type of listeners targeted by this event.
- */
- @Override
- public Class extends Listener>> getTargetClass() {
- return targetClass;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java b/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java
deleted file mode 100644
index 413e57a..0000000
--- a/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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;
-
-/**
- * An interface representing an event that targets a specific class of listeners.
- * The class targeted by this event is determined by calling the {@link #getTargetClass()} method.
- * This interface is used to indicate that an event is designed to be directed at a specific listener class.
- *
- * @author 7orivorian
- * @see ClassTargetingEvent
- * @since 3.0.0
- */
-public interface IClassTargetingEvent {
-
- /**
- * Determines if a listener is targeted by a specific event.
- *
- * This method checks if the given event is not an instance of {@code IClassTargetingEvent}
- * or, if it is, delegates the check to the {@code isListenerTargeted} method of the event.
- *
- * @param listener the listener to check
- * @param event the event to check against
- * @return {@code true} if the event targets the listener, {@code false} otherwise.
- * @since 3.3.0
- */
- static boolean isListenerTargetedByEvent(Listener> listener, Object event) {
- return !(event instanceof IClassTargetingEvent e)
- || e.isListenerTargeted(listener);
- }
-
- /**
- * Retrieves the target class of listeners for this event.
- *
- * @return The class that represents the type of listeners targeted by this event.
- */
- Class extends Listener>> getTargetClass();
-
- /**
- * Checks if the listener is an instance of the target class of this event.
- *
- * This default method verifies if the provided listener is an instance of the class
- * that the event targets by using the {@code getTargetClass} method.
- *
- * @param listener the listener to check
- * @return {@code true} if the listener is an instance of the target class, {@code false} otherwise.
- * @since 3.3.0
- */
- default boolean isListenerTargeted(Listener> listener) {
- return getTargetClass().isInstance(listener);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/subscriber/Subscriber.java b/src/main/java/me/tori/wraith/subscriber/Subscriber.java
deleted file mode 100644
index a0faa12..0000000
--- a/src/main/java/me/tori/wraith/subscriber/Subscriber.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * A concrete implementation of {@link ISubscriber} that manages event listeners and their registration.
- * This class provides methods to register single or multiple event listeners and retrieve registered listeners.
- *
- * @author 7orivorian
- * @see ISubscriber
- * @since 1.0.0
- */
-public class Subscriber implements ISubscriber {
-
- private final List<@NotNull Listener>> listeners = new ArrayList<>();
-
- /**
- * Registers a single event listener with this subscriber.
- *
- * @param listener The event listener to register.
- * @param The type of the listener.
- * @return The registered listener.
- */
- @Override
- public > T registerListener(@NotNull T listener) {
- listeners.add(listener);
- return listener;
- }
-
- /**
- * Registers multiple event listeners with this subscriber.
- *
- * @param listeners The event listeners to register.
- * @param The type of the listeners.
- * @return An array containing the registered listeners.
- */
- @SafeVarargs
- @Override
- public final > T[] registerListeners(@NotNull T... listeners) {
- this.listeners.addAll(Arrays.asList(listeners));
- return listeners;
- }
-
- /**
- * Retrieves a collection of event listeners registered with this subscriber.
- *
- * @return A collection of registered event listeners.
- */
- @Override
- public Collection> getListeners() {
- return listeners;
- }
-
- @Override
- public String toString() {
- return "Subscriber{" +
- "listeners=" + listeners +
- '}';
- }
-}
\ No newline at end of file
diff --git a/src/main/java/me/tori/wraith/event/staged/EventStage.java b/src/main/test/dev/tori/wraith/BenchmarkMain.java
similarity index 76%
rename from src/main/java/me/tori/wraith/event/staged/EventStage.java
rename to src/main/test/dev/tori/wraith/BenchmarkMain.java
index 10cbdda..a0a3ea9 100644
--- a/src/main/java/me/tori/wraith/event/staged/EventStage.java
+++ b/src/main/test/dev/tori/wraith/BenchmarkMain.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024 7orivorian.
+ * 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
@@ -19,18 +19,19 @@
* THE SOFTWARE.
*/
-package me.tori.wraith.event.staged;
+package dev.tori.wraith;
+
+import org.openjdk.jmh.Main;
+
+import java.io.IOException;
/**
- * Represents the possible stages at which an event can occur.
- *
- * @author 7orivorian
- * @see IStagedEvent
- * @see StagedEvent
- * @since 1.0.0
+ * @author 7orivorian
+ * @since 4.0.0
*/
-public enum EventStage {
- PRE,
- PERI,
- POST
+public class BenchmarkMain {
+
+ public static void main(String[] args) throws IOException {
+ Main.main(args);
+ }
}
\ No newline at end of file
diff --git a/src/main/test/dev/tori/wraith/DispatchTest.java b/src/main/test/dev/tori/wraith/DispatchTest.java
new file mode 100644
index 0000000..466de58
--- /dev/null
+++ b/src/main/test/dev/tori/wraith/DispatchTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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 dev.tori.wraith;
+
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.listener.LambdaEventListener;
+import dev.tori.wraith.subscriber.Subscriber;
+
+/**
+ * @author 7orivorian
+ * @since 4.0.0
+ */
+public class DispatchTest {
+
+ public static void main(String[] args) {
+ final EventBus bus = new EventBus();
+ bus.subscribe(new Subscriber() {{
+ registerListeners(
+ new LambdaEventListener<>(Target.all(), 100, event -> {
+ System.out.println("Event dispatched: " + event.getClass().getSimpleName());
+ }),
+ new LambdaEventListener<>(Target.fine(EventA.class), (EventA event) -> {
+ event.mod();
+ System.out.println("Handled event: {");
+ System.out.println(" " + event);
+ System.out.println("}");
+ }),
+ new LambdaEventListener<>(Target.fine(EventB.class), (EventB event) -> {
+ event.mod();
+ System.out.println("Handled event: {");
+ System.out.println(" " + event);
+ System.out.println("}");
+ }),
+ new LambdaEventListener<>(Target.fine(EventC.class), (EventC event) -> {
+ event.mod();
+ System.out.println("Handled event: {");
+ System.out.println(" " + event);
+ System.out.println("}");
+ })
+ );
+ }});
+
+ bus.dispatch(new EventA());
+ bus.dispatch(new EventB());
+ bus.dispatch(new EventC());
+ }
+
+ static class EventA {
+
+ private int mods = 0;
+
+ public void mod() {
+ this.mods++;
+ }
+
+ @Override
+ public String toString() {
+ return "EventA{" +
+ "mods=" + mods +
+ '}';
+ }
+ }
+
+ static class EventB {
+
+ private int mods = 0;
+
+ public void mod() {
+ this.mods++;
+ }
+
+ @Override
+ public String toString() {
+ return "EventB{" +
+ "mods=" + mods +
+ '}';
+ }
+ }
+
+ static class EventC {
+
+ private int mods = 0;
+
+ public void mod() {
+ this.mods++;
+ }
+
+ @Override
+ public String toString() {
+ return "EventC{" +
+ "mods=" + mods +
+ '}';
+ }
+ }
+}
\ No newline at end of file
diff --git a/examples/java/me/tori/example/expanded/ExampleListener.java b/src/main/test/dev/tori/wraith/MyBenchmark.java
similarity index 55%
rename from examples/java/me/tori/example/expanded/ExampleListener.java
rename to src/main/test/dev/tori/wraith/MyBenchmark.java
index 7d0ebaf..84dca75 100644
--- a/examples/java/me/tori/example/expanded/ExampleListener.java
+++ b/src/main/test/dev/tori/wraith/MyBenchmark.java
@@ -19,27 +19,46 @@
* THE SOFTWARE.
*/
-package me.tori.example.expanded;
+package dev.tori.wraith;
-import me.tori.wraith.event.staged.EventStage;
-import me.tori.wraith.listener.EventListener;
+import dev.tori.wraith.bus.EventBus;
+import dev.tori.wraith.event.Target;
+import dev.tori.wraith.listener.EventListener;
+import org.openjdk.jmh.annotations.*;
+
+import java.util.concurrent.TimeUnit;
/**
- * Example listener.
- *
* @author 7orivorian
- * @since 1.0.0
+ * @since 3.2.0
*/
-class ExampleListener extends EventListener {
+@State(Scope.Thread)
+public class MyBenchmark {
- public ExampleListener() {
- super(ExampleEvent.class);
- }
+ @State(Scope.Thread)
+ public static class BenchmarkState {
+ EventListener