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

org.spongepowered.api.command.parameter.Parameter Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
 * This file is part of SpongeAPI, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered 
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.api.command.parameter;

import io.leangen.geantyref.TypeToken;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.Game;
import org.spongepowered.api.ResourceKey;
import org.spongepowered.api.Server;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.command.Command;
import org.spongepowered.api.command.CommandCause;
import org.spongepowered.api.command.CommandCompletion;
import org.spongepowered.api.command.CommandExecutor;
import org.spongepowered.api.command.exception.ArgumentParseException;
import org.spongepowered.api.command.parameter.managed.ValueCompleter;
import org.spongepowered.api.command.parameter.managed.ValueParameter;
import org.spongepowered.api.command.parameter.managed.ValueParameterModifier;
import org.spongepowered.api.command.parameter.managed.ValueParser;
import org.spongepowered.api.command.parameter.managed.ValueUsage;
import org.spongepowered.api.command.parameter.managed.operator.Operator;
import org.spongepowered.api.command.parameter.managed.standard.ResourceKeyedValueParameters;
import org.spongepowered.api.command.parameter.managed.standard.VariableValueParameters;
import org.spongepowered.api.data.persistence.DataContainer;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.living.player.User;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.registry.DefaultedRegistryReference;
import org.spongepowered.api.registry.DefaultedRegistryType;
import org.spongepowered.api.registry.Registry;
import org.spongepowered.api.registry.RegistryHolder;
import org.spongepowered.api.registry.RegistryKey;
import org.spongepowered.api.registry.RegistryType;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.Builder;
import org.spongepowered.api.util.Color;
import org.spongepowered.api.util.ResettableBuilder;
import org.spongepowered.api.world.server.ServerLocation;
import org.spongepowered.api.world.server.ServerWorld;
import org.spongepowered.configurate.util.Types;
import org.spongepowered.math.vector.Vector3d;
import org.spongepowered.plugin.PluginContainer;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URL;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Defines how an element of a command argument string should be parsed.
 *
 * 

Parameters that parse input and return an object into the * {@link CommandContext} should be of type {@link Parameter.Value} in * order to maximize type safety. However, there are also other important * ways that parameters can be used:

* *
    *
  • {@link #firstOfBuilder(Parameter)} allows for multiple parameters that * do not have the same return type to attempt to parse an input * successfully.
  • *
  • {@link #seqBuilder(Parameter)} allows for the grouping of multiple * parameters that will be executed one after another.
  • *
  • {@link Subcommand}s can be placed anywhere in a parameter * chain where a {@link Parameter} can be added, if successfully parsed, * any containing {@link Command} would take precedence and its * {@link Command#process(CommandCause, ArgumentReader.Mutable)} method will be called instead * of any parent.
  • *
* *

{@link Parameter}s are intended for use with {@link org.spongepowered.api.command.Command.Builder}s. *

*/ public interface Parameter { /** * Creates a {@link Parameter.Key} for storing values against. * * @param key The string key * @param typeToken The type of value that this key represents * @param The type * @return The {@link Key} */ static Key key(@NonNull final String key, @NonNull final TypeToken typeToken) { return Sponge.game().builderProvider().provide(Key.Builder.class).build(key, typeToken); } /** * Creates a {@link Parameter.Key} for storing values against. * * @param key The string key * @param type The type of value that this key represents. Must not omit any * type parameters. * @param The type * @return The {@link Key} */ static Key key(@NonNull final String key, @NonNull final Class type) { Types.requireCompleteParameters(type); return Sponge.game().builderProvider().provide(Key.Builder.class).build(key, type); } /** * Gets a builder that builds a {@link Parameter.Value}. * *

If your parameter type is generic, use * {@link #builder(TypeToken)} instead.

* * @param The type of parameter * @param valueClass The type of value class * @return The {@link Value.Builder} */ static Value.Builder builder(@NonNull final Class valueClass) { return Sponge.game().factoryProvider().provide(Factory.class).createParameterBuilder(valueClass); } /** * Gets a builder that builds a {@link Parameter.Value}. * * @param The type of parameter * @param typeToken The type of value class as a {@link TypeToken} * @return The {@link Value.Builder} */ static Value.Builder builder(@NonNull final TypeToken typeToken) { return Sponge.game().factoryProvider().provide(Factory.class).createParameterBuilder(typeToken); } /** * Gets a builder that builds a {@link Parameter.Value}. * * @param The type of parameter * @param key The key to initialize this builder with * @return The {@link Value.Builder} */ static Value.Builder builder(final Parameter.@NonNull Key key) { return Sponge.game().factoryProvider().provide(Factory.class).createParameterBuilder(key); } /** * Gets a builder that builds a {@link Parameter.Value}. * *

If your parameter type is generic, use * {@link #builder(TypeToken, ValueParameter)} instead.

* * @param The type of parameter * @param valueClass The type of value class as a {@link Class} * @param parameter The value parameter * @return The {@link Value.Builder} */ static Value.Builder builder(@NonNull final Class valueClass, @NonNull final ValueParameter parameter) { return Parameter.builder(valueClass).addParser(parameter); } /** * Gets a builder that builds a {@link Parameter.Value}. * * @param The type of parameter * @param typeToken The type of value class as a {@link TypeToken} * @param parameter The value parameter * @return The {@link Value.Builder} */ static Value.Builder builder(@NonNull final TypeToken typeToken, @NonNull final ValueParameter parameter) { return Parameter.builder(typeToken).addParser(parameter); } /** * Gets a builder that builds a {@link Parameter.Value}. * * @param The type of parameter * @param The {@link ValueParameter} to be used as a parser * @param parameter The value parameter * @param valueClass The type of value class * @return The {@link Value.Builder} */ static > Value.Builder builder(@NonNull final Class valueClass, @NonNull final DefaultedRegistryReference parameter) { return Parameter.builder(valueClass, parameter.get()); } /** * Gets a builder that builds a {@link Parameter.Value}. * * @param The type of parameter * @param The {@link ValueParameter} to be used as a parser * @param parameter The value parameter * @param typeToken The type of value class as a {@link TypeToken} * @return The {@link Value.Builder} */ static > Value.Builder builder(@NonNull final TypeToken typeToken, @NonNull final Supplier parameter) { return Parameter.builder(typeToken, parameter.get()); } /** * Gets a {@link Parameter} that represents a subcommand. * *

If a {@link Subcommand} alias in a parameter chain * is successfully matched, then element parsing will continue * with the parameters supplied to {@link Command}. It is * implementation dependent as to what happens if a subcommand * fails to parse.

* * @param subcommand The {@link Command} to execute * @param alias The first alias of the subcommand * @param aliases Subsequent aliases, if any * @return The {@link Subcommand} for use in a {@link Parameter} chain */ static Subcommand subcommand(final Command.@NonNull Parameterized subcommand, @NonNull final String alias, final String @NonNull... aliases) { final Subcommand.Builder builder = Sponge.game().builderProvider().provide(Subcommand.Builder.class) .subcommand(subcommand) .addAlias(alias); for (final String a : aliases) { builder.addAlias(a); } return builder.build(); } /** * Returns a {@link Parameter.FirstOfBuilder} that allows plugins to attempt * to parse an argument using the supplied parameters in order. Once a * parameter has parsed the argument successfully, no more parameters * supplied here will be attempted. * * @param parameter The first {@link Parameter} * @return The {@link Parameter.FirstOfBuilder} to continue chaining */ static Parameter.FirstOfBuilder firstOfBuilder(@NonNull final Parameter parameter) { return Sponge.game().builderProvider().provide(FirstOfBuilder.class).or(parameter); } /** * Returns a {@link Parameter} that attempts to parse an argument using the * supplied parameters in order. Once a parameter has parsed the argument * successfully, no more parameters supplied here will be attempted. * * @param first The first {@link Parameter} that should be used for parsing * @param second The second {@link Parameter} that should be used for * parsing, should the first {@link Parameter} fail to do so * @param parameters The remaining {@link Parameter}s * @return The {@link Parameter} */ static Parameter firstOf(@NonNull final Parameter first, @NonNull final Parameter second, final Parameter @NonNull... parameters) { return Sponge.game().builderProvider().provide(FirstOfBuilder.class).or(first).or(second).orFirstOf(parameters).build(); } /** * Returns a {@link Parameter} that attempts to parse an argument using the * supplied parameters in order. Once a parameter has parsed the argument * successfully, no more parameters supplied here will be attempted. * * @param parameters The {@link Parameter}s * @return The {@link Parameter} */ static Parameter firstOf(@NonNull final Iterable parameters) { return Sponge.game().builderProvider().provide(FirstOfBuilder.class).orFirstOf(parameters).build(); } /** * Returns a {@link Parameter.SequenceBuilder} that parses arguments using * the supplied parameters in order. * * @param parameter The first {@link Parameter} in the sequence * @return The {@link Parameter.SequenceBuilder}, to continue building the * chain */ static Parameter.SequenceBuilder seqBuilder(@NonNull final Parameter parameter) { return Sponge.game().builderProvider().provide(SequenceBuilder.class).then(parameter); } /** * Returns a {@link Parameter} that parses arguments using the supplied * parameters in order. * * @param first The first {@link Parameter} that should be used for parsing * @param second The second {@link Parameter} that should be used for * parsing * @param parameters The subsequent {@link Parameter}s to parse * @return The {@link Parameter} */ static Parameter seq(@NonNull final Parameter first, @NonNull final Parameter second, final Parameter @NonNull... parameters) { return Sponge.game().builderProvider().provide(SequenceBuilder.class).then(first).then(second).then(parameters).build(); } /** * Returns a {@link Parameter} that parses arguments using the supplied * parameters in order. * * @param parameters The {@link Parameter}s * @return The {@link Parameter} */ static Parameter seq(@NonNull final Iterable parameters) { return Sponge.game().builderProvider().provide(SequenceBuilder.class).then(parameters).build(); } // Convenience methods for getting the common parameter types - all in once place. // Modifiers (for the most part) are on the Parameter.Builder itself. /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#BIG_DECIMAL}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder bigDecimal() { return Parameter.builder(BigDecimal.class, ResourceKeyedValueParameters.BIG_DECIMAL); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#BIG_INTEGER}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder bigInteger() { return Parameter.builder(BigInteger.class, ResourceKeyedValueParameters.BIG_INTEGER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#BLOCK_STATE}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder blockState() { return Parameter.builder(BlockState.class, ResourceKeyedValueParameters.BLOCK_STATE); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#BOOLEAN}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder bool() { return Parameter.builder(Boolean.class, ResourceKeyedValueParameters.BOOLEAN); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#COLOR}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder color() { return Parameter.builder(Color.class, ResourceKeyedValueParameters.COLOR); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#DATA_CONTAINER}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder dataContainer() { return Parameter.builder(DataContainer.class, ResourceKeyedValueParameters.DATA_CONTAINER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#DATE_TIME}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder dateTime() { return Parameter.builder(LocalDateTime.class, ResourceKeyedValueParameters.DATE_TIME); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#DURATION}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder duration() { return Parameter.builder(Duration.class, ResourceKeyedValueParameters.DURATION); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#DOUBLE}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder doubleNumber() { return Parameter.builder(Double.class, ResourceKeyedValueParameters.DOUBLE); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#ENTITY}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder entity() { return Parameter.builder(Entity.class, ResourceKeyedValueParameters.ENTITY); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#ENTITY} * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder entityOrTarget() { return Parameter.entity().addParser(ResourceKeyedValueParameters.TARGET_ENTITY); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#TEXT_FORMATTING_CODE}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder formattingCodeText() { return Parameter.builder(Component.class, ResourceKeyedValueParameters.TEXT_FORMATTING_CODE); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#TEXT_FORMATTING_CODE_ALL}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder formattingCodeTextOfRemainingElements() { return Parameter.builder(Component.class, ResourceKeyedValueParameters.TEXT_FORMATTING_CODE_ALL); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#INTEGER}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder integerNumber() { return Parameter.builder(Integer.class, ResourceKeyedValueParameters.INTEGER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#IP}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder ip() { return Parameter.builder(InetAddress.class, ResourceKeyedValueParameters.IP); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#ITEM_STACK_SNAPSHOT}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder itemStackSnapshot() { return Parameter.builder(ItemStackSnapshot.class, ResourceKeyedValueParameters.ITEM_STACK_SNAPSHOT); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#TEXT_JSON}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder jsonText() { return Parameter.builder(Component.class, ResourceKeyedValueParameters.TEXT_JSON); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#TEXT_JSON_ALL}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder jsonTextOfRemainingElements() { return Parameter.builder(Component.class, ResourceKeyedValueParameters.TEXT_JSON_ALL); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#LOCATION}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder location() { return Parameter.builder(ServerLocation.class, ResourceKeyedValueParameters.LOCATION); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#LONG}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder longNumber() { return Parameter.builder(Long.class, ResourceKeyedValueParameters.LONG); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#OPERATOR}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder operator() { return Parameter.builder(Operator.class, ResourceKeyedValueParameters.OPERATOR); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#PLAYER}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder player() { return Parameter.builder(ServerPlayer.class, ResourceKeyedValueParameters.PLAYER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#PLAYER}, else the target * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder playerOrTarget() { return Parameter.player().addParser(ResourceKeyedValueParameters.TARGET_PLAYER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#PLUGIN}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder plugin() { return Parameter.builder(PluginContainer.class, ResourceKeyedValueParameters.PLUGIN); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link VariableValueParameters#doubleRange()}, using the specified * bounds (inclusive). * * @param min The minimum value. * @param max The maximum value. * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder rangedDouble(final double min, final double max) { return Parameter.builder(Double.class).addParser(VariableValueParameters.doubleRange().min(min).max(max).build()); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link VariableValueParameters#integerRange()}, using the specified * bounds (inclusive). * * @param min The minimum value. * @param max The maximum value. * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder rangedInteger(final int min, final int max) { return Parameter.builder(Integer.class).addParser(VariableValueParameters.integerRange().min(min).max(max).build()); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#REMAINING_JOINED_STRINGS}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder remainingJoinedStrings() { return Parameter.builder(String.class, ResourceKeyedValueParameters.REMAINING_JOINED_STRINGS); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#RESOURCE_KEY}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder resourceKey() { return Parameter.builder(ResourceKey.class, ResourceKeyedValueParameters.RESOURCE_KEY); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#ROTATION}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder rotation() { return Parameter.builder(Vector3d.class, ResourceKeyedValueParameters.ROTATION); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#STRING}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder string() { return Parameter.builder(String.class, ResourceKeyedValueParameters.STRING); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#URL}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder url() { return Parameter.builder(URL.class, ResourceKeyedValueParameters.URL); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#USER}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder user() { return Parameter.builder(UUID.class, ResourceKeyedValueParameters.USER); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#UUID}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder uuid() { return Parameter.builder(UUID.class, ResourceKeyedValueParameters.UUID); } /** * Creates a builder that has the {@link ValueParameter} set to * {@link ResourceKeyedValueParameters#VECTOR3D}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder vector3d() { return Parameter.builder(Vector3d.class, ResourceKeyedValueParameters.VECTOR3D); } /** * Creates a builder that has the {@link ValueParameter} set to {@link ResourceKeyedValueParameters#WORLD}. * * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder world() { return Parameter.builder(ServerWorld.class, ResourceKeyedValueParameters.WORLD); } /** * Creates a builder that has the {@link ValueParameter} that allows you to * choose from cataloged types. * *

See {@link VariableValueParameters.RegistryEntryBuilder * #defaultNamespace(String)} for how default namespaces work.

* *

If the {@link Game} or {@link Server} scoped {@link RegistryHolder} * is required, * {@link VariableValueParameters.RegistryEntryBuilder#GLOBAL_HOLDER_PROVIDER} * or {@link VariableValueParameters.RegistryEntryBuilder#SERVER_HOLDER_PROVIDER} * may be used.

* * @param type The registry value type to check for choices * @param holderProvider A {@link Function} that provides the appropriate * {@link RegistryHolder} to get the appropriate {@link Registry} * @param registryKey The {@link RegistryKey} that represents the target * {@link Registry} * @param defaultNamespaces The default namespaces that will be used with the * provided value if the supplied argument is un-namespaced * @param The type of registry value * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder registryElement( final TypeToken type, @NonNull final Function holderProvider, @NonNull final RegistryType registryKey, @NonNull final String @NonNull... defaultNamespaces) { return Parameter.registryElement( type, Collections.singletonList(holderProvider), registryKey, defaultNamespaces ); } /** * Creates a builder that has the {@link ValueParameter} that allows you to * choose from cataloged types. * *

See {@link VariableValueParameters.RegistryEntryBuilder * #defaultNamespace(String)} for how default namespaces work.

* *

If the {@link Game} or {@link Server} scoped {@link RegistryHolder} * is required, * {@link VariableValueParameters.RegistryEntryBuilder#GLOBAL_HOLDER_PROVIDER} * or {@link VariableValueParameters.RegistryEntryBuilder#SERVER_HOLDER_PROVIDER} * may be used.

* * @param type The registry value type to check for choices * @param holderProviders {@link Function}s that provides the appropriate * {@link RegistryHolder} to get the appropriate {@link Registry} * @param registryKey The {@link RegistryKey} that represents the target * {@link Registry} * @param defaultNamespaces The default namespaces that will be used with the * provided value if the supplied argument is un-namespaced * @param The type of registry value * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder registryElement( final @NonNull TypeToken type, final @NonNull List> holderProviders, final @NonNull RegistryType registryKey, final @NonNull String @NonNull... defaultNamespaces) { final VariableValueParameters.RegistryEntryBuilder vvp = VariableValueParameters.registryEntryBuilder(holderProviders, registryKey); for (final String namespace : defaultNamespaces) { vvp.defaultNamespace(namespace); } return Parameter.builder(type, vvp.build()); } /** * Creates a builder that has the {@link ValueParameter} that allows you to * choose from types registered in a given {@link Registry}. * *

See {@link VariableValueParameters.RegistryEntryBuilder * #defaultNamespace(String)} for how default namespaces work.

* * @param type The registry value type to check for choices * @param registryType The {@link DefaultedRegistryType} to use * when retrieving objects * @param defaultNamespaces The default namespaces that will be used with the * provided value if the supplied argument is un-namespaced * @param The type of registyr value * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder registryElement( final TypeToken type, @NonNull final DefaultedRegistryType registryType, @NonNull final String @NonNull... defaultNamespaces) { final VariableValueParameters.RegistryEntryBuilder vvp = VariableValueParameters.registryEntryBuilder(registryType); for (final String namespace : defaultNamespaces) { vvp.defaultNamespace(namespace); } return Parameter.builder(type, vvp.build()); } /** * Creates a builder that has a {@link ValueParameter} that allows you to * specify a set of choices that must be chosen from * *

This will return a parser that will return {@link String}s

* * @param choices The choices * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder choices(final String @NonNull... choices) { final VariableValueParameters.StaticChoicesBuilder builder = VariableValueParameters .staticChoicesBuilder(String.class) .showInUsage(true); for (final String choice : choices) { builder.addChoice(choice, choice); } return Parameter.builder(String.class, builder.build()); } /** * Creates a builder that has a {@link ValueParameter} that allows you to * specify a set of choices that must be chosen from. These choices map to * objects that will get put in the {@link CommandContext} when a choice is * selected. * * @param The type of parameter * @param returnType The type of object that will be returned by the parser * to be built by this builder. * @param choices The choices * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder choices(@NonNull final Class returnType, @NonNull final Map choices) { return Parameter.builder(returnType, VariableValueParameters.staticChoicesBuilder(returnType) .addChoices(choices) .showInUsage(true).build()); } /** * Creates a builder that has a {@link ValueParameter} that allows you to * specify a set of choices that must be chosen from. These choices map to * objects that will get put in the {@link CommandContext} when a choice is * selected, through the use of the {@code valueFunction}. * * @param The type of parameter * @param returnType The type of object that will be returned by the parser * to be built by this builder. * @param valueFunction The function that returns an object to put in the * {@link CommandContext} based on the supplied choice * @param choices The choices * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder choices( @NonNull final Class returnType, @NonNull final Function valueFunction, @NonNull final Supplier> choices) { return Parameter.builder(returnType, VariableValueParameters .dynamicChoicesBuilder(returnType) .showInUsage(true) .choices(choices) .results(valueFunction) .build()); } /** * Creates a builder that has a {@link ValueParameter} that requires an * argument that matches the name of a supplied {@link Enum} type * * @param enumClass The {@link Enum} class type * @param The type of {@link Enum} * @return A {@link Parameter.Value.Builder} */ static > Parameter.Value.Builder enumValue(@NonNull final Class enumClass) { return Parameter.builder(enumClass, VariableValueParameters.enumChoices(enumClass)); } /** * Creates a builder that has a {@link ValueParameter} that requires an * argument to be a literal specified * * @param returnType The type of object that will be returned by the parser * to be built by this builder. * @param returnedValue The object to put in the {@link CommandContext} if * the literal matches. * @param literal The literal to match * @param The type of value * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder literal( @NonNull final Class returnType, @NonNull final T returnedValue, final String @NonNull... literal) { final Collection iterable = Arrays.asList(literal); return Parameter.literal(returnType, returnedValue, () -> iterable); } /** * Creates a builder that has a {@link ValueParameter} that requires an * argument to be a literal specified * * @param The type of parameter * @param returnedValue The object to put in the {@link CommandContext} if * the literal matches * @param literalSupplier A function that provies the literal to match at * invocation * @param returnType The type of return * @return A {@link Parameter.Value.Builder} */ static Parameter.Value.Builder literal( @NonNull final Class returnType, @NonNull final T returnedValue, @NonNull final Supplier> literalSupplier) { return Parameter.builder(returnType, VariableValueParameters.literalBuilder(returnType) .returnValue(() -> returnedValue) .literal(literalSupplier).build()); } /** * Gets whether this parameter is optional. * *

An optional parameter will not throw an exception if it cannot parse * an input, instead passing control to another parameter.

* * @return true if optional, else false. */ boolean isOptional(); /** * Gets whether this parameter is known to be able to be explicitly * considered a terminal parameter without regarding its place in a * command. * *

A terminal parameter will pass control to the command's associated * {@link CommandExecutor} if the parameter consumes the end of an input * string.

* *

Because this parameter may be reused across multiple commands, there * may be some circumstances where this parameter will act as a terminal * parameter but this is false, such as when this is at the end of a * parameter chain or the following parameters are all optional. The return * value from this method generally will return whether this element is * terminal without regard to other parameters in a * command.

* * @return true if known to be terminal. */ boolean isTerminal(); /** * A {@link Key} * * @param The type. */ interface Key { /** * Gets the string key associated with this parameter. * * @return The key. */ String key(); /** * Gets the {@link TypeToken} of the type of object that this parameter * should return from parsing. * * @return The {@link TypeToken} */ Type type(); /** * Return whether the value is an instance of this key's value type. * * @param value value to check * @return if instance */ boolean isInstance(Object value); /** * Cast the provided value to the value type. * * @param value value * @return the casted value * @throws ClassCastException if {@code value} is not of the correct type */ T cast(Object value); /** * A "builder" that allows for keys to be built. */ interface Builder extends ResettableBuilder, Builder> { /** * Creates a key with the provided key and value class it * represents. * * @param key The key * @param typeToken The {@link TypeToken} that represents the * type of value it stores * @param The type of the value represented by the key * @return The built {@link Key} */ Key build(@NonNull String key, @NonNull TypeToken typeToken); /** * Creates a key with the provided key and value class it * represents. * * @param key The key * @param type The {@link Class} that represents the * non-parameterized type of value it stores * @param The type of the value represented by the key * @return The built {@link Key} */ Key build(@NonNull String key, @NonNull Class type); } } /** * Represents a {@link Parameter} that attempts to parse an argument to * obtain a value of type {@code T}. * *

This type of {@link Parameter} will attempt to parse an input * using the {@link ValueParser}s in the order that they are returned in * {@link #parsers()}. If a {@link ValueParser} fails to parse an * argument, the next in the list will be tried, if the final * {@link ValueParser} cannot parse the argument, this element will * throw a {@link ArgumentParseException}.

* * @param The type of value returned from the {@link ValueParser}s */ interface Value extends Parameter { /** * The key that a parameter result is stored under. * * @return The key. */ Key key(); /** * The {@link ValueParser}s to use when parsing an argument. They will be * tried in this order. * *

There must always be at least one {@link ValueParser}. If this element * is optional and has a default result, it will be the last element in the * returned {@link Collection}.

* * @return The parameters. */ Collection> parsers(); /** * Gets the {@link ValueCompleter} associated with this {@link Value}. * * @return The {@link ValueCompleter}. */ ValueCompleter completer(); /** * Gets the {@link ValueParameterModifier} that affects this parameter, * if any. * * @return The {@link ValueParameterModifier}, if set. */ Optional> modifier(); /** * Gets the {@link ValueUsage} associated with this {@link Value}, if * any was set. * * @return The {@link ValueUsage}, if set. */ Optional valueUsage(); /** * Gets a {@link Predicate} that indicates whether a given {@link Cause} * should parse this {@link Parameter}. * * @return the predicate */ Predicate requirement(); /** * Parses the next element(s) in the {@link CommandContext}. * * @param reader The {@link ArgumentReader.Mutable} containing the strings * that need to be parsed * @param context The {@link CommandContext.Builder} that contains the * current state of the execution * @throws ArgumentParseException thrown if the parameter could not be * parsed */ void parse(ArgumentReader.@NonNull Mutable reader, CommandContext.@NonNull Builder context) throws ArgumentParseException; /** * Returns potential completions of the current tokenized argument. The * completion will be based on {@link ArgumentReader#remaining()}. * * @param reader The {@link ArgumentReader} containing the strings that need * to be parsed * @param context The {@link CommandContext} that contains the * current state of the execution. * @return The potential completions. * @throws ArgumentParseException thrown if the parameter could not be * parsed */ List complete(ArgumentReader.@NonNull Immutable reader, @NonNull CommandContext context) throws ArgumentParseException; /** * Gets the usage of this parameter. * * @param cause The {@link CommandCause} that requested the usage * @return The usage */ String usage(CommandCause cause); /** * If set, this parameter will repeat until the argument string has * been parsed. * * @return if true, consumes all arguments */ boolean willConsumeAllRemaining(); /** * Builds a {@link Parameter} from constituent components. */ interface Builder extends org.spongepowered.api.util.Builder, Builder> { /** * The key that the parameter will place parsed values into. * *

This is a mandatory element.

* * @param key The key. * @return This builder, for chaining */ Builder key(String key); /** * The key that the parameter will place parsed values into. * *

This is a mandatory element.

* * @param key The key. * @return This builder, for chaining */ Builder key(Parameter.Key key); /** * The {@link ValueParser} that will extract the value(s) from the * parameters. If this is a {@link ValueParameter}, the object's * complete and usage methods will be used for completion and usage * unless this builder's {@link #completer(ValueCompleter)}} and * {@link #usage(ValueUsage)} methods are specified. * * @param parser The {@link ValueParameter} to use * @return This builder, for chaining */ Builder addParser(ValueParser parser); /** * The {@link ValueParser} that will extract the value(s) from the * parameters. If this is a {@link ValueParameter}, the object's * complete and usage methods will be used for completion and usage * unless this builder's {@link #completer(ValueCompleter)}} and * {@link #usage(ValueUsage)} methods are specified. * * @param The {@link ValueParser} to be used as a parser * @param parser The {@link ValueParser} to use * @return This builder, for chaining */ default > Builder addParser(@NonNull final DefaultedRegistryReference parser) { return this.addParser(parser.get()); } /** * Provides a function that provides tab completions * *

Optional. If this is null (or never set), * completions will either be done via the supplied * {@link Builder#addParser(ValueParser)} or will just return an empty * list. If this is supplied, no modifiers will run on completion.

* * @param completer The {@link ValueCompleter} * @return This builder, for chaining */ Builder completer(@Nullable ValueCompleter completer); /** * Provides a modifier that allows for the modification of the * outcome of an argument parse or a completion. This is primarily * intended for use with Mojang/Sponge standard parameters, allowing * developers to tweak the input of a standard parameter without * having to worry about completion types. * *

Developers should only use this when they use a parameter * type that they do not control. If you are using this with a * {@link ValueParameter}, {@link ValueParser} or * {@link ValueCompleter} that you control (that is, able to modify * the source of), it is strongly recommended that you do that * instead. For more information about how a modifier should be * used, read the {@link ValueParameterModifier} docs instead.

* *

Optional. If this is null (or never set), any * outcomes will not be modified.

* * @param modifier The modifier * @return This builder, for chaning */ Builder modifier(@Nullable ValueParameterModifier modifier); /** * Sets the usage. The {@link Function} accepts the parameter key * and the calling {@link Cause}. * *

Optional. If this is null (or never set), * the usage string will either be provided via the supplied * {@link #addParser(ValueParser)} or will just return * the parameter's key. If this is supplied, no modifiers will run on * usage.

* * @param usage The function * @return This builder, for chaining */ Builder usage(@Nullable ValueUsage usage); /** * Sets a function that determines what is required of the * appropriate {@link Subject} in the provided {@link Cause} before * this parameter is parsed. * *

If the source does not have this permission, this parameter * will simply be skipped. Consider combining this with * {@link #optional()} so that those with permission can also skip * this parameter.

* * @param permission The permission to check for, or {@code null} for * no check. * @return This builder, for chaining */ Builder requiredPermission(@Nullable String permission); /** * Sets a function that determines what is required of the provided * {@link Cause} before this parameter attempts to parse. * *

If this is set to {@code null}, this parameter will always * attempt to parse, subject to other modifiers.

* *

Note: this will overwrite any requirements set * using {@link #requiredPermission(String)}}.

* * @param executionRequirements A function that sets the * @return This builder, for chaining */ Builder requirements(@Nullable Predicate executionRequirements); /** * If set, this parameter will repeat until the argument string has * been parsed. * *

For example, if you have the argument string,

* *
             *     1 2 3 4
             * 
* *

and you use {@link ResourceKeyedValueParameters#INTEGER} without * setting this method, this parameter will parse the first element, * 1, and the remaining elements will be left for the next parameter * in the chain. If you call this method, the resulting * {@link Parameter.Value} will continuously parse the argument string * until either:

*
    *
  • The entire argument string has been parsed, in which case * the parsing is considered complete and command execution will * continue
  • *
  • A part of the argument string could not be parsed, in which * case an exception will be raised. If this element is also marked * as {@link #optional()}, then parsing will continue * as if nothing has been parsed.
  • *
* *

Unless marked as optional, this element must be able to consume * at least one argument. This will automatically mark the element * as {@link #terminal() terminal}.

* * @return This builder, for chaining */ Builder consumeAllRemaining(); /** * Marks this parameter as optional, such that if an argument does not * exist or cannot be parsed, an exception is not thrown, and * no value is returned. * * @return This builder, for chaining */ Builder optional(); /** * Marks this parameter as a terminal parameter. Any * terminal parameter can be considered as a point where argument * parsing can stop, allowing control to pass to the command's * associated {@link CommandExecutor}. * *

Note that a parameter may be considered terminal even if this * isn't set, including if the parameter will consume the rest of * the argument string, or if all following arguments are * {@link #optional()}. In these scenarios, the built parameter * may not be aware of its terminal status.

* * @return This builder, for chaining. */ Builder terminal(); /** * Creates a {@link Parameter} from the builder. * * @return The {@link Parameter} */ @Override Parameter.Value build(); } } /** * A {@link Subcommand} represents a literal argument where, if parsed, should * indicate to the command processor that the * {@link CommandExecutor} of the command * should change. */ interface Subcommand extends Parameter { /** * The command that is parsed and potentially run when this subcommand * is parsed. * * @return The command to run. */ Command.Parameterized command(); /** * The alias for the subcommand. * * @return The subcommand. */ Set aliases(); interface Builder extends org.spongepowered.api.util.Builder { /** * Sets an alias for the subcommand. This can be executed more * than once. * * @param alias The alias * @return This builder, for chaining */ Builder addAlias(String alias); /** * Sets the {@link Command.Parameterized} to execute for this subcommand. * * @param command The {@link Command.Parameterized} * @return This builder, for chaining. */ Builder subcommand(Command.Parameterized command); /** * Builds this subcommand parameter. * *

An alias and the command must be set, else a * {@link IllegalStateException} will be thrown.

* * @return The {@link Subcommand} */ @Override Subcommand build(); } } /** * A parameter that consists of multiple parameters */ interface Multi extends Parameter { /** * Returns the child parameters. * * @return the child parameters */ List childParameters(); } /** * Specifies a builder for creating a {@link Parameter} that returns a * parameter that concatenates all parameters into a single * parameter to be executed one by one. */ interface SequenceBuilder extends Builder { /** * Sets that this sequence of parameters is optional, and will be * ignored if it isn't specified - but will throw an error if this * is passed something to parse that it cannot parse. * * @return This builder, for chaining */ SequenceBuilder terminal(); /** * Sets that this parameter is weak optional and will be ignored if it * cannot parse the next element(s). * * @return This builder, for chaining */ SequenceBuilder optional(); /** * Defines the next parameter in the parameter sequence. * * @param parameter The parameter * @return This builder, for chaining */ SequenceBuilder then(Parameter parameter); /** * Adds a set of {@link Parameter}s to this builder. * *

The parameters will be parsed in the provided order.

* * @param parameters The parameters to add * @return This builder, for chaining */ default SequenceBuilder then(final Parameter @NonNull... parameters) { return this.then(Arrays.asList(parameters)); } /** * Adds a set of {@link Parameter}s to this builder. * *

The parameters will be parsed in the provided order.

* * @param parameters The parameters to add * @return This builder, for chaining */ default SequenceBuilder then(@NonNull final Iterable parameters) { for (final Parameter parameter : parameters) { this.then(parameter); } return this; } /** * Creates a {@link Parameter} from the builder. * * @return The {@link Parameter} */ @Override Multi build(); } /** * Specifies a builder for creating a {@link Parameter} that returns a * parameter that concatenates all parameters into a single * parameter to be executed one by one. */ interface FirstOfBuilder extends Builder { /** * Sets that this parameter is optional, and will be ignored if it isn't * specified - but will throw an error if this is passed something to * parse that it cannot parse. * * @return This builder, for chaining */ FirstOfBuilder terminal(); /** * Sets that this parameter is weak optional and will be ignored if it * cannot parse the next element(s). * * @return This builder, for chaining */ FirstOfBuilder optional(); /** * Adds a parameter that can be used to parse an argument. Parameters * are checked in the order they are added to the builder. * * @param parameter The parameter * @return This builder, for chaining */ FirstOfBuilder or(Parameter parameter); /** * Adds a set of {@link Parameter}s to this builder. * *

The parameters will be parsed in the provided order until one * succeeds.

* * @param parameters The parameters to add * @return This builder, for chaining */ default FirstOfBuilder orFirstOf(final Parameter @NonNull... parameters) { return this.orFirstOf(Arrays.asList(parameters)); } /** * Adds a set of {@link Parameter}s to this builder. * *

The parameters will be parsed in the provided order until one * succeeds.

* * @param parameters The parameters to add * @return This builder, for chaining */ default FirstOfBuilder orFirstOf(@NonNull final Iterable parameters) { for (final Parameter parameter : parameters) { this.or(parameter); } return this; } /** * Creates a {@link Multi} from the builder. * * @return The {@link Multi} */ @Override Multi build(); } /** * Contains methods to create the generic builders. */ interface Factory { /** * Creates a {@link Parameter.Value.Builder} initialized with the provided {@link Key}. * * @param key A key to start with * @param The type of object that will be returned by the built * {@link Parameter.Value} * @return The builder. */ Value.Builder createParameterBuilder(Parameter.Key key); /** * Creates a {@link Parameter.Value.Builder} of the indicated generic type. * * @param parameterClass The class * @param The type of object that will be returned by the built * {@link Parameter.Value} * @return The builder. */ Value.Builder createParameterBuilder(TypeToken parameterClass); /** * Creates a {@link Parameter.Value.Builder} of the indicated generic type. * * @param parameterClass The class * @param The type of object that will be returned by the built * {@link Parameter.Value} * @return The builder. */ Value.Builder createParameterBuilder(Class parameterClass); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy