Skip to content

DX | 26-05-2025 | Release #201

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

Merged
merged 9 commits into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## v2.1.2

### Date: 26-May-2025

- Global field implementation

## v2.1.1

### Date: 1-Apr-2025
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.contentstack.sdk</groupId>
<artifactId>java</artifactId>
<version>2.1.1</version>
<version>2.1.2</version>
<packaging>jar</packaging>
<name>contentstack-java</name>
<description>Java SDK for Contentstack Content Delivery API</description>
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/contentstack/sdk/CSBackgroundTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,15 @@ protected void checkHeader(@NotNull Map<String, Object> headers) {
}
}

protected CSBackgroundTask(GlobalField globalField, Stack stackInstance, String controller, String url,
HashMap<String, Object> headers, HashMap<String, Object> urlParams, String requestInfo,
ResultCallBack callback) {
checkHeader(headers);
String completeUrl = stackInstance.config.getEndpoint() + url;
CSConnectionRequest csConnectionRequest = new CSConnectionRequest(globalField);
csConnectionRequest.setURLQueries(urlParams);
this.service = stackInstance.service;
csConnectionRequest.setParams(completeUrl, headers, controller, requestInfo, callback, this.service, stackInstance);
}

}
10 changes: 10 additions & 0 deletions src/main/java/com/contentstack/sdk/CSConnectionRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public CSConnectionRequest(ContentType contentType) {
this.endpoint = contentType.stackInstance.config.getEndpoint();
}

public CSConnectionRequest(GlobalField globalField) {
this.endpoint = globalField.stackInstance.config.getEndpoint();
}

public void setQueryInstance(Query queryInstance) {
this.endpoint = queryInstance.contentTypeInstance.stackInstance.config.getEndpoint();
}
Expand Down Expand Up @@ -167,6 +171,12 @@ public synchronized void onRequestFinished(CSHttpConnection request) {
if (request.getCallBackObject() != null) {
((ContentTypesCallback) request.getCallBackObject()).onRequestFinish(model);
}
} else if (request.getController().equalsIgnoreCase(Constants.FETCHGLOBALFIELDS)) {
GlobalFieldsModel model = new GlobalFieldsModel();
model.setJSON(jsonResponse);
if (request.getCallBackObject() != null) {
((GlobalFieldsCallback) request.getCallBackObject()).onRequestFinish(model);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/contentstack/sdk/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected Constants() {
*/
// REQUEST_CONTROLLER
public enum REQUEST_CONTROLLER {
QUERY, ENTRY, ASSET, SYNC, CONTENTTYPES, ASSETLIBRARY
QUERY, ENTRY, ASSET, SYNC, CONTENTTYPES, ASSETLIBRARY, GLOBALFIELDS
}

// GET REQUEST TYPE
Expand All @@ -65,6 +65,7 @@ public enum REQUEST_CONTROLLER {
public static final String FETCHASSETS = "getAssets";
public static final String FETCHSYNC = "getSync";
public static final String FETCHCONTENTTYPES = "getContentTypes";
public static final String FETCHGLOBALFIELDS = "getGlobalFields";

public static final String CONTENT_TYPE_NAME = "Please set contentType name.";
public static final String QUERY_EXCEPTION = "Please provide valid params.";
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/com/contentstack/sdk/GlobalField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.contentstack.sdk;

import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.logging.Logger;

/**
* This call returns information of a specific global field. It returns the
* global field schema.
*
*/
public class GlobalField {

protected static final Logger logger = Logger.getLogger(GlobalField.class.getSimpleName());
protected String globalFieldUid;
protected Stack stackInstance = null;
protected JSONObject params = new JSONObject();
protected LinkedHashMap<String, Object> headers = null;

protected GlobalField() {
this.headers = new LinkedHashMap<>();
}

protected GlobalField(@NotNull String globalFieldUid) {
this.globalFieldUid = globalFieldUid;
this.headers = new LinkedHashMap<>();
}

protected void setStackInstance(Stack stack) {
this.stackInstance = stack;
this.headers = stack.headers;
}

/**
* Sets header on {@link Stack}.
*
* @param headerKey
* the header key
* @param headerValue
* the header value
*/
public void setHeader(String headerKey, String headerValue) {
if (!headerKey.isEmpty() && !headerValue.isEmpty()) {
this.headers.put(headerKey, headerValue);
}
}

/**
* Remove header from {@link Stack}
*
* @param headerKey
* the header key
*/
public void removeHeader(String headerKey) {
if (!headerKey.isEmpty()) {
this.headers.remove(headerKey);
}
}

/**
* Fetch.
*
* @param params
* the params
* @param callback
* the callback
* @throws IllegalAccessException
* illegal access exception
*/

public GlobalField includeBranch() {
this.params.put("include_branch", true);
return this;
}

public GlobalField includeGlobalFieldSchema() {
this.params.put("include_global_field_schema", true);
return this;
}

public void fetch(final GlobalFieldsCallback callback) throws IllegalAccessException {
String urlString = "global_fields/" + globalFieldUid;
if (globalFieldUid == null || globalFieldUid.isEmpty()) {
throw new IllegalAccessException("globalFieldUid is required");
}
fetchGlobalFields(urlString, this.params, this.headers, callback);
}

public void findAll(final GlobalFieldsCallback callback) {
String urlString = "global_fields";
fetchGlobalFields(urlString, this.params, this.headers, callback);
}

private void fetchGlobalFields(String urlString, JSONObject params, HashMap<String, Object> headers,
GlobalFieldsCallback callback) {
if (callback != null) {
HashMap<String, Object> urlParams = getUrlParams(params);
new CSBackgroundTask(this, stackInstance, Constants.FETCHGLOBALFIELDS, urlString, headers, urlParams,
Constants.REQUEST_CONTROLLER.GLOBALFIELDS.toString(), callback);
}
}

private HashMap<String, Object> getUrlParams(JSONObject urlQueriesJSON) {
HashMap<String, Object> hashMap = new HashMap<>();
if (urlQueriesJSON != null && urlQueriesJSON.length() > 0) {
Iterator<String> itStr = urlQueriesJSON.keys();
while (itStr.hasNext()) {
String key = itStr.next();
Object value = urlQueriesJSON.opt(key);
hashMap.put(key, value);
}
}
return hashMap;
}
}
18 changes: 18 additions & 0 deletions src/main/java/com/contentstack/sdk/GlobalFieldsCallback.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.contentstack.sdk;

/**
* The callback for Content Types that contains GlobalFieldsModel and Error
*/
public abstract class GlobalFieldsCallback implements ResultCallBack {

public abstract void onCompletion(GlobalFieldsModel globalFieldsModel, Error error);

void onRequestFinish(GlobalFieldsModel globalFieldsModel) {
onCompletion(globalFieldsModel, null);
}

@Override
public void onRequestFail(ResponseType responseType, Error error) {
onCompletion(null, error);
}
}
59 changes: 59 additions & 0 deletions src/main/java/com/contentstack/sdk/GlobalFieldsModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.contentstack.sdk;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;

/**
* The GlobalFieldsModel that contains global fields response
*/
public class GlobalFieldsModel {

private Object response;
private JSONArray responseJSONArray = new JSONArray();

public void setJSON(JSONObject responseJSON) {
if (responseJSON != null) {
String gfKey = "global_field";
if (responseJSON.has(gfKey) && responseJSON.opt(gfKey) instanceof LinkedHashMap) {
try {
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(gfKey));
} catch (Exception e) {
System.err.println("Error processing 'global_field': " + e.getMessage());
}
}
String gfListKey = "global_fields";
if (responseJSON.has(gfListKey) && responseJSON.opt(gfListKey) instanceof ArrayList) {
try {
ArrayList<LinkedHashMap<?, ?>> globalFields = (ArrayList) responseJSON.get(gfListKey);
List<Object> objectList = new ArrayList<>();
if (!globalFields.isEmpty()) {
globalFields.forEach(model -> {
if (model instanceof LinkedHashMap) {
// Convert LinkedHashMap to JSONObject
JSONObject jsonModel = new JSONObject((LinkedHashMap<?, ?>) model);
objectList.add(jsonModel);
} else {
System.err.println("Invalid type in 'global_fields' list. Expected LinkedHashMap.");
}
});
}
this.response = new JSONArray(objectList);
this.responseJSONArray = new JSONArray(objectList);
} catch (Exception e) {
System.err.println("Error processing 'global_fields': " + e.getMessage());
}
}
}
}

public Object getResponse() {
return this.response;
}

public JSONArray getResultArray() {
return responseJSONArray;
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/contentstack/sdk/Stack.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class Stack {
protected LinkedHashMap<String, Object> headers;
protected Config config;
protected String contentType;
protected String globalField;
protected String livePreviewEndpoint;
protected APIService service;
protected String apiKey;
Expand Down Expand Up @@ -212,6 +213,19 @@ public ContentType contentType(String contentTypeUid) {
return ct;
}

public GlobalField globalField(@NotNull String globalFieldUid) {
this.globalField = globalFieldUid;
GlobalField gf = new GlobalField(globalFieldUid);
gf.setStackInstance(this);
return gf;
}

public GlobalField globalField() {
GlobalField gf = new GlobalField();
gf.setStackInstance(this);
return gf;
}

/**
* Assets refer to all the media files (images, videos, PDFs, audio files, and so on) uploaded in your Contentstack
* repository for future use. These files can be attached and used in multiple entries.
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/contentstack/sdk/TestEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void onCompletion(ResponseType responseType, QueryResult queryresult, Err
if (error == null) {
List<LinkedHashMap<?, ?>> list = (ArrayList)queryresult.receiveJson.get("entries");
LinkedHashMap<?, ?> firstObj = list.get(0);
entryUid = (String)firstObj.get("uid");
// entryUid = (String)firstObj.get("uid");
assertTrue(entryUid.startsWith("blt"));
logger.info("passed..");
} else {
Expand Down
68 changes: 68 additions & 0 deletions src/test/java/com/contentstack/sdk/TestGlobalFields.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.contentstack.sdk;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class TestGlobalFields {

private GlobalFieldsModel globalFieldsModel;
private final Stack stack = Credentials.getStack();

@BeforeEach
void setUp() {
globalFieldsModel = new GlobalFieldsModel();
}

@Test
void testSetJSONWithNull() {
globalFieldsModel.setJSON(null);
assertNull(globalFieldsModel.getResponse());
assertEquals(0, globalFieldsModel.getResultArray().length());
}

@Test
void testSetJSONWithEmptyObject() {
globalFieldsModel.setJSON(new JSONObject());
assertNull(globalFieldsModel.getResponse());
assertEquals(0, globalFieldsModel.getResultArray().length());
}

@Test
void testFetchGlobalFieldByUid() throws IllegalAccessException {
GlobalField globalField = stack.globalField("specific_gf_uid");
globalField.fetch(new GlobalFieldsCallback() {
@Override
public void onCompletion(GlobalFieldsModel model, Error error) {
JSONArray resp = model.getResultArray();
Assertions.assertTrue(resp.isEmpty());
}
});
}

@Test
void testFindGlobalFieldsIncludeBranch() {
GlobalField globalField = stack.globalField().includeBranch();
globalField.findAll(new GlobalFieldsCallback() {
@Override
public void onCompletion(GlobalFieldsModel globalFieldsModel, Error error) {
assertTrue(globalFieldsModel.getResultArray() instanceof JSONArray);
assertNotNull(((JSONArray) globalFieldsModel.getResponse()).length());
}
});
}

@Test
void testFindGlobalFields() throws IllegalAccessException {
GlobalField globalField = stack.globalField().includeBranch();
globalField.findAll(new GlobalFieldsCallback() {
@Override
public void onCompletion(GlobalFieldsModel globalFieldsModel, Error error) {
assertTrue(globalFieldsModel.getResultArray() instanceof JSONArray);
assertNotNull(((JSONArray) globalFieldsModel.getResponse()).length());
}
});
}
}
Loading