From d57cdee98ed8a105529959a69bc3668f34153136 Mon Sep 17 00:00:00 2001 From: mohammed-eladly-afaqy Date: Tue, 15 Oct 2019 22:30:28 +0200 Subject: [PATCH 1/3] pass specific Gson, and cast Json Object to specific POJO --- .../com/redislabs/modules/rejson/JReJSON.java | 481 ++++++++++-------- .../modules/rejson/GsonClientTest.java | 68 +++ 2 files changed, 337 insertions(+), 212 deletions(-) create mode 100644 src/test/java/com/redislabs/modules/rejson/GsonClientTest.java diff --git a/src/main/java/com/redislabs/modules/rejson/JReJSON.java b/src/main/java/com/redislabs/modules/rejson/JReJSON.java index c11ac1a..1ff76bc 100644 --- a/src/main/java/com/redislabs/modules/rejson/JReJSON.java +++ b/src/main/java/com/redislabs/modules/rejson/JReJSON.java @@ -29,7 +29,6 @@ package com.redislabs.modules.rejson; import com.google.gson.Gson; - import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.commands.ProtocolCommand; @@ -44,72 +43,44 @@ */ public class JReJSON { - private static final Gson gson = new Gson(); - - private enum Command implements ProtocolCommand { - DEL("JSON.DEL"), - GET("JSON.GET"), - SET("JSON.SET"), - TYPE("JSON.TYPE"); - private final byte[] raw; - - Command(String alt) { - raw = SafeEncoder.encode(alt); - } - - public byte[] getRaw() { - return raw; - } - } + private static Gson gson; + private Pool client; - /** - * Existential modifier for the set command, by default we don't care - */ - public enum ExistenceModifier implements ProtocolCommand { - DEFAULT(""), - NOT_EXISTS("NX"), - MUST_EXIST("XX"); - private final byte[] raw; - - ExistenceModifier(String alt) { - raw = SafeEncoder.encode(alt); - } - - public byte[] getRaw() { - return raw; - } - } - - private Pool client; - /** * Creates a client to the local machine */ public JReJSON() { this("localhost", 6379); + gson = new Gson(); } - + /** * Creates a client to the specific host/post - * + * * @param host Redis host * @param port Redis port */ - public JReJSON(String host, int port) { + public JReJSON(String host, int port, Gson gson) { this(new JedisPool(host, port)); + JReJSON.gson = gson; } - + /** * Creates a client using provided Jedis pool - * + * * @param jedis bring your own Jedis pool */ public JReJSON(Pool jedis) { this.client = jedis; } + public JReJSON(String host, int port) { + this(new JedisPool(host, port)); + } + /** - * Helper to check for errors and throw them as an exception + * Helper to check for errors and throw them as an exception + * * @param str the reply string to "analyze" * @throws RuntimeException */ @@ -120,6 +91,7 @@ private static void assertReplyNotError(final String str) { /** * Helper to check for an OK reply + * * @param str the reply string to "scrutinize" */ private static void assertReplyOK(final String str) { @@ -129,6 +101,7 @@ private static void assertReplyOK(final String str) { /** * Helper to handle single optional path argument situations + * * @param path a single optional path * @return the provided path or root if not */ @@ -140,154 +113,129 @@ private static Path getSingleOptionalPath(Path... path) { if (1 == path.length) { // take 1 return path[0]; } - + // throw out the baby with the water throw new RuntimeException("Only a single optional path is allowed"); } - /** - * Deletes the root path - * @param key the key name - * @return the number of paths deleted (0 or 1) - */ - public Long del(String key) { - return del(key, Path.ROOT_PATH); - } - - /** * Deletes a path - * @param key the key name + * + * @param conn the Jedis connection + * @param key the key name * @param path optional single path in the object, defaults to root - * @return path deleted - */ - public Long del(String key, Path path) { - byte[][] args = new byte[2][]; - args[0] = SafeEncoder.encode(key); - args[1] = SafeEncoder.encode(path.toString()); - - try (Jedis conn = getConnection()) { - conn.getClient().sendCommand(Command.DEL, args); - return conn.getClient().getIntegerReply(); - } - } - - /** - * Gets an object at the root path - * @param key the key name - * @return the requested object + * @return the number of paths deleted (0 or 1) + * @deprecated use {@link #del(String, Path)} instead */ - public T get(String key) { - return get(key, Path.ROOT_PATH); + @Deprecated + public static Long del(Jedis conn, String key, Path... path) { + + List args = new ArrayList<>(2); + + args.add(SafeEncoder.encode(key)); + args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); + + conn.getClient() + .sendCommand(Command.DEL, args.toArray(new byte[args.size()][])); + Long rep = conn.getClient().getIntegerReply(); + conn.close(); + + return rep; } - + /** * Gets an object - * @param key the key name - * @param paths optional one ore more paths in the object + * + * @param conn the Jedis connection + * @param key the key name + * @param paths optional one ore more paths in the object, defaults to root * @return the requested object + * @deprecated use {@link #get(String, Path...)} instead */ - public T get(String key, Path... paths) { - byte[][] args = new byte[1 + paths.length][]; - int i=0; - args[i] = SafeEncoder.encode(key); - for (Path p :paths) { - args[++i] = SafeEncoder.encode(p.toString()); + @Deprecated + public static Object get(Jedis conn, String key, Path... paths) { + + List args = new ArrayList<>(2); + + args.add(SafeEncoder.encode(key)); + for (Path p : paths) { + args.add(SafeEncoder.encode(p.toString())); } - String rep; - try (Jedis conn = getConnection()) { - conn.getClient().sendCommand(Command.GET, args); - rep = conn.getClient().getBulkReply(); - } - assertReplyNotError(rep); - return (T)gson.fromJson(rep, Object.class); - } + conn.getClient() + .sendCommand(Command.GET, args.toArray(new byte[args.size()][])); + String rep = conn.getClient().getBulkReply(); + conn.close(); - /** - * Sets an object at the root path - * @param key the key name - * @param object the Java object to store - * @param flag an existential modifier - */ - public void set(String key, Object object, ExistenceModifier flag) { - set(key, object, flag, Path.ROOT_PATH); - } - - /** - * Sets an object in the root path - * @param key the key name - * @param object the Java object to store - */ - public void set(String key, Object object) { - set(key, object, ExistenceModifier.DEFAULT, Path.ROOT_PATH); - } - - /** - * Sets an object without caring about target path existing - * @param key the key name - * @param object the Java object to store - * @param path in the object - */ - public void set(String key, Object object, Path path) { - set(key, object, ExistenceModifier.DEFAULT, path); + assertReplyNotError(rep); + return gson.fromJson(rep, Object.class); } - + /** * Sets an object - * @param key the key name + * + * @param conn the Jedis connection + * @param key the key name * @param object the Java object to store - * @param flag an existential modifier - * @param path in the object + * @param flag an existential modifier + * @param path optional single path in the object, defaults to root + * @deprecated use {@link #set(String, Object, ExistenceModifier, Path)} instead */ - public void set(String key, Object object, ExistenceModifier flag, Path path) { + @Deprecated + public static void set(Jedis conn, String key, Object object, ExistenceModifier flag, Path... path) { List args = new ArrayList<>(4); args.add(SafeEncoder.encode(key)); - args.add(SafeEncoder.encode(path.toString())); + args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); args.add(SafeEncoder.encode(gson.toJson(object))); if (ExistenceModifier.DEFAULT != flag) { args.add(flag.getRaw()); } - String status; - try (Jedis conn = getConnection()) { - conn.getClient() - .sendCommand(Command.SET, args.toArray(new byte[args.size()][])); - status = conn.getClient().getStatusCodeReply(); - } + conn.getClient() + .sendCommand(Command.SET, args.toArray(new byte[args.size()][])); + String status = conn.getClient().getStatusCodeReply(); + conn.close(); + assertReplyOK(status); } - + /** - * Gets the class of an object at the root path - * @param key the key name - * @return the Java class of the requested object + * Sets an object without caring about target path existing + * + * @param conn the Jedis connection + * @param key the key name + * @param object the Java object to store + * @param path optional single path in the object, defaults to root + * @deprecated use {@link #set(String, Object, ExistenceModifier, Path)} instead */ - public Class type(String key) { - return type(key); + @Deprecated + public static void set(Jedis conn, String key, Object object, Path... path) { + set(conn, key, object, ExistenceModifier.DEFAULT, path); } - + /** * Gets the class of an object - * @param key the key name - * @param path a path in the object + * + * @param conn the Jedis connection + * @param key the key name + * @param path optional single path in the object, defaults to root * @return the Java class of the requested object + * @deprecated use {@link #type(String, Path)} instead */ - public Class type(String key, Path path) { + @Deprecated + public static Class type(Jedis conn, String key, Path... path) { List args = new ArrayList<>(2); args.add(SafeEncoder.encode(key)); - args.add(SafeEncoder.encode(path.toString())); + args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); - String rep; - try (Jedis conn = getConnection()) { - conn.getClient() + conn.getClient() .sendCommand(Command.TYPE, args.toArray(new byte[args.size()][])); - rep = conn.getClient().getBulkReply(); - } + String rep = conn.getClient().getBulkReply(); + conn.close(); assertReplyNotError(rep); @@ -310,121 +258,196 @@ public Class type(String key, Path path) { throw new java.lang.RuntimeException(rep); } } - /** - * Deletes a path - * @param conn the Jedis connection + * Deletes the root path + * * @param key the key name - * @param path optional single path in the object, defaults to root * @return the number of paths deleted (0 or 1) - * @deprecated use {@link #del(String, Path)} instead */ - @Deprecated - public static Long del(Jedis conn, String key, Path... path) { - - List args = new ArrayList<>(2); + public Long del(String key) { + return del(key, Path.ROOT_PATH); + } - args.add(SafeEncoder.encode(key)); - args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); + /** + * Deletes a path + * + * @param key the key name + * @param path optional single path in the object, defaults to root + * @return path deleted + */ + public Long del(String key, Path path) { + byte[][] args = new byte[2][]; + args[0] = SafeEncoder.encode(key); + args[1] = SafeEncoder.encode(path.toString()); - conn.getClient() - .sendCommand(Command.DEL, args.toArray(new byte[args.size()][])); - Long rep = conn.getClient().getIntegerReply(); - conn.close(); + try (Jedis conn = getConnection()) { + conn.getClient().sendCommand(Command.DEL, args); + return conn.getClient().getIntegerReply(); + } + } - return rep; + /** + * Gets an object at the root path + * + * @param key the key name + * @return the requested object + */ + public T get(String key) { + return get(key, Path.ROOT_PATH); } + /** - * Gets an object - * @param conn the Jedis connection + * Gets casted object at the root path + * * @param key the key name - * @param paths optional one ore more paths in the object, defaults to root * @return the requested object - * @deprecated use {@link #get(String, Path...)} instead */ - @Deprecated - public static Object get(Jedis conn, String key, Path... paths) { + public T get(String key, Class tClass) { + return get(key, tClass, Path.ROOT_PATH); + } - List args = new ArrayList<>(2); + /** + * Gets an object + * + * @param key the key name + * @param paths optional one ore more paths in the object + * @return the requested object + */ + public T get(String key, Path... paths) { + byte[][] args = new byte[1 + paths.length][]; + int i = 0; + args[i] = SafeEncoder.encode(key); + for (Path p : paths) { + args[++i] = SafeEncoder.encode(p.toString()); + } - args.add(SafeEncoder.encode(key)); - for (Path p :paths) { - args.add(SafeEncoder.encode(p.toString())); + String rep; + try (Jedis conn = getConnection()) { + conn.getClient().sendCommand(Command.GET, args); + rep = conn.getClient().getBulkReply(); } + assertReplyNotError(rep); + return (T) gson.fromJson(rep, Object.class); + } - conn.getClient() - .sendCommand(Command.GET, args.toArray(new byte[args.size()][])); - String rep = conn.getClient().getBulkReply(); - conn.close(); + /** + * Get casted Object + * + * @param key + * @param tClass + * @param paths + * @param + * @return + */ + public T get(String key, Class tClass, Path... paths) { + byte[][] args = new byte[1 + paths.length][]; + int i = 0; + args[i] = SafeEncoder.encode(key); + for (Path p : paths) { + args[++i] = SafeEncoder.encode(p.toString()); + } + String rep; + try (Jedis conn = getConnection()) { + conn.getClient().sendCommand(Command.GET, args); + rep = conn.getClient().getBulkReply(); + } assertReplyNotError(rep); - return gson.fromJson(rep, Object.class); + return gson.fromJson(rep, tClass); + } + + /** + * Sets an object at the root path + * + * @param key the key name + * @param object the Java object to store + * @param flag an existential modifier + */ + public void set(String key, Object object, ExistenceModifier flag) { + set(key, object, flag, Path.ROOT_PATH); + } + + /** + * Sets an object in the root path + * + * @param key the key name + * @param object the Java object to store + */ + public void set(String key, Object object) { + set(key, object, ExistenceModifier.DEFAULT, Path.ROOT_PATH); + } + + /** + * Sets an object without caring about target path existing + * + * @param key the key name + * @param object the Java object to store + * @param path in the object + */ + public void set(String key, Object object, Path path) { + set(key, object, ExistenceModifier.DEFAULT, path); } /** * Sets an object - * @param conn the Jedis connection - * @param key the key name + * + * @param key the key name * @param object the Java object to store - * @param flag an existential modifier - * @param path optional single path in the object, defaults to root - * @deprecated use {@link #set(String, Object, ExistenceModifier, Path)} instead + * @param flag an existential modifier + * @param path in the object */ - @Deprecated - public static void set(Jedis conn, String key, Object object, ExistenceModifier flag, Path... path) { + public void set(String key, Object object, ExistenceModifier flag, Path path) { List args = new ArrayList<>(4); args.add(SafeEncoder.encode(key)); - args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); + args.add(SafeEncoder.encode(path.toString())); args.add(SafeEncoder.encode(gson.toJson(object))); if (ExistenceModifier.DEFAULT != flag) { args.add(flag.getRaw()); } - conn.getClient() - .sendCommand(Command.SET, args.toArray(new byte[args.size()][])); - String status = conn.getClient().getStatusCodeReply(); - conn.close(); - + String status; + try (Jedis conn = getConnection()) { + conn.getClient() + .sendCommand(Command.SET, args.toArray(new byte[args.size()][])); + status = conn.getClient().getStatusCodeReply(); + } assertReplyOK(status); } /** - * Sets an object without caring about target path existing - * @param conn the Jedis connection + * Gets the class of an object at the root path + * * @param key the key name - * @param object the Java object to store - * @param path optional single path in the object, defaults to root - * @deprecated use {@link #set(String, Object, ExistenceModifier, Path)} instead + * @return the Java class of the requested object */ - @Deprecated - public static void set(Jedis conn, String key, Object object, Path... path) { - set(conn,key, object, ExistenceModifier.DEFAULT, path); + public Class type(String key) { + return type(key); } - + /** * Gets the class of an object - * @param conn the Jedis connection - * @param key the key name - * @param path optional single path in the object, defaults to root + * + * @param key the key name + * @param path a path in the object * @return the Java class of the requested object - * @deprecated use {@link #type(String, Path)} instead */ - @Deprecated - public static Class type(Jedis conn, String key, Path... path) { + public Class type(String key, Path path) { List args = new ArrayList<>(2); args.add(SafeEncoder.encode(key)); - args.add(SafeEncoder.encode(getSingleOptionalPath(path).toString())); + args.add(SafeEncoder.encode(path.toString())); - conn.getClient() - .sendCommand(Command.TYPE, args.toArray(new byte[args.size()][])); - String rep = conn.getClient().getBulkReply(); - conn.close(); + String rep; + try (Jedis conn = getConnection()) { + conn.getClient() + .sendCommand(Command.TYPE, args.toArray(new byte[args.size()][])); + rep = conn.getClient().getBulkReply(); + } assertReplyNotError(rep); @@ -447,8 +470,42 @@ public static Class type(Jedis conn, String key, Path... path) { throw new java.lang.RuntimeException(rep); } } - + private Jedis getConnection() { return this.client.getResource(); } + + private enum Command implements ProtocolCommand { + DEL("JSON.DEL"), + GET("JSON.GET"), + SET("JSON.SET"), + TYPE("JSON.TYPE"); + private final byte[] raw; + + Command(String alt) { + raw = SafeEncoder.encode(alt); + } + + public byte[] getRaw() { + return raw; + } + } + + /** + * Existential modifier for the set command, by default we don't care + */ + public enum ExistenceModifier implements ProtocolCommand { + DEFAULT(""), + NOT_EXISTS("NX"), + MUST_EXIST("XX"); + private final byte[] raw; + + ExistenceModifier(String alt) { + raw = SafeEncoder.encode(alt); + } + + public byte[] getRaw() { + return raw; + } + } } diff --git a/src/test/java/com/redislabs/modules/rejson/GsonClientTest.java b/src/test/java/com/redislabs/modules/rejson/GsonClientTest.java new file mode 100644 index 0000000..d4586f4 --- /dev/null +++ b/src/test/java/com/redislabs/modules/rejson/GsonClientTest.java @@ -0,0 +1,68 @@ +package com.redislabs.modules.rejson; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Name : GsonClientTest + *

+ * Description : Passing Specific Gson + *

+ * Date : 15/10/2019 + *

+ * Create by : Mohammed ElAdly + */ +public class GsonClientTest { + + static JReJSON client; + static Gson gson; + + @BeforeClass + public static void setUp() { + + + GsonBuilder gsonBuilder = new GsonBuilder(); + + gson = gsonBuilder.create(); + + client = new JReJSON("localhost", 7001, gson); + } + + @Test + public void passSpecificGson() { + + client.set("personObj", new Person()); + + Object personObj = client.get("personObj"); + Person personObj1 = client.get("personObj", Person.class); + + System.out.println("Object:" + personObj); + + String personObj2 = client.get("personObj", new Path(".name")).toString(); + System.out.println(personObj2); + + System.out.println("Casted Object: " + personObj1); + + + } + + private static class Person { + public String name; + public int age; + + public Person() { + this.name = "Mohammed ElAdly"; + this.age = 27; + } + + @Override + public String toString() { + return "Person{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } + } +} \ No newline at end of file From 74bc30ffeedf5a2789cb3eb3511292d63d4bd29b Mon Sep 17 00:00:00 2001 From: Mohammed ElAdly <52999400+mohammed-eladly-afaqy@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:14:10 +0200 Subject: [PATCH 2/3] Set theme jekyll-theme-merlot --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c50ff38 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-merlot \ No newline at end of file From 340618433cdeb94e229485c3b6646dcd95817b83 Mon Sep 17 00:00:00 2001 From: Mohammed ElAdly <52999400+mohammed-eladly-afaqy@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:15:46 +0200 Subject: [PATCH 3/3] Set theme jekyll-theme-slate --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index c50ff38..c741881 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-merlot \ No newline at end of file +theme: jekyll-theme-slate \ No newline at end of file