From fd9856c474e177e00d05f1f5eb009911b81ae2f3 Mon Sep 17 00:00:00 2001 From: Adrian Todt Date: Wed, 4 Mar 2020 20:33:34 -0300 Subject: [PATCH] New Types utility class, which replaces generated classes just to get simple type information. --- src/main/java/com/rethinkdb/ast/ReqlAst.java | 36 ++--- src/main/java/com/rethinkdb/net/Util.java | 3 +- src/main/java/com/rethinkdb/utils/Types.java | 131 ++++++++++++++++++ .../java/com/rethinkdb/RethinkDBTest.java | 61 ++++---- 4 files changed, 168 insertions(+), 63 deletions(-) create mode 100644 src/main/java/com/rethinkdb/utils/Types.java diff --git a/src/main/java/com/rethinkdb/ast/ReqlAst.java b/src/main/java/com/rethinkdb/ast/ReqlAst.java index a426a112..dece91ad 100644 --- a/src/main/java/com/rethinkdb/ast/ReqlAst.java +++ b/src/main/java/com/rethinkdb/ast/ReqlAst.java @@ -9,8 +9,8 @@ import com.rethinkdb.model.OptArgs; import com.rethinkdb.net.Connection; import com.rethinkdb.net.Result; +import com.rethinkdb.utils.Types; -import java.lang.reflect.Type; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; @@ -95,7 +95,7 @@ public Result run(Connection conn, Result.FetchMode fetchMode) { * @return The result of this query */ public Result run(Connection conn, Class typeRef) { - return conn.run(this, new OptArgs(), null, new ClassReference<>(typeRef)); + return conn.run(this, new OptArgs(), null, Types.of(typeRef)); } /** @@ -135,7 +135,7 @@ public Result run(Connection conn, OptArgs runOpts, Result.FetchMode fet * @return The result of this query */ public Result run(Connection conn, OptArgs runOpts, Class typeRef) { - return conn.run(this, runOpts, null, new ClassReference<>(typeRef)); + return conn.run(this, runOpts, null, Types.of(typeRef)); } /** @@ -163,7 +163,7 @@ public Result run(Connection conn, OptArgs runOpts, TypeReference type * @return The result of this query */ public Result run(Connection conn, Result.FetchMode fetchMode, Class typeRef) { - return conn.run(this, new OptArgs(), fetchMode, new ClassReference<>(typeRef)); + return conn.run(this, new OptArgs(), fetchMode, Types.of(typeRef)); } /** @@ -192,7 +192,7 @@ public Result run(Connection conn, Result.FetchMode fetchMode, TypeRefere * @return The result of this query */ public Result run(Connection conn, OptArgs runOpts, Result.FetchMode fetchMode, Class typeRef) { - return conn.run(this, runOpts, fetchMode, new ClassReference<>(typeRef)); + return conn.run(this, runOpts, fetchMode, Types.of(typeRef)); } /** @@ -254,7 +254,7 @@ public CompletableFuture> runAsync(Connection conn, Result.FetchM * @return The result of this query */ public CompletableFuture> runAsync(Connection conn, Class typeRef) { - return conn.runAsync(this, new OptArgs(), null, new ClassReference<>(typeRef)); + return conn.runAsync(this, new OptArgs(), null, Types.of(typeRef)); } /** @@ -294,7 +294,7 @@ public CompletableFuture> runAsync(Connection conn, OptArgs runOp * @return The result of this query */ public CompletableFuture> runAsync(Connection conn, OptArgs runOpts, Class typeRef) { - return conn.runAsync(this, runOpts, null, new ClassReference<>(typeRef)); + return conn.runAsync(this, runOpts, null, Types.of(typeRef)); } /** @@ -322,7 +322,7 @@ public CompletableFuture> runAsync(Connection conn, OptArgs runOpt * @return The result of this query */ public CompletableFuture> runAsync(Connection conn, Result.FetchMode fetchMode, Class typeRef) { - return conn.runAsync(this, new OptArgs(), fetchMode, new ClassReference<>(typeRef)); + return conn.runAsync(this, new OptArgs(), fetchMode, Types.of(typeRef)); } /** @@ -351,7 +351,7 @@ public CompletableFuture> runAsync(Connection conn, Result.FetchMo * @return The result of this query */ public CompletableFuture> runAsync(Connection conn, OptArgs runOpts, Result.FetchMode fetchMode, Class typeRef) { - return conn.runAsync(this, runOpts, fetchMode, new ClassReference<>(typeRef)); + return conn.runAsync(this, runOpts, fetchMode, Types.of(typeRef)); } /** @@ -438,22 +438,4 @@ private void astToString(StringBuilder builder, String name, String indent, bool } } } - - /** - * A TypeReference that accepts an class instead of compiler type information. - * - * @param the type referred to. - */ - private static class ClassReference extends TypeReference { - private Class c; - - ClassReference(Class c) { - this.c = c; - } - - @Override - public Type getType() { - return c; - } - } } \ No newline at end of file diff --git a/src/main/java/com/rethinkdb/net/Util.java b/src/main/java/com/rethinkdb/net/Util.java index 32c35126..cf97e6ab 100644 --- a/src/main/java/com/rethinkdb/net/Util.java +++ b/src/main/java/com/rethinkdb/net/Util.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.rethinkdb.RethinkDB; import com.rethinkdb.gen.exc.ReqlDriverError; +import com.rethinkdb.utils.Types; import java.io.IOException; import java.nio.ByteBuffer; @@ -11,7 +12,7 @@ import java.util.*; public class Util { - private static final TypeReference> mapTypeRef = new TypeReference>() {}; + private static final TypeReference> mapTypeRef = Types.mapOf(String.class, Object.class); private Util() {} diff --git a/src/main/java/com/rethinkdb/utils/Types.java b/src/main/java/com/rethinkdb/utils/Types.java new file mode 100644 index 00000000..3ac9079c --- /dev/null +++ b/src/main/java/com/rethinkdb/utils/Types.java @@ -0,0 +1,131 @@ +package com.rethinkdb.utils; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; +import java.util.stream.Collectors; + +/** + * An utility class that can create simple generic type references without having to grab information from the compiler. + */ +public class Types { + private Types() { + } + + public static TypeReference of(Class type) { + return new BuiltTypeRef<>(Objects.requireNonNull(type, "type")); + } + + public static TypeReference> listOf(Class type) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(List.class, Objects.requireNonNull(type, "type")) + ); + } + + public static TypeReference> listOf(TypeReference type) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(List.class, Objects.requireNonNull(type, "type").getType()) + ); + } + + public static TypeReference> setOf(Class type) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Set.class, Objects.requireNonNull(type, "type")) + ); + } + + public static TypeReference> setOf(TypeReference type) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Set.class, Objects.requireNonNull(type, "type").getType()) + ); + } + + public static TypeReference> mapOf(Class keyType, Class valueType) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Map.class, Objects.requireNonNull(keyType, "keyType"), Objects.requireNonNull(valueType, "valueType")) + ); + } + + public static TypeReference> mapOf(TypeReference keyType, Class valueType) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Map.class, Objects.requireNonNull(keyType, "keyType").getType(), Objects.requireNonNull(valueType, "valueType")) + ); + } + + public static TypeReference> mapOf(Class keyType, TypeReference valueType) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Map.class, Objects.requireNonNull(keyType, "keyType"), Objects.requireNonNull(valueType, "valueType").getType()) + ); + } + + public static TypeReference> mapOf(TypeReference keyType, TypeReference valueType) { + return new BuiltTypeRef<>( + new BuiltParametrizedType(Map.class, Objects.requireNonNull(keyType, "keyType").getType(), Objects.requireNonNull(valueType, "valueType").getType()) + ); + } + + private static class BuiltTypeRef extends TypeReference { + private final Type type; + + private BuiltTypeRef(Type type) { + this.type = type; + } + + @Override + public Type getType() { + return type; + } + } + + private static class BuiltParametrizedType implements ParameterizedType { + private final Class type; + private final Type[] params; + + public BuiltParametrizedType(Class type, Type... params) { + if (params.length != type.getTypeParameters().length) { + throw new MalformedParameterizedTypeException(); + } + this.type = type; + this.params = params; + } + + @Override + public Type[] getActualTypeArguments() { + return params.clone(); + } + + @Override + public Type getRawType() { + return type; + } + + @Override + public Type getOwnerType() { + return type.getDeclaringClass(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ParameterizedType)) return false; + ParameterizedType that = (ParameterizedType) o; + return Objects.equals(type, that.getRawType()) && + Objects.equals(type.getDeclaringClass(), that.getOwnerType()) && + Arrays.equals(params, that.getActualTypeArguments()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(params) ^ Objects.hashCode(type) ^ Objects.hashCode(type.getDeclaringClass()); + } + + @Override + public String toString() { + return type.getName() + Arrays.stream(params).map(Type::getTypeName) + .collect(Collectors.joining(", ", "<", ">")); + } + } +} diff --git a/src/test/java/com/rethinkdb/RethinkDBTest.java b/src/test/java/com/rethinkdb/RethinkDBTest.java index 0696c3a2..abc52b29 100644 --- a/src/test/java/com/rethinkdb/RethinkDBTest.java +++ b/src/test/java/com/rethinkdb/RethinkDBTest.java @@ -7,6 +7,7 @@ import com.rethinkdb.model.OptArgs; import com.rethinkdb.net.Connection; import com.rethinkdb.net.Result; +import com.rethinkdb.utils.Types; import net.jodah.concurrentunit.Waiter; import org.junit.*; import org.junit.rules.ExpectedException; @@ -24,6 +25,8 @@ import static org.junit.Assert.*; public class RethinkDBTest { + private static final TypeReference> stringList = Types.listOf(String.class); + private static final TypeReference> stringObjectMap = Types.mapOf(String.class, Object.class); public static final RethinkDB r = RethinkDB.r; Connection conn; @@ -156,67 +159,62 @@ public void testCoerceFailureInfinity() { @Test public void testSplitEdgeCases() { - TypeReference> typeRef = new TypeReference>() {}; - List emptySplitNothing = r.expr("").split().run(conn, typeRef).single(); + List emptySplitNothing = r.expr("").split().run(conn, stringList).single(); assertEquals(emptyList(), emptySplitNothing); - List nullSplit = r.expr("").split(null).run(conn, typeRef).single(); + List nullSplit = r.expr("").split(null).run(conn, stringList).single(); assertEquals(emptyList(), nullSplit); - List emptySplitSpace = r.expr("").split(" ").run(conn, typeRef).single(); + List emptySplitSpace = r.expr("").split(" ").run(conn, stringList).single(); assertEquals(singletonList(""), emptySplitSpace); - List emptySplitEmpty = r.expr("").split("").run(conn, typeRef).single(); + List emptySplitEmpty = r.expr("").split("").run(conn, stringList).single(); assertEquals(emptyList(), emptySplitEmpty); - List emptySplitNull5 = r.expr("").split(null, 5).run(conn, typeRef).single(); + List emptySplitNull5 = r.expr("").split(null, 5).run(conn, stringList).single(); assertEquals(emptyList(), emptySplitNull5); - List emptySplitSpace5 = r.expr("").split(" ", 5).run(conn, typeRef).single(); + List emptySplitSpace5 = r.expr("").split(" ", 5).run(conn, stringList).single(); assertEquals(singletonList(""), emptySplitSpace5); - List emptySplitEmpty5 = r.expr("").split("", 5).run(conn, typeRef).single(); + List emptySplitEmpty5 = r.expr("").split("", 5).run(conn, stringList).single(); assertEquals(emptyList(), emptySplitEmpty5); } @Test public void testSplitWithNullOrWhitespace() { - TypeReference> typeRef = new TypeReference>() {}; - List extraWhitespace = r.expr("aaaa bbbb cccc ").split().run(conn, typeRef).single(); + List extraWhitespace = r.expr("aaaa bbbb cccc ").split().run(conn, stringList).single(); assertEquals(Arrays.asList("aaaa", "bbbb", "cccc"), extraWhitespace); - List extraWhitespaceNull = r.expr("aaaa bbbb cccc ").split(null).run(conn, typeRef).single(); + List extraWhitespaceNull = r.expr("aaaa bbbb cccc ").split(null).run(conn, stringList).single(); assertEquals(Arrays.asList("aaaa", "bbbb", "cccc"), extraWhitespaceNull); - List extraWhitespaceSpace = r.expr("aaaa bbbb cccc ").split(" ").run(conn, typeRef).single(); + List extraWhitespaceSpace = r.expr("aaaa bbbb cccc ").split(" ").run(conn, stringList).single(); assertEquals(Arrays.asList("aaaa", "bbbb", "", "cccc", ""), extraWhitespaceSpace); - List extraWhitespaceEmpty = r.expr("aaaa bbbb cccc ").split("").run(conn, typeRef).single(); + List extraWhitespaceEmpty = r.expr("aaaa bbbb cccc ").split("").run(conn, stringList).single(); assertEquals(Arrays.asList("a", "a", "a", "a", " ", "b", "b", "b", "b", " ", " ", "c", "c", "c", "c", " "), extraWhitespaceEmpty); } @Test public void testSplitWithString() { - TypeReference> typeRef = new TypeReference>() {}; - List b = r.expr("aaaa bbbb cccc ").split("b").run(conn, typeRef).single(); + List b = r.expr("aaaa bbbb cccc ").split("b").run(conn, stringList).single(); assertEquals(Arrays.asList("aaaa ", "", "", "", " cccc "), b); } @Test public void testTableInsert() { - TypeReference> typeRef = new TypeReference>() {}; MapObject foo = r.hashMap("hi", "There") .with("yes", 7) .with("no", null); - Map result = r.db(dbName).table(tableName).insert(foo).run(conn, typeRef).single(); + Map result = r.db(dbName).table(tableName).insert(foo).run(conn, stringObjectMap).single(); assertNotNull(result); assertEquals(1L, result.get("inserted")); } @Test public void testDbGlobalArgInserted() { - TypeReference> typeRef = new TypeReference>() {}; final String tblName = "test_global_optargs"; try { @@ -234,25 +232,25 @@ public void testDbGlobalArgInserted() { try { // no optarg set, no default db conn.use(null); - Map x1 = r.table(tblName).get(1).run(conn, typeRef).single(); + Map x1 = r.table(tblName).get(1).run(conn, stringObjectMap).single(); assertNotNull(x1); assertEquals("test", x1.get("dbName")); // no optarg set, default db set conn.use("conn_default"); - Map x2 = r.table(tblName).get(1).run(conn, typeRef).single(); + Map x2 = r.table(tblName).get(1).run(conn, stringObjectMap).single(); assertNotNull(x2); assertEquals("conn_default", x2.get("dbName")); // optarg set, no default db conn.use(null); - Map x3 = r.table(tblName).get(1).run(conn, OptArgs.of("db", "optargs"), typeRef).single(); + Map x3 = r.table(tblName).get(1).run(conn, OptArgs.of("db", "optargs"), stringObjectMap).single(); assertNotNull(x3); assertEquals("optargs", x3.get("dbName")); // optarg set, default db conn.use("conn_default"); - Map x4 = r.table(tblName).get(1).run(conn, OptArgs.of("db", "optargs"), typeRef).single(); + Map x4 = r.table(tblName).get(1).run(conn, OptArgs.of("db", "optargs"), stringObjectMap).single(); assertNotNull(x4); assertEquals("optargs", x4.get("dbName")); @@ -289,10 +287,8 @@ public void testResultTryWithResources() { @Test public void testTableSelectOfPojo() { - TypeReference> typeRef = new TypeReference>() {}; - TestPojo pojo = new TestPojo("foo", new TestPojoInner(42L, true)); - Map pojoResult = r.db(dbName).table(tableName).insert(pojo).run(conn, typeRef).single(); + Map pojoResult = r.db(dbName).table(tableName).insert(pojo).run(conn, stringObjectMap).single(); assertNotNull(pojoResult); assertEquals(1L, pojoResult.get("inserted")); @@ -307,12 +303,10 @@ public void testTableSelectOfPojo() { @Test public void testTableSelectOfPojoSequence() { - TypeReference> typeRef = new TypeReference>() {}; - TestPojo pojoOne = new TestPojo("foo", new TestPojoInner(42L, true)); TestPojo pojoTwo = new TestPojo("bar", new TestPojoInner(53L, false)); - Map pojoOneResult = r.db(dbName).table(tableName).insert(pojoOne).run(conn, typeRef).single(); - Map pojoTwoResult = r.db(dbName).table(tableName).insert(pojoTwo).run(conn, typeRef).single(); + Map pojoOneResult = r.db(dbName).table(tableName).insert(pojoOne).run(conn, stringObjectMap).single(); + Map pojoTwoResult = r.db(dbName).table(tableName).insert(pojoTwo).run(conn, stringObjectMap).single(); assertNotNull(pojoOneResult); assertNotNull(pojoTwoResult); assertEquals(1L, pojoOneResult.get("inserted")); @@ -335,14 +329,13 @@ public void testTableSelectOfPojoSequence() { @Test(timeout = 40000) public void testConcurrentWrites() throws TimeoutException, InterruptedException { - TypeReference> typeRef = new TypeReference>() {}; final int total = 500; final AtomicInteger writeCounter = new AtomicInteger(0); final Waiter waiter = new Waiter(); for (int i = 0; i < total; i++) new Thread(() -> { final TestPojo pojo = new TestPojo("writezz", new TestPojoInner(10L, true)); - final Map result = r.db(dbName).table(tableName).insert(pojo).run(conn, typeRef).single(); + final Map result = r.db(dbName).table(tableName).insert(pojo).run(conn, stringObjectMap).single(); waiter.assertNotNull(result); waiter.assertEquals(1L, Objects.requireNonNull(result).get("inserted")); writeCounter.getAndIncrement(); @@ -356,14 +349,13 @@ public void testConcurrentWrites() throws TimeoutException, InterruptedException @Test(timeout = 20000) public void testConcurrentReads() throws TimeoutException, InterruptedException { - TypeReference> typeRef = new TypeReference>() {}; final int total = 500; final AtomicInteger readCounter = new AtomicInteger(0); // write to the database and retrieve the id final TestPojo pojo = new TestPojo("readzz", new TestPojoInner(10L, true)); final Map result = r.db(dbName).table(tableName).insert(pojo) - .optArg("return_changes", true).run(conn, typeRef).single(); + .optArg("return_changes", true).run(conn, stringObjectMap).single(); assertNotNull(result); final String id = ((List) result.get("generated_keys")).get(0).toString(); @@ -391,13 +383,12 @@ public void testConcurrentReads() throws TimeoutException, InterruptedException @Test(timeout = 20000) public void testConcurrentCursor() throws TimeoutException, InterruptedException { - TypeReference> typeRef = new TypeReference>() {}; final int total = 500; final Waiter waiter = new Waiter(); for (int i = 0; i < total; i++) new Thread(() -> { final TestPojo pojo = new TestPojo("writezz", new TestPojoInner(10L, true)); - final Map result = r.db(dbName).table(tableName).insert(pojo).run(conn, typeRef).single(); + final Map result = r.db(dbName).table(tableName).insert(pojo).run(conn, stringObjectMap).single(); waiter.assertNotNull(result); waiter.assertEquals(1L, Objects.requireNonNull(result).get("inserted")); waiter.resume();