Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Back merge #64

Merged
merged 8 commits into from
Jul 31, 2024
Merged
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
Loading