001/*
002 * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
003 *
004 *  Permission is hereby granted, free of charge, to any person obtaining
005 *  a copy of this software and associated documentation files (the
006 *  "Software"), to deal in the Software without restriction, including
007 *  without limitation the rights to use, copy, modify, merge, publish,
008 *  distribute, sublicense, and/or sell copies of the Software, and to
009 *  permit persons to whom the Software is furnished to do so, subject to
010 *  the following conditions:
011 *
012 *  The above copyright notice and this permission notice shall be
013 *  included in all copies or substantial portions of the Software.
014 *
015 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
016 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
017 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
018 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
019 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
020 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
021 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
022 */
023
024package co.aikar.commands;
025
026import java.util.Arrays;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030
031public class CommandCompletionContext<I extends CommandIssuer> {
032    private final RegisteredCommand command;
033    protected final I issuer;
034    private final String input;
035    private final String config;
036    private final Map<String, String> configs = new HashMap<>();
037    private final List<String> args;
038
039    CommandCompletionContext(RegisteredCommand command, I issuer, String input, String config, String[] args) {
040        this.command = command;
041        this.issuer = issuer;
042        this.input = input;
043        if (config != null) {
044            String[] configs = ACFPatterns.COMMA.split(config);
045            for (String conf : configs) {
046                String[] confsplit = ACFPatterns.EQUALS.split(conf, 2);
047                this.configs.put(confsplit[0].toLowerCase(), confsplit.length > 1 ? confsplit[1] : null);
048            }
049            this.config = configs[0];
050        } else {
051            this.config = null;
052        }
053
054        this.args = Arrays.asList(args);
055    }
056
057    public Map<String, String> getConfigs() {
058        return configs;
059    }
060
061    public String getConfig(String key) {
062        return getConfig(key, null);
063    }
064
065    public String getConfig(String key, String def) {
066        return this.configs.getOrDefault(key.toLowerCase(), def);
067    }
068
069    public boolean hasConfig(String key) {
070        return this.configs.containsKey(key.toLowerCase());
071    }
072
073    public <T> T getContextValue(Class<? extends T> clazz) throws InvalidCommandArgument {
074        return getContextValue(clazz, null);
075    }
076
077    public <T> T getContextValue(Class<? extends T> clazz, Integer paramIdx) throws InvalidCommandArgument {
078        String name = null;
079        if (paramIdx != null) {
080            if (paramIdx >= command.parameters.length) {
081                throw new IllegalArgumentException("Param index is higher than number of parameters");
082            }
083            CommandParameter param = command.parameters[paramIdx];
084            Class<?> paramType = param.getType();
085            if (!clazz.isAssignableFrom(paramType)) {
086                throw new IllegalArgumentException(param.getName() + ":" + paramType.getName() + " can not satisfy " + clazz.getName());
087            }
088            name = param.getName();
089        } else {
090            CommandParameter[] parameters = command.parameters;
091            for (int i = 0; i < parameters.length; i++) {
092                final CommandParameter parameter = parameters[i];
093                if (clazz.isAssignableFrom(parameter.getType())) {
094                    paramIdx = i;
095                    name = parameter.getName();
096                    break;
097                }
098            }
099            if (paramIdx == null) {
100                throw new IllegalStateException("Can not find any parameter that can satisfy " + clazz.getName());
101            }
102        }
103        //noinspection unchecked
104        Map<String, Object> resolved = command.resolveContexts(issuer, args, args.size() - 1);
105        if (resolved == null || paramIdx > resolved.size()) {
106            ACFUtil.sneaky(new CommandCompletionTextLookupException());
107        }
108
109        //noinspection unchecked
110        return (T) resolved.get(name);
111    }
112
113    public CommandIssuer getIssuer() {
114        return issuer;
115    }
116
117    public String getInput() {
118        return input;
119    }
120
121    public String getConfig() {
122        return config;
123    }
124
125    public boolean isAsync() {
126        return CommandManager.getCurrentCommandOperationContext().isAsync();
127    }
128}