From 238da28076245565f811c7a3cdf8ed15db010e03 Mon Sep 17 00:00:00 2001 From: Kaktushose <42280757+Kaktushose@users.noreply.github.com> Date: Sun, 9 Feb 2025 15:49:48 +0100 Subject: [PATCH] more improvements --- .../definitions/description/ClassFinder.java | 7 +- .../definitions/description/Descriptor.java | 2 +- .../reflective/ReflectiveClassFinder.java | 2 +- .../InteractionControllerInstantiator.java | 2 +- .../embeds/error/ErrorMessageFactory.java | 4 +- .../jda/commands/extension/Extension.java | 24 ++-- .../commands/extension/Implementation.java | 116 +++++++++--------- .../commands/extension/JDACBuilderData.java | 52 ++++---- .../permissions/PermissionsProvider.java | 2 +- .../commands/scope/GuildScopeProvider.java | 2 +- .../jda/commands/guice/GuiceExtension.java | 59 +++++---- ...uiceInteractionControllerInstantiator.java | 8 +- 12 files changed, 136 insertions(+), 144 deletions(-) diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassFinder.java b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassFinder.java index dc0a155a..57160ede 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassFinder.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/ClassFinder.java @@ -8,14 +8,14 @@ import java.util.SequencedCollection; /// [ClassFinder]s search for classes annotated with a specific annotation -public non-sealed interface ClassFinder extends Implementation.ExtensionImplementable { +public non-sealed interface ClassFinder extends Implementation.ExtensionProvidable { /// This method searches for classes annotated with the given annotation. /// /// @param annotationClass the class of the annotation /// @return the found classes @NotNull - SequencedCollection> search(Class annotationClass); + SequencedCollection> search(@NotNull Class annotationClass); /// This method searches for classes annotated with the given annotation, which have the given super type. /// @@ -23,7 +23,8 @@ public non-sealed interface ClassFinder extends Implementation.ExtensionImplemen /// @param superType the [Class], which is a supertype of the found classes /// @return the found classes @SuppressWarnings("unchecked") - default SequencedCollection> search(Class annotationClass, Class superType) { + @NotNull + default SequencedCollection> search(@NotNull Class annotationClass, @NotNull Class superType) { return search(annotationClass).stream() .filter(superType::isAssignableFrom) .map(aClass -> (Class) aClass) diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java index 47e7b6ba..33a55bee 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/Descriptor.java @@ -5,7 +5,7 @@ /// A [Descriptor] takes a [Class] as input and transforms it into a [ClassDescription]. @FunctionalInterface -public non-sealed interface Descriptor extends Implementation.ExtensionImplementable { +public non-sealed interface Descriptor extends Implementation.ExtensionProvidable { /// the default [Descriptor], which builds [ClassDescription] using [java.lang.reflect] Descriptor REFLECTIVE = new ReflectiveDescriptor(); diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java index 3673577a..4b31b3a6 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/definitions/description/reflective/ReflectiveClassFinder.java @@ -25,7 +25,7 @@ public ReflectiveClassFinder(Class clazz, String[] packages) { } @Override - public @NotNull SequencedCollection> search(Class annotationClass) { + public @NotNull SequencedCollection> search(@NotNull Class annotationClass) { var filter = new FilterBuilder(); for (String pkg : packages) { filter.includePackage(pkg); diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/dispatching/instance/InteractionControllerInstantiator.java b/core/src/main/java/com/github/kaktushose/jda/commands/dispatching/instance/InteractionControllerInstantiator.java index 9dda7d19..0c873dc4 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/dispatching/instance/InteractionControllerInstantiator.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/dispatching/instance/InteractionControllerInstantiator.java @@ -14,7 +14,7 @@ /// classes annotated with [Interaction] but there can be only one instance per class of those per [`Runtime`]({@docRoot}/index.html#runtime-concept-heading). /// Instances of interactions should be treated like runtime scoped singletons, so to speak. @FunctionalInterface -public non-sealed interface InteractionControllerInstantiator extends Implementation.ExtensionImplementable { +public non-sealed interface InteractionControllerInstantiator extends Implementation.ExtensionProvidable { /// This method will be called each time an instance of a class annotated with [Interaction] is needed. /// diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java b/core/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java index 61b3f1ed..30310a7c 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/embeds/error/ErrorMessageFactory.java @@ -2,7 +2,7 @@ import com.github.kaktushose.jda.commands.definitions.interactions.InteractionDefinition; import com.github.kaktushose.jda.commands.definitions.interactions.command.OptionDataDefinition.ConstraintDefinition; -import com.github.kaktushose.jda.commands.extension.Implementation.ExtensionImplementable; +import com.github.kaktushose.jda.commands.extension.Implementation.ExtensionProvidable; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent; import net.dv8tion.jda.api.utils.messages.MessageCreateData; @@ -15,7 +15,7 @@ /// /// @see DefaultErrorMessageFactory /// @see JsonErrorMessageFactory -public non-sealed interface ErrorMessageFactory extends ExtensionImplementable { +public non-sealed interface ErrorMessageFactory extends ExtensionProvidable { /// Gets a [MessageCreateData] to send when type adapting of the user input failed. /// diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/extension/Extension.java b/core/src/main/java/com/github/kaktushose/jda/commands/extension/Extension.java index 37c9a559..7d2968d8 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/extension/Extension.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/extension/Extension.java @@ -3,7 +3,7 @@ import com.github.kaktushose.jda.commands.JDACBuilder; import com.github.kaktushose.jda.commands.definitions.description.Descriptor; import com.github.kaktushose.jda.commands.dispatching.instance.InteractionControllerInstantiator; -import com.github.kaktushose.jda.commands.extension.Implementation.ExtensionImplementable; +import com.github.kaktushose.jda.commands.extension.Implementation.ExtensionProvidable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,12 +13,12 @@ /// Implementations of this interface, that are registered by Javas service provider interface, will be called /// in [JDACBuilder] to configure the framework. /// -/// This class provides ways to extend the framework with own functionality: -/// - [#providedImplementations()]: By implementing this method and returning a list of own implementations of -/// interfaces marked with [ExtensionImplementable], you can for example provide an own implementation of [InteractionControllerInstantiator] -/// or [Descriptor]. These implementations will override the default ones. +/// This interface provides ways to extend the framework with own functionality: +/// - [#providedImplementations()]: By implementing this method and returning a collection of [Implementation]s, you can +/// for example provide an own implementation of [InteractionControllerInstantiator] or [Descriptor]. These +/// implementations will override the default ones. /// -/// If the implementation of this class needs additional configuration data, implementations have to provide an +/// - If the [Extension] needs additional configuration data, implementations have to provide an /// own implementation of [Data] that the user has to register in the builder by calling [JDACBuilder#extensionData(Data...)]. /// /// ### Example @@ -53,17 +53,15 @@ /// ``` public interface Extension { - /// Will be called right after jda-commands loaded the Extension. + /// Initialises the [Extension] with to provided [Data]. Will be called right after jda-commands loaded the Extension. /// /// @param data The custom implementation of [Data] if given by the User. This can be safely cast to the type returned by [#dataType()]. void init(@Nullable Data data); - /// By implementing this method and returning a list of own implementations of interfaces marked with - /// [ExtensionImplementable], you can for example provide an own implementation of [InteractionClassProvider] - /// or [Descriptor]. These implementations will override the default ones. + /// Gets a collection of [Implementation]s this [Extension] provides. /// - /// @return a collection of [Implementation]s that should be used to retrieve certain implementations of an interface. - /// @apiNote Please note that this method is called multiple times during framework creation. If the identity of the implementations + /// @return a collection of [Implementation]s + /// @implNote Please note that this method is called multiple times during framework creation. If the identity of the implementations /// is important, you should always return the same instance. @NotNull default Collection<@NotNull Implementation> providedImplementations() { @@ -76,7 +74,7 @@ default Class dataType() { return Void.class; } - /// Implementations of this interface are providing additional configuration to implementations of [Extension] + /// Implementations of this interface are providing additional configuration to implementations of [Extension]. interface Data {} } diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/extension/Implementation.java b/core/src/main/java/com/github/kaktushose/jda/commands/extension/Implementation.java index f51a300d..7df1ae9e 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/extension/Implementation.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/extension/Implementation.java @@ -14,98 +14,94 @@ import org.jetbrains.annotations.NotNull; import java.lang.annotation.Annotation; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.SequencedCollection; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -/// Instances of this class are used to provide custom implementations of classes implementing [ExtensionImplementable], -/// please note that [TypeAdapter]s, [Middleware]s and [Validator]s are only providable by their corresponding container types: -/// [TypeAdapterContainer], [MiddlewareContainer], [ValidatorContainer]. +/// Instances of [Implementation] are used to provide custom implementations of [ExtensionProvidable] interfaces, namely: +/// - [ClassFinder] +/// - [Descriptor] +/// - [InteractionControllerInstantiator] +/// - [ErrorMessageFactory] +/// - [MiddlewareContainer] (wrapper type for [Middleware]) +/// - [TypeAdapterContainer] (wrapper type for [TypeAdapter]) +/// - [ValidatorContainer] (wrapper type for [Validator]) +/// - [PermissionsProvider] +/// - [GuildScopeProvider] /// -/// Such instances are returned by [Extension#providedImplementations()] and used by the [JDACBuilder]. +/// Such instances of [Implementation] are returned by [Extension#providedImplementations()] and used by the [JDACBuilder] to +/// configure jda-commands. /// -/// If the collection returned by [java.util.function.Supplier#get()] ([#supplier()]) is empty then this implementation is discarded and thus treated as non-existent. +/// @param type the [Class] of the implemented interface +/// @param supplier the [Function] used to retrieve instances of the custom implementation +/// @implNote If the [#supplier()] returns an empty collection, then this [Implementation] is discarded and thus treated as non-existent. /// -/// All extensions/ implementations can only provide one instance of an [ExtensionImplementable] interface, expect for -/// [TypeAdapter]s, [Middleware]s and [Validator]s, which can be implemented multiple times. -/// -/// @param type the [Class] of the implemented interface -/// @param supplier the [java.util.function.Supplier] used to retrieve instances of the custom implementations -public record Implementation( +/// @apiNote The [TypeAdapter]s, [Middleware]s and [Validator]s are only providable by their corresponding container types: +/// [TypeAdapterContainer], [MiddlewareContainer] and [ValidatorContainer]. +/// @see Extension +public record Implementation( @NotNull Class type, @NotNull Function<@NotNull JDACBuilderData, @NotNull SequencedCollection<@NotNull T>> supplier ) { - /// A marker interface that all types providable by an [Implementation] implement - public sealed interface ExtensionImplementable permits ClassFinder, Descriptor, InteractionControllerInstantiator, ErrorMessageFactory, MiddlewareContainer, TypeAdapterContainer, ValidatorContainer, PermissionsProvider, GuildScopeProvider {} + /// A marker interface that all types providable by an [Extension] share. + public sealed interface ExtensionProvidable permits ClassFinder, Descriptor, InteractionControllerInstantiator, ErrorMessageFactory, + MiddlewareContainer, TypeAdapterContainer, ValidatorContainer, PermissionsProvider, GuildScopeProvider {} /// A container type for providing [TypeAdapter]s. - /// @param type the [Class] for which the [TypeAdapter] should be registered + /// + /// @param type the [Class] for which the [TypeAdapter] should be registered /// @param adapter the [TypeAdapter] implementation - public record TypeAdapterContainer(@NotNull Class type, @NotNull TypeAdapter adapter) implements ExtensionImplementable {} + public record TypeAdapterContainer(@NotNull Class type, @NotNull TypeAdapter adapter) implements ExtensionProvidable {} /// A container type for providing [Middleware]s. - /// @param priority the [Priority] with which the [Middleware] should be registered + /// + /// @param priority the [Priority] with which the [Middleware] should be registered /// @param middleware the [Middleware] implementation - public record MiddlewareContainer(@NotNull Priority priority, @NotNull Middleware middleware) implements ExtensionImplementable {} + public record MiddlewareContainer(@NotNull Priority priority, @NotNull Middleware middleware) implements ExtensionProvidable {} /// A container type for providing [Validator]s. + /// /// @param annotation the [Annotation] for which the [Validator] should be registered - /// @param validator the [Validator] implementation - public record ValidatorContainer(@NotNull Class annotation, @NotNull Validator validator) implements ExtensionImplementable {} - - public static Implementation single(@NotNull Class type, @NotNull Function<@NotNull JDACBuilderData, @NotNull T> supplier) { - return new Implementation<>( - type, - (builder -> List.of(supplier.apply(builder))) - ); + /// @param validator the [Validator] implementation + public record ValidatorContainer(@NotNull Class annotation, @NotNull Validator validator) implements ExtensionProvidable {} + + public static Implementation single(@NotNull Class type, + @NotNull Function<@NotNull JDACBuilderData, + @NotNull T> supplier) { + return new Implementation<>(type, (builder -> List.of(supplier.apply(builder)))); } - SequencedCollection implementations(JDACBuilderData builder) { - checkCycling(builder); + SequencedCollection implementations(JDACBuilderData data) { + if (data.alreadyCalled.stream().anyMatch(provider -> provider.type.equals(type))) { + throw new JDACBuilder.ConfigurationException( + "Cycling dependencies while getting implementations of %s! \n%s".formatted(type, format(data)) + ); + } - builder.alreadyCalled.add(this); // scope entry + data.alreadyCalled.add(this); // scope entry // other suppliers could be called here // Scoping this will create a simple stack of already called methods, allowing checking for cycling dependencies (Implementation#type()) - SequencedCollection apply = supplier().apply(builder); + SequencedCollection apply = supplier().apply(data); - builder.alreadyCalled.remove(this); // scope leave + data.alreadyCalled.remove(this); // scope leave return apply; } - private void checkCycling(JDACBuilderData builder) { - boolean alreadyCalled = builder.alreadyCalled - .stream() - .anyMatch(provider -> provider.type.equals(type)); - - if (alreadyCalled) { - List stack = builder.alreadyCalled - .reversed() - .stream() - .map(provider -> { - var extension = builder.implementation(provider.type) - .stream() - .findAny() - .map(Map.Entry::getKey) - .orElseThrow() - .getClass(); - return new GraphEntry(extension, provider.type); - }) - .toList(); - - throw new JDACBuilder.ConfigurationException("Cycling dependencies while getting implementations of %s! \n%s" - .formatted(type, format(stack))); - } - } + private record GraphEntry(Class extension, Class provides) {} - private record GraphEntry( - Class extension, - Class provides - ) {} + private String format(JDACBuilderData data) { + List stack = data.alreadyCalled.reversed().stream() + .map(provider -> { + var extension = data.implementations(provider.type).stream().findAny().map(Map.Entry::getKey).orElseThrow().getClass(); + return new GraphEntry(extension, provider.type); + }) + .toList(); - private String format(List stack) { if (stack.size() == 1) { GraphEntry entry = stack.getFirst(); return "%s provides and needs %s, thus calls itself".formatted(entry.extension.getSimpleName(), entry.provides.getSimpleName()); diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/extension/JDACBuilderData.java b/core/src/main/java/com/github/kaktushose/jda/commands/extension/JDACBuilderData.java index 8f093b17..7b71fe78 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/extension/JDACBuilderData.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/extension/JDACBuilderData.java @@ -15,6 +15,7 @@ import com.github.kaktushose.jda.commands.dispatching.validation.Validator; import com.github.kaktushose.jda.commands.embeds.error.DefaultErrorMessageFactory; import com.github.kaktushose.jda.commands.embeds.error.ErrorMessageFactory; +import com.github.kaktushose.jda.commands.extension.Implementation.ExtensionProvidable; import com.github.kaktushose.jda.commands.extension.internal.ExtensionFilter; import com.github.kaktushose.jda.commands.permissions.DefaultPermissionsProvider; import com.github.kaktushose.jda.commands.permissions.PermissionsProvider; @@ -50,7 +51,6 @@ public sealed class JDACBuilderData permits JDACBuilder { protected final Map, Extension.Data> extensionData = new HashMap<>(); protected ExtensionFilter extensionFilter = new ExtensionFilter(JDACBuilder.FilterStrategy.EXCLUDE, List.of()); - // loadable by extension protected InteractionControllerInstantiator controllerInstantiator = null; @@ -94,38 +94,38 @@ private Collection extensions() { } @SuppressWarnings("unchecked") - SequencedCollection> implementation(Class type) { + SequencedCollection> implementations(Class type) { return extensions() .stream() - .flatMap(extension -> - extension.providedImplementations() - .stream() - .filter(provider -> provider.type().isAssignableFrom(type)) - .flatMap(implementation -> implementation.implementations(this).stream()) - .map(value -> Map.entry(extension, (T) value)) - ) - .toList(); + .flatMap(extension -> extension.providedImplementations().stream() + .filter(implementation -> implementation.type().isAssignableFrom(type)) + .flatMap(implementation -> implementation.implementations(this).stream()) + .map(value -> Map.entry(extension, (T) value)) + ).toList(); } - private T load(Class type, T setValue, T defaultValue) { + private T load(Class type, T setValue, T defaultValue) { if (setValue != null) return setValue; - SequencedCollection> implementations = implementation(type); + + var implementations = implementations(type); if (implementations.isEmpty()) { if (defaultValue != null) return defaultValue; throw new JDACBuilder.ConfigurationException("No implementation for %s found. Please provide!".formatted(type)); - } else if (implementations.size() == 1) { + } + + if (implementations.size() == 1) { return implementations.getFirst().getValue(); - } else { - String foundImplementations = implementations.stream() - .map(entry -> "extension %s -> %s".formatted(entry.getKey(), entry.getValue())) - .collect(Collectors.joining(System.lineSeparator())); - - throw new JDACBuilder.ConfigurationException( - "Found multiple implementations of %s, please exclude the unwanted extension: \n%s" - .formatted(type, foundImplementations) - ); } + + String foundImplementations = implementations.stream() + .map(entry -> "extension %s -> %s".formatted(entry.getKey(), entry.getValue())) + .collect(Collectors.joining(System.lineSeparator())); + + throw new JDACBuilder.ConfigurationException( + "Found multiple implementations of %s, please exclude the unwanted extension: \n%s" + .formatted(type, foundImplementations) + ); } /// the packages provided by the user for classpath scanning @@ -201,7 +201,7 @@ public Descriptor descriptor() { /// @return the [ClassFinder]s to be used. Can be added via an [Extension] @NotNull public Collection classFinders() { - Collection all = implementation(ClassFinder.class) + Collection all = implementations(ClassFinder.class) .stream() .map(Map.Entry::getValue) .collect(Collectors.toSet()); @@ -225,7 +225,7 @@ public ClassFinder mergedClassFinder() { /// @return the [Middleware]s to be used. Can be added via an [Extension] @NotNull public Collection> middlewares() { - Collection> all = implementation(Implementation.MiddlewareContainer.class) + Collection> all = implementations(Implementation.MiddlewareContainer.class) .stream() .map(Map.Entry::getValue) .map(container -> Map.entry(container.priority(), container.middleware())) @@ -237,7 +237,7 @@ public Collection> middlewares() { /// @return the [Validator]s to be used. Can be added via an [Extension] @NotNull public Map, Validator> validators() { - Map, Validator> all = implementation(Implementation.ValidatorContainer.class) + Map, Validator> all = implementations(Implementation.ValidatorContainer.class) .stream() .map(Map.Entry::getValue) .collect(Collectors.toMap(Implementation.ValidatorContainer::annotation, Implementation.ValidatorContainer::validator)); @@ -248,7 +248,7 @@ public Map, Validator> validators() { /// @return the [TypeAdapter]s to be used. Can be added via an [Extension] @NotNull public Map, TypeAdapter> typeAdapters() { - Map, TypeAdapter> all = implementation(Implementation.TypeAdapterContainer.class) + Map, TypeAdapter> all = implementations(Implementation.TypeAdapterContainer.class) .stream() .map(Map.Entry::getValue) .collect(Collectors.toMap(Implementation.TypeAdapterContainer::type, Implementation.TypeAdapterContainer::adapter)); diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java b/core/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java index 1f3a1f1d..5c2fb843 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/permissions/PermissionsProvider.java @@ -11,7 +11,7 @@ /// /// @see DefaultPermissionsProvider /// @see Permissions Permission -public non-sealed interface PermissionsProvider extends Implementation.ExtensionImplementable { +public non-sealed interface PermissionsProvider extends Implementation.ExtensionProvidable { /// Checks if a [User] has permissions. Compared to [#hasPermission(Member, InvocationContext)] this method will be /// called if the command gets executed in a non-guild context, where no member object is available. diff --git a/core/src/main/java/com/github/kaktushose/jda/commands/scope/GuildScopeProvider.java b/core/src/main/java/com/github/kaktushose/jda/commands/scope/GuildScopeProvider.java index 0ed69aae..49e1b789 100644 --- a/core/src/main/java/com/github/kaktushose/jda/commands/scope/GuildScopeProvider.java +++ b/core/src/main/java/com/github/kaktushose/jda/commands/scope/GuildScopeProvider.java @@ -10,7 +10,7 @@ /// /// @see DefaultGuildScopeProvider @FunctionalInterface -public non-sealed interface GuildScopeProvider extends Function>, Implementation.ExtensionImplementable { +public non-sealed interface GuildScopeProvider extends Function>, Implementation.ExtensionProvidable { /// Gets a Set of guild ids the provided command should be registered for. /// diff --git a/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/GuiceExtension.java b/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/GuiceExtension.java index 738bbdb2..25b2824c 100644 --- a/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/GuiceExtension.java +++ b/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/GuiceExtension.java @@ -8,6 +8,9 @@ import com.github.kaktushose.jda.commands.embeds.error.ErrorMessageFactory; import com.github.kaktushose.jda.commands.extension.Extension; import com.github.kaktushose.jda.commands.extension.Implementation; +import com.github.kaktushose.jda.commands.extension.Implementation.MiddlewareContainer; +import com.github.kaktushose.jda.commands.extension.Implementation.TypeAdapterContainer; +import com.github.kaktushose.jda.commands.extension.Implementation.ValidatorContainer; import com.github.kaktushose.jda.commands.extension.JDACBuilderData; import com.github.kaktushose.jda.commands.guice.internal.GuiceExtensionModule; import com.github.kaktushose.jda.commands.guice.internal.GuiceInteractionControllerInstantiator; @@ -35,7 +38,7 @@ public class GuiceExtension implements Extension { private static final Class IMPLEMENTATION_ANN = com.github.kaktushose.jda.commands.guice.Implementation.class; - private final List> loadableClasses = List.of( + private final List> loadableClasses = List.of( Descriptor.class, ErrorMessageFactory.class, PermissionsProvider.class, @@ -52,13 +55,15 @@ public void init(@Nullable Data data) { this.injector = found.createChildInjector(new GuiceExtensionModule()); } + @NotNull @Override - public @NotNull Collection> providedImplementations() { + public Collection> providedImplementations() { List> implementations = new ArrayList<>(); implementations.add(Implementation.single( InteractionControllerInstantiator.class, - _ -> new GuiceInteractionControllerInstantiator(this))); + _ -> new GuiceInteractionControllerInstantiator(injector) + )); addDynamicImplementations(implementations); return implementations; @@ -69,48 +74,40 @@ private void addDynamicImplementations(List> list) { // load single types for (var type : loadableClasses) { list.add(new Implementation<>( - (Class) type, - builder -> searchImplementedClasses(builder, type) - .map(instance -> (Implementation.ExtensionImplementable) instance) + (Class) type, + builder -> instances(builder, type) + .map(instance -> (Implementation.ExtensionProvidable) instance) .toList() )); } // load multiple implementable types list.add(new Implementation<>( - Implementation.TypeAdapterContainer.class, - builder -> searchImplementedClasses(builder, TypeAdapter.class) - .map(adapter -> new Implementation.TypeAdapterContainer( - adapter.getClass().getAnnotation(IMPLEMENTATION_ANN).clazz(), - adapter) - ) - .toList() + TypeAdapterContainer.class, builder -> instances(builder, TypeAdapter.class) + .map(adapter -> new TypeAdapterContainer( + adapter.getClass().getAnnotation(IMPLEMENTATION_ANN).clazz(), + adapter) + ).toList() )); list.add(new Implementation<>( - Implementation.ValidatorContainer.class, - builder -> searchImplementedClasses(builder, Validator.class) - .map(validator -> new Implementation.ValidatorContainer( - validator.getClass().getAnnotation(IMPLEMENTATION_ANN).annotation(), - validator) - ) - .toList() + ValidatorContainer.class, builder -> instances(builder, Validator.class) + .map(validator -> new ValidatorContainer( + validator.getClass().getAnnotation(IMPLEMENTATION_ANN).annotation(), + validator) + ).toList() )); - list.add(new Implementation<>( - Implementation.MiddlewareContainer.class, - builder -> searchImplementedClasses(builder, Middleware.class) - .map(middleware -> new Implementation.MiddlewareContainer( - middleware.getClass().getAnnotation(IMPLEMENTATION_ANN).priority(), - middleware) - ) - .toList() + list.add(new Implementation<>(MiddlewareContainer.class, builder -> instances(builder, Middleware.class) + .map(middleware -> new MiddlewareContainer( + middleware.getClass().getAnnotation(IMPLEMENTATION_ANN).priority(), + middleware) + ).toList() )); } - private Stream searchImplementedClasses(JDACBuilderData builder, Class type) { - return builder - .mergedClassFinder() + private Stream instances(JDACBuilderData builder, Class type) { + return builder.mergedClassFinder() .search(IMPLEMENTATION_ANN, type) .stream() .map(injector::getInstance); diff --git a/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/internal/GuiceInteractionControllerInstantiator.java b/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/internal/GuiceInteractionControllerInstantiator.java index 479d2900..31c10eb5 100644 --- a/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/internal/GuiceInteractionControllerInstantiator.java +++ b/guice-extension/src/main/java/com/github/kaktushose/jda/commands/guice/internal/GuiceInteractionControllerInstantiator.java @@ -10,10 +10,10 @@ @ApiStatus.Internal public class GuiceInteractionControllerInstantiator implements InteractionControllerInstantiator { - private final GuiceExtension extension; + private final Injector injector; - public GuiceInteractionControllerInstantiator(GuiceExtension extension) { - this.extension = extension; + public GuiceInteractionControllerInstantiator(Injector injector) { + this.injector = injector; } @Override @@ -25,7 +25,7 @@ public T instance(Class clazz, Context context) { /// This has the effect, that each class annotated with [Interaction] will be treated as a runtime scoped singleton. @Override public InteractionControllerInstantiator forRuntime(String id, JDA jda) { - Injector childInjector = extension.injector().createChildInjector(new InteractionControllerInstantiatorModule(jda)); + Injector childInjector = injector.createChildInjector(new InteractionControllerInstantiatorModule(jda)); return new InteractionControllerInstantiator() { @Override