diff --git a/CHANGELOG.md b/CHANGELOG.md index 52b7b07..0a28090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## v2.1.2 + +### Date: 26-May-2025 + +- Global field implementation + ## v2.1.1 ### Date: 1-Apr-2025 diff --git a/pom.xml b/pom.xml index 5ab23a8..7aa3656 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.contentstack.sdk java - 2.1.1 + 2.1.2 jar contentstack-java Java SDK for Contentstack Content Delivery API diff --git a/src/main/java/com/contentstack/sdk/CSBackgroundTask.java b/src/main/java/com/contentstack/sdk/CSBackgroundTask.java index 893408d..aaebb39 100644 --- a/src/main/java/com/contentstack/sdk/CSBackgroundTask.java +++ b/src/main/java/com/contentstack/sdk/CSBackgroundTask.java @@ -100,4 +100,15 @@ protected void checkHeader(@NotNull Map headers) { } } + protected CSBackgroundTask(GlobalField globalField, Stack stackInstance, String controller, String url, + HashMap headers, HashMap 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); + } + } diff --git a/src/main/java/com/contentstack/sdk/CSConnectionRequest.java b/src/main/java/com/contentstack/sdk/CSConnectionRequest.java index 64daeb4..2209053 100644 --- a/src/main/java/com/contentstack/sdk/CSConnectionRequest.java +++ b/src/main/java/com/contentstack/sdk/CSConnectionRequest.java @@ -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(); } @@ -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); + } } } diff --git a/src/main/java/com/contentstack/sdk/Constants.java b/src/main/java/com/contentstack/sdk/Constants.java index 2491722..c1eb614 100644 --- a/src/main/java/com/contentstack/sdk/Constants.java +++ b/src/main/java/com/contentstack/sdk/Constants.java @@ -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 @@ -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."; diff --git a/src/main/java/com/contentstack/sdk/GlobalField.java b/src/main/java/com/contentstack/sdk/GlobalField.java new file mode 100644 index 0000000..11901cf --- /dev/null +++ b/src/main/java/com/contentstack/sdk/GlobalField.java @@ -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 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 headers, + GlobalFieldsCallback callback) { + if (callback != null) { + HashMap urlParams = getUrlParams(params); + new CSBackgroundTask(this, stackInstance, Constants.FETCHGLOBALFIELDS, urlString, headers, urlParams, + Constants.REQUEST_CONTROLLER.GLOBALFIELDS.toString(), callback); + } + } + + private HashMap getUrlParams(JSONObject urlQueriesJSON) { + HashMap hashMap = new HashMap<>(); + if (urlQueriesJSON != null && urlQueriesJSON.length() > 0) { + Iterator itStr = urlQueriesJSON.keys(); + while (itStr.hasNext()) { + String key = itStr.next(); + Object value = urlQueriesJSON.opt(key); + hashMap.put(key, value); + } + } + return hashMap; + } +} diff --git a/src/main/java/com/contentstack/sdk/GlobalFieldsCallback.java b/src/main/java/com/contentstack/sdk/GlobalFieldsCallback.java new file mode 100755 index 0000000..189e08a --- /dev/null +++ b/src/main/java/com/contentstack/sdk/GlobalFieldsCallback.java @@ -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); + } +} diff --git a/src/main/java/com/contentstack/sdk/GlobalFieldsModel.java b/src/main/java/com/contentstack/sdk/GlobalFieldsModel.java new file mode 100644 index 0000000..aad19e0 --- /dev/null +++ b/src/main/java/com/contentstack/sdk/GlobalFieldsModel.java @@ -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> globalFields = (ArrayList) responseJSON.get(gfListKey); + List 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; + } +} diff --git a/src/main/java/com/contentstack/sdk/Stack.java b/src/main/java/com/contentstack/sdk/Stack.java index 93e1ec9..2174bed 100644 --- a/src/main/java/com/contentstack/sdk/Stack.java +++ b/src/main/java/com/contentstack/sdk/Stack.java @@ -32,6 +32,7 @@ public class Stack { protected LinkedHashMap headers; protected Config config; protected String contentType; + protected String globalField; protected String livePreviewEndpoint; protected APIService service; protected String apiKey; @@ -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. diff --git a/src/test/java/com/contentstack/sdk/TestEntry.java b/src/test/java/com/contentstack/sdk/TestEntry.java index b5830e2..3dfde0f 100644 --- a/src/test/java/com/contentstack/sdk/TestEntry.java +++ b/src/test/java/com/contentstack/sdk/TestEntry.java @@ -42,7 +42,7 @@ public void onCompletion(ResponseType responseType, QueryResult queryresult, Err if (error == null) { List> 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 { diff --git a/src/test/java/com/contentstack/sdk/TestGlobalFields.java b/src/test/java/com/contentstack/sdk/TestGlobalFields.java new file mode 100644 index 0000000..f20ee08 --- /dev/null +++ b/src/test/java/com/contentstack/sdk/TestGlobalFields.java @@ -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()); + } + }); + } +} \ No newline at end of file