From 8e3b29d22e62556a04a8a3103170a8e1977a0849 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Wed, 28 Jun 2017 10:54:10 +0200 Subject: [PATCH] Split ParsedArgument into fixed or dynamic, added copy methods for caching contexts --- .../arguments/IntegerArgumentType.java | 3 +- .../brigadier/context/CommandContext.java | 7 ++ .../context/DynamicParsedArgument.java | 54 +++++++++++++++ .../context/FixedParsedArgument.java | 46 +++++++++++++ .../brigadier/context/ParsedArgument.java | 38 ++--------- .../brigadier/context/CommandContextTest.java | 21 ++++++ .../context/DynamicParsedArgumentTest.java | 67 +++++++++++++++++++ .../context/FixedParsedArgumentTest.java | 27 ++++++++ .../brigadier/context/ParsedArgumentTest.java | 15 ----- 9 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/mojang/brigadier/context/DynamicParsedArgument.java create mode 100644 src/main/java/com/mojang/brigadier/context/FixedParsedArgument.java create mode 100644 src/test/java/com/mojang/brigadier/context/DynamicParsedArgumentTest.java create mode 100644 src/test/java/com/mojang/brigadier/context/FixedParsedArgumentTest.java delete mode 100644 src/test/java/com/mojang/brigadier/context/ParsedArgumentTest.java diff --git a/src/main/java/com/mojang/brigadier/arguments/IntegerArgumentType.java b/src/main/java/com/mojang/brigadier/arguments/IntegerArgumentType.java index 43bb9f4..d2da367 100644 --- a/src/main/java/com/mojang/brigadier/arguments/IntegerArgumentType.java +++ b/src/main/java/com/mojang/brigadier/arguments/IntegerArgumentType.java @@ -3,6 +3,7 @@ package com.mojang.brigadier.arguments; import com.google.common.base.Splitter; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.context.FixedParsedArgument; import com.mojang.brigadier.context.ParsedArgument; import com.mojang.brigadier.exceptions.CommandException; import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType; @@ -54,7 +55,7 @@ public class IntegerArgumentType implements CommandArgumentType { throw ERROR_TOO_BIG.create(value, maximum); } - return new ParsedArgument<>(raw, value); + return new FixedParsedArgument<>(raw, value); } catch (NumberFormatException ignored) { throw ERROR_NOT_A_NUMBER.create(raw); } diff --git a/src/main/java/com/mojang/brigadier/context/CommandContext.java b/src/main/java/com/mojang/brigadier/context/CommandContext.java index 30ad752..e2705ac 100644 --- a/src/main/java/com/mojang/brigadier/context/CommandContext.java +++ b/src/main/java/com/mojang/brigadier/context/CommandContext.java @@ -2,6 +2,7 @@ package com.mojang.brigadier.context; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; import com.google.common.primitives.Primitives; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; @@ -78,4 +79,10 @@ public class CommandContext { public Map, String> getNodes() { return nodes; } + + public CommandContext copy() { + Map> arguments = Maps.newHashMap(); + this.arguments.forEach((k, v) -> arguments.put(k, v.copy())); + return new CommandContext<>(source, arguments, command, nodes); + } } diff --git a/src/main/java/com/mojang/brigadier/context/DynamicParsedArgument.java b/src/main/java/com/mojang/brigadier/context/DynamicParsedArgument.java new file mode 100644 index 0000000..4edb165 --- /dev/null +++ b/src/main/java/com/mojang/brigadier/context/DynamicParsedArgument.java @@ -0,0 +1,54 @@ +package com.mojang.brigadier.context; + +import java.util.function.Supplier; + +public class DynamicParsedArgument implements ParsedArgument { + private final String raw; + private Supplier supplier; + private boolean evaluated; + private T result; + + public DynamicParsedArgument(String raw, Supplier supplier) { + this.raw = raw; + this.supplier = supplier; + } + + @Override + public String getRaw() { + return raw; + } + + @Override + public T getResult() { + if (!evaluated) { + result = supplier.get(); + evaluated = true; + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DynamicParsedArgument)) return false; + + DynamicParsedArgument that = (DynamicParsedArgument) o; + + if (!raw.equals(that.raw)) return false; + if (!supplier.equals(that.supplier)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = raw.hashCode(); + result = 31 * result + supplier.hashCode(); + return result; + } + + @Override + public ParsedArgument copy() { + return new DynamicParsedArgument<>(raw, supplier); + } +} diff --git a/src/main/java/com/mojang/brigadier/context/FixedParsedArgument.java b/src/main/java/com/mojang/brigadier/context/FixedParsedArgument.java new file mode 100644 index 0000000..4d54931 --- /dev/null +++ b/src/main/java/com/mojang/brigadier/context/FixedParsedArgument.java @@ -0,0 +1,46 @@ +package com.mojang.brigadier.context; + +public class FixedParsedArgument implements ParsedArgument { + private final String raw; + private final T result; + + public FixedParsedArgument(String raw, T result) { + this.raw = raw; + this.result = result; + } + + @Override + public String getRaw() { + return raw; + } + + @Override + public T getResult() { + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof FixedParsedArgument)) return false; + + FixedParsedArgument that = (FixedParsedArgument) o; + + if (!raw.equals(that.raw)) return false; + if (!result.equals(that.result)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = raw.hashCode(); + result = 31 * result + this.result.hashCode(); + return result; + } + + @Override + public ParsedArgument copy() { + return new FixedParsedArgument<>(raw, result); + } +} diff --git a/src/main/java/com/mojang/brigadier/context/ParsedArgument.java b/src/main/java/com/mojang/brigadier/context/ParsedArgument.java index 7d4ed3a..578888b 100644 --- a/src/main/java/com/mojang/brigadier/context/ParsedArgument.java +++ b/src/main/java/com/mojang/brigadier/context/ParsedArgument.java @@ -1,39 +1,9 @@ package com.mojang.brigadier.context; -public class ParsedArgument { - private final String raw; - private final T result; +public interface ParsedArgument { + String getRaw(); - public ParsedArgument(String raw, T result) { - this.raw = raw; - this.result = result; - } + T getResult(); - public String getRaw() { - return raw; - } - - public T getResult() { - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ParsedArgument)) return false; - - ParsedArgument that = (ParsedArgument) o; - - if (!raw.equals(that.raw)) return false; - if (!result.equals(that.result)) return false; - - return true; - } - - @Override - public int hashCode() { - int result1 = raw.hashCode(); - result1 = 31 * result1 + result.hashCode(); - return result1; - } + ParsedArgument copy(); } diff --git a/src/test/java/com/mojang/brigadier/context/CommandContextTest.java b/src/test/java/com/mojang/brigadier/context/CommandContextTest.java index ca29ee6..a680584 100644 --- a/src/test/java/com/mojang/brigadier/context/CommandContextTest.java +++ b/src/test/java/com/mojang/brigadier/context/CommandContextTest.java @@ -9,12 +9,17 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import java.util.function.Supplier; + import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class CommandContextTest { @@ -74,4 +79,20 @@ public class CommandContextTest { assertThat(context.getInput(), is("foo 100 baz")); } + + @Test + public void testCopy() throws Exception { + Object first = new Object(); + Object second = new Object(); + @SuppressWarnings("unchecked") Supplier supplier = (Supplier) mock(Supplier.class); + + when(supplier.get()).thenReturn(first); + CommandContext context = builder.withNode(literal("test").build(), "test").withArgument("test", new DynamicParsedArgument<>("test", supplier)).build(); + assertThat(context.getArgument("test", Object.class).getResult(), is(first)); + + when(supplier.get()).thenReturn(second); + CommandContext copy = context.copy(); + assertThat(context, is(equalTo(copy))); + assertThat(copy.getArgument("test", Object.class).getResult(), is(second)); + } } \ No newline at end of file diff --git a/src/test/java/com/mojang/brigadier/context/DynamicParsedArgumentTest.java b/src/test/java/com/mojang/brigadier/context/DynamicParsedArgumentTest.java new file mode 100644 index 0000000..f7ce6f5 --- /dev/null +++ b/src/test/java/com/mojang/brigadier/context/DynamicParsedArgumentTest.java @@ -0,0 +1,67 @@ +package com.mojang.brigadier.context; + +import com.google.common.testing.EqualsTester; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.function.Supplier; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DynamicParsedArgumentTest { + private DynamicParsedArgument subject; + @Mock + private Supplier supplier; + + @Before + public void setUp() throws Exception { + subject = new DynamicParsedArgument<>("raw", supplier); + } + + @Test + public void suppliedOnce() throws Exception { + Object result = new Object(); + when(supplier.get()).thenReturn(result); + + assertThat("first evaluation", subject.getResult(), is(result)); + assertThat("already evaluated", subject.getResult(), is(result)); + + verify(supplier, times(1)).get(); + } + + @Test + public void copy() throws Exception { + Object result = new Object(); + when(supplier.get()).thenReturn(result); + assertThat(subject.getResult(), is(result)); + + Object newResult = new Object(); + when(supplier.get()).thenReturn(newResult); + ParsedArgument copy = subject.copy(); + assertThat(copy.getResult(), is(newResult)); + + assertThat(copy, is(equalTo(subject))); + + verify(supplier, times(2)).get(); + } + + @Test + public void testEquals() throws Exception { + new EqualsTester() + .addEqualityGroup(new FixedParsedArgument<>("foo", "bar"), new FixedParsedArgument<>("foo", "bar")) + .addEqualityGroup(new FixedParsedArgument<>("bar", "baz"), new FixedParsedArgument<>("bar", "baz")) + .addEqualityGroup(new FixedParsedArgument<>("foo", "baz"), new FixedParsedArgument<>("foo", "baz")) + .testEquals(); + } +} \ No newline at end of file diff --git a/src/test/java/com/mojang/brigadier/context/FixedParsedArgumentTest.java b/src/test/java/com/mojang/brigadier/context/FixedParsedArgumentTest.java new file mode 100644 index 0000000..502a6b8 --- /dev/null +++ b/src/test/java/com/mojang/brigadier/context/FixedParsedArgumentTest.java @@ -0,0 +1,27 @@ +package com.mojang.brigadier.context; + +import com.google.common.testing.EqualsTester; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class FixedParsedArgumentTest { + @Test + public void testEquals() throws Exception { + new EqualsTester() + .addEqualityGroup(new FixedParsedArgument<>("foo", "bar"), new FixedParsedArgument<>("foo", "bar")) + .addEqualityGroup(new FixedParsedArgument<>("bar", "baz"), new FixedParsedArgument<>("bar", "baz")) + .addEqualityGroup(new FixedParsedArgument<>("foo", "baz"), new FixedParsedArgument<>("foo", "baz")) + .testEquals(); + } + + @Test + public void copy() throws Exception { + final FixedParsedArgument argument = new FixedParsedArgument<>("foo", "bar"); + assertThat(argument.copy(), is(equalTo(argument))); + } +} \ No newline at end of file diff --git a/src/test/java/com/mojang/brigadier/context/ParsedArgumentTest.java b/src/test/java/com/mojang/brigadier/context/ParsedArgumentTest.java deleted file mode 100644 index e50bb08..0000000 --- a/src/test/java/com/mojang/brigadier/context/ParsedArgumentTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mojang.brigadier.context; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; - -public class ParsedArgumentTest { - @Test - public void testEquals() throws Exception { - new EqualsTester() - .addEqualityGroup(new ParsedArgument<>("foo", "bar"), new ParsedArgument<>("foo", "bar")) - .addEqualityGroup(new ParsedArgument<>("bar", "baz"), new ParsedArgument<>("bar", "baz")) - .addEqualityGroup(new ParsedArgument<>("foo", "baz"), new ParsedArgument<>("foo", "baz")) - .testEquals(); - } -} \ No newline at end of file