From 2343fb989e8cb76cbc3b1a28241b25f87291d2ab Mon Sep 17 00:00:00 2001 From: Shailesh Mishra Date: Fri, 15 Dec 2023 00:48:32 +0530 Subject: [PATCH] v1.12.3 - Taxonomy query support - Early Access Feature Support --- .../java/com/contentstack/sdk/APIService.java | 4 +- .../java/com/contentstack/sdk/Taxonomy.java | 102 ++++++++---------- .../contentstack/sdk/TaxonomyCallback.java | 19 ---- .../com/contentstack/sdk/TaxonomyTest.java | 85 +++++++-------- 4 files changed, 91 insertions(+), 119 deletions(-) diff --git a/src/main/java/com/contentstack/sdk/APIService.java b/src/main/java/com/contentstack/sdk/APIService.java index a14af8e5..5bf3462b 100644 --- a/src/main/java/com/contentstack/sdk/APIService.java +++ b/src/main/java/com/contentstack/sdk/APIService.java @@ -4,7 +4,7 @@ import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.HeaderMap; -import retrofit2.http.QueryMap; +import retrofit2.http.Query; import retrofit2.http.Url; import java.util.LinkedHashMap; @@ -23,5 +23,5 @@ Call getRequest( @GET("v3/taxonomies/entries") Call getTaxonomy( @HeaderMap Map headers, - @QueryMap Map query); + @Query("query") String query); } diff --git a/src/main/java/com/contentstack/sdk/Taxonomy.java b/src/main/java/com/contentstack/sdk/Taxonomy.java index 207607f9..308f4188 100644 --- a/src/main/java/com/contentstack/sdk/Taxonomy.java +++ b/src/main/java/com/contentstack/sdk/Taxonomy.java @@ -1,36 +1,47 @@ package com.contentstack.sdk; -import okhttp3.Request; import okhttp3.ResponseBody; import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; import retrofit2.Call; -import retrofit2.Response; import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; +import java.util.LinkedHashMap; +import java.util.List; /** - * The type Taxonomy. - * - * @author Shailesh Mishra
Taxonomy :

Taxonomy, currently in the Early Access Phase simplifies the process of organizing content in your system, making it effortless to find and retrieve information. + * @author Shailesh Mishra + *
+ * Taxonomy : + * Taxonomy, currently in the Early Access Phase simplifies + * the process of organizing content in your system, making + * it effortless to find and retrieve information. + * @implSpec To implement the taxonomy use below code + *

+ *     {@code
+ *     Stack stack = Contentstack.stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT");
+ *     Taxonomy taxonomy = stack.taxonomy()
+ *     }
+ * 
+ * @see headers; protected APIService service; - protected HashMap query = new HashMap<>(); + protected JSONObject query = new JSONObject(); protected Config config; /** * Instantiates a new Taxonomy. * - * @param service the service - * @param config the config - * @param headers the headers + * @param service the service of type {@link APIService} + * @param config the config of type {@link Config} + * @param headers the headers of the {@link LinkedHashMap} */ - public Taxonomy(APIService service, Config config, LinkedHashMap headers) { + protected Taxonomy(APIService service, Config config, LinkedHashMap headers) { this.service = service; this.headers = headers; this.config = config; @@ -55,11 +66,10 @@ public Taxonomy(APIService service, Config config, LinkedHashMap * @param listOfItems the list of taxonomy fields * @return an instance of the Taxonomy with the specified conditions added to the query */ - public Taxonomy in(String taxonomy, String[] listOfItems) { - String formattedValues = Arrays.stream(listOfItems).map(value -> "\"" + value.trim() + "\"").collect(Collectors.joining(" , ")); - - String stringify = "{ \"$in\" : [" + formattedValues + "] }}"; - this.query.put(taxonomy, stringify); + public Taxonomy in(String taxonomy, List listOfItems) { + JSONObject innerObj = new JSONObject(); + innerObj.put("$in", listOfItems); + this.query.put(taxonomy, innerObj); return this; } @@ -79,29 +89,22 @@ public Taxonomy in(String taxonomy, String[] listOfItems) { * ]} * * - * Example: If you want to retrieve entries with either the color or size taxonomy applied and linked to the terms yellow and small, respectively. + * Example: If you want to retrieve entries with either the color or size taxonomy applied and linked to the terms yellow and small, respectively. *
*
      *
-     * {$or: [
+     * { $or: [
      * { "taxonomies.color" : "yellow" },
      * { "taxonomies.size" : "small" }
      * ]}
      *
-     *
      * 
* - * @param listOfItems - * @return + * @param listOfItems the list of items + * @return instance {@link Taxonomy} */ - public Taxonomy or(@NotNull List> listOfItems) { - for (int i = 0; i < listOfItems.size(); i++) { - HashMap param = listOfItems.get(i); - if (i > 0) { - this.query.put("$or", listOfItems.toArray()); - } - this.query.put("$or", param); - } + public Taxonomy or(@NotNull List listOfItems) { + this.query.put("$or", listOfItems); return this; } @@ -135,14 +138,8 @@ public Taxonomy or(@NotNull List> listOfItems) { * @param listOfItems the list of items to that you want to include in the query string * @return instance of the Taxonomy */ - public Taxonomy and(@NotNull List> listOfItems) { - for (int i = 0; i < listOfItems.size(); i++) { - HashMap param = listOfItems.get(i); - if (i > 0) { - this.query.put("$and", listOfItems.toArray()); - } - this.query.put("$and", param); - } + public Taxonomy and(@NotNull List listOfItems) { + this.query.put("$and", listOfItems.toString()); return this; } @@ -166,9 +163,9 @@ public Taxonomy and(@NotNull List> listOfItems) { * @return instance of Taxonomy */ public Taxonomy exists(@NotNull String taxonomy, @NotNull Boolean value) { - HashMap param = new HashMap<>(); - param.put("$exists", value); - this.query.put(taxonomy, param); + JSONObject json = new JSONObject(); + json.put("$exists", value); + this.query.put(taxonomy, json); return this; } @@ -191,7 +188,7 @@ public Taxonomy exists(@NotNull String taxonomy, @NotNull Boolean value) { * @return instance of Taxonomy */ public Taxonomy equalAndBelow(@NotNull String taxonomy, @NotNull String termsUid) { - HashMap param = new HashMap<>(); + JSONObject param = new JSONObject(); param.put("$eq_below", termsUid); this.query.put(taxonomy, param); return this; @@ -206,7 +203,7 @@ public Taxonomy equalAndBelow(@NotNull String taxonomy, @NotNull String termsUid * @return instance of Taxonomy */ public Taxonomy equalAndBelowWithLevel(@NotNull String taxonomy, @NotNull String termsUid, @NotNull int level) { - Map innerMap = new HashMap<>(); + JSONObject innerMap = new JSONObject(); innerMap.put("$eq_below", termsUid + ", level: " + level); this.query.put(taxonomy, innerMap); return this; @@ -232,7 +229,7 @@ public Taxonomy equalAndBelowWithLevel(@NotNull String taxonomy, @NotNull String * @return instance of Taxonomy */ public Taxonomy below(@NotNull String taxonomy, @NotNull String termsUid) { - HashMap param = new HashMap<>(); + JSONObject param = new JSONObject(); param.put("$below", termsUid); this.query.put(taxonomy, param); return this; @@ -257,7 +254,7 @@ public Taxonomy below(@NotNull String taxonomy, @NotNull String termsUid) { * @return instance of Taxonomy */ public Taxonomy equalAbove(@NotNull String taxonomy, @NotNull String termUid) { - Map innerMap = new HashMap<>(); + JSONObject innerMap = new JSONObject(); innerMap.put("$eq_above", termUid); this.query.put(taxonomy, innerMap); return this; @@ -282,7 +279,7 @@ public Taxonomy equalAbove(@NotNull String taxonomy, @NotNull String termUid) { * @return instance of {@link Taxonomy} */ public Taxonomy above(@NotNull String taxonomy, @NotNull String termUid) { - Map innerMap = new HashMap<>(); + JSONObject innerMap = new JSONObject(); innerMap.put("$above", termUid); this.query.put(taxonomy, innerMap); return this; @@ -295,9 +292,7 @@ public Taxonomy above(@NotNull String taxonomy, @NotNull String termUid) { * @return instance of Call */ protected Call makeRequest() { - HashMap map = new HashMap<>(); - map.put("query", query); - return this.service.getTaxonomy(this.headers, map); + return this.service.getTaxonomy(this.headers, this.query.toString()); } @@ -308,13 +303,8 @@ protected Call makeRequest() { */ public void find(TaxonomyCallback callback) { try { - Response response = makeRequest().execute(); - if (response.isSuccessful()) { - callback.onResponse(response.body()); - } else { - Request request = makeRequest().request(); - callback.onFailure(request, response.errorBody()); - } + ResponseBody response = makeRequest().execute().body(); + callback.onResponse(response); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/contentstack/sdk/TaxonomyCallback.java b/src/main/java/com/contentstack/sdk/TaxonomyCallback.java index 3de08db1..2a52fa89 100644 --- a/src/main/java/com/contentstack/sdk/TaxonomyCallback.java +++ b/src/main/java/com/contentstack/sdk/TaxonomyCallback.java @@ -1,28 +1,9 @@ package com.contentstack.sdk; -import okhttp3.Request; import okhttp3.ResponseBody; public interface TaxonomyCallback { - /** - * Called when the HTTP response was successfully returned by the remote server. The callback may - * proceed to read the response body. The response is still live until - * its response body is {@linkplain ResponseBody closed}. The recipient of the callback may - * consume the response body on another thread. - * - *

Note that transport-layer success (receiving a HTTP response code, headers and body) does - * not necessarily indicate application-layer success: {@code response} may still indicate an - * unhappy HTTP response code like 404 or 500. - */ void onResponse(ResponseBody response); - /** - * Called when the request could not be executed due to cancellation, a connectivity problem or - * timeout. Because networks can fail during an exchange, it is possible that the remote server - * accepted the request before the failure. - */ - void onFailure(Request request, ResponseBody errorMessage); - - } \ No newline at end of file diff --git a/src/test/java/com/contentstack/sdk/TaxonomyTest.java b/src/test/java/com/contentstack/sdk/TaxonomyTest.java index 91d5f5d6..e945348e 100644 --- a/src/test/java/com/contentstack/sdk/TaxonomyTest.java +++ b/src/test/java/com/contentstack/sdk/TaxonomyTest.java @@ -1,15 +1,11 @@ package com.contentstack.sdk; -import okhttp3.HttpUrl; import okhttp3.Request; +import org.json.JSONObject; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; @@ -25,99 +21,104 @@ void testInstance() { @Test void operationIn() { Taxonomy taxonomy = stack.taxonomy(); - String[] listOfItem = {"red", "yellow"}; - Request req = taxonomy.in("taxonomies.color", listOfItem).makeRequest().request(); - + List listOfItems = new ArrayList<>(); + listOfItems.add("red"); + listOfItems.add("yellow"); + Request req = taxonomy.in("taxonomies.color", listOfItems).makeRequest().request(); Assertions.assertEquals(3, req.headers().size()); Assertions.assertEquals("GET", req.method()); Assertions.assertEquals("cdn.contentstack.io", req.url().host()); Assertions.assertEquals("/v3/taxonomies/entries", req.url().encodedPath()); - Assertions.assertEquals("[query]", req.url().queryParameterNames().toString()); + Assertions.assertEquals("query={\"taxonomies.color\":{\"$in\":[\"red\",\"yellow\"]}}", req.url().query()); } @Test void operationOr() { + +// query={ $or: [ +// { "taxonomies.taxonomy_uid_1" : "term_uid1" }, +// { "taxonomies.taxonomy_uid_2" : "term_uid2" } +// ]} + Taxonomy taxonomy = stack.taxonomy(); - List> listOfItems = new ArrayList<>(); - HashMap items = new HashMap<>(); - items.put("taxonomies.taxonomy_uid_1", "term_uid1"); - items.put("taxonomies.taxonomy_uid_2", "term_uid2"); - listOfItems.add(items); + List listOfItems = new ArrayList<>(); + JSONObject item1 = new JSONObject(); + item1.put("taxonomies.color", "yellow"); + JSONObject item2 = new JSONObject(); + item2.put("taxonomies.size", "small"); + listOfItems.add(item1); + listOfItems.add(item2); taxonomy.or(listOfItems); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("[query]", req.url().queryParameterNames().toString()); - - } + Assertions.assertEquals("query={\"$or\":[{\"taxonomies.color\":\"yellow\"},{\"taxonomies.size\":\"small\"}]}", req.url().query()); - public static String decodeUrl(HttpUrl encodedUrl) { - String decodedUrl = null; - try { - decodedUrl = URLDecoder.decode(encodedUrl.toString(), StandardCharsets.UTF_8.toString()); - return decodedUrl; - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); // Handle the exception according to your requirements - } - return decodedUrl; } @Test void operatorAnd() { Taxonomy taxonomy = stack.taxonomy(); - List> listOfItems = new ArrayList<>(); - HashMap items = new HashMap<>(); - items.put("taxonomies.taxonomy_uid_1", "term_uid1"); - items.put("taxonomies.taxonomy_uid_2", "term_uid2"); - listOfItems.add(items); + List listOfItems = new ArrayList<>(); + JSONObject items1 = new JSONObject(); + items1.put("taxonomies.color", "green"); + JSONObject items2 = new JSONObject(); + items2.put("taxonomies.computers", "laptop"); + listOfItems.add(items1); + listOfItems.add(items2); taxonomy.and(listOfItems); + // {$and: [{"taxonomies.color" : "green" }, { "taxonomies.computers" : "laptop" }]} Request req = taxonomy.makeRequest().request(); + Assertions.assertEquals("query={\"$and\":\"[{\\\"taxonomies.color\\\":\\\"green\\\"}, {\\\"taxonomies.computers\\\":\\\"laptop\\\"}]\"}", req.url().query()); } @Test void operationExists() { // create instance of taxonomy - Taxonomy taxonomy = stack.taxonomy().exists("listOfItems", true); + Taxonomy taxonomy = stack.taxonomy().exists("taxonomies.color", true); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("query={$or={taxonomies.taxonomy_uid_2=term_uid2, taxonomies.taxonomy_uid_1=term_uid1}}", req.url().query()); + //{"taxonomies.color" : { "$exists": true }} + //{"taxonomies.color":{"$exists":true}} + Assertions.assertEquals("query={\"taxonomies.color\":{\"$exists\":true}}", req.url().query()); } @Test void operationEqualAndBelow() { // create instance of taxonomy - Taxonomy taxonomy = stack.taxonomy().equalAndBelow("listOfItems", "uid1"); + Taxonomy taxonomy = stack.taxonomy().equalAndBelow("taxonomies.color", "blue"); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("query={$or={taxonomies.taxonomy_uid_2=term_uid2, taxonomies.taxonomy_uid_1=term_uid1}}", req.url().query()); + // {"taxonomies.color" : { "$eq_below": "blue" }} + Assertions.assertEquals("query={\"taxonomies.color\":{\"$eq_below\":\"blue\"}}", req.url().query()); } @Test - void operationBelow() { - Taxonomy taxonomy = stack.taxonomy().equalAndBelowWithLevel("listOfItems", "uid1", 3); + void operationBelowWithLevel() { + Taxonomy taxonomy = stack.taxonomy().equalAndBelowWithLevel("taxonomies.color", "blue", 3); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("query={$or={taxonomies.taxonomy_uid_2=term_uid2, taxonomies.taxonomy_uid_1=term_uid1}}", req.url().query()); + Assertions.assertEquals("query={\"taxonomies.color\":{\"$eq_below\":\"blue, level: 3\"}}", req.url().query()); } @Test void operationEqualAbove() { - Taxonomy taxonomy = stack.taxonomy().equalAbove("listOfItems", "uid1"); + Taxonomy taxonomy = stack.taxonomy().equalAbove("taxonomies.appliances", "led"); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("query={$or={taxonomies.taxonomy_uid_2=term_uid2, taxonomies.taxonomy_uid_1=term_uid1}}", req.url().query()); + Assertions.assertEquals("query={\"taxonomies.appliances\":{\"$eq_above\":\"led\"}}", req.url().query()); } @Test void above() { - Taxonomy taxonomy = stack.taxonomy().above("listOfItems", "uid1"); + Taxonomy taxonomy = stack.taxonomy().above("taxonomies.appliances", "led"); Request req = taxonomy.makeRequest().request(); - Assertions.assertEquals("query={$or={taxonomies.taxonomy_uid_2=term_uid2, taxonomies.taxonomy_uid_1=term_uid1}}", req.url().query()); + Assertions.assertEquals("query={\"taxonomies.appliances\":{\"$above\":\"led\"}}", req.url().query()); }