net.lenni0451.commandlib.builder.LineBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of CommandLib Show documentation
Show all versions of CommandLib Show documentation
A command lib with a simple and powerful API
The newest version!
package net.lenni0451.commandlib.builder;
import net.lenni0451.commandlib.contexts.ExecutionContext;
import net.lenni0451.commandlib.nodes.ArgumentNode;
import net.lenni0451.commandlib.nodes.TypedNode;
import net.lenni0451.commandlib.types.ArgumentType;
import net.lenni0451.commandlib.utils.Util;
import net.lenni0451.commandlib.utils.interfaces.CommandExceptionHandler;
import net.lenni0451.commandlib.utils.interfaces.CompletionsProvider;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.*;
/**
* Easily build a line of arguments into an {@link ArgumentNode}.
*
* @param The type of the executor
*/
public class LineBuilder {
/**
* Create a new line builder.
*
* @param The type of the executor
* @return The created line builder
*/
public static LineBuilder create() {
return new LineBuilder<>();
}
private final List> nodes = new ArrayList<>();
private LineBuilder() {
}
/**
* Add an existing node to the line.
*
* @param node The node
* @return The line builder
*/
public LineBuilder node(final ArgumentNode node) {
this.nodes.add(new LineNode<>(node));
return this;
}
/**
* Start building an argument and add it to the line.
*
* @param name The name of the argument
* @param type The argument type
* @param The type of the argument
* @return The line builder
*/
public LineBuilder arg(final String name, final ArgumentType type) {
this.nodes.add(new LineNode<>(name, null, type));
return this;
}
/**
* Start building an argument and add it to the line.
*
* @param name The name of the argument
* @param description The description of the argument
* @param type The argument type
* @param The type of the argument
* @return The line builder
*/
public LineBuilder arg(final String name, @Nullable final String description, final ArgumentType type) {
this.nodes.add(new LineNode<>(name, description, type));
return this;
}
/**
* Add a validator to the last added argument.
*
* @param validator The validator
* @param The type of the argument
* @return The line builder
* @throws IllegalStateException If no argument was added before
*/
public LineBuilder validator(@Nullable final Predicate validator) {
if (this.nodes.isEmpty()) throw new IllegalStateException("No argument was added before");
this.nodes.get(this.nodes.size() - 1).validator = Util.cast(validator);
return this;
}
/**
* Add a completions provider to the last added argument.
*
* @param completionsProvider The completions provider
* @return The line builder
* @throws IllegalStateException If no argument was added before
*/
public LineBuilder completions(@Nullable final CompletionsProvider completionsProvider) {
if (this.nodes.isEmpty()) throw new IllegalStateException("No argument was added before");
this.nodes.get(this.nodes.size() - 1).completionsProvider = completionsProvider;
return this;
}
/**
* Add an exception handler to the last added argument.
*
* @param exceptionHandler The exception handler
* @return The line builder
* @throws IllegalStateException If no argument was added before
*/
public LineBuilder exceptionHandler(@Nullable final CommandExceptionHandler exceptionHandler) {
if (this.nodes.isEmpty()) throw new IllegalStateException("No argument was added before");
this.nodes.get(this.nodes.size() - 1).exceptionHandler = exceptionHandler;
return this;
}
/**
* Set the default value of the last added argument.
*
* @param defaultValue The default value
* @param The type of the argument
* @return The line builder
* @throws IllegalStateException If no argument was added before
*/
public LineBuilder defaultValue(@Nullable final T defaultValue) {
if (this.nodes.isEmpty()) throw new IllegalStateException("No argument was added before");
this.nodes.get(this.nodes.size() - 1).defaultValue = Util.cast(defaultValue);
return this;
}
/**
* Set the {@link Runnable} executor of the line and build the line into an {@link ArgumentNode}.
*
* @param runnable The executor
* @param The return type of the executor
* @return The created {@link ArgumentNode}
*/
public ArgumentNode executes(final Runnable runnable) {
return this.build((def, node) -> node.executes(runnable));
}
/**
* Set the {@link Consumer} executor of the line and build the line into an {@link ArgumentNode}.
* The consumer will receive the {@link ExecutionContext} as argument.
*
* @param consumer The executor
* @param The return type of the executor
* @return The created {@link ArgumentNode}
*/
public ArgumentNode executes(final Consumer> consumer) {
return this.build((def, node) -> node.executes(ctx -> {
for (LineNode lineNode : def) ctx.getArguments().put(lineNode.name, lineNode.defaultValue);
consumer.accept(ctx);
}));
}
/**
* Set the {@link Supplier} executor of the line and build the line into an {@link ArgumentNode}.
*
* @param supplier The executor
* @param The return type of the executor
* @return The created {@link ArgumentNode}
*/
public ArgumentNode executes(final Supplier supplier) {
return this.build((def, node) -> node.executes(supplier));
}
/**
* Set the {@link Function} executor of the line and build the line into an {@link ArgumentNode}.
* The function will receive the {@link ExecutionContext} as argument.
*
* @param function The executor
* @param The return type of the executor
* @return The created {@link ArgumentNode}
*/
public ArgumentNode executes(final Function, R> function) {
return this.build((def, node) -> node.executes((Function, R>) ctx -> {
for (LineNode lineNode : def) ctx.getArguments().put(lineNode.name, lineNode.defaultValue);
return function.apply(ctx);
}));
}
private ArgumentNode build(final BiConsumer>, ArgumentNode> executorAppender) {
if (this.nodes.isEmpty()) throw new IllegalStateException("No arguments defined");
ArgumentNode root = null;
ArgumentNode current = null;
for (int i = 0; i < this.nodes.size(); i++) {
LineNode node = (LineNode) this.nodes.get(i);
LineNode next = i + 1 < this.nodes.size() ? (LineNode) this.nodes.get(i + 1) : null;
ArgumentNode newNode = node.toArgumentNode();
if (next == null || next.defaultValue != null) {
List> defaults = Util.cast(this.nodes.subList(i + 1, this.nodes.size()));
executorAppender.accept(defaults, newNode);
}
if (root == null) root = newNode;
if (current != null) current.then(newNode);
current = newNode;
}
return root;
}
private static class LineNode {
private final ArgumentNode node;
private final String name;
private final String description;
private final ArgumentType type;
private Predicate validator;
private CompletionsProvider completionsProvider;
private CommandExceptionHandler exceptionHandler;
private T defaultValue;
private LineNode(final ArgumentNode node) {
this.node = node;
this.name = null;
this.description = null;
this.type = null;
}
private LineNode(final String name, @Nullable final String description, final ArgumentType argumentType) {
this.node = null;
this.name = name;
this.description = description;
this.type = argumentType;
}
private ArgumentNode toArgumentNode() {
ArgumentNode node;
if (this.node == null) node = new TypedNode<>(this.name, this.description, this.type);
else node = this.node;
node
.validator(this.validator)
.completions(this.completionsProvider)
.exceptionHandler(this.exceptionHandler);
return node;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy