Skip to content

Commit fa4f045

Browse files
feat: add support for global fields with add and remove header
1 parent c126a1d commit fa4f045

File tree

8 files changed

+313
-1
lines changed

8 files changed

+313
-1
lines changed

src/main/java/com/contentstack/sdk/CSBackgroundTask.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,15 @@ protected void checkHeader(@NotNull Map<String, Object> headers) {
100100
}
101101
}
102102

103+
protected CSBackgroundTask(GlobalField globalField, Stack stackInstance, String controller, String url,
104+
HashMap<String, Object> headers, HashMap<String, Object> urlParams, String requestInfo,
105+
ResultCallBack callback) {
106+
checkHeader(headers);
107+
String completeUrl = stackInstance.config.getEndpoint() + url;
108+
CSConnectionRequest csConnectionRequest = new CSConnectionRequest(globalField);
109+
csConnectionRequest.setURLQueries(urlParams);
110+
this.service = stackInstance.service;
111+
csConnectionRequest.setParams(completeUrl, headers, controller, requestInfo, callback, this.service, stackInstance);
112+
}
113+
103114
}

src/main/java/com/contentstack/sdk/CSConnectionRequest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public CSConnectionRequest(ContentType contentType) {
5353
this.endpoint = contentType.stackInstance.config.getEndpoint();
5454
}
5555

56+
public CSConnectionRequest(GlobalField globalField) {
57+
this.endpoint = globalField.stackInstance.config.getEndpoint();
58+
}
59+
5660
public void setQueryInstance(Query queryInstance) {
5761
this.endpoint = queryInstance.contentTypeInstance.stackInstance.config.getEndpoint();
5862
}
@@ -167,6 +171,12 @@ public synchronized void onRequestFinished(CSHttpConnection request) {
167171
if (request.getCallBackObject() != null) {
168172
((ContentTypesCallback) request.getCallBackObject()).onRequestFinish(model);
169173
}
174+
} else if (request.getController().equalsIgnoreCase(Constants.FETCHGLOBALFIELDS)) {
175+
GlobalFieldsModel model = new GlobalFieldsModel();
176+
model.setJSON(jsonResponse);
177+
if (request.getCallBackObject() != null) {
178+
((GlobalFieldsCallback) request.getCallBackObject()).onRequestFinish(model);
179+
}
170180
}
171181
}
172182

src/main/java/com/contentstack/sdk/Constants.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected Constants() {
5454
*/
5555
// REQUEST_CONTROLLER
5656
public enum REQUEST_CONTROLLER {
57-
QUERY, ENTRY, ASSET, SYNC, CONTENTTYPES, ASSETLIBRARY
57+
QUERY, ENTRY, ASSET, SYNC, CONTENTTYPES, ASSETLIBRARY, GLOBALFIELDS
5858
}
5959

6060
// GET REQUEST TYPE
@@ -65,6 +65,7 @@ public enum REQUEST_CONTROLLER {
6565
public static final String FETCHASSETS = "getAssets";
6666
public static final String FETCHSYNC = "getSync";
6767
public static final String FETCHCONTENTTYPES = "getContentTypes";
68+
public static final String FETCHGLOBALFIELDS = "getGlobalFields";
6869

6970
public static final String CONTENT_TYPE_NAME = "Please set contentType name.";
7071
public static final String QUERY_EXCEPTION = "Please provide valid params.";
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package com.contentstack.sdk;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.json.JSONObject;
5+
6+
import java.util.HashMap;
7+
import java.util.Iterator;
8+
import java.util.LinkedHashMap;
9+
import java.util.logging.Logger;
10+
11+
/**
12+
* <a href=
13+
* "https://www.contentstack.com/docs/developers/apis/content-delivery-api/#single-content-type">ContentType</a>
14+
* This
15+
* call returns information of a specific global field. It returns the global
16+
* field schema, but does not include its
17+
* entries.
18+
*
19+
*/
20+
public class GlobalField {
21+
22+
protected static final Logger logger = Logger.getLogger(GlobalField.class.getSimpleName());
23+
protected String globalFieldUid;
24+
protected Stack stackInstance = null;
25+
protected JSONObject params;
26+
protected LinkedHashMap<String, Object> headers = null;
27+
28+
protected GlobalField() throws IllegalAccessException {
29+
throw new IllegalAccessException("Can Not Access Private Modifier");
30+
}
31+
32+
protected GlobalField(String globalFieldUid) {
33+
this.globalFieldUid = globalFieldUid;
34+
}
35+
36+
protected void setStackInstance(Stack stack) {
37+
this.stackInstance = stack;
38+
this.headers = stack.headers;
39+
}
40+
41+
/**
42+
* Sets header on {@link Stack}.
43+
*
44+
* @param headerKey
45+
* the header key
46+
* @param headerValue
47+
* the header value
48+
*/
49+
public void setHeader(String headerKey, String headerValue) {
50+
if (!headerKey.isEmpty() && !headerValue.isEmpty()) {
51+
this.headers.put(headerKey, headerValue);
52+
}
53+
}
54+
55+
/**
56+
* Remove header from {@link Stack}
57+
*
58+
* @param headerKey
59+
* the header key
60+
*/
61+
public void removeHeader(String headerKey) {
62+
if (!headerKey.isEmpty()) {
63+
this.headers.remove(headerKey);
64+
}
65+
}
66+
/**
67+
* Fetch.
68+
*
69+
* @param params
70+
* the params
71+
* @param callback
72+
* the callback
73+
* @throws IllegalAccessException
74+
* illegal access exception
75+
*/
76+
77+
public GlobalField includeBranch() {
78+
params.put("include_branch", false);
79+
return this;
80+
}
81+
82+
public void fetch(@NotNull JSONObject params, final GlobalFieldsCallback callback) throws IllegalAccessException {
83+
String urlString = "global_fields/" + globalFieldUid;
84+
Iterator<String> keys = params.keys();
85+
while (keys.hasNext()) {
86+
String key = keys.next();
87+
Object value = params.opt(key);
88+
params.put(key, value);
89+
}
90+
params.put("environment", headers.get("environment"));
91+
if (globalFieldUid == null || globalFieldUid.isEmpty()) {
92+
throw new IllegalAccessException("globalFieldUid is required");
93+
}
94+
fetchGlobalFields(urlString, params, headers, callback);
95+
}
96+
97+
private void fetchGlobalFields(String urlString, JSONObject params, HashMap<String, Object> headers,
98+
GlobalFieldsCallback callback) {
99+
if (callback != null) {
100+
HashMap<String, Object> urlParams = getUrlParams(params);
101+
new CSBackgroundTask(this, stackInstance, Constants.FETCHGLOBALFIELDS, urlString, headers, urlParams,
102+
Constants.REQUEST_CONTROLLER.GLOBALFIELDS.toString(), callback);
103+
}
104+
}
105+
106+
107+
private HashMap<String, Object> getUrlParams(JSONObject urlQueriesJSON) {
108+
HashMap<String, Object> hashMap = new HashMap<>();
109+
if (urlQueriesJSON != null && urlQueriesJSON.length() > 0) {
110+
Iterator<String> itStr = urlQueriesJSON.keys();
111+
while (itStr.hasNext()) {
112+
String key = itStr.next();
113+
Object value = urlQueriesJSON.opt(key);
114+
hashMap.put(key, value);
115+
}
116+
}
117+
return hashMap;
118+
}
119+
120+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.contentstack.sdk;
2+
3+
/**
4+
* The callback for Content Types that contains GlobalFieldsModel and Error
5+
*/
6+
public abstract class GlobalFieldsCallback implements ResultCallBack {
7+
8+
public abstract void onCompletion(GlobalFieldsModel globalFieldsModel, Error error);
9+
10+
void onRequestFinish(GlobalFieldsModel globalFieldsModel) {
11+
onCompletion(globalFieldsModel, null);
12+
}
13+
14+
@Override
15+
public void onRequestFail(ResponseType responseType, Error error) {
16+
onCompletion(null, error);
17+
}
18+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.contentstack.sdk;
2+
3+
import java.util.ArrayList;
4+
import java.util.LinkedHashMap;
5+
import java.util.List;
6+
import org.json.JSONArray;
7+
import org.json.JSONObject;
8+
9+
10+
11+
/**
12+
* The GlobalFieldsModel that contains global fields response
13+
*/
14+
public class GlobalFieldsModel {
15+
16+
private Object response;
17+
private JSONArray responseJSONArray = new JSONArray();
18+
19+
public void setJSON(JSONObject responseJSON) {
20+
if (responseJSON != null) {
21+
String ctKey = "global_field";
22+
if (responseJSON.has(ctKey) && responseJSON.opt(ctKey) instanceof LinkedHashMap) {
23+
try {
24+
this.response = new JSONObject((LinkedHashMap<?, ?>) responseJSON.get(ctKey));
25+
} catch (Exception e) {
26+
System.err.println("Error processing 'global_field': " + e.getMessage());
27+
}
28+
}
29+
String gfListKey = "global_fields";
30+
if (responseJSON.has(gfListKey) && responseJSON.opt(gfListKey) instanceof ArrayList) {
31+
try {
32+
ArrayList<LinkedHashMap<?, ?>> globalFields = (ArrayList) responseJSON.get(gfListKey);
33+
List<Object> objectList = new ArrayList<>();
34+
if (!globalFields.isEmpty()) {
35+
globalFields.forEach(model -> {
36+
if (model instanceof LinkedHashMap) {
37+
// Convert LinkedHashMap to JSONObject
38+
JSONObject jsonModel = new JSONObject((LinkedHashMap<?, ?>) model);
39+
objectList.add(jsonModel);
40+
} else {
41+
System.err.println("Invalid type in 'global_fields' list. Expected LinkedHashMap.");
42+
}
43+
});
44+
}
45+
this.response = new JSONArray(objectList);
46+
this.responseJSONArray = new JSONArray(objectList);
47+
} catch (Exception e) {
48+
System.err.println("Error processing 'global_fields': " + e.getMessage());
49+
}
50+
}
51+
}
52+
}
53+
54+
public Object getResponse() {
55+
return this.response;
56+
}
57+
58+
public JSONArray getResultArray() {
59+
return responseJSONArray;
60+
}
61+
}

src/main/java/com/contentstack/sdk/Stack.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class Stack {
3232
protected LinkedHashMap<String, Object> headers;
3333
protected Config config;
3434
protected String contentType;
35+
protected String globalField;
3536
protected String livePreviewEndpoint;
3637
protected APIService service;
3738
protected String apiKey;
@@ -212,6 +213,25 @@ public ContentType contentType(String contentTypeUid) {
212213
return ct;
213214
}
214215

216+
public GlobalField globalField(String globalFieldUid) {
217+
this.globalField = globalFieldUid;
218+
GlobalField gf = new GlobalField(globalFieldUid);
219+
gf.setStackInstance(this);
220+
return gf;
221+
}
222+
223+
public void getGlobalFields(@NotNull JSONObject params, final GlobalFieldsCallback callback) {
224+
Iterator<String> keys = params.keys();
225+
while (keys.hasNext()) {
226+
String key = keys.next();
227+
Object value = params.opt(key);
228+
params.put(key, value);
229+
}
230+
if (this.headers.containsKey(ENVIRONMENT)) {
231+
params.put(ENVIRONMENT, this.headers.get(ENVIRONMENT));
232+
}
233+
fetchGlobalFields("global_fields", params, this.headers, callback);
234+
}
215235
/**
216236
* Assets refer to all the media files (images, videos, PDFs, audio files, and so on) uploaded in your Contentstack
217237
* repository for future use. These files can be attached and used in multiple entries.
@@ -547,6 +567,17 @@ private void fetchContentTypes(String urlString, JSONObject
547567
}
548568
}
549569

570+
private void fetchGlobalFields(String urlString, JSONObject
571+
globalFieldParam, HashMap<String, Object> headers,
572+
GlobalFieldsCallback callback) {
573+
if (callback != null) {
574+
HashMap<String, Object> queryParam = getUrlParams(globalFieldParam);
575+
String requestInfo = REQUEST_CONTROLLER.GLOBALFIELDS.toString();
576+
new CSBackgroundTask(this, Constants.FETCHGLOBALFIELDS, urlString, headers, queryParam, requestInfo,
577+
callback);
578+
}
579+
}
580+
550581
private void fetchFromNetwork(String urlString, JSONObject urlQueries,
551582
HashMap<String, Object> headers, SyncResultCallBack callback) {
552583
if (callback != null) {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.contentstack.sdk;
2+
import org.json.JSONArray;
3+
import org.json.JSONObject;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.Test;
7+
import static org.junit.jupiter.api.Assertions.*;
8+
9+
public class TestGlobalFields {
10+
11+
private GlobalFieldsModel globalFieldsModel;
12+
private final Stack stack = Credentials.getStack();
13+
14+
@BeforeEach
15+
void setUp() {
16+
globalFieldsModel = new GlobalFieldsModel();
17+
}
18+
19+
@Test
20+
void testSetJSONWithNull() {
21+
globalFieldsModel.setJSON(null);
22+
assertNull(globalFieldsModel.getResponse());
23+
assertEquals(0, globalFieldsModel.getResultArray().length());
24+
}
25+
26+
@Test
27+
void testSetJSONWithEmptyObject() {
28+
globalFieldsModel.setJSON(new JSONObject());
29+
assertNull(globalFieldsModel.getResponse());
30+
assertEquals(0, globalFieldsModel.getResultArray().length());
31+
}
32+
33+
@Test
34+
void testFetchGlobalFieldByUid() throws IllegalAccessException {
35+
GlobalField globalField = stack.globalField("specific_gf_uid");
36+
JSONObject paramObj = new JSONObject();
37+
paramObj.put("ctKeyOne", "ctKeyValue1");
38+
paramObj.put("ctKeyTwo", "ctKeyValue2");
39+
globalField.fetch(paramObj, new GlobalFieldsCallback() {
40+
@Override
41+
public void onCompletion(GlobalFieldsModel model, Error error) {
42+
JSONArray resp = model.getResultArray();
43+
Assertions.assertTrue(resp.isEmpty());
44+
}
45+
});
46+
}
47+
48+
@Test
49+
void testFetchAllGlobalFields() {
50+
JSONObject param = new JSONObject();
51+
stack.getGlobalFields(param, new GlobalFieldsCallback() {
52+
@Override
53+
public void onCompletion(GlobalFieldsModel globalFieldsModel, Error error) {
54+
assertTrue(globalFieldsModel.getResultArray() instanceof JSONArray);
55+
assertNotNull(((JSONArray) globalFieldsModel.getResponse()).length());
56+
57+
}
58+
});
59+
}
60+
}

0 commit comments

Comments
 (0)