package com.cardshifter.server.model; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Supplier; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameters; import com.cardshifter.api.both.ChatMessage; import com.cardshifter.server.commands.CommandContext; /** * Handles chat style commands such as '/example 1 2 something' * @author Simon Forsberg * */ public class CommandHandler { private static final Logger logger = LogManager.getLogger(CommandHandler.class); private final Map<String, CommandInfo<?>> commands; private final Server server; public static interface CommandHandle<T> { void handle(CommandContext command, T parameters); } public class CommandInfo<T> { private Supplier<T> supplier; private CommandHandle<T> handler; public CommandInfo(Supplier<T> supplier, CommandHandle<T> consumer) { this.supplier = supplier; this.handler = consumer; } public void handleCommand(Command cmd) { T obj = supplier.get(); JCommander commander = new JCommander(obj); commander.parse(cmd.getAllParameters()); handler.handle(new CommandContext(server, cmd, cmd.getSender()), obj); } public JCommander getCommander() { return new JCommander(supplier.get()); } public String getDescription() { Parameters params = supplier.get().getClass().getAnnotation(Parameters.class); return params == null ? "(No description)" : params.commandDescription(); } } public CommandHandler(Server server) { this.commands = new ConcurrentHashMap<>(); this.server = server; } public void addHandler(String command, Consumer<Command> handler) { commands.put(command, new CommandInfo<Object>(() -> new Object(), (a, b) -> {}){ @Override public void handleCommand(Command cmd) { handler.accept(cmd); } }); } public void addHandler(String command, CommandInfo<?> handler) { commands.put(command, handler); } public <T> void addHandler(String command, Supplier<T> obj, CommandHandle<T> consumer) { this.addHandler(command, new CommandInfo<>(obj, consumer)); } public boolean handle(Command command) { try { CommandInfo<?> handler = commands.get(command.getCommand()); if (handler == null) { command.getSender().sendToClient(new ChatMessage(1, "Server", "Invalid command: " + command)); } else { handler.handleCommand(command); } return handler != null; } catch (RuntimeException ex) { logger.error(ex.getMessage(), ex); return false; } } public Map<String, CommandInfo<?>> getCommands() { return Collections.unmodifiableMap(commands); } }