1 package dev.sympho.modular_commands.api.command.parameter;
2
3 import javax.annotation.Nullable;
4
5 import org.checkerframework.checker.nullness.qual.NonNull;
6 import org.checkerframework.checker.regex.qual.Regex;
7 import org.checkerframework.common.value.qual.MatchesRegex;
8 import org.checkerframework.dataflow.qual.Pure;
9 import org.checkerframework.dataflow.qual.SideEffectFree;
10 import org.immutables.value.Value;
11
12 import dev.sympho.modular_commands.api.command.Command;
13 import dev.sympho.modular_commands.api.command.parameter.parse.ArgumentParser;
14 import dev.sympho.modular_commands.utils.ParameterUtils;
15
16 // BEGIN LONG LINES
17 /**
18 * Specification for a parameter received for a command.
19 *
20 * <p>Irrespective of whether the command it is used with is compatible with interactions
21 * or not, all values must be compatible with the
22 * <a href="https://discord.com/developers/docs/interactions/application-commands#application-command-object">
23 * Discord API specification</a> for command parameters.
24 *
25 * @param <T> The type of argument that is provided.
26 * @version 1.0
27 * @since 1.0
28 */
29 // END LONG LINES
30 @Value.Immutable
31 @Value.Style(
32 visibility = Value.Style.ImplementationVisibility.PACKAGE,
33 overshadowImplementation = true
34 )
35 public interface Parameter<T extends @NonNull Object> {
36
37 /** Pattern for valid parameter names in the Discord API. */
38 @Regex String NAME_REGEX = Command.NAME_REGEX;
39 /** Pattern for valid parameter descriptions in the Discord API. */
40 @Regex String DESCRIPTION_REGEX = Command.DESCRIPTION_REGEX;
41
42 /**
43 * The name of the parameter.
44 *
45 * @return The value.
46 */
47 @Pure
48 @MatchesRegex( NAME_REGEX ) String name();
49
50 /**
51 * The description of the parameter.
52 *
53 * @return The value.
54 */
55 @Pure
56 @MatchesRegex( DESCRIPTION_REGEX ) String description();
57
58 /**
59 * Whether the parameter must be provided to invoke the command.
60 *
61 * @return The value.
62 * @implSpec The default is {@code false}.
63 */
64 @Pure
65 @Value.Default
66 default boolean required() {
67 return false;
68 }
69
70 /**
71 * The default value for the parameter.
72 *
73 * <p>If {@code null}, the parameter has no default and will be {@code null} if missing.
74 *
75 * <p>Note that this property is only meaningful if {@link #required()} is {@code false}.
76 *
77 * @return The value.
78 * @implSpec The default is {@code null}.
79 */
80 @Pure
81 // TODO: Replace JSR305 @Nullable with Checker's
82 // Blocked by https://github.com/immutables/immutables/issues/1262
83 @Nullable T defaultValue();
84
85 /**
86 * The parser to use to process received arguments.
87 *
88 * @return The value.
89 */
90 @Pure
91 ArgumentParser<?, T> parser();
92
93 /**
94 * Validates that the properties of this instance are valid.
95 *
96 * @throws IllegalArgumentException if any of properties are invalid.
97 * @throws NullPointerException if a {@code null} value was found where not allowed.
98 * @see ParameterUtils#validate(Parameter)
99 */
100 @Pure
101 @Value.Check
102 default void validate() throws IllegalArgumentException, NullPointerException {
103
104 ParameterUtils.validate( this );
105
106 }
107
108 /**
109 * Creates a new builder.
110 *
111 * @param <T> The argument type.
112 * @return The builder.
113 */
114 @SideEffectFree
115 static <T extends @NonNull Object> Builder<T> builder() {
116 return new Builder<>();
117 }
118
119 /**
120 * Creates a new builder initialized with the properties of the given parameter.
121 *
122 * @param <T> The argument type.
123 * @param base The base instance to copy.
124 * @return The builder.
125 */
126 @SideEffectFree
127 static <T extends @NonNull Object> Builder<T> builder( final Parameter<T> base ) {
128 return new Builder<T>().from( base );
129 }
130
131 /**
132 * The default builder.
133 *
134 * @param <T> The argument type.
135 * @since 1.0
136 */
137 @SuppressWarnings( "MissingCtor" )
138 class Builder<T extends @NonNull Object> extends ImmutableParameter.Builder<T> {}
139
140 }