All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.alangomes.springspigot.command.DefaultCommandExecutor Maven / Gradle / Ivy

There is a newer version: 0.20.7
Show newest version
package dev.alangomes.springspigot.command;

import com.google.common.annotations.VisibleForTesting;
import dev.alangomes.springspigot.configuration.DynamicValue;
import dev.alangomes.springspigot.configuration.Instance;
import dev.alangomes.springspigot.picocli.CommandLineDefinition;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandException;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import picocli.CommandLine;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

import static org.apache.commons.lang.BooleanUtils.toBoolean;

@Slf4j
@Primary
@Component
@ConditionalOnBean(annotation = CommandLine.Command.class)
public class DefaultCommandExecutor implements CommandExecutor {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired(required = false)
    private AbstractAutoProxyCreator proxyCreator;

    @Autowired
    private CommandLineDefinition cli;

    @Setter(value = AccessLevel.PACKAGE, onMethod_ = @VisibleForTesting)
    @DynamicValue("${spigot.messages.command_error:&cAn internal error occurred while attemping to perform this " +
            "command}")
    private Instance commandErrorMessage;

    @Setter(value = AccessLevel.PACKAGE, onMethod_ = @VisibleForTesting)
    @DynamicValue("${spigot.messages.missing_parameter_error:&cMissing parameter: %s}")
    private Instance missingParameterErrorMessage;

    @Setter(value = AccessLevel.PACKAGE, onMethod_ = @VisibleForTesting)
    @DynamicValue("${spigot.messages.parameter_error:&cInvalid parameter: %s}")
    private Instance parameterErrorMessage;

    @Getter(value = AccessLevel.PACKAGE, onMethod_ = @VisibleForTesting)
    @Setter(value = AccessLevel.PACKAGE, onMethod_ = @VisibleForTesting)
    @DynamicValue("${spigot.commands.enable_cache:false}")
    private Instance cacheEnabled;

    private CommandLine commandLineCache;

    @Override
    public CommandResult execute(String... commandParts) {
        if (commandParts.length == 0) {
            return CommandResult.unknown();
        }
        try {
            if (!toBoolean(cacheEnabled.get()) || commandLineCache == null) {
                commandLineCache = cli.build(applicationContext);
            }
            val output = new ArrayList();
            val commands = commandLineCache.parse(commandParts);

            if (commands.isEmpty()) {
                return CommandResult.unknown();
            }
            val commandLine = commands.get(commands.size() - 1);
            val command = proxyCreator != null ? proxyCreator.getEarlyBeanReference(commandLine.getCommand(), null) :
                    commandLine.getCommand();

            if (command instanceof Runnable) {
                ((Runnable) command).run();
            } else if (command instanceof Callable) {
                val result = ((Callable) command).call();
                output.addAll(buildOutput(result));
            }
            return new CommandResult(output);
        } catch (CommandLine.InitializationException ex) {
            log.error("Unexpected exception during command initialization", ex);
            return CommandResult.unknown();
        } catch (CommandLine.UnmatchedArgumentException ignored) {
        } catch (CommandLine.MissingParameterException ex) {
            val message = String.format(missingParameterErrorMessage.get(), ex.getMissing().get(0).paramLabel());
            return new CommandResult(ChatColor.translateAlternateColorCodes('&', message), true);
        } catch (CommandLine.ParameterException ex) {
            val message = String.format(parameterErrorMessage.get(), ex.getArgSpec().paramLabel());
            return new CommandResult(ChatColor.translateAlternateColorCodes('&', message), true);
        } catch (CommandException ex) {
            return new CommandResult(ChatColor.RED + ex.getMessage(), true);
        } catch (Exception ex) {
            log.error("Unexpected exception while running /" + StringUtils.join(commandParts, " "), ex);
            return new CommandResult(ChatColor.translateAlternateColorCodes('&', commandErrorMessage.get()), true);
        }
        return CommandResult.unknown();
    }

    private List buildOutput(Object result) {
        if (result instanceof String) {
            return Collections.singletonList(ChatColor.translateAlternateColorCodes('&', (String) result));
        } else if (result instanceof Collection) {
            return ((Collection) result)
                    .stream()
                    .flatMap(res -> buildOutput(res).stream())
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy