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

net.lenni0451.commandlib.nodes.ArgumentNode Maven / Gradle / Ivy

The newest version!
package net.lenni0451.commandlib.nodes;

import net.lenni0451.commandlib.contexts.CompletionContext;
import net.lenni0451.commandlib.contexts.ExecutionContext;
import net.lenni0451.commandlib.exceptions.ArgumentParseException;
import net.lenni0451.commandlib.exceptions.HandledException;
import net.lenni0451.commandlib.utils.StringReader;
import net.lenni0451.commandlib.utils.interfaces.ArgumentRequirement;
import net.lenni0451.commandlib.utils.interfaces.CommandExceptionHandler;
import net.lenni0451.commandlib.utils.interfaces.CompletionsProvider;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * The abstract argument node class containing all methods required to build a customizable argument tree.
 *
 * @param  The type of the executor
 * @param  The type of the argument
 */
public abstract class ArgumentNode {

    private final String name;
    private final String description;
    private final List> children;
    protected int weight = 0;
    protected boolean providesArgument = true;
    private ArgumentRequirement requirement = e -> true;
    private Predicate validator;
    private CompletionsProvider completionsProvider;
    private CommandExceptionHandler exceptionHandler;
    private Function, ?> executor;

    public ArgumentNode(final String name) {
        this(name, null);
    }

    public ArgumentNode(final String name, @Nullable final String description) {
        this.name = name;
        this.description = description;
        this.children = new ArrayList<>();
    }

    /**
     * @return The name of the argument
     */
    public String name() {
        return this.name;
    }

    /**
     * @return The description of the argument
     */
    @Nullable
    public String description() {
        return this.description;
    }

    /**
     * @return The children of this argument
     */
    public List> children() {
        return this.children;
    }

    /**
     * @return The weight of this argument
     */
    public int weight() {
        return this.weight;
    }

    /**
     * @return If this node provides an argument (See {@link StringNode})
     */
    public boolean providesArgument() {
        return this.providesArgument;
    }

    /**
     * @return The requirement of this argument
     */
    @Nonnull
    public ArgumentRequirement requirement() {
        return this.requirement;
    }

    /**
     * @return The validator of this argument
     */
    @Nullable
    public Predicate validator() {
        return this.validator;
    }

    /**
     * @return The completions provider of this argument
     */
    @Nullable
    public CompletionsProvider completionsProvider() {
        return this.completionsProvider;
    }

    /**
     * @return The exception handler of this argument
     */
    @Nullable
    public CommandExceptionHandler exceptionHandler() {
        return this.exceptionHandler;
    }

    /**
     * @return The executor of this argument
     */
    @Nullable
    public Function, ?> executor() {
        return this.executor;
    }

    /**
     * Parse the value of this argument.
     *
     * @param executionContext The execution context
     * @param stringReader     The string reader
     * @return The parsed value
     * @throws ArgumentParseException If the value could not be parsed
     * @throws RuntimeException       If an unexpected error occurred
     */
    @Nonnull
    public T value(final ExecutionContext executionContext, final StringReader stringReader) throws ArgumentParseException, RuntimeException {
        T value;
        try {
            value = this.parseValue(executionContext, stringReader);
        } catch (ArgumentParseException | RuntimeException e) {
            if (this.exceptionHandler != null && executionContext.isExecution()) {
                this.exceptionHandler.handle(executionContext, e);
                throw new HandledException(e);
            }
            throw e;
        }
        if (this.validator != null && !this.validator.test(value)) throw ArgumentParseException.namedReason(this.name, "Invalid value");
        return value;
    }

    /**
     * Provide the completions of this argument.
     *
     * @param completionContext The completion context
     * @param executionContext  The execution context
     * @param reader            The string reader
     * @return The completions
     */
    public Set parseCompletions(final CompletionContext completionContext, final ExecutionContext executionContext, final StringReader reader) {
        Set completions = new HashSet<>();
        if (this.completionsProvider != null) this.completionsProvider.provide(completions, executionContext, reader);
        else this.parseCompletions(completions, completionContext, executionContext, reader);
        return completions;
    }

    /**
     * Parse the value of this argument.
     *
     * @param executionContext The execution context
     * @param stringReader     The string reader
     * @return The parsed value
     * @throws ArgumentParseException If the value could not be parsed
     * @throws RuntimeException       If an unexpected error occurred
     */
    @Nonnull
    protected abstract T parseValue(final ExecutionContext executionContext, final StringReader stringReader) throws ArgumentParseException, RuntimeException;

    /**
     * Provide the completions of this argument.
     *
     * @param completions       The completions
     * @param completionContext The completion context
     * @param executionContext  The execution context
     * @param stringReader      The string reader
     */
    protected abstract void parseCompletions(final Set completions, final CompletionContext completionContext, final ExecutionContext executionContext, final StringReader stringReader);

    /**
     * Add a child to this argument node.
     *
     * @param child The child
     * @return This argument node
     */
    public ArgumentNode then(final ArgumentNode child) {
        this.children.add(child);
        return this;
    }

    /**
     * Add multiple children to this argument node.
     *
     * @param children The children
     * @return This argument node
     */
    public ArgumentNode then(final List> children) {
        this.children.addAll(children);
        return this;
    }

    /**
     * Set the requirement of this argument node.
     *
     * @param requirement The requirement
     * @return This argument node
     */
    public ArgumentNode requires(final ArgumentRequirement requirement) {
        this.requirement = requirement;
        return this;
    }

    /**
     * Set the validator of this argument node.
     *
     * @param validator The validator
     * @return This argument node
     */
    public ArgumentNode validator(@Nullable final Predicate validator) {
        this.validator = validator;
        return this;
    }

    /**
     * Set the custom completions provider of this argument node.
     *
     * @param completionsProvider The completions provider
     * @return This argument node
     */
    public ArgumentNode completions(@Nullable final CompletionsProvider completionsProvider) {
        this.completionsProvider = completionsProvider;
        return this;
    }

    /**
     * Set the exception handler of this argument node.
     *
     * @param exceptionHandler The exception handler
     * @return This argument node
     */
    public ArgumentNode exceptionHandler(@Nullable final CommandExceptionHandler exceptionHandler) {
        this.exceptionHandler = exceptionHandler;
        return this;
    }

    /**
     * Set the {@link Runnable} executor of this argument node.
     *
     * @param runnable The runnable
     * @return This argument node
     */
    public ArgumentNode executes(final Runnable runnable) {
        this.executor = executionContext -> {
            runnable.run();
            return null;
        };
        return this;
    }

    /**
     * Set the {@link Consumer} executor of this argument node.
     *
     * @param consumer The consumer
     * @return This argument node
     */
    public ArgumentNode executes(final Consumer> consumer) {
        this.executor = executionContext -> {
            consumer.accept(executionContext);
            return null;
        };
        return this;
    }

    /**
     * Set the {@link Supplier} executor of this argument node.
     *
     * @param supplier The supplier
     * @return This argument node
     */
    public ArgumentNode executes(final Supplier supplier) {
        this.executor = executionContext -> supplier.get();
        return this;
    }

    /**
     * Set the {@link Function} executor of this argument node.
     *
     * @param function The function
     * @return This argument node
     */
    public ArgumentNode executes(final Function, ?> function) {
        this.executor = function;
        return this;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy