Skip to content

Commit b7fc5d0

Browse files
committed
FINERACT-2494: Add unit tests for ApiParameterHelper and improve implementation
FINERACT-2494: Refactor ApiParameterHelper to remove duplication and add edge-case tests
1 parent 701cfae commit b7fc5d0

File tree

2 files changed

+233
-27
lines changed

2 files changed

+233
-27
lines changed

fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelper.java

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
package org.apache.fineract.infrastructure.core.api;
2020

2121
import jakarta.ws.rs.core.MultivaluedMap;
22-
import java.util.Arrays;
2322
import java.util.HashSet;
2423
import java.util.Locale;
24+
import java.util.Objects;
2525
import java.util.Set;
2626
import org.apache.commons.lang3.StringUtils;
2727
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
@@ -35,49 +35,58 @@ private ApiParameterHelper() {
3535
}
3636

3737
public static Long commandId(final MultivaluedMap<String, String> queryParams) {
38-
Long id = null;
39-
if (queryParams.getFirst("commandId") != null) {
38+
if (queryParams != null && queryParams.getFirst("commandId") != null) {
4039
final String value = queryParams.getFirst("commandId");
4140
if (StringUtils.isNotBlank(value)) {
42-
id = Long.valueOf(value);
41+
return Long.valueOf(value);
4342
}
4443
}
45-
return id;
44+
return null;
4645
}
4746

4847
public static Set<String> extractFieldsForResponseIfProvided(final MultivaluedMap<String, String> queryParams) {
49-
Set<String> fields = new HashSet<>();
50-
String commaSeparatedParameters = "";
51-
if (queryParams.getFirst("fields") != null) {
52-
commaSeparatedParameters = queryParams.getFirst("fields");
53-
if (StringUtils.isNotBlank(commaSeparatedParameters)) {
54-
fields = new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*"))); // NOSONAR
55-
}
56-
}
57-
return fields;
48+
return extractParameters(queryParams, "fields");
5849
}
5950

6051
public static Set<String> extractAssociationsForResponseIfProvided(final MultivaluedMap<String, String> queryParams) {
61-
Set<String> fields = new HashSet<>();
62-
String commaSeparatedParameters = "";
63-
if (queryParams.getFirst("associations") != null) {
64-
commaSeparatedParameters = queryParams.getFirst("associations");
65-
if (StringUtils.isNotBlank(commaSeparatedParameters)) {
66-
fields = new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*"))); // NOSONAR
52+
return extractParameters(queryParams, "associations");
53+
}
54+
55+
private static Set<String> extractParameters(final MultivaluedMap<String, String> queryParams, final String key) {
56+
Objects.requireNonNull(queryParams, "queryParams map cannot be null");
57+
Set<String> parameters = new HashSet<>();
58+
if (queryParams.get(key) != null) {
59+
for (String paramValue : queryParams.get(key)) {
60+
if (StringUtils.isNotBlank(paramValue)) {
61+
String[] split = StringUtils.split(paramValue, ",");
62+
for (String s : split) {
63+
if (StringUtils.isNotBlank(s)) {
64+
parameters.add(s.trim());
65+
}
66+
}
67+
}
6768
}
6869
}
69-
return fields;
70+
return parameters;
7071
}
7172

72-
public static void excludeAssociationsForResponseIfProvided(final String commaSeparatedParameters, Set<String> fields) {
73-
if (StringUtils.isNotBlank(commaSeparatedParameters)) {
74-
fields.removeAll(new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*")))); // NOSONAR
73+
public static void excludeAssociationsForResponseIfProvided(final MultivaluedMap<String, String> queryParams,
74+
final Set<String> fields) {
75+
Objects.requireNonNull(queryParams, "queryParams map cannot be null");
76+
String exclude = queryParams.getFirst("exclude");
77+
if (StringUtils.isNotBlank(exclude)) {
78+
excludeAssociationsForResponseIfProvided(exclude, fields);
7579
}
7680
}
7781

78-
public static void excludeAssociationsForResponseIfProvided(final MultivaluedMap<String, String> queryParams, Set<String> fields) {
79-
if (queryParams.getFirst("exclude") != null) {
80-
excludeAssociationsForResponseIfProvided(queryParams.getFirst("exclude"), fields);
82+
public static void excludeAssociationsForResponseIfProvided(final String commaSeparatedParameters, final Set<String> fields) {
83+
if (StringUtils.isNotBlank(commaSeparatedParameters)) {
84+
String[] split = StringUtils.split(commaSeparatedParameters, ",");
85+
for (String s : split) {
86+
if (StringUtils.isNotBlank(s)) {
87+
fields.remove(s.trim());
88+
}
89+
}
8190
}
8291
}
8392

@@ -138,4 +147,24 @@ public static boolean genericResultSet(final MultivaluedMap<String, String> quer
138147
public static boolean genericResultSetPassed(final MultivaluedMap<String, String> queryParams) {
139148
return queryParams.getFirst(GENERIC_RESULT_SET) != null;
140149
}
150+
151+
public static Integer extractLimitParameter(final MultivaluedMap<String, String> queryParameters) {
152+
Objects.requireNonNull(queryParameters, "queryParameters map cannot be null");
153+
final String limit = queryParameters.getFirst("limit");
154+
return StringUtils.isNotBlank(limit) ? Integer.valueOf(limit.trim()) : null;
155+
}
156+
157+
public static Integer extractOffsetParameter(final MultivaluedMap<String, String> queryParameters) {
158+
Objects.requireNonNull(queryParameters, "queryParameters map cannot be null");
159+
final String offset = queryParameters.getFirst("offset");
160+
return StringUtils.isNotBlank(offset) ? Integer.valueOf(offset.trim()) : null;
161+
}
162+
163+
public static String extractOrderBy(MultivaluedMap<String, String> queryParameters) {
164+
return (queryParameters != null) ? queryParameters.getFirst("orderBy") : null;
165+
}
166+
167+
public static String extractSortOrder(MultivaluedMap<String, String> queryParameters) {
168+
return (queryParameters != null) ? queryParameters.getFirst("sortOrder") : null;
169+
}
141170
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.core.api;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertNull;
23+
import static org.junit.jupiter.api.Assertions.assertThrows;
24+
import static org.junit.jupiter.api.Assertions.assertTrue;
25+
26+
import jakarta.ws.rs.core.MultivaluedHashMap;
27+
import jakarta.ws.rs.core.MultivaluedMap;
28+
import java.util.Set;
29+
import org.junit.jupiter.api.Test;
30+
31+
class ApiParameterHelperTest {
32+
33+
@Test
34+
void testExtractFieldsForResponseIfProvided() {
35+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
36+
queryParams.add("fields", "id,name,description");
37+
38+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
39+
assertEquals(3, result.size());
40+
assertTrue(result.contains("id"));
41+
assertTrue(result.contains("name"));
42+
assertTrue(result.contains("description"));
43+
}
44+
45+
@Test
46+
void testExtractFieldsWhenMissing() {
47+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
48+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
49+
assertTrue(result.isEmpty());
50+
}
51+
52+
@Test
53+
void testExtractPaginationParameters() {
54+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
55+
queryParameters.add("offset", "10");
56+
queryParameters.add("limit", "100");
57+
58+
assertEquals(10, ApiParameterHelper.extractOffsetParameter(queryParameters));
59+
assertEquals(100, ApiParameterHelper.extractLimitParameter(queryParameters));
60+
}
61+
62+
@Test
63+
void testExtractPaginationInvalidNumbers() {
64+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
65+
queryParameters.add("offset", "abc");
66+
queryParameters.add("limit", "xyz");
67+
68+
assertThrows(NumberFormatException.class, () -> ApiParameterHelper.extractOffsetParameter(queryParameters));
69+
70+
assertThrows(NumberFormatException.class, () -> ApiParameterHelper.extractLimitParameter(queryParameters));
71+
}
72+
73+
@Test
74+
void testExtractPaginationWithNegativeValues() {
75+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
76+
queryParameters.add("offset", "-1");
77+
queryParameters.add("limit", "-10");
78+
79+
assertEquals(-1, ApiParameterHelper.extractOffsetParameter(queryParameters));
80+
assertEquals(-10, ApiParameterHelper.extractLimitParameter(queryParameters));
81+
}
82+
83+
@Test
84+
void testExtractSortingParameters() {
85+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
86+
queryParameters.add("orderBy", "name");
87+
queryParameters.add("sortOrder", "DESC");
88+
89+
assertEquals("name", ApiParameterHelper.extractOrderBy(queryParameters));
90+
assertEquals("DESC", ApiParameterHelper.extractSortOrder(queryParameters));
91+
}
92+
93+
@Test
94+
void testExtractSortingWhenMissing() {
95+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
96+
97+
assertNull(ApiParameterHelper.extractOrderBy(queryParameters));
98+
assertNull(ApiParameterHelper.extractSortOrder(queryParameters));
99+
}
100+
101+
@Test
102+
void testNullInputHandling() {
103+
assertThrows(NullPointerException.class, () -> ApiParameterHelper.extractFieldsForResponseIfProvided(null));
104+
}
105+
106+
@Test
107+
void testExtractFieldsWithWhitespace() {
108+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
109+
queryParams.add("fields", "id, name , description");
110+
111+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
112+
113+
assertTrue(result.contains("id"));
114+
assertTrue(result.contains("name"));
115+
assertTrue(result.contains("description"));
116+
}
117+
118+
@Test
119+
void testExtractSortingWithEmptyValues() {
120+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
121+
queryParameters.add("orderBy", "");
122+
assertEquals("", ApiParameterHelper.extractOrderBy(queryParameters));
123+
}
124+
125+
@Test
126+
void shouldHandleDeduplication() {
127+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
128+
queryParams.add("fields", "id,name,id");
129+
130+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
131+
assertEquals(2, result.size());
132+
assertTrue(result.contains("id"));
133+
assertTrue(result.contains("name"));
134+
}
135+
136+
@Test
137+
void shouldHandleEmptyAndBlankValues() {
138+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
139+
queryParams.add("fields", "id,, ,name");
140+
141+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
142+
assertEquals(2, result.size());
143+
assertTrue(result.contains("id"));
144+
assertTrue(result.contains("name"));
145+
}
146+
147+
@Test
148+
void shouldHandleMixedMultiValueAndCommas() {
149+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
150+
queryParams.add("fields", "id,name");
151+
queryParams.add("fields", "description, status");
152+
153+
Set<String> result = ApiParameterHelper.extractFieldsForResponseIfProvided(queryParams);
154+
assertEquals(4, result.size());
155+
assertTrue(result.contains("status"));
156+
}
157+
158+
@Test
159+
void testExtractPaginationWithLargeNumbers() {
160+
MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
161+
queryParameters.add("limit", "3000000000");
162+
assertThrows(NumberFormatException.class, () -> ApiParameterHelper.extractLimitParameter(queryParameters));
163+
}
164+
165+
@Test
166+
void testExtractAssociationsForResponseIfProvided() {
167+
MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>();
168+
queryParams.add("associations", "all, transactions");
169+
170+
Set<String> result = ApiParameterHelper.extractAssociationsForResponseIfProvided(queryParams);
171+
172+
assertEquals(2, result.size());
173+
assertTrue(result.contains("all"));
174+
assertTrue(result.contains("transactions"));
175+
}
176+
177+
}

0 commit comments

Comments
 (0)