001//
002// MIT License
003//
004// Copyright (c) 2021 Alexander Söderberg & Contributors
005//
006// Permission is hereby granted, free of charge, to any person obtaining a copy
007// of this software and associated documentation files (the "Software"), to deal
008// in the Software without restriction, including without limitation the rights
009// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010// copies of the Software, and to permit persons to whom the Software is
011// furnished to do so, subject to the following conditions:
012//
013// The above copyright notice and this permission notice shall be included in all
014// copies or substantial portions of the Software.
015//
016// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022// SOFTWARE.
023//
024package cloud.commandframework.arguments.parser;
025
026import cloud.commandframework.context.CommandContext;
027import io.leangen.geantyref.TypeToken;
028import org.checkerframework.checker.nullness.qual.NonNull;
029
030import java.lang.annotation.Annotation;
031import java.util.Collection;
032import java.util.List;
033import java.util.Optional;
034import java.util.function.BiFunction;
035import java.util.function.Function;
036
037/**
038 * Registry of {@link ArgumentParser} that allows these arguments to be
039 * referenced by a {@link Class} (or really, a {@link TypeToken})
040 * or a {@link String} key
041 *
042 * @param <C> Command sender type
043 */
044public interface ParserRegistry<C> {
045
046    /**
047     * Register a parser supplier
048     *
049     * @param type     The type that is parsed by the parser
050     * @param supplier The function that generates the parser. The map supplied my contain parameters used
051     *                 to configure the parser, many of which are documented in {@link StandardParameters}
052     * @param <T>      Generic type specifying what is produced by the parser
053     */
054    <T> void registerParserSupplier(
055            @NonNull TypeToken<T> type,
056            @NonNull Function<@NonNull ParserParameters, @NonNull ArgumentParser<C, ?>> supplier
057    );
058
059    /**
060     * Register a named parser supplier
061     *
062     * @param name     Parser name
063     * @param supplier The function that generates the parser. The map supplied my contain parameters used
064     *                 to configure the parser, many of which are documented in {@link StandardParameters}
065     */
066    void registerNamedParserSupplier(
067            @NonNull String name,
068            @NonNull Function<@NonNull ParserParameters, @NonNull ArgumentParser<C, ?>> supplier
069    );
070
071    /**
072     * Register a mapper that maps annotation instances to a map of parameter-object pairs
073     *
074     * @param annotation Annotation class
075     * @param mapper     Mapper that maps the pair (annotation, type to be parsed) to a map of
076     *                   {@link ParserParameter parameter}-{@link Object object} pairs
077     * @param <A>        Annotation type
078     * @param <T>        Type of the object that the parser is retrieved for
079     */
080    <A extends Annotation, T> void registerAnnotationMapper(
081            @NonNull Class<A> annotation,
082            @NonNull BiFunction<@NonNull A, @NonNull TypeToken<?>,
083                    @NonNull ParserParameters> mapper
084    );
085
086    /**
087     * Parse annotations into {@link ParserParameters}
088     *
089     * @param parsingType The type that is produced by the parser that is requesting the parsing parameters
090     * @param annotations The annotations to be parsed
091     * @return Parsed parameters
092     */
093    @NonNull ParserParameters parseAnnotations(
094            @NonNull TypeToken<?> parsingType,
095            @NonNull Collection<? extends Annotation> annotations
096    );
097
098    /**
099     * Attempt to create a {@link ArgumentParser} for a specified type, using
100     * an instance of {@link ParserParameter} to configure the parser settings
101     *
102     * @param type             Type that should be produced by the parser
103     * @param parserParameters Parser parameters
104     * @param <T>              Generic type
105     * @return Parser, if one can be created
106     */
107    <T> @NonNull Optional<ArgumentParser<C, T>> createParser(
108            @NonNull TypeToken<T> type,
109            @NonNull ParserParameters parserParameters
110    );
111
112    /**
113     * Attempt to create a {@link ArgumentParser} for a specified type, using
114     * an instance of {@link ParserParameter} to configure the parser settings
115     *
116     * @param name             Parser
117     * @param parserParameters Parser parameters
118     * @param <T>              Generic type
119     * @return Parser, if one can be created
120     */
121    <T> @NonNull Optional<ArgumentParser<C, T>> createParser(
122            @NonNull String name,
123            @NonNull ParserParameters parserParameters
124    );
125
126    /**
127     * Register a new named suggestion provider
128     *
129     * @param name                Name of the suggestions provider. The name is case independent.
130     * @param suggestionsProvider The suggestions provider
131     * @see #getSuggestionProvider(String) Get a suggestion provider
132     * @since 1.1.0
133     */
134    void registerSuggestionProvider(
135            @NonNull String name,
136            @NonNull BiFunction<@NonNull CommandContext<C>, @NonNull String, @NonNull List<String>> suggestionsProvider
137    );
138
139    /**
140     * Get a named suggestion provider, if a suggestion provider with the given name exists in the registry
141     *
142     * @param name Suggestion provider name. The name is case independent.
143     * @return Optional that either contains the suggestion provider, or is empty if no
144     *         suggestion provider is registered with the given name
145     * @see #registerSuggestionProvider(String, BiFunction) Register a suggestion provider
146     * @since 1.1.0
147     */
148    @NonNull Optional<BiFunction<@NonNull CommandContext<C>, @NonNull String, @NonNull List<String>>> getSuggestionProvider(
149            @NonNull String name
150    );
151
152}