diff --git a/src/main/java/redis/clients/jedis/BuilderFactory.java b/src/main/java/redis/clients/jedis/BuilderFactory.java index adce27f1f4..b1ca7455b9 100644 --- a/src/main/java/redis/clients/jedis/BuilderFactory.java +++ b/src/main/java/redis/clients/jedis/BuilderFactory.java @@ -975,30 +975,8 @@ public Map build(Object data) { } }; - public static final Builder> COMMAND_INFO_RESPONSE = new Builder>() { - @Override - public Map build(Object data) { - if (data == null) { - return null; - } - - List rawList = (List) data; - Map map = new HashMap<>(rawList.size()); - - for (Object rawCommandInfo : rawList) { - if (rawCommandInfo == null) { - continue; - } - - List commandInfo = (List) rawCommandInfo; - String name = STRING.build(commandInfo.get(0)); - CommandInfo info = CommandInfo.COMMAND_INFO_BUILDER.build(commandInfo); - map.put(name, info); - } - - return map; - } - }; + @Deprecated + public static final Builder> COMMAND_INFO_RESPONSE = CommandInfo.COMMAND_INFO_RESPONSE; public static final Builder> LATENCY_LATEST_RESPONSE = new Builder>() { @Override diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index b6148189a8..fb2efd6460 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -8250,7 +8250,7 @@ public List>> commandGetKeysAndFlags(String... com public Map commandInfo(String... commands) { checkIsInMultiOrPipeline(); connection.sendCommand(COMMAND, joinParameters(Keyword.INFO.name(), commands)); - return BuilderFactory.COMMAND_INFO_RESPONSE.build(connection.getOne()); + return CommandInfo.COMMAND_INFO_RESPONSE.build(connection.getOne()); } public List commandList() { diff --git a/src/main/java/redis/clients/jedis/resps/CommandInfo.java b/src/main/java/redis/clients/jedis/resps/CommandInfo.java index 9f3481b5a1..efdf582102 100644 --- a/src/main/java/redis/clients/jedis/resps/CommandInfo.java +++ b/src/main/java/redis/clients/jedis/resps/CommandInfo.java @@ -2,12 +2,17 @@ import redis.clients.jedis.Builder; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import static redis.clients.jedis.BuilderFactory.STRING_LIST; import static redis.clients.jedis.BuilderFactory.LONG; +import static redis.clients.jedis.BuilderFactory.STRING; +import static redis.clients.jedis.BuilderFactory.STRING_LIST; public class CommandInfo { + + private final String name; private final long arity; private final List flags; private final long firstKey; @@ -15,10 +20,22 @@ public class CommandInfo { private final long step; private final List aclCategories; private final List tips; - private final List subcommands; + private final Map subcommands; + /** + * THIS IGNORES 'subcommands' parameter. + * @param subcommands WILL BE IGNORED + * @deprecated + */ + @Deprecated public CommandInfo(long arity, List flags, long firstKey, long lastKey, long step, List aclCategories, List tips, List subcommands) { + this((String) null, arity, flags, firstKey, lastKey, step, aclCategories, tips, (Map) null); + } + + private CommandInfo(String name, long arity, List flags, long firstKey, long lastKey, long step, + List aclCategories, List tips, Map subcommands) { + this.name = name; this.arity = arity; this.flags = flags; this.firstKey = firstKey; @@ -29,6 +46,13 @@ public CommandInfo(long arity, List flags, long firstKey, long lastKey, this.subcommands = subcommands; } + /** + * Command name + */ + public String getName() { + return name; + } + /** * Arity is the number of arguments a command expects. It follows a simple pattern: * A positive integer means a fixed number of arguments. @@ -89,15 +113,23 @@ public List getTips() { /** * All the command's subcommands, if any */ - public List getSubcommands() { + public Map getSubcommands() { return subcommands; } public static final Builder COMMAND_INFO_BUILDER = new Builder() { @Override public CommandInfo build(Object data) { + if (data == null) { + return null; + } + List commandData = (List) data; + if (commandData.isEmpty()) { + return null; + } + String name = STRING.build(commandData.get(0)); long arity = LONG.build(commandData.get(1)); List flags = STRING_LIST.build(commandData.get(2)); long firstKey = LONG.build(commandData.get(3)); @@ -105,9 +137,31 @@ public CommandInfo build(Object data) { long step = LONG.build(commandData.get(5)); List aclCategories = STRING_LIST.build(commandData.get(6)); List tips = STRING_LIST.build(commandData.get(7)); - List subcommands = STRING_LIST.build(commandData.get(9)); + Map subcommands = COMMAND_INFO_RESPONSE.build(commandData.get(9)); + + return new CommandInfo(name, arity, flags, firstKey, lastKey, step, aclCategories, tips, subcommands); + } + }; - return new CommandInfo(arity, flags, firstKey, lastKey, step, aclCategories, tips, subcommands); + public static final Builder> COMMAND_INFO_RESPONSE = new Builder>() { + @Override + public Map build(Object data) { + if (data == null) { + return null; + } + + List rawList = (List) data; + Map map = new HashMap<>(rawList.size()); + + for (Object rawCommandInfo : rawList) { + CommandInfo info = CommandInfo.COMMAND_INFO_BUILDER.build(rawCommandInfo); + if (info != null) { + map.put(info.getName(), info); + } + } + + return map; } }; + } diff --git a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java index 4c9059f8d0..4b67a295c7 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/ControlCommandsTest.java @@ -520,6 +520,27 @@ public void commandInfo() { assertEquals(0, setInfo.getSubcommands().size()); } + @Test // GitHub Issue #4020 + public void commandInfoAcl() { + Map infos = jedis.commandInfo("ACL"); + assertThat(infos, Matchers.aMapWithSize(1)); + + CommandInfo aclInfo = infos.get("acl"); + assertEquals(-2, aclInfo.getArity()); + assertEquals(0, aclInfo.getFlags().size()); + assertEquals(0, aclInfo.getFirstKey()); + assertEquals(0, aclInfo.getLastKey()); + assertEquals(0, aclInfo.getStep()); + assertEquals(1, aclInfo.getAclCategories().size()); + assertEquals(0, aclInfo.getTips().size()); + assertThat(aclInfo.getSubcommands().size(), Matchers.greaterThanOrEqualTo(13)); + aclInfo.getSubcommands().forEach((name, subcommand) -> { + assertThat(name, Matchers.startsWith("acl|")); + assertNotNull(subcommand); + assertEquals(name, subcommand.getName()); + }); + } + @Test public void commandList() { List commands = jedis.commandList();