This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new ab8bb930ec FINERACT-2333: Batch API - Support date format: from array
to string
ab8bb930ec is described below
commit ab8bb930ec932715ce44d57022baad5615d5c78f
Author: Adam Saghy <[email protected]>
AuthorDate: Mon Jul 21 20:15:49 2025 +0200
FINERACT-2333: Batch API - Support date format: from array to string
---
.../fineract/batch/service/ResolutionHelper.java | 31 +++++---
.../batch/service/ResolutionHelperTest.java | 90 ++++++++++++++++++++++
2 files changed, 110 insertions(+), 11 deletions(-)
diff --git
a/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
b/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
index 332041706e..672f7927c4 100644
---
a/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
+++
b/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
@@ -25,6 +25,8 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -134,7 +136,7 @@ public class ResolutionHelper {
// parameter
for (Map.Entry<String, JsonElement> element :
jsonRequestBody.entrySet()) {
final String key = element.getKey();
- final JsonElement value =
resolveDependentVariables(element.getValue(), responseCtx);
+ final JsonElement value =
resolveDependentVariables(element.getValue(), requestBody, responseCtx);
jsonResultBody.add(key, value);
}
// Set the body after dependency resolution
@@ -163,44 +165,51 @@ public class ResolutionHelper {
return request;
}
- private JsonElement resolveDependentVariables(final JsonElement
jsonElement, final ReadContext responseCtx) {
+ private JsonElement resolveDependentVariables(final JsonElement
jsonElement, final String requestBody, final ReadContext responseCtx) {
JsonElement value;
if (jsonElement.isJsonObject()) {
final JsonObject jsObject = jsonElement.getAsJsonObject();
- value = processJsonObject(jsObject, responseCtx);
+ value = processJsonObject(jsObject, requestBody, responseCtx);
} else if (jsonElement.isJsonArray()) {
final JsonArray jsElementArray = jsonElement.getAsJsonArray();
- value = processJsonArray(jsElementArray, responseCtx);
+ value = processJsonArray(jsElementArray, requestBody, responseCtx);
} else if (jsonElement.isJsonNull()) {
// No further processing of null values
value = jsonElement;
} else {
- value = processJsonPrimitive(jsonElement, responseCtx);
+ value = processJsonPrimitive(jsonElement, requestBody,
responseCtx);
}
return value;
}
- private JsonElement processJsonObject(final JsonObject jsObject, final
ReadContext responseCtx) {
+ private JsonElement processJsonObject(final JsonObject jsObject, final
String requestBody, final ReadContext responseCtx) {
JsonObject valueObj = new JsonObject();
for (Map.Entry<String, JsonElement> element : jsObject.entrySet()) {
- valueObj.add(element.getKey(),
resolveDependentVariables(element.getValue(), responseCtx));
+ valueObj.add(element.getKey(),
resolveDependentVariables(element.getValue(), requestBody, responseCtx));
}
return valueObj;
}
- private JsonArray processJsonArray(final JsonArray elementArray, final
ReadContext responseCtx) {
+ private JsonArray processJsonArray(final JsonArray elementArray, final
String requestBody, final ReadContext responseCtx) {
JsonArray valueArr = new JsonArray();
for (JsonElement element : elementArray) {
- valueArr.add(resolveDependentVariables(element, responseCtx));
+ valueArr.add(resolveDependentVariables(element, requestBody,
responseCtx));
}
return valueArr;
}
- private JsonElement processJsonPrimitive(final JsonElement element, final
ReadContext responseCtx) {
+ private JsonElement processJsonPrimitive(final JsonElement element, final
String requestBody, final ReadContext responseCtx) {
JsonElement value = element;
if (element instanceof JsonPrimitive) {
String paramVal = element.getAsString();
- if (paramVal.contains("$.")) {
+ if (paramVal.contains("$[ARRAYDATE]")) {
+ String resolvableParamVal = paramVal.replace("$[ARRAYDATE]",
"$");
+ final String resParamValue =
responseCtx.read(resolvableParamVal).toString();
+ JsonArray date = (JsonArray)
this.fromJsonHelper.parse(resParamValue);
+ String dateFormat = JsonPath.read(requestBody, "$.dateFormat");
+ return new
JsonPrimitive(DateTimeFormatter.ofPattern(dateFormat)
+ .format(LocalDate.of(date.get(0).getAsInt(),
date.get(1).getAsInt(), date.get(2).getAsInt())));
+ } else if (paramVal.contains("$.")) {
// Get the value of the parameter from parent response
final String resParamValue =
responseCtx.read(paramVal).toString();
value = this.fromJsonHelper.parse(resParamValue);
diff --git
a/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
b/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
index 1a735b9d6f..fcccb567d1 100644
---
a/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
+++
b/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
@@ -21,6 +21,7 @@ package org.apache.fineract.batch.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -104,4 +105,93 @@ public class ResolutionHelperTest {
assertEquals("{\"key1\":\"value1\",\"key2\":{\"subKey\":false},\"key3\":[1,2,3],\"key4\":null}",
resolvedRequest.getBody());
assertEquals("/resource/id", resolvedRequest.getRelativeUrl());
}
+
+ @Test
+ void testResolveRequestWithArrayDateParameter() {
+ // Test resolving a JSON primitive with array date format
+ BatchRequest batchRequest = new BatchRequest();
+ batchRequest
+ .setBody("{\"dateFormat\":\"dd MMMM
yyyy\",\"startDate\":\"$[ARRAYDATE].dates[0]\",\"endDate\":\"$[ARRAYDATE].dates[1]\"}");
+ batchRequest.setRelativeUrl("/resource/endpoint");
+
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{\"dates\":[[2023,5,15],[2023,6,15]]}");
+
+ // Mock the response context
+ ReadContext readContext = mock(ReadContext.class);
+ when(readContext.read("$.dates[0]")).thenReturn(new int[] { 2023, 5,
15 });
+ when(readContext.read("$.dates[1]")).thenReturn(new int[] { 2023, 6,
15 });
+
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+
+ // Check for possible date formats
+ String body = resolvedRequest.getBody();
+ assertTrue(body.contains("\"startDate\":\"15 May 2023\"") ||
body.contains("\"startDate\":\"15 May, 2023\"")
+ || body.contains("\"startDate\":\"15 May. 2023\"") ||
body.contains("\"startDate\":\"May 15, 2023\""));
+ assertTrue(body.contains("\"endDate\":\"15 June 2023\"") ||
body.contains("\"endDate\":\"15 June, 2023\"")
+ || body.contains("\"endDate\":\"15 Jun. 2023\"") ||
body.contains("\"endDate\":\"June 15, 2023\""));
+ }
+
+ @Test
+ void testResolveRequestWithNestedJsonPrimitives() {
+ // Test resolving nested JSON primitives
+ BatchRequest batchRequest = new BatchRequest();
+
batchRequest.setBody("{\"nested\":{\"key1\":\"$.value1\",\"key2\":123,\"key3\":true,\"key4\":null}}");
+ batchRequest.setRelativeUrl("/resource/endpoint");
+
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{\"value1\":\"resolvedValue\"}");
+
+ // Mock the response context
+ ReadContext readContext = mock(ReadContext.class);
+ when(readContext.read("$.value1")).thenReturn("resolvedValue");
+
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+
assertEquals("{\"nested\":{\"key1\":\"resolvedValue\",\"key2\":123,\"key3\":true,\"key4\":null}}",
resolvedRequest.getBody());
+ }
+
+ @Test
+ void testResolveRequestWithPrimitiveTypes() {
+ // Test resolving different primitive types
+ BatchRequest batchRequest = new BatchRequest();
+
batchRequest.setBody("{\"string\":\"text\",\"number\":123.45,\"boolean\":true,\"nullValue\":null}");
+ batchRequest.setRelativeUrl("/resource/endpoint");
+
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{}"); // Empty response as we're not using any
references
+
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+
+ // The JSON might be reordered, so we need to check for existence of
each key-value pair
+ String body = resolvedRequest.getBody();
+ assertTrue(body.contains("\"string\":\"text\""));
+ assertTrue(body.contains("\"number\":123.45"));
+ assertTrue(body.contains("\"boolean\":true"));
+ assertTrue(body.contains("\"nullValue\":null"));
+ }
+
+ @Test
+ void testResolveRequestWithComplexReferencePath() {
+ // Test resolving with complex reference paths
+ BatchRequest batchRequest = new BatchRequest();
+ batchRequest.setBody("{\"user\": {\"name\":
\"$.userData.name\",\"age\": \"$.userData.age\"}}");
+ batchRequest.setRelativeUrl("/users/$.userData.id");
+
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{\"userData\":{\"id\": 42,\"name\":
\"John\",\"age\": 30}}");
+
+ // Mock the response context
+ ReadContext readContext = mock(ReadContext.class);
+ when(readContext.read("$.userData.name")).thenReturn("John");
+ when(readContext.read("$.userData.age")).thenReturn(30);
+ when(readContext.read("$.userData.id")).thenReturn(42);
+
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+ assertEquals("{\"user\":{\"name\":\"John\",\"age\":30}}",
resolvedRequest.getBody());
+ assertEquals("/users/42", resolvedRequest.getRelativeUrl());
+ }
}