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 co.aikar.commands.annotation.Default; 027import co.aikar.commands.annotation.Flags; 028import co.aikar.commands.annotation.Optional; 029import co.aikar.commands.contexts.ContextResolver; 030import co.aikar.commands.contexts.IssuerAwareContextResolver; 031import co.aikar.commands.contexts.IssuerOnlyContextResolver; 032import com.google.common.collect.ImmutableMap; 033import com.google.common.collect.Maps; 034import java.lang.annotation.Annotation; 035import java.lang.reflect.Parameter; 036import java.util.List; 037import java.util.Map; 038 039@SuppressWarnings({"WeakerAccess", "unused"}) 040public class CommandExecutionContext <T extends CommandExecutionContext, I extends CommandIssuer> { 041 private final RegisteredCommand cmd; 042 private final Parameter param; 043 protected final I issuer; 044 private final List<String> args; 045 private final int index; 046 private final Map<String, Object> passedArgs; 047 private final Map<String, String> flags; 048 049 CommandExecutionContext(RegisteredCommand cmd, Parameter param, I sender, List<String> args, 050 int index, Map<String, Object> passedArgs) { 051 this.cmd = cmd; 052 this.param = param; 053 this.issuer = sender; 054 this.args = args; 055 this.index = index; 056 this.passedArgs = passedArgs; 057 Flags flags = param.getAnnotation(Flags.class); 058 if (flags != null) { 059 this.flags = Maps.newHashMap(); 060 for (String s : ACFPatterns.COMMA.split(cmd.scope.manager.getCommandReplacements().replace(flags.value()))) { 061 String[] v = ACFPatterns.EQUALS.split(s, 2); 062 this.flags.put(v[0], v.length > 1 ? v[1] : null); 063 } 064 } else { 065 this.flags = ImmutableMap.of(); 066 } 067 } 068 069 public String popFirstArg() { 070 return !args.isEmpty() ? args.remove(0) : null; 071 } 072 073 public String popLastArg() { 074 return !args.isEmpty() ? args.remove(args.size() - 1) : null; 075 } 076 077 public String getFirstArg() { 078 return !args.isEmpty() ? args.get(0) : null; 079 } 080 081 public String getLastArg() { 082 return !args.isEmpty() ? args.get(args.size() - 1) : null; 083 } 084 085 public boolean isLastArg() { 086 return cmd.parameters.length -1 == index; 087 } 088 089 public int getNumParams() { 090 return cmd.parameters.length; 091 } 092 093 public boolean canOverridePlayerContext() { 094 int numRequired = getNumParams(); 095 for (int i = 0; i < cmd.resolvers.length; i++) { 096 Parameter parameter = cmd.parameters[i]; 097 //noinspection unchecked 098 ContextResolver<?, ?> resolver = cmd.resolvers[i]; 099 if (parameter.getAnnotation(Optional.class) != null || parameter.getAnnotation(Default.class) != null) { 100 numRequired--; 101 } else if (resolver instanceof IssuerAwareContextResolver || resolver instanceof IssuerOnlyContextResolver) { 102 numRequired--; 103 } 104 } 105 106 return numRequired >= args.size(); 107 } 108 109 public Object getResolvedArg(String arg) { 110 return passedArgs.get(arg); 111 } 112 113 public Object getResolvedArg(Class<?>... classes) { 114 for (Class<?> clazz : classes) { 115 for (Object passedArg : passedArgs.values()) { 116 if (clazz.isInstance(passedArg)) { 117 return passedArg; 118 } 119 } 120 } 121 122 return null; 123 } 124 125 public <T> T getResolvedArg(String key, Class<?>... classes) { 126 final Object o = passedArgs.get(key); 127 for (Class<?> clazz : classes) { 128 if (clazz.isInstance(o)) { 129 //noinspection unchecked 130 return (T) o; 131 } 132 } 133 134 return null; 135 } 136 137 public boolean isOptional() { 138 return param.getAnnotation(Optional.class) != null; 139 } 140 public boolean hasFlag(String flag) { 141 return flags.containsKey(flag); 142 } 143 144 public String getFlagValue(String flag, String def) { 145 return flags.getOrDefault(flag, def); 146 } 147 148 public Integer getFlagValue(String flag, Integer def) { 149 return ACFUtil.parseInt(this.flags.get(flag), def); 150 } 151 152 public <T extends Annotation> T getAnnotation(Class<T> cls) { 153 return param.getAnnotation(cls); 154 } 155 156 public <T extends Annotation> boolean hasAnnotation(Class<T> cls) { 157 return param.getAnnotation(cls) != null; 158 } 159 160 public RegisteredCommand getCmd() { 161 return this.cmd; 162 } 163 164 public Parameter getParam() { 165 return this.param; 166 } 167 168 public I getIssuer() { 169 return this.issuer; 170 } 171 172 public List<String> getArgs() { 173 return this.args; 174 } 175 176 public int getIndex() { 177 return this.index; 178 } 179 180 public Map<String, Object> getPassedArgs() { 181 return this.passedArgs; 182 } 183 184 public Map<String, String> getFlags() { 185 return this.flags; 186 } 187 188 public String joinArgs() { 189 return ACFUtil.join(args, " "); 190 } 191 public String joinArgs(String sep) { 192 return ACFUtil.join(args, sep); 193 } 194}