Skip to content

Commit

Permalink
Merge pull request #62 from contentstack/feat/DX-199-Taxonomy-impleme…
Browse files Browse the repository at this point in the history
…ntation-testcase

Feat/dx 199 taxonomy implementation testcase
  • Loading branch information
cs-raj authored Jul 31, 2024
2 parents fe5ae71 + 76f6b5a commit 7ac4075
Show file tree
Hide file tree
Showing 14 changed files with 697 additions and 14 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# CHANGELOG

## Version 3.16.0

### Date: 31-July-2024

- Taxonomy Support

---

## Version 3.15.1

### Date: 24-June-2024
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Or,

To add the Contentstack Android SDK to your existing project manually, perform the steps given below:

1. [Download the Android SDK](https://docs.contentstack.com/platforms/android/android_sdk_latest)
1. [Download the Android SDK](https://github.com/contentstack/contentstack-android/archive/refs/heads/master.zip)
and extract the ZIP file to your local disk.
2. Add references/dependencies using Eclipse/Android Studio:

Expand Down
29 changes: 27 additions & 2 deletions contentstack/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android.buildFeatures.buildConfig true
mavenPublishing {
publishToMavenCentral(SonatypeHost.DEFAULT)
signAllPublications()
coordinates("com.contentstack.sdk", "android", "3.15.1")
coordinates("com.contentstack.sdk", "android", "3.16.0")

pom {
name = "contentstack-android"
Expand Down Expand Up @@ -67,6 +67,8 @@ android {
exclude("META-INF/notice.txt")
exclude("META-INF/ASL2.0")
exclude("META-INF/*.kotlin_module")
exclude("META-INF/LICENSE.md")
exclude("META-INF/LICENSE-notice.md")
}

testOptions {
Expand Down Expand Up @@ -99,7 +101,7 @@ android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
minSdkVersion 23
minSdk 24
versionCode 1
versionName "1.0"
useLibrary 'org.apache.http.legacy'
Expand Down Expand Up @@ -137,13 +139,15 @@ android {
}
configurations { archives }
dependencies {
androidTestImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
def multidex = "2.0.1"
def volley = "1.2.1"
def junit = "4.13.2"
configurations.configureEach { resolutionStrategy.force 'com.android.support:support-annotations:23.1.0' }
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "com.android.volley:volley:$volley"
implementation "junit:junit:$junit"

// For AGP 7.4+
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
testImplementation 'junit:junit:4.13.2'
Expand All @@ -154,6 +158,27 @@ dependencies {

// implementation 'com.squareup.okio:okio:3.9.0'
implementation 'com.github.rjeschke:txtmark:0.12'
// // Retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation 'com.squareup.retrofit2:converter-gson'
// // OkHttp
implementation 'com.squareup.okhttp3:okhttp'
// implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'

constraints {
implementation('com.squareup.retrofit2:converter-gson:2.9.0') {
because 'gson 2.8.5 used by retrofit has a vulnerability'
}
implementation('com.google.code.gson:[email protected]') {
because 'gson 2.8.5 used by retrofit has a vulnerability'
}
implementation('com.squareup.okhttp3:okhttp:4.9.3') {
because 'kotlin stdlib 1.4.10 used by okhttp has a vulnerability'
}
implementation('org.jetbrains.kotlin:[email protected]') {
because 'kotlin stdlib 1.4.10 used by okhttp has a vulnerability'
}
}
}
tasks.register('clearJar', Delete) { delete 'build/libs/contentstack.jar' }
tasks.register('unzip', Copy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package com.contentstack.sdk;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.runners.MethodSorters;
import org.junit.*;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import static junit.framework.TestCase.*;

import android.content.Context;
import android.util.Log;

import androidx.test.core.app.ApplicationProvider;

import okhttp3.Request;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Response;


public class TaxonomyTestCase {

private static Stack stack;
private final static String TAG = TaxonomyTestCase.class.getSimpleName();


@BeforeClass
public static void oneTimeSetUp() throws Exception {
Context appContext = ApplicationProvider.getApplicationContext();
Config config = new Config();
String DEFAULT_HOST = BuildConfig.host;
config.setHost(DEFAULT_HOST);
stack = Contentstack.stack(appContext, BuildConfig.APIKey, BuildConfig.deliveryToken, BuildConfig.environment, config);
}

@Test
public void testInstance() {
assertNotNull(stack);
}

@Test
public void operationIn() {
Taxonomy taxonomy = stack.taxonomy();
List<String> listOfItems = new ArrayList<>();
listOfItems.add("maroon");
listOfItems.add("red");
Request req = taxonomy.in("taxonomies.color", listOfItems).makeRequest().request();
assertEquals("GET", req.method());
assertEquals("cdn.contentstack.io", req.url().host());
assertEquals("/v3/taxonomies/entries", req.url().encodedPath());
assertEquals("query={\"taxonomies.color\":{\"$in\":[\"maroon\",\"red\"]}}", req.url().query());
}

@Test
public void operationOr() throws JSONException, IOException {
// query={ $or: [
// { "taxonomies.taxonomy_uid_1" : "term_uid1" },
// { "taxonomies.taxonomy_uid_2" : "term_uid2" }
// ]}
Taxonomy taxonomy = stack.taxonomy();
List<JSONObject> listOfItems = new ArrayList<>();
JSONObject item1 = new JSONObject();
item1.put("taxonomies.color", "orange");
JSONObject item2 = new JSONObject();
item2.put("taxonomies.country", "zambia");
listOfItems.add(item1);
listOfItems.add(item2);
taxonomy.or(listOfItems);
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"$or\":[{\"taxonomies.color\":\"orange\"},{\"taxonomies.country\":\"zambia\"}]}", req.url().query());

}

@Test
public void operatorAnd() throws JSONException {
Taxonomy taxonomy = stack.taxonomy();
List<JSONObject> listOfItems = new ArrayList<>();
JSONObject items1 = new JSONObject();
items1.put("taxonomies.color", "green");
JSONObject items2 = new JSONObject();
items2.put("taxonomies.country", "india");
listOfItems.add(items1);
listOfItems.add(items2);
taxonomy.and(listOfItems);
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"$and\":[{\"taxonomies.color\":\"green\"},{\"taxonomies.country\":\"india\"}]}", req.url().query());
}


@Test
public void operationExists() throws IOException {
Taxonomy taxonomy = stack.taxonomy().exists("taxonomies.color", true);
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"taxonomies.color\":{\"$exists\":true}}", req.url().query());
}


@Test
public void operationEqualAndBelow() throws IOException {
Taxonomy taxonomy = stack.taxonomy().equalAndBelow("taxonomies.color", "red");
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"taxonomies.color\":{\"$eq_below\":\"red\"}}", req.url().query());
}


@Test
public void operationEqualAbove() {
Taxonomy taxonomy = stack.taxonomy().equalAbove("taxonomies.appliances", "led");
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"taxonomies.appliances\":{\"$eq_above\":\"led\"}}", req.url().query());

}

@Test
public void above() {
Taxonomy taxonomy = stack.taxonomy().above("taxonomies.appliances", "led");
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"taxonomies.appliances\":{\"$above\":\"led\"}}", req.url().query());
}

@Test
public void below() {
Taxonomy taxonomy = stack.taxonomy().below("taxonomies.appliances", "TV");
Request req = taxonomy.makeRequest().request();
assertEquals("query={\"taxonomies.appliances\":{\"$below\":\"TV\"}}", req.url().query());
}

@Test
public void aboveAPI() {
Taxonomy taxonomy = stack.taxonomy().below("taxonomies.color", "red");
Request req = taxonomy.makeRequest().request();
taxonomy.find(new TaxonomyCallback() {
@Override
public void onResponse(JSONObject response, Error error) {
Log.d("Result",response.toString());
}
});
assertEquals("query={\"taxonomies.color\":{\"$below\":\"red\"}}", req.url().query());
}


}

23 changes: 23 additions & 0 deletions contentstack/src/main/java/com/contentstack/sdk/APIService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.contentstack.sdk;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.HeaderMap;
import retrofit2.http.Query;
import retrofit2.http.Url;

import java.util.LinkedHashMap;
import java.util.Map;


public interface APIService {
@GET
Call<ResponseBody> getRequest(
@Url String url, @HeaderMap LinkedHashMap<String, Object> headers);

@GET("v3/taxonomies/entries")
Call<ResponseBody> getTaxonomy(
@HeaderMap Map<String, Object> headers,
@Query("query") String query);
}
4 changes: 2 additions & 2 deletions contentstack/src/main/java/com/contentstack/sdk/Asset.java
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ public void fetch(FetchResultCallback callback) {
urlQueries.put("environment", headers.get("environment"));
}
String mainStringForMD5 = urlEndpoint + new JSONObject().toString() + headers.toString();
String md5Value = new SDKUtil().getMD5FromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + md5Value);
String shaValue = new SDKUtil().getSHAFromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + shaValue);

switch (cachePolicyForCall) {
case IGNORE_CACHE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,8 @@ public void fetchAll(FetchAssetsCallback assetsCallback) {
urlQueries.put("environment", headers.get("environment"));
}
String mainStringForMD5 = URL + new JSONObject().toString() + headers.toString();
String md5Value = new SDKUtil().getMD5FromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + md5Value);
String shaValue = new SDKUtil().getSHAFromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + shaValue);
switch (cachePolicyForCall) {
case IGNORE_CACHE:
fetchFromNetwork(URL, urlQueries, headers, cacheFile.getPath(), assetsCallback);
Expand Down
58 changes: 58 additions & 0 deletions contentstack/src/main/java/com/contentstack/sdk/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import android.text.TextUtils;

import java.net.Proxy;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import okhttp3.ConnectionPool;


/**
Expand All @@ -17,6 +21,10 @@ public class Config {
protected String environment = null;
protected String branch = null;
protected String[] earlyAccess = null;
protected Proxy proxy = null;
protected ConnectionPool connectionPool = new ConnectionPool();
protected String endpoint;



/**
Expand Down Expand Up @@ -179,5 +187,55 @@ public String getEnvironment() {
return environment;
}

/**
* Proxy can be set like below.
*
* @param proxy Proxy setting, typically a type (http, socks) and a socket address. A Proxy is an immutable object
* <br>
* <br>
* <b>Example:</b><br>
* <br>
* <code>
* java.net.Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxyHost", "proxyPort"));
* java.net.Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("sl.theproxyvpn.io", 80)); Config
* config = new Config(); config.setProxy(proxy);
* </code>
*/
public void setProxy(Proxy proxy) {
this.proxy = proxy;
}

/**
* Returns the Proxy instance
*
* @return Proxy
*/
public Proxy getProxy() {
return this.proxy;
}

/**
* Manages reuse of HTTP and HTTP/2 connections for reduced network latency. HTTP requests that * share the same
* {@link okhttp3.Address} may share a {@link okhttp3.Connection}. This class implements the policy * of which
* connections to keep open for future use.
*
* @param maxIdleConnections the maxIdleConnections default value is 5
* @param keepAliveDuration the keepAliveDuration default value is 5
* @param timeUnit the timeUnit default value is TimeUnit. MINUTES
* @return ConnectionPool
*/
public ConnectionPool connectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
this.connectionPool = new ConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
return this.connectionPool;
}

protected String getEndpoint() {
return endpoint + "/" + getVersion() + "/";
}

protected void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}


}
4 changes: 2 additions & 2 deletions contentstack/src/main/java/com/contentstack/sdk/Entry.java
Original file line number Diff line number Diff line change
Expand Up @@ -1087,9 +1087,9 @@ public void fetch(EntryResultCallBack callBack) {
}

String mainStringForMD5 = URL + new JSONObject().toString() + headerAll.toString();
String md5Value = new SDKUtil().getMD5FromString(mainStringForMD5.trim());
String shaValue = new SDKUtil().getSHAFromString(mainStringForMD5.trim());

File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + md5Value);
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + shaValue);


switch (cachePolicyForCall) {
Expand Down
4 changes: 2 additions & 2 deletions contentstack/src/main/java/com/contentstack/sdk/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -1595,8 +1595,8 @@ protected void execQuery(SingleQueryResultCallback callBack, QueryResultsCallBac
mainJSON.put("query", urlQueries);
mainJSON.put("_method", SDKConstant.RequestMethod.GET.toString());
String mainStringForMD5 = URL + mainJSON.toString() + headers.toString();
String md5Value = new SDKUtil().getMD5FromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + md5Value);
String shaValue = new SDKUtil().getSHAFromString(mainStringForMD5.trim());
File cacheFile = new File(SDKConstant.cacheFolderName + File.separator + shaValue);
CachePolicy cachePolicy = CachePolicy.NETWORK_ONLY;//contentTypeInstance.stackInstance.globalCachePolicyForCall;
if (cachePolicyForCall != null) {
cachePolicy = cachePolicyForCall;
Expand Down
Loading

0 comments on commit 7ac4075

Please sign in to comment.