diff --git a/.gitignore b/.gitignore index 5a45940..c563bd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,670 @@ -/.idea/ -/target/ -/dependency-reduced-pom.xml -/developer-docs/ \ No newline at end of file +### Wraith Specifics +developer-docs + +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### NotepadPP template +# Notepad++ backups # +*.bak + +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Eclipse template +.metadata +bin/ +tmp/ +*.tmp +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp_proj +*_wpftmp.csproj +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +*.code-workspace + +# Local History for Visual Studio Code + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### Gradle template +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +# JDT-specific (Eclipse Java Development Tools) + +### Vim template +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### SublimeText template +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings diff --git a/README.md b/README.md index fce1a70..83e33ab 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Lightweight Java event library created and maintained by [7orivorian](https://gi com.github.7orivorian Wraith - 3.2.2 + 3.3.0 ``` @@ -51,13 +51,13 @@ repositories { ```gradle dependencies { - implementation 'com.github.7orivorian:Wraith:3.2.2' + implementation 'com.github.7orivorian:Wraith:3.3.0' } ``` ### Other -Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/releases/tag/3.2.2) +Download a `.jar` file from [releases](https://github.com/7orivorian/Wraith/releases/tag/3.3.0) # Building @@ -99,6 +99,7 @@ Once you've defined your subscriber, you can subscribe it to an event bus direct public class Consts { private static final IEventBus EVENT_BUS = new EventBus(); } + public class ExampleSubscriber extends Subscriber { public ExampleSubscriber() { @@ -200,8 +201,7 @@ public class ExampleSubscriber extends Subscriber {
Details... -To dispatch an event to an event bus, call one of the `dispatch` methods defined in any `IEventBus` -implementation, passing your event as a parameter: +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; diff --git a/examples/java/me/tori/example/expanded/ExampleEvent.java b/examples/java/me/tori/example/expanded/ExampleEvent.java index 686219f..3b1a423 100644 --- a/examples/java/me/tori/example/expanded/ExampleEvent.java +++ b/examples/java/me/tori/example/expanded/ExampleEvent.java @@ -21,17 +21,17 @@ package me.tori.example.expanded; -import me.tori.wraith.event.cancelable.CancelableEvent; import me.tori.wraith.event.staged.EventStage; import me.tori.wraith.event.staged.IStagedEvent; +import me.tori.wraith.event.status.StatusEvent; /** * Example event. - *

Last updated for version 3.1.0 * - * @author 7orivorian + * @author 7orivorian + * @since 1.0.0 */ -class ExampleEvent extends CancelableEvent implements IStagedEvent { +class ExampleEvent extends StatusEvent implements IStagedEvent { private String message; private final EventStage stage; diff --git a/examples/java/me/tori/example/expanded/ExampleListener.java b/examples/java/me/tori/example/expanded/ExampleListener.java index c3de8fc..7d0ebaf 100644 --- a/examples/java/me/tori/example/expanded/ExampleListener.java +++ b/examples/java/me/tori/example/expanded/ExampleListener.java @@ -26,10 +26,9 @@ /** * Example listener. - *

Last updated for version 3.1.0 * - * @author 7orivorian - * @since 1.0.0 + * @author 7orivorian + * @since 1.0.0 */ class ExampleListener extends EventListener { diff --git a/examples/java/me/tori/example/expanded/ExampleMain.java b/examples/java/me/tori/example/expanded/ExampleMain.java index 310be01..25b663f 100644 --- a/examples/java/me/tori/example/expanded/ExampleMain.java +++ b/examples/java/me/tori/example/expanded/ExampleMain.java @@ -26,10 +26,10 @@ import me.tori.wraith.event.staged.EventStage; /** - * Example program - *

Last updated for version 3.1.0 + * Example program. * - * @author 7orivorian + * @author 7orivorian + * @since 1.0.0 */ class ExampleMain { @@ -44,7 +44,7 @@ public static void main(String[] args) { EVENT_BUS.dispatch(event1); - if (!event1.isCanceled()) { + if (!event1.isSuppressed()) { System.out.println(event1.getMessage()); } @@ -52,7 +52,7 @@ public static void main(String[] args) { EVENT_BUS.dispatch(event2); - if (!event2.isCanceled()) { + if (!event2.isSuppressed()) { System.out.println(event2.getMessage()); } } diff --git a/examples/java/me/tori/example/expanded/ExampleSubscriber.java b/examples/java/me/tori/example/expanded/ExampleSubscriber.java index a8dae62..f3cf156 100644 --- a/examples/java/me/tori/example/expanded/ExampleSubscriber.java +++ b/examples/java/me/tori/example/expanded/ExampleSubscriber.java @@ -27,10 +27,9 @@ /** * Example subscriber. - *

Last updated for version 3.1.0 * - * @author 7orivorian - * @since 1.0.0 + * @author 7orivorian + * @since 1.0.0 */ class ExampleSubscriber extends Subscriber { diff --git a/examples/java/me/tori/example/simple/SimpleExample.java b/examples/java/me/tori/example/simple/SimpleExample.java index b346f28..3d6fdfa 100644 --- a/examples/java/me/tori/example/simple/SimpleExample.java +++ b/examples/java/me/tori/example/simple/SimpleExample.java @@ -22,16 +22,14 @@ package me.tori.example.simple; import me.tori.wraith.bus.EventBus; -import me.tori.wraith.event.cancelable.CancelableEvent; +import me.tori.wraith.event.status.StatusEvent; import me.tori.wraith.listener.LambdaEventListener; import me.tori.wraith.subscriber.Subscriber; /** - * One-class example - *

- * Last updated for version 3.1.0 + * One-class example. * - * @author 7orivorian + * @author 7orivorian */ class SimpleExample { @@ -45,38 +43,23 @@ public static void main(String[] args) { // Subscribe to the event bus bus.subscribe(subscriber); - SimpleEvent event; - // Create a simple event - // This event will be canceled, see the lambda in SimpleSubscriber to know why ;P - event = new SimpleEvent("Pie is gross!"); - - if (!bus.dispatch(event)) { - // Only log the message if our event isn't canceled - System.out.println(event.getMessage()); - } + SimpleEvent event = new SimpleEvent("Pie is delicious <3"); - event = new SimpleEvent("Pie is delicious <3"); - if (!bus.dispatch(event)) { - System.out.println(event.getMessage()); - } + // Dispatch our event + bus.dispatch(event); } private static final class SimpleSubscriber extends Subscriber { public SimpleSubscriber() { registerListener( - new LambdaEventListener<>(SimpleEvent.class, event -> { - if (event.getMessage().contains("gross")) { - // Pie is not gross, so we cancel this event, preventing it from being written to the console - event.cancel(); - } - }) + new LambdaEventListener<>(SimpleEvent.class, event -> System.out.println(event.getMessage())) ); } } - private static final class SimpleEvent extends CancelableEvent { + private static final class SimpleEvent extends StatusEvent { private final String message; diff --git a/pom.xml b/pom.xml index 3e33b59..c829fcb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ me.tori Wraith jar - 3.2.2 + 3.3.0 diff --git a/src/main/java/me/tori/wraith/bus/EventBus.java b/src/main/java/me/tori/wraith/bus/EventBus.java index 3ef51c9..7879c69 100644 --- a/src/main/java/me/tori/wraith/bus/EventBus.java +++ b/src/main/java/me/tori/wraith/bus/EventBus.java @@ -32,6 +32,7 @@ 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}. @@ -172,23 +173,45 @@ public void unregister(Listener listener) { } /** - * Dispatches an event to listeners. + * Convenience method to dispatch an event with no {@linkplain Listener#getType() listener type} restriction, and + * normal processing priority. * - * @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} + * @see #dispatch(Object, Class, boolean) + * @since 3.3.0 */ @Override public boolean dispatch(Object event) { - return dispatch(event, null); + return dispatch(event, null, false); } /** - * Dispatches an event to listeners. + * Convenience method to dispatch an event with an optional {@linkplain Listener#getType() listener type} restriction, and + * normal processing priority. * - *

The {@code type} parameter serves as a filtering mechanism for listeners, enabling you to selectively invoke + * @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 @@ -197,9 +220,10 @@ public boolean dispatch(Object event) { * {@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) { + 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!"); @@ -209,8 +233,8 @@ public boolean dispatch(Object event, Class type) { dispatchToEachListener( event, this.listeners.get(event.getClass()), - listener -> (type == null) || (listener.getType() == null) || (listener.getType() == type), - false + listener -> listener.isAcceptableType(type) && IClassTargetingEvent.isListenerTargetedByEvent(listener, event), + invertPriority ); if (event instanceof IStatusEvent e) { @@ -228,7 +252,9 @@ public boolean dispatch(Object event, Class type) { * {@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); @@ -246,28 +272,12 @@ public boolean dispatchTargeted(IClassTargetingEvent event) { * {@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) { - 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 -> ((type == null) || (listener.getType() == null) || (listener.getType() == type)) - && listener.getClass().equals(event.getTargetClass()), - false - ); - - if (event instanceof IStatusEvent e) { - return e.isSuppressed() || e.isTerminated(); - } - } - return false; + return dispatch(event, type); } /** @@ -279,7 +289,9 @@ public boolean dispatchTargeted(IClassTargetingEvent event, Class type) { * {@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); @@ -298,7 +310,9 @@ public boolean dispatchInverted(Object event) { * {@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 + "!"); @@ -310,7 +324,7 @@ public boolean dispatchInverted(Object event, Class type) { dispatchToEachListener( event, this.listeners.get(event.getClass()), - listener -> (type == null) || (listener.getType() == null) || (listener.getType() == type), + listener -> listener.isAcceptableType(type) && IClassTargetingEvent.isListenerTargetedByEvent(listener, event), true ); @@ -365,7 +379,6 @@ public boolean isShutdown() { /** * @return the {@code id} of this event bus - * @author 7orivorian * @since 3.1.0 */ public int getId() { @@ -381,42 +394,32 @@ public int getId() { * @param event the event to be handled by each listener that satisfies the predicate * @param listeners the list of listeners to be processed * @param predicate the condition that each listener must satisfy to have the action applied - * @param invertPriority if {@code true}, listeners are processed in reverse order; otherwise, + * @param invertPriority if {@code true}, listeners are processed in order of inverse priority; otherwise, * they are processed in normal order * @since 3.2.0 */ - @SuppressWarnings("DuplicatedCode") private void dispatchToEachListener(Object event, List listeners, Predicate predicate, boolean invertPriority) { if (listeners != null && !listeners.isEmpty()) { + ListIterator iterator; + Supplier supplier; if (invertPriority) { - ListIterator iterator = listeners.listIterator(listeners.size()); - while (iterator.hasPrevious()) { - Listener listener = iterator.previous(); - if (!predicate.test(listener)) { - continue; - } - listener.invoke(event); - if ((event instanceof IStatusEvent e) && e.isTerminated()) { - break; - } - if (!listener.shouldPersist()) { - listeners.remove(listener); - } - } + iterator = listeners.listIterator(listeners.size()); + supplier = () -> (iterator.hasPrevious() ? iterator.previous() : null); } else { - Iterator iterator = listeners.listIterator(0); - while (iterator.hasNext()) { - Listener listener = iterator.next(); - if (!predicate.test(listener)) { - continue; - } - listener.invoke(event); - if ((event instanceof IStatusEvent e) && e.isTerminated()) { - break; - } - if (!listener.shouldPersist()) { - listeners.remove(listener); - } + 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); } } } @@ -424,7 +427,8 @@ private void dispatchToEachListener(Object event, List listeners, Pred /** * 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}. + *

+ * 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 diff --git a/src/main/java/me/tori/wraith/bus/IEventBus.java b/src/main/java/me/tori/wraith/bus/IEventBus.java index 6e905e4..a2167af 100644 --- a/src/main/java/me/tori/wraith/bus/IEventBus.java +++ b/src/main/java/me/tori/wraith/bus/IEventBus.java @@ -41,49 +41,86 @@ public interface IEventBus { int DEFAULT_PRIORITY = 0; /** + * Subscribes the specified subscriber to this event bus. + * * @param subscriber the {@link ISubscriber} to be subscribed * @see #register(Listener) */ void subscribe(ISubscriber subscriber); /** + * Unsubscribes the specified subscriber from this event bus. + * * @param subscriber the {@link ISubscriber} to be unsubscribed * @see #unregister(Listener) */ void unsubscribe(ISubscriber subscriber); /** + * Registers the specified listener to this event bus. + * * @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 */ void unregister(Listener listener); /** + * Dispatches the specified event to all registered 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 + * {@code false} otherwise. */ boolean dispatch(Object event); /** + * 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}) * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, - * {@code false} otherwise + * {@code false} otherwise. */ boolean dispatch(Object event, Class type); /** - * Shuts down this event bus, preventing future events from being dispatched + * Dispatches the specified event to all registered listeners, with the option to invert the processing priority. + * + * @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 + * @return {@code true} if the given event is {@linkplain IStatusEvent suppressed or terminated} by any listener, + * {@code false} otherwise. + */ + 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 invertPriority if {@code true}, listeners are processed in order of inverse priority; otherwise, + * 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. + */ + boolean dispatch(Object event, Class type, boolean invertPriority); + + /** + * Shuts down this event bus, preventing future events from being dispatched. */ void shutdown(); /** - * @return {@code true} if this event bus is shut down, {@code false} otherwise + * Checks if this event bus is shut down. + * + * @return {@code true} if this event bus is shut down, {@code false} otherwise. */ boolean isShutdown(); } \ 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 index b1e51a2..a49ecbc 100644 --- a/src/main/java/me/tori/wraith/bus/InvertableEventBus.java +++ b/src/main/java/me/tori/wraith/bus/InvertableEventBus.java @@ -24,9 +24,11 @@ import me.tori.wraith.event.status.IStatusEvent; /** - * @author 7orivorian - * @since 3.0.0 + * @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 { /** @@ -34,7 +36,9 @@ public interface InvertableEventBus extends IEventBus { * @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); /** @@ -43,6 +47,8 @@ public interface InvertableEventBus extends IEventBus { * @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 index f44517d..6bc6752 100644 --- a/src/main/java/me/tori/wraith/bus/TargetableEventBus.java +++ b/src/main/java/me/tori/wraith/bus/TargetableEventBus.java @@ -25,25 +25,31 @@ import me.tori.wraith.event.targeted.IClassTargetingEvent; /** - * @author 7orivorian - * @since 3.0.0 + * @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} + * {@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} + * {@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/cancelable/CancelableEvent.java b/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java deleted file mode 100644 index ae3f539..0000000 --- a/src/main/java/me/tori/wraith/event/cancelable/CancelableEvent.java +++ /dev/null @@ -1,44 +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.cancelable; - -import me.tori.wraith.event.status.StatusEvent; - -import static me.tori.wraith.event.status.IStatusEvent.EventStatus.SUPPRESSED; - -/** - * Default implementation of the {@link ICancelableEvent} interface. - * - * @author 7orivorian - * @see ICancelableEvent - * @since 1.0.0 - */ -@Deprecated(forRemoval = true, since = "3.2.0") -public class CancelableEvent extends StatusEvent implements ICancelableEvent { - - @Override - public String toString() { - return "Cancelable{" + - "canceled=" + (getEventStatus() == SUPPRESSED) + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java b/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.java deleted file mode 100644 index 13b14ea..0000000 --- a/src/main/java/me/tori/wraith/event/cancelable/ICancelableEvent.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.wraith.event.cancelable; - -import me.tori.wraith.event.status.IStatusEvent; - -/** - * @author 7orivorian - * @see CancelableEvent - * @since 1.0.0 - * @deprecated Use {@link IStatusEvent} instead. - */ -@Deprecated(forRemoval = true, since = "3.2.0") -public interface ICancelableEvent extends IStatusEvent { - - /** - * @return {@code true} if this event is canceled, {@code false} otherwise - * @see #isSuppressed() - */ - default boolean isCanceled() { - return isSuppressed(); - } - - /** - * @see #setSuppressed(boolean) - */ - default void setCanceled(boolean canceled) { - setSuppressed(canceled); - } - - /** - * @see #suppress() - */ - default void cancel() { - suppress(); - } -} \ 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 index 5700c91..413e57a 100644 --- a/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java +++ b/src/main/java/me/tori/wraith/event/targeted/IClassTargetingEvent.java @@ -34,10 +34,40 @@ */ 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> 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/listener/Listener.java b/src/main/java/me/tori/wraith/listener/Listener.java index cfdb508..5cf68d1 100644 --- a/src/main/java/me/tori/wraith/listener/Listener.java +++ b/src/main/java/me/tori/wraith/listener/Listener.java @@ -62,7 +62,7 @@ public interface Listener extends Invokable { /** * Determines whether this listener should persist after being invoked. * - * @return {@code true} if the listener should persist, {@code false} otherwise + * @return {@code true} if the listener should persist, {@code false} otherwise. * @see EventBus#forEachListener(List, Predicate, Consumer, boolean) * @since 3.2.0 */ @@ -74,10 +74,29 @@ default boolean shouldPersist() { /** * Indicates whether this listener is inherently persistent. * - * @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 */ default boolean hasIndefinitePersistence() { return true; } + + /** + * 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: + *

+ * + * @param type the class type to check for acceptability + * @return {@code true} if the type is acceptable, {@code false} otherwise. + * @since 3.3.0 + */ + default boolean isAcceptableType(Class type) { + return (type == null) || (getType() == null) || (getType() == type); + } } \ No newline at end of file diff --git a/src/main/java/me/tori/wraith/listener/ListenerBuilder.java b/src/main/java/me/tori/wraith/listener/ListenerBuilder.java index bf576c0..2c02670 100644 --- a/src/main/java/me/tori/wraith/listener/ListenerBuilder.java +++ b/src/main/java/me/tori/wraith/listener/ListenerBuilder.java @@ -36,7 +36,7 @@ *

Usage Example: *

  * {@code
- * EventListener listener = new ListenerBuilder()
+ * EventListener listener = new ListenerBuilder<>()
  *     .target(MyEvent.class)
  *     .type(SomeSpecificType.class)
  *     .priority(5)
@@ -46,7 +46,7 @@
  * }
  * 
* - * @param the type of event this listener handles + * @param the type of event the built listener handles * @author 7orivorian * @see EventListener * @since 3.2.0 @@ -147,7 +147,7 @@ public EventListener build() { Objects.requireNonNull(invokable, "invokable must not be null"); if ((persistent && (persists > 0)) || (!persistent && (persists <= 0))) { throw new IllegalArgumentException( - "Persistency missmatch. persistent=" + persistent + " and persists>" + persists + " is not allowed." + "Persistency missmatch. persistent=" + persistent + " and persists=" + persists + " is not allowed." ); } return new EventListener<>(target, type, priority, persists) { diff --git a/src/main/java/me/tori/wraith/task/ScheduledTask.java b/src/main/java/me/tori/wraith/task/ScheduledTask.java index d257077..54e4041 100644 --- a/src/main/java/me/tori/wraith/task/ScheduledTask.java +++ b/src/main/java/me/tori/wraith/task/ScheduledTask.java @@ -25,14 +25,15 @@ /** * Represents a task that can be scheduled for execution based on events, with an optional delay. - * The task's execution is triggered when an event of the specified target class is dispatched. + * The task's execution is triggered when an event of the specified target class is dispatched, before any + * listeners are invoked. * *

The delay value determines the number of event dispatches that should occur before the task is executed. * The delay decrements with each event dispatch, and once it becomes less than or equal to 0, the task is executed. * - * @author 7orivorian + * @author 7orivorian * @see TaskExecutor - * @since 3.0.0 + * @since 3.0.0 */ public abstract class ScheduledTask implements Runnable { diff --git a/src/main/test/me/tori/wraith/persistency/PersistencyTest.java b/src/main/test/me/tori/wraith/persistency/PersistencyTest.java index 1fd050e..56bec70 100644 --- a/src/main/test/me/tori/wraith/persistency/PersistencyTest.java +++ b/src/main/test/me/tori/wraith/persistency/PersistencyTest.java @@ -22,7 +22,7 @@ package me.tori.wraith.persistency; import me.tori.wraith.bus.EventBus; -import me.tori.wraith.event.cancelable.CancelableEvent; +import me.tori.wraith.event.status.StatusEvent; import me.tori.wraith.listener.EventListener; import me.tori.wraith.subscriber.Subscriber; import org.junit.jupiter.api.Assertions; @@ -62,7 +62,7 @@ public void testIndefiniteEvent() { } } - public static class MyListener extends EventListener { + static class MyListener extends EventListener { public MyListener(int persists) { super(MyEvent.class, null, 0, persists); @@ -70,11 +70,11 @@ public MyListener(int persists) { @Override public void invoke(MyEvent event) { - event.cancel(); + event.terminate(); } } - public static class MyEvent extends CancelableEvent { + static class MyEvent extends StatusEvent { } } \ No newline at end of file diff --git a/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java b/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java index a7ddbb3..b0186d8 100644 --- a/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java +++ b/src/main/test/me/tori/wraith/targetedevent/TargetedEventTest.java @@ -22,7 +22,7 @@ package me.tori.wraith.targetedevent; import me.tori.wraith.bus.EventBus; -import me.tori.wraith.event.cancelable.CancelableEvent; +import me.tori.wraith.event.status.StatusEvent; import me.tori.wraith.event.targeted.IClassTargetingEvent; import me.tori.wraith.listener.EventListener; import me.tori.wraith.listener.Listener; @@ -51,7 +51,7 @@ public void testTargetedEvent() { assertFalse(bus.dispatchTargeted(event)); } - public static class MyListener extends EventListener { + static class MyListener extends EventListener { public MyListener() { super(TestEvent.class); @@ -63,7 +63,7 @@ public void invoke(TestEvent event) { } } - public static class OtherListener extends EventListener { + static class OtherListener extends EventListener { public OtherListener() { super(TestEvent.class); @@ -71,11 +71,11 @@ public OtherListener() { @Override public void invoke(TestEvent event) { - event.cancel(); + event.terminate(); } } - public static class TestEvent extends CancelableEvent implements IClassTargetingEvent { + static class TestEvent extends StatusEvent implements IClassTargetingEvent { private final Class> targetClass;