From 272225ac07b79bc89f1a37f73188e74cfda537c7 Mon Sep 17 00:00:00 2001 From: tueem Date: Tue, 22 Apr 2025 14:22:27 +0200 Subject: [PATCH] feat(structure): add Structure abstractions and API --- .../interaction/annotation/Button.java | 7 ++ .../structure/ComponentStructureMethod.java | 64 +++++++++++++++++++ .../structure/MethodStructureProvider.java | 39 +++++++++++ .../structure/PriorityStructureProvider.java | 31 +++++++++ .../structure/StaticStructureProvider.java | 31 +++++++++ .../marinara/structure/StructureProvider.java | 7 ++ .../annotation/ComponentStructure.java | 5 ++ .../structure/data/ButtonStructureData.java | 26 ++++++++ .../parser/ComponentStructureParser.java | 44 +++++++++++++ .../wrapper/ComponentStructureConverter.java | 9 +++ 10 files changed, 263 insertions(+) create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/ComponentStructureMethod.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/MethodStructureProvider.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/PriorityStructureProvider.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/StaticStructureProvider.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/StructureProvider.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/annotation/ComponentStructure.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/data/ButtonStructureData.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/structure/parser/ComponentStructureParser.java create mode 100644 lib/src/main/java/net/tomatentum/marinara/wrapper/ComponentStructureConverter.java diff --git a/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/Button.java b/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/Button.java index 6c23a2a..219eb46 100644 --- a/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/Button.java +++ b/lib/src/main/java/net/tomatentum/marinara/interaction/annotation/Button.java @@ -5,8 +5,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import net.tomatentum.marinara.structure.data.ButtonStructureData.ButtonStyle; + @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Button { public String value(); //aka customId + public String label() default "default_button"; + public ButtonStyle style() default ButtonStyle.PRIMARY; + public String url() default ""; + public boolean disabled() default false; + public String emoji() default ""; } diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/ComponentStructureMethod.java b/lib/src/main/java/net/tomatentum/marinara/structure/ComponentStructureMethod.java new file mode 100644 index 0000000..273f961 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/ComponentStructureMethod.java @@ -0,0 +1,64 @@ +package net.tomatentum.marinara.structure; + +import java.lang.reflect.Method; +import java.util.Optional; +import java.util.Set; + +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.ReflectedMethodFactory; +import net.tomatentum.cutin.ReflectedMethodFactory.ParserResults; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.structure.parser.ComponentStructureParser; + +public class ComponentStructureMethod extends ReflectedMethod { + + private InteractionIdentifier identifier; + + private ComponentStructureMethod( + Method method, + Object containingObject, + InteractionIdentifier identifier + ) { + super(method, containingObject); + this.identifier = identifier; + } + + @Override + public Object getParameter(Void context, int index) { + return null; + } + + @Override + public InteractionIdentifier identifier() { + return this.identifier; + } + + public static class Factory implements ReflectedMethodFactory.Factory { + + private Class buttonClass; + + public Factory(Class buttonClass) { + this.buttonClass = buttonClass; + } + + @Override + public void addParser(Set parser) { + parser.add(new ComponentStructureParser(buttonClass)); + } + + @Override + public Optional> produce( + Method method, + Object containingObject, + ParserResults parserResults) { + InteractionIdentifier identifier = parserResults.get(ComponentStructureParser.class); + if (identifier == null) + return Optional.empty(); + + return Optional.of(new ComponentStructureMethod(method, containingObject, identifier)); + } + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/MethodStructureProvider.java b/lib/src/main/java/net/tomatentum/marinara/structure/MethodStructureProvider.java new file mode 100644 index 0000000..d1e8cb5 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/MethodStructureProvider.java @@ -0,0 +1,39 @@ +package net.tomatentum.marinara.structure; + +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.ReflectedMethodFactoryImpl; +import net.tomatentum.cutin.container.LoneMethodContainer; +import net.tomatentum.cutin.method.ReflectedMethod; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; + +public class MethodStructureProvider + extends LoneMethodContainer + implements StructureProvider { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private Class buttonClass; + + public MethodStructureProvider(Class buttonClass) { + super(new ReflectedMethodFactoryImpl<>()); + super.factory().addFactory(new ComponentStructureMethod.Factory(buttonClass)); + this.buttonClass = buttonClass; + } + + @Override + public B button(InteractionIdentifier identifier) { + Optional> method = super.findFirstFor(identifier); + if (method.isEmpty()) return null; + try { + return buttonClass.cast(method.get().run(null)); + }catch (ClassCastException ex) { + logger.warn("Structure Method {} return type did not match expected {}", method.get(), buttonClass); + return null; + } + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/PriorityStructureProvider.java b/lib/src/main/java/net/tomatentum/marinara/structure/PriorityStructureProvider.java new file mode 100644 index 0000000..86edae2 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/PriorityStructureProvider.java @@ -0,0 +1,31 @@ +package net.tomatentum.marinara.structure; + +import java.util.Map; +import java.util.TreeMap; + +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; + +public class PriorityStructureProvider implements StructureProvider { + + private Map> providerMap; + + public PriorityStructureProvider() { + this.providerMap = new TreeMap<>(); + } + + public PriorityStructureProvider addProvider(StructureProvider provider, short priority) { + this.providerMap.put(priority, provider); + return this; + } + + @Override + public B button(InteractionIdentifier identifier) { + for (short priority : this.providerMap.keySet()) { + B result = this.providerMap.get(priority).button(identifier); + if (result != null) + return result; + } + return null; + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/StaticStructureProvider.java b/lib/src/main/java/net/tomatentum/marinara/structure/StaticStructureProvider.java new file mode 100644 index 0000000..2b3ca43 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/StaticStructureProvider.java @@ -0,0 +1,31 @@ +package net.tomatentum.marinara.structure; + +import java.util.HashMap; +import java.util.Map; + +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.structure.data.ButtonStructureData; +import net.tomatentum.marinara.wrapper.ComponentStructureConverter; + +public class StaticStructureProvider implements StructureProvider { + + private ComponentStructureConverter converter; + + private Map buttonMap; + + public StaticStructureProvider(ComponentStructureConverter converter) { + this.converter = converter; + this.buttonMap = new HashMap<>(); + } + + public StaticStructureProvider addButton(InteractionIdentifier identifier, ButtonStructureData data) { + this.buttonMap.put(identifier, this.converter.convertButton(data)); + return this; + } + + @Override + public B button(InteractionIdentifier identifier) { + return this.buttonMap.get(identifier); + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/StructureProvider.java b/lib/src/main/java/net/tomatentum/marinara/structure/StructureProvider.java new file mode 100644 index 0000000..c23a927 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/StructureProvider.java @@ -0,0 +1,7 @@ +package net.tomatentum.marinara.structure; + +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; + +public interface StructureProvider { + B button(InteractionIdentifier identifier); +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/annotation/ComponentStructure.java b/lib/src/main/java/net/tomatentum/marinara/structure/annotation/ComponentStructure.java new file mode 100644 index 0000000..ff877ba --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/annotation/ComponentStructure.java @@ -0,0 +1,5 @@ +package net.tomatentum.marinara.structure.annotation; + +public @interface ComponentStructure { + public String customId(); +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/data/ButtonStructureData.java b/lib/src/main/java/net/tomatentum/marinara/structure/data/ButtonStructureData.java new file mode 100644 index 0000000..158cd8f --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/data/ButtonStructureData.java @@ -0,0 +1,26 @@ +package net.tomatentum.marinara.structure.data; + +import net.tomatentum.marinara.interaction.annotation.Button; + +public record ButtonStructureData( + String customId, + String label, + ButtonStyle style, + String url, + boolean disabled, + String emoji + ) { + + public ButtonStructureData(Button button) { + this(button.value(), button.label(), button.style(), button.url(), button.disabled(), button.emoji()); + } + + public enum ButtonStyle { + PRIMARY, + SECONDARY, + SUCCESS, + DANGER, + LINK; + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/structure/parser/ComponentStructureParser.java b/lib/src/main/java/net/tomatentum/marinara/structure/parser/ComponentStructureParser.java new file mode 100644 index 0000000..63534eb --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/structure/parser/ComponentStructureParser.java @@ -0,0 +1,44 @@ +package net.tomatentum.marinara.structure.parser; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomatentum.cutin.MethodParser; +import net.tomatentum.cutin.util.ReflectionUtil; +import net.tomatentum.marinara.interaction.InteractionType; +import net.tomatentum.marinara.interaction.ident.InteractionIdentifier; +import net.tomatentum.marinara.structure.annotation.ComponentStructure; + +public class ComponentStructureParser implements MethodParser { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private Class buttonClass; + + public ComponentStructureParser(Class buttonClass) { + this.buttonClass = buttonClass; + } + + @Override + public Object parse(Method method, Object containingObject) { + if (!method.isAnnotationPresent(ComponentStructure.class)) + return null; + InteractionIdentifier.Builder builder = InteractionIdentifier.builder() + .name(method.getAnnotation(ComponentStructure.class).customId()); + + if (buttonClass.isAssignableFrom(method.getReturnType())) + builder.type(InteractionType.BUTTON); + + if (builder.type() == null) { + logger.error("Structure Method {} return type did not match any of the required {}", String.join(","), buttonClass); + return null; + } + + logger.trace("Parsed Structure Method of {} with result {}", ReflectionUtil.getFullMethodName(method), builder.build()); + return builder.build(); + + } + +} diff --git a/lib/src/main/java/net/tomatentum/marinara/wrapper/ComponentStructureConverter.java b/lib/src/main/java/net/tomatentum/marinara/wrapper/ComponentStructureConverter.java new file mode 100644 index 0000000..ceb7db3 --- /dev/null +++ b/lib/src/main/java/net/tomatentum/marinara/wrapper/ComponentStructureConverter.java @@ -0,0 +1,9 @@ +package net.tomatentum.marinara.wrapper; + +import net.tomatentum.marinara.structure.data.ButtonStructureData; + +public interface ComponentStructureConverter { + + B convertButton(ButtonStructureData data); + +}