Skip to content

Commit

Permalink
FINERACT-2081: Fix "resolve dependent variable" logic of Batch reques…
Browse files Browse the repository at this point in the history
…t resolver
  • Loading branch information
adamsaghy committed Jan 22, 2025
1 parent 384a52b commit 6348140
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import java.util.ArrayList;
Expand Down Expand Up @@ -133,7 +134,7 @@ public BatchRequest resolveRequest(final BatchRequest request, final BatchRespon
// parameter
for (Map.Entry<String, JsonElement> element : jsonRequestBody.entrySet()) {
final String key = element.getKey();
final JsonElement value = resolveDependentVariables(element, responseCtx);
final JsonElement value = resolveDependentVariables(element.getValue(), responseCtx);
jsonResultBody.add(key, value);
}
// Set the body after dependency resolution
Expand Down Expand Up @@ -162,52 +163,48 @@ public BatchRequest resolveRequest(final BatchRequest request, final BatchRespon
return request;
}

private JsonElement resolveDependentVariables(final Map.Entry<String, JsonElement> entryElement, final ReadContext responseCtx) {
private JsonElement resolveDependentVariables(final JsonElement jsonElement, final ReadContext responseCtx) {
JsonElement value;
final JsonElement element = entryElement.getValue();
if (element.isJsonObject()) {
final JsonObject jsObject = element.getAsJsonObject();
if (jsonElement.isJsonObject()) {
final JsonObject jsObject = jsonElement.getAsJsonObject();
value = processJsonObject(jsObject, responseCtx);
} else if (element.isJsonArray()) {
final JsonArray jsElementArray = element.getAsJsonArray();
} else if (jsonElement.isJsonArray()) {
final JsonArray jsElementArray = jsonElement.getAsJsonArray();
value = processJsonArray(jsElementArray, responseCtx);
} else if (element.isJsonNull()) {
} else if (jsonElement.isJsonNull()) {
// No further processing of null values
value = element;
value = jsonElement;
} else {
value = resolveDependentVariable(element, responseCtx);
value = processJsonPrimitive(jsonElement, responseCtx);
}
return value;
}

private JsonElement processJsonObject(final JsonObject jsObject, final ReadContext responseCtx) {
JsonObject valueObj = new JsonObject();
for (Map.Entry<String, JsonElement> element : jsObject.entrySet()) {
final String key = element.getKey();
final JsonElement value = resolveDependentVariable(element.getValue(), responseCtx);
valueObj.add(key, value);
valueObj.add(element.getKey(), resolveDependentVariables(element.getValue(), responseCtx));
}
return valueObj;
}

private JsonArray processJsonArray(final JsonArray elementArray, final ReadContext responseCtx) {
JsonArray valueArr = new JsonArray();
for (JsonElement element : elementArray) {
if (element.isJsonObject()) {
final JsonObject jsObject = element.getAsJsonObject();
valueArr.add(processJsonObject(jsObject, responseCtx));
}
valueArr.add(resolveDependentVariables(element, responseCtx));
}
return valueArr;
}

private JsonElement resolveDependentVariable(final JsonElement element, final ReadContext responseCtx) {
private JsonElement processJsonPrimitive(final JsonElement element, final ReadContext responseCtx) {
JsonElement value = element;
String paramVal = element.getAsString();
if (paramVal.contains("$.")) {
// Get the value of the parameter from parent response
final String resParamValue = responseCtx.read(paramVal).toString();
value = this.fromJsonHelper.parse(resParamValue);
if (element instanceof JsonPrimitive) {
String paramVal = element.getAsString();
if (paramVal.contains("$.")) {
// Get the value of the parameter from parent response
final String resParamValue = responseCtx.read(paramVal).toString();
value = this.fromJsonHelper.parse(resParamValue);
}
}
return value;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.jayway.jsonpath.ReadContext;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.batch.exception.BatchReferenceInvalidException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.junit.jupiter.api.Test;

public class ResolutionHelperTest {

private final FromJsonHelper fromJsonHelper = new FromJsonHelper();
private final ResolutionHelper resolutionHelper = new ResolutionHelper(fromJsonHelper);

@Test
void testBuildNodesTreeWithValidRequests() {
List<BatchRequest> requests = new ArrayList<>();
BatchRequest firstRequest = new BatchRequest();
firstRequest.setRequestId(1L);
firstRequest.setBody("{\"key1\": \"value1\", \"key2\": 12, \"key3\": null, \"key4\": false}");
firstRequest.setRelativeUrl("/resource/id");
requests.add(firstRequest);
BatchRequest secondRequest = new BatchRequest();
secondRequest.setRequestId(2L);
secondRequest.setReference(1L);
secondRequest.setRelativeUrl("/resource/id");
secondRequest.setBody("{\"key1\": { \"subKey\": false }, \"key2\": [1,2,3]}");
requests.add(secondRequest);
BatchRequest thirdRequest = new BatchRequest();
thirdRequest.setRequestId(3L);
thirdRequest.setReference(2L);
requests.add(thirdRequest);
List<ResolutionHelper.BatchRequestNode> nodes = resolutionHelper.buildNodesTree(requests);
assertEquals(1, nodes.size());
assertEquals(1, nodes.get(0).getRequest().getRequestId());
assertEquals("{\"key1\": \"value1\", \"key2\": 12, \"key3\": null, \"key4\": false}", nodes.get(0).getRequest().getBody());
assertEquals(1, nodes.get(0).getChildNodes().size());
assertEquals(2, nodes.get(0).getChildNodes().get(0).getRequest().getRequestId());
assertEquals("{\"key1\": { \"subKey\": false }, \"key2\": [1,2,3]}", nodes.get(0).getChildNodes().get(0).getRequest().getBody());
}

@Test
void testBuildNodesTreeWithInvalidReference() {
List<BatchRequest> requests = new ArrayList<>();
BatchRequest invalidRequest = new BatchRequest();
invalidRequest.setRequestId(2L);
// Not existing reference
invalidRequest.setReference(1L);
requests.add(invalidRequest);
assertThrows(BatchReferenceInvalidException.class, () -> resolutionHelper.buildNodesTree(requests));
}

@Test
void testResolveRequestWithValidDependenciesResolveParameterFromResponse() {
BatchRequest batchRequest = new BatchRequest();
batchRequest.setBody("{\"key1\": \"$.value1\"}");
batchRequest.setRelativeUrl("/resource/$.id?key=value");
BatchResponse parentResponse = new BatchResponse();
parentResponse.setBody("{\"value1\": \"resolvedValue\", \"id\": \"123\"}");
ReadContext readContext = mock(ReadContext.class);
when(readContext.read("$.value1")).thenReturn("resolvedValue");
when(readContext.read("$.id")).thenReturn("123");
BatchRequest resolvedRequest = resolutionHelper.resolveRequest(batchRequest, parentResponse);
assertNotNull(resolvedRequest);
assertEquals("{\"key1\":\"resolvedValue\"}", resolvedRequest.getBody());
assertEquals("/resource/123?key=value", resolvedRequest.getRelativeUrl());
}

@Test
void testResolveRequestWithNoDependencies() {
BatchRequest batchRequest = new BatchRequest();
batchRequest.setBody("{\"key1\": \"value1\",\"key2\": { \"subKey\": false }, \"key3\": [1,2,3], \"key4\": null}");
batchRequest.setRelativeUrl("/resource/id");
BatchResponse parentResponse = new BatchResponse();
parentResponse.setBody("{\"value2\": \"not used\"}");
BatchRequest resolvedRequest = resolutionHelper.resolveRequest(batchRequest, parentResponse);
assertNotNull(resolvedRequest);
assertEquals("{\"key1\":\"value1\",\"key2\":{\"subKey\":false},\"key3\":[1,2,3],\"key4\":null}", resolvedRequest.getBody());
assertEquals("/resource/id", resolvedRequest.getRelativeUrl());
}
}

0 comments on commit 6348140

Please sign in to comment.