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;
025
026import cloud.commandframework.arguments.parser.ArgumentParseResult;
027import cloud.commandframework.arguments.parser.ArgumentParser;
028import cloud.commandframework.context.CommandContext;
029import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
030import org.checkerframework.checker.nullness.qual.NonNull;
031
032import java.util.ArrayList;
033import java.util.Arrays;
034import java.util.Collections;
035import java.util.HashSet;
036import java.util.List;
037import java.util.Queue;
038import java.util.Set;
039import java.util.TreeSet;
040
041/**
042 * {@link CommandArgument} type that recognizes fixed strings. This type does not parse variables.
043 *
044 * @param <C> Command sender type
045 */
046public final class StaticArgument<C> extends CommandArgument<C, String> {
047
048    private StaticArgument(final boolean required, final @NonNull String name, final @NonNull String... aliases) {
049        super(required, name, new StaticArgumentParser<>(name, aliases), String.class);
050    }
051
052    /**
053     * Create a new static argument instance for a required command argument
054     *
055     * @param name    Argument name
056     * @param aliases Argument aliases
057     * @param <C>     Command sender type
058     * @return Constructed argument
059     */
060    public static <C> @NonNull StaticArgument<C> of(
061            final @NonNull String name,
062            final @NonNull String... aliases
063    ) {
064        return new StaticArgument<>(true, name, aliases);
065    }
066
067    /**
068     * Register a new alias
069     *
070     * @param alias New alias
071     */
072    public void registerAlias(final @NonNull String alias) {
073        ((StaticArgumentParser<C>) this.getParser()).insertAlias(alias);
074    }
075
076    /**
077     * Get an immutable view of the aliases
078     *
079     * @return Immutable view of the argument aliases
080     */
081    public @NonNull Set<@NonNull String> getAliases() {
082        return Collections.unmodifiableSet(((StaticArgumentParser<C>) this.getParser()).getAcceptedStrings());
083    }
084
085    /**
086     * Get an immutable list of all aliases that are not the main literal
087     *
088     * @return Immutable view of the optional argument aliases
089     */
090    public @NonNull List<@NonNull String> getAlternativeAliases() {
091        return Collections.unmodifiableList(new ArrayList<>(((StaticArgumentParser<C>) this.getParser()).alternativeAliases));
092    }
093
094
095    private static final class StaticArgumentParser<C> implements ArgumentParser<C, String> {
096
097        private final Set<String> allAcceptedAliases = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
098        private final Set<String> alternativeAliases = new HashSet<>();
099
100        private final String name;
101
102        private StaticArgumentParser(final @NonNull String name, final @NonNull String... aliases) {
103            this.name = name;
104            this.allAcceptedAliases.add(this.name);
105            this.allAcceptedAliases.addAll(Arrays.asList(aliases));
106            this.alternativeAliases.addAll(Arrays.asList(aliases));
107        }
108
109        @Override
110        public @NonNull ArgumentParseResult<String> parse(
111                final @NonNull CommandContext<C> commandContext,
112                final @NonNull Queue<@NonNull String> inputQueue
113        ) {
114            final String string = inputQueue.peek();
115            if (string == null) {
116                return ArgumentParseResult.failure(new NoInputProvidedException(
117                        StaticArgumentParser.class,
118                        commandContext
119                ));
120            }
121            if (this.allAcceptedAliases.contains(string)) {
122                inputQueue.remove();
123                return ArgumentParseResult.success(this.name);
124            }
125            return ArgumentParseResult.failure(new IllegalArgumentException(string));
126        }
127
128        @Override
129        public @NonNull List<@NonNull String> suggestions(
130                final @NonNull CommandContext<C> commandContext,
131                final @NonNull String input
132        ) {
133            return Collections.singletonList(this.name);
134        }
135
136        /**
137         * Get the accepted strings
138         *
139         * @return Accepted strings
140         */
141        public @NonNull Set<@NonNull String> getAcceptedStrings() {
142            return this.allAcceptedAliases;
143        }
144
145        /**
146         * Insert a new alias
147         *
148         * @param alias New alias
149         */
150        public void insertAlias(final @NonNull String alias) {
151            this.allAcceptedAliases.add(alias);
152            this.alternativeAliases.add(alias);
153        }
154
155    }
156
157}