Skip to content

Commit

Permalink
GH-41 Add Optional arguments handling. GH-40 GH-39 (#41)
Browse files Browse the repository at this point in the history
Add test for argument handle.
Add @handler annotation.
Add SingleArgumentHandler#toOptionHandler() method.
Add raw type support for LiteCommandsBuilder.
Add NativeBind class.
Implement test platform (LiteTestPlatform).
  • Loading branch information
Rollczi authored Feb 11, 2022
1 parent 1b60dc0 commit b14f379
Show file tree
Hide file tree
Showing 34 changed files with 602 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ private LiteBukkitFactory() {

}

public static LiteCommandsBuilder builder(Server server, String fallbackPrefix) {
return LiteFactory.builder()
public static LiteCommandsBuilder<CommandSender, LiteBukkitPlatformManager> builder(Server server, String fallbackPrefix) {
return LiteFactory.<CommandSender, LiteBukkitPlatformManager>builder()
.bind(Server.class, server)
.bind(CommandSender.class, new OriginalSenderBind())
.platform(new LiteBukkitPlatformManager(server, fallbackPrefix));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ private LiteBungeeFactory() {

}

public static LiteCommandsBuilder builder(Plugin plugin) {
return LiteFactory.builder()
public static LiteCommandsBuilder<CommandSender, LiteBungeePlatformManager> builder(Plugin plugin) {
return LiteFactory.<CommandSender, LiteBungeePlatformManager>builder()
.bind(Plugin.class, plugin)
.bind(ProxyServer.class, plugin.getProxy())
.bind(CommandSender.class, new OriginalSenderBind())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
public class LiteCommands {

private final LiteRegisterResolvers registerResolvers;
private final LitePlatformManager platformManager;
private final LitePlatformManager<?> platformManager;
private final MessagesService messagesService;
private final Injector injector;
private final Logger logger;

LiteCommands(LiteRegisterResolvers registerResolvers, LitePlatformManager platformManager, MessagesService messagesService, Injector injector, Logger logger) {
LiteCommands(LiteRegisterResolvers registerResolvers, LitePlatformManager<?> platformManager, MessagesService messagesService, Injector injector, Logger logger) {
this.registerResolvers = registerResolvers;
this.platformManager = platformManager;
this.messagesService = messagesService;
Expand All @@ -26,8 +26,8 @@ public LiteRegisterResolvers getRegisterResolvers() {
return registerResolvers;
}

public LitePlatformManager getPlatformManager() {
return platformManager;
public <SENDER, P extends LitePlatformManager<SENDER>> P getPlatformManager() {
return (P) platformManager;
}

public MessagesService getMessagesService() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.rollczi.litecommands;

import dev.rollczi.litecommands.argument.OptionArgumentHandler;
import dev.rollczi.litecommands.bind.NativeBind;
import dev.rollczi.litecommands.component.ExecutionResult;
import dev.rollczi.litecommands.argument.ArgumentHandler;
import dev.rollczi.litecommands.argument.ArgumentName;
Expand All @@ -12,7 +14,6 @@
import dev.rollczi.litecommands.valid.messages.ContextualMessage;
import dev.rollczi.litecommands.valid.messages.LiteMessage;
import dev.rollczi.litecommands.valid.messages.MessagesService;
import dev.rollczi.litecommands.annotations.Arg;
import dev.rollczi.litecommands.annotations.parser.AnnotationParser;
import dev.rollczi.litecommands.annotations.parser.LiteAnnotationParser;
import dev.rollczi.litecommands.component.LiteComponent;
Expand All @@ -24,6 +25,7 @@
import dev.rollczi.litecommands.valid.messages.UseSchemeFormatting;
import org.panda_lang.utilities.inject.DependencyInjection;
import org.panda_lang.utilities.inject.Injector;
import panda.std.Option;
import panda.utilities.text.Formatter;

import java.util.ArrayList;
Expand All @@ -37,113 +39,126 @@
import java.util.function.Supplier;
import java.util.logging.Logger;

public class LiteCommandsBuilder {
public class LiteCommandsBuilder<SENDER, P extends LitePlatformManager<SENDER>> {

private final Set<Class<?>> commandClasses = new HashSet<>();
private final Set<Object> commandInstances = new HashSet<>();
private final Set<Bind> binds = new HashSet<>();
private final Map<Class<?>, ArgumentHandler<?>> argumentHandlers = new HashMap<>();
private final Set<NativeBind> binds = new HashSet<>();
private final Map<Class<?>, Set<ArgumentHandler<?>>> argumentHandlers = new HashMap<>();
private final MessagesService messagesService = new MessagesService();
private final LiteRegisterResolvers registerResolvers = new LiteRegisterResolvers();
private final Formatter placeholders = new Formatter();
private ExecutionResultHandler executionResultHandler;
private LitePlatformManager<?> platformManager;
private P platformManager;
private Injector baseInjector = DependencyInjection.createInjector();
private Logger logger = Logger.getLogger("LiteCommands");

public LiteCommandsBuilder() {
}

public LiteCommandsBuilder command(Collection<Class<?>> commands) {
public LiteCommandsBuilder<SENDER, P> command(Collection<Class<?>> commands) {
this.commandClasses.addAll(commands);
return this;
}

public LiteCommandsBuilder command(Class<?>... commands) {
public LiteCommandsBuilder<SENDER, P> command(Class<?>... commands) {
return this.command(Arrays.asList(commands));
}

public LiteCommandsBuilder commandInstance(Collection<Object> commands) {
public LiteCommandsBuilder<SENDER, P> commandInstance(Collection<Object> commands) {
this.commandInstances.addAll(commands);
return this;
}

public LiteCommandsBuilder commandInstance(Object... commands) {
public LiteCommandsBuilder<SENDER, P> commandInstance(Object... commands) {
return this.commandInstance(Arrays.asList(commands));
}

public LiteCommandsBuilder bind(Collection<Bind> binds) {
this.binds.addAll(binds);
public LiteCommandsBuilder<SENDER, P> baseInjector(Injector baseInjector) {
this.baseInjector = baseInjector;
return this;
}

public LiteCommandsBuilder baseInjector(Injector baseInjector) {
this.baseInjector = baseInjector;
public LiteCommandsBuilder<SENDER, P> bind(Collection<NativeBind> binds) {
this.binds.addAll(binds);
return this;
}

public LiteCommandsBuilder bind(Bind... bind) {
public LiteCommandsBuilder<SENDER, P> bind(NativeBind... bind) {
return this.bind(Arrays.asList(bind));
}

public LiteCommandsBuilder<SENDER, P> bind(Bind... bind) {
return this.bind(Arrays.asList(bind));
}

public <T> LiteCommandsBuilder bind(Class<T> on, LiteBind liteBind) {
public <T> LiteCommandsBuilder<SENDER, P> bind(Class<T> on, LiteBind liteBind) {
this.bind((resources) -> resources.on(on)
.assignHandler((property, annotation, objects) -> liteBind.apply(InjectUtils.getContextFromObjects(objects).getInvocation())));
return this;
}

public <T> LiteCommandsBuilder bind(Class<T> on, Object instance) {
public <T> LiteCommandsBuilder<SENDER, P> bind(Class<T> on, Object instance) {
this.bind((resources) -> resources.on(on).assignInstance(instance));
return this;
}

public <T> LiteCommandsBuilder bind(Class<T> on, Supplier<Object> supplier) {
public <T> LiteCommandsBuilder<SENDER, P> bind(Class<T> on, Supplier<Object> supplier) {
this.bind((resources) -> resources.on(on).assignInstance(supplier));
return this;
}

public <T> LiteCommandsBuilder argument(Class<T> on, ArgumentHandler<T> argumentHandler) {
this.argumentHandlers.put(on, argumentHandler);
public <T> LiteCommandsBuilder<SENDER, P> argument(Class<T> on, ArgumentHandler<T> argumentHandler) {
Set<ArgumentHandler<?>> handlers = this.argumentHandlers.computeIfAbsent(on, key -> new HashSet<>());

handlers.add(argumentHandler);
return this;
}

public <T, O extends Option<?>> LiteCommandsBuilder<SENDER, P> argument(Class<O> optionalClass, OptionArgumentHandler<T> argumentHandler) {
Set<ArgumentHandler<?>> handlers = this.argumentHandlers.computeIfAbsent(optionalClass, key -> new HashSet<>());

handlers.add(argumentHandler);
return this;
}

@Deprecated
public LiteCommandsBuilder message(ValidationInfo validationInfo, ContextualMessage message) {
public LiteCommandsBuilder<SENDER, P> message(ValidationInfo validationInfo, ContextualMessage message) {
this.messagesService.registerMessage(validationInfo, message);
return this;
}

public LiteCommandsBuilder message(ValidationInfo validationInfo, LiteMessage message) {
public LiteCommandsBuilder<SENDER, P> message(ValidationInfo validationInfo, LiteMessage message) {
this.messagesService.registerMessage(validationInfo, message);
return this;
}

public LiteCommandsBuilder formatting(UseSchemeFormatting formatting) {
public LiteCommandsBuilder<SENDER, P> formatting(UseSchemeFormatting formatting) {
this.messagesService.setUseSchemeFormatting(formatting);
return this;
}

public LiteCommandsBuilder placeholder(String key, Supplier<String> supplier) {
public LiteCommandsBuilder<SENDER, P> placeholder(String key, Supplier<String> supplier) {
this.placeholders.register(key, supplier);
return this;
}

public LiteCommandsBuilder placeholder(String key, String text) {
public LiteCommandsBuilder<SENDER, P> placeholder(String key, String text) {
this.placeholders.register(key, text);
return this;
}

public LiteCommandsBuilder placeholders(Map<String, Supplier<String>> placeholders) {
public LiteCommandsBuilder<SENDER, P> placeholders(Map<String, Supplier<String>> placeholders) {
placeholders.forEach(this.placeholders::register);
return this;
}

public LiteCommandsBuilder platform(LitePlatformManager<?> platformManager) {
public LiteCommandsBuilder<SENDER, P> platform(P platformManager) {
this.platformManager = platformManager;
return this;
}

public LiteCommandsBuilder logger(Logger logger) {
public LiteCommandsBuilder<SENDER, P> logger(Logger logger) {
this.logger = logger;
return this;
}
Expand All @@ -157,39 +172,25 @@ public LiteCommands register() {
executionResultHandler = new LiteExecutionResultHandler(messagesService);
}

AnnotationParser parser = new LiteAnnotationParser(argumentHandlers, placeholders);

Injector injector = baseInjector.fork(resources -> {
for (Bind bind : binds) {
bind.bind(resources);
for (NativeBind bind : binds) {
bind.bind(parser, resources);
}

resources.annotatedWith(Arg.class).assignHandler((property, arg, objects) -> {
LiteComponent.ContextOfResolving context = InjectUtils.getContextFromObjects(objects);

for (Map.Entry<Class<?>, ArgumentHandler<?>> entry : argumentHandlers.entrySet()) {
Class<?> on = entry.getKey();
ArgumentHandler<?> argumentHandler = entry.getValue();

if (!on.isAssignableFrom(property.getType())) {
continue;
}

return argumentHandler.parse(context, arg.value());
}

return null;
});
});

// Checks for legacy implementations
for (ArgumentHandler<?> handler : argumentHandlers.values()) {
if (handler.getClass().isAnnotationPresent(ArgumentName.class)) {
continue;
}
for (Set<ArgumentHandler<?>> handlers : argumentHandlers.values()) {
for (ArgumentHandler<?> handler : handlers) {
if (handler.getClass().isAnnotationPresent(ArgumentName.class)) {
continue;
}

logger.warning( "annotation @ArgumentName isn't present before class " + handler.getClass());
logger.warning( "annotation @ArgumentName isn't present before class " + handler.getClass());
}
}

AnnotationParser parser = new LiteAnnotationParser(argumentHandlers, placeholders);
LiteComponentFactory factory = new LiteComponentFactory(logger, injector, parser);

for (Object instance : commandInstances) {
Expand All @@ -212,8 +213,8 @@ public LiteCommands register() {
return new LiteCommands(registerResolvers, platformManager, messagesService, injector, logger);
}

public static LiteCommandsBuilder builder() {
return new LiteCommandsBuilder();
public static <SENDER, P extends LitePlatformManager<SENDER>> LiteCommandsBuilder<SENDER, P> builder() {
return new LiteCommandsBuilder<>();
}

private static class DefaultExecutor implements Executor {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package dev.rollczi.litecommands;

import dev.rollczi.litecommands.bind.basic.ArgAnnotationBind;
import dev.rollczi.litecommands.bind.basic.LiteInvocationBind;
import dev.rollczi.litecommands.bind.basic.ArgumentsBind;
import dev.rollczi.litecommands.bind.basic.LiteSenderBind;
import dev.rollczi.litecommands.platform.LitePlatformManager;
import dev.rollczi.litecommands.platform.LiteSender;

public class LiteFactory {

public static LiteCommandsBuilder builder() {
return LiteCommandsBuilder.builder()
public static <SENDER, P extends LitePlatformManager<SENDER>> LiteCommandsBuilder<SENDER, P> builder() {
return LiteCommandsBuilder.<SENDER, P>builder()
.bind(new ArgAnnotationBind())
.bind(String[].class, new ArgumentsBind())
.bind(LiteSender.class, new LiteSenderBind())
.bind(LiteInvocation.class, new LiteInvocationBind());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.rollczi.litecommands.annotations;

import dev.rollczi.litecommands.argument.ArgumentHandler;
import org.panda_lang.utilities.inject.annotations.Injectable;

import java.lang.annotation.ElementType;
Expand All @@ -15,10 +14,4 @@

int value();

//TODO: Add option to use only one handler.
// public void execute1(@Arg(0) String custom) { ... }
// public void execute2(@Arg(value = 0, only = Handler1.class) String custom) { ... }
// public void execute3(@Arg(value = 0, only = Handler2.class) String custom) { ... }
Class<? extends ArgumentHandler> only() default ArgumentHandler.class;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.rollczi.litecommands.annotations;

import dev.rollczi.litecommands.argument.ArgumentHandler;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Handler {

Class<? extends ArgumentHandler> value() default ArgumentHandler.class;

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

public interface AnnotationParser {

Expand All @@ -21,6 +23,8 @@ public interface AnnotationParser {
*/
Option<ScopeMetaData> parse(AnnotatedElement annotatedElement);

Option<ArgumentHandler<?>> getArgumentHandler(Class<?> argumentClass);
Set<ArgumentHandler<?>> getArgumentHandler(Class<?> argumentClass);

Map<Class<?>, Set<ArgumentHandler<?>>> getArgumentHandlers();

}
Loading

0 comments on commit b14f379

Please sign in to comment.