feat(structure): add Structure abstractions and API
All checks were successful
github-mirror / push-github (push) Successful in 1m43s
Build / Gradle-Build (push) Successful in 15s
Test / Gradle-Test (push) Successful in 26s

This commit is contained in:
tueem 2025-04-22 14:22:27 +02:00
parent 42a675dc96
commit 272225ac07
Signed by: tueem
GPG Key ID: 65C8667EC17A88FB
10 changed files with 263 additions and 0 deletions

View File

@ -5,8 +5,15 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import net.tomatentum.marinara.structure.data.ButtonStructureData.ButtonStyle;
@Target({ElementType.METHOD}) @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface Button { public @interface Button {
public String value(); //aka customId 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 "";
} }

View File

@ -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<InteractionIdentifier, Void> {
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<InteractionIdentifier, Void> {
private Class<? extends Object> buttonClass;
public Factory(Class<? extends Object> buttonClass) {
this.buttonClass = buttonClass;
}
@Override
public void addParser(Set<MethodParser> parser) {
parser.add(new ComponentStructureParser(buttonClass));
}
@Override
public Optional<ReflectedMethod<InteractionIdentifier, Void>> 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));
}
}
}

View File

@ -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<B extends Object>
extends LoneMethodContainer<InteractionIdentifier, Void>
implements StructureProvider<B> {
private Logger logger = LoggerFactory.getLogger(getClass());
private Class<? extends B> buttonClass;
public MethodStructureProvider(Class<? extends B> buttonClass) {
super(new ReflectedMethodFactoryImpl<>());
super.factory().addFactory(new ComponentStructureMethod.Factory(buttonClass));
this.buttonClass = buttonClass;
}
@Override
public B button(InteractionIdentifier identifier) {
Optional<ReflectedMethod<InteractionIdentifier, Void>> 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;
}
}
}

View File

@ -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<B extends Object> implements StructureProvider<B> {
private Map<Short, StructureProvider<B>> providerMap;
public PriorityStructureProvider() {
this.providerMap = new TreeMap<>();
}
public PriorityStructureProvider<B> addProvider(StructureProvider<B> 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;
}
}

View File

@ -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<B extends Object> implements StructureProvider<B> {
private ComponentStructureConverter<B> converter;
private Map<InteractionIdentifier, B> buttonMap;
public StaticStructureProvider(ComponentStructureConverter<B> converter) {
this.converter = converter;
this.buttonMap = new HashMap<>();
}
public StaticStructureProvider<B> 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);
}
}

View File

@ -0,0 +1,7 @@
package net.tomatentum.marinara.structure;
import net.tomatentum.marinara.interaction.ident.InteractionIdentifier;
public interface StructureProvider<B extends Object> {
B button(InteractionIdentifier identifier);
}

View File

@ -0,0 +1,5 @@
package net.tomatentum.marinara.structure.annotation;
public @interface ComponentStructure {
public String customId();
}

View File

@ -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;
}
}

View File

@ -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<? extends Object> buttonClass;
public ComponentStructureParser(Class<? extends Object> 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();
}
}

View File

@ -0,0 +1,9 @@
package net.tomatentum.marinara.wrapper;
import net.tomatentum.marinara.structure.data.ButtonStructureData;
public interface ComponentStructureConverter<B extends Object> {
B convertButton(ButtonStructureData data);
}