Skip to main content
The InputArgument class encapsulates a single command argument, providing access to its value, presence status, parameter metadata, and annotations.

Overview

InputArgument instances are passed to argument providers and contain:
  • The raw string value of the argument
  • Whether the argument was provided or not (Status)
  • Parameter metadata (name, type, annotations)
  • Access to forwarded annotations like @Range and @Opt
  • Additional data storage for custom providers

Class Definition

public final class InputArgument
Package: me.vaperion.blade.argument

Constructors

// Standard constructor
public InputArgument(@NotNull BladeParameter parameter,
                     @Nullable String value,
                     @NotNull Status status)

// Constructor without value/status (for internal use)
public InputArgument(@NotNull BladeParameter parameter)

Core Methods

Accessing the Value

getValue()
String
Returns the raw string value of the argument, or null if not present.
String value = arg.getValue();
if (value != null) {
    // Argument was provided
}
requireValue()
String
Returns the value of the argument, throwing an exception if not present.Returns: The non-null value of the argumentThrows: IllegalStateException if the value is null
@Override
public Player provide(@NotNull Context ctx, @NotNull InputArgument arg) {
    String value = arg.requireValue(); // Throws if null
    
    Player player = Bukkit.getPlayer(value);
    if (player == null) {
        throw BladeParseError.recoverable(
            "Player '" + value + "' not found."
        );
    }
    
    return player;
}

Checking Status

getStatus()
Status
Returns the presence status of the argument.
Status status = arg.getStatus();
if (status == Status.PRESENT) {
    // Argument was provided
} else if (status == Status.NOT_PRESENT) {
    // Argument was not provided
}

// Or use convenience method
if (status.isPresent()) {
    // Process argument
}

Status Enum

The Status enum indicates whether an argument was provided:
Status.PRESENT
enum
The argument was provided by the user.
Status.NOT_PRESENT
enum
The argument was not provided by the user.
isPresent()
boolean
Convenience method on Status enum to check if the argument was provided.
if (arg.getStatus().isPresent()) {
    // Argument was provided
}

Parameter Metadata

getParameter()
BladeParameter
Returns the parameter metadata containing name, type, and annotations.
BladeParameter param = arg.getParameter();
String name = param.name();           // "target"
Class<?> type = param.type();         // Player.class
List<Annotation> data = param.data(); // All annotations

Optional Arguments

optional()
Opt
Returns the @Opt annotation if the argument is optional, or null otherwise.
Opt opt = arg.optional();
if (opt != null) {
    Opt.Type type = opt.value();
    String custom = opt.custom();
}
isOptionalWithType(Opt.Type type)
boolean
Checks if the argument is optional with a specific type.
type
Opt.Type
required
The optional type to check (EMPTY, CUSTOM, SENDER, etc.)
if (arg.isOptionalWithType(Opt.Type.SENDER)) {
    // Return the sender as the default value
    return ctx.sender().parseAs(Player.class);
}
isOptionalAcceptingNull()
boolean
Checks if the argument is optional and accepts null values.Returns true if:
  • Type is EMPTY
  • Type is SENDER
  • Type is EMPTY_OR_CUSTOM with empty custom value
if (arg.isOptionalAcceptingNull()) {
    return null; // Null is acceptable
}

Range Constraints

range()
Range
Returns the @Range annotation if present, or null otherwise.
Range range = arg.range();
if (range != null) {
    double min = range.min(); // 0.0
    double max = range.max(); // 100.0
    
    if (value < min || value > max) {
        throw BladeParseError.recoverable(
            "Value must be between " + min + " and " + max
        );
    }
}

Forwarded Annotations

Access custom annotations marked with @Forwarded:
annotation(Class<T> annotationClass)
T
Returns the first annotation of the specified type, or null if not present.
annotationClass
Class<T>
required
The annotation class to retrieve
// Custom annotation
@Forwarded
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MaxLength {
    int value();
}

// In provider
MaxLength maxLength = arg.annotation(MaxLength.class);
if (maxLength != null && value.length() > maxLength.value()) {
    throw BladeParseError.recoverable(
        "Value exceeds maximum length of " + maxLength.value()
    );
}
annotationList(Class<T> annotationClass)
List<T>
Returns all annotations of the specified type.
annotationClass
Class<T>
required
The annotation class to retrieve
List<CustomAnnotation> annotations = arg.annotationList(CustomAnnotation.class);
for (CustomAnnotation annotation : annotations) {
    // Process each annotation
}

Data Storage

getData()
List<String>
Returns a mutable list for storing custom data.Providers can use this to store intermediate parsing results or metadata.
List<String> data = arg.getData();
data.add("parsed");
data.add("additional-info");

Usage in Providers

Basic Provider

public class IntegerProvider implements ArgumentProvider<Integer> {
    @Override
    public Integer provide(@NotNull Context ctx, @NotNull InputArgument arg) {
        // Get the value (throws if not present)
        String value = arg.requireValue();
        
        try {
            int result = Integer.parseInt(value);
            
            // Check for @Range annotation
            Range range = arg.range();
            if (range != null) {
                if (result < range.min() || result > range.max()) {
                    throw BladeParseError.recoverable(
                        "Value must be between " + range.min() + 
                        " and " + range.max()
                    );
                }
            }
            
            return result;
        } catch (NumberFormatException e) {
            throw BladeParseError.recoverable(
                "'" + value + "' is not a valid integer."
            );
        }
    }
}

Provider with Optional Arguments

public class PlayerProvider implements ArgumentProvider<Player> {
    @Override
    public boolean handlesNullInputArguments() {
        return true; // Handle optional arguments
    }
    
    @Override
    public Player provide(@NotNull Context ctx, @NotNull InputArgument arg) {
        // Check if argument is optional with SENDER type
        if (arg.isOptionalWithType(Opt.Type.SENDER)) {
            if (arg.getStatus() == Status.NOT_PRESENT) {
                // Return sender as default
                return ctx.sender().parseAs(Player.class);
            }
        }
        
        // Parse normally
        String value = arg.requireValue();
        Player player = Bukkit.getPlayer(value);
        
        if (player == null) {
            throw BladeParseError.recoverable(
                "Player '" + value + "' not found."
            );
        }
        
        return player;
    }
}

Provider with Custom Annotations

// Define a forwarded annotation
@Forwarded
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Pattern {
    String value();
}

// Use in provider
public class StringProvider implements ArgumentProvider<String> {
    @Override
    public String provide(@NotNull Context ctx, @NotNull InputArgument arg) {
        String value = arg.requireValue();
        
        // Check for @Pattern annotation
        Pattern pattern = arg.annotation(Pattern.class);
        if (pattern != null) {
            if (!value.matches(pattern.value())) {
                throw BladeParseError.recoverable(
                    "Value must match pattern: " + pattern.value()
                );
            }
        }
        
        return value;
    }
}

// Use in command
@Command("setname")
public void setName(Context ctx, 
                   @Pattern("[a-zA-Z0-9_]+") String name) {
    // name is guaranteed to match the pattern
}

Command Parameter Example

Using InputArgument concepts in command parameters:
@Command("give")
public void giveCommand(
    Context ctx,
    Player target,
    Material material,
    @Range(min = 1, max = 64) @Opt("1") int amount
) {
    // amount is optional with default "1"
    // amount is constrained between 1 and 64
    
    ItemStack item = new ItemStack(material, amount);
    target.getInventory().addItem(item);
}

See Also

Build docs developers (and LLMs) love