From d28d87fea62b45def9aa1ddeb3fd011728cbaa65 Mon Sep 17 00:00:00 2001 From: Ambika Date: Sat, 21 Mar 2026 11:42:34 +0530 Subject: [PATCH] FINERACT-2494: Add ApiParameterHelper tests --- .../core/api/ApiParameterHelper.java | 145 +++++++----- .../core/api/ApiParameterHelperTest.java | 220 ++++++++++++++++++ 2 files changed, 306 insertions(+), 59 deletions(-) create mode 100644 fineract-core/src/test/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelperTest.java diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelper.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelper.java index db4d7f060f6..26a28ca1a64 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelper.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelper.java @@ -23,119 +23,146 @@ import java.util.HashSet; import java.util.Locale; import java.util.Set; +import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper; public final class ApiParameterHelper { private static final String GENERIC_RESULT_SET = "genericResultSet"; + + // Optimized for performance and Error Prone compliance + private static final Pattern COMMA_SEPARATOR = Pattern.compile("\\s*,\\s*"); private ApiParameterHelper() { - } + // ---------------- COMMAND ID ---------------- + public static Long commandId(final MultivaluedMap queryParams) { - Long id = null; - if (queryParams.getFirst("commandId") != null) { + if (queryParams != null && queryParams.getFirst("commandId") != null) { final String value = queryParams.getFirst("commandId"); if (StringUtils.isNotBlank(value)) { - id = Long.valueOf(value); + try { + return Long.valueOf(value); + } catch (NumberFormatException e) { + return null; + } } } - return id; + return null; } + // ---------------- FIELDS ---------------- + public static Set extractFieldsForResponseIfProvided(final MultivaluedMap queryParams) { - Set fields = new HashSet<>(); - String commaSeparatedParameters = ""; - if (queryParams.getFirst("fields") != null) { - commaSeparatedParameters = queryParams.getFirst("fields"); - if (StringUtils.isNotBlank(commaSeparatedParameters)) { - fields = new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*"))); // NOSONAR + if (queryParams != null && queryParams.getFirst("fields") != null) { + String value = queryParams.getFirst("fields"); + if (StringUtils.isNotBlank(value)) { + return new HashSet<>(Arrays.asList(COMMA_SEPARATOR.split(value))); } } - return fields; + return new HashSet<>(); } + // ---------------- ASSOCIATIONS ---------------- + public static Set extractAssociationsForResponseIfProvided(final MultivaluedMap queryParams) { - Set fields = new HashSet<>(); - String commaSeparatedParameters = ""; - if (queryParams.getFirst("associations") != null) { - commaSeparatedParameters = queryParams.getFirst("associations"); - if (StringUtils.isNotBlank(commaSeparatedParameters)) { - fields = new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*"))); // NOSONAR + if (queryParams != null && queryParams.getFirst("associations") != null) { + String value = queryParams.getFirst("associations"); + if (StringUtils.isNotBlank(value)) { + return new HashSet<>(Arrays.asList(COMMA_SEPARATOR.split(value))); } } - return fields; + return new HashSet<>(); } public static void excludeAssociationsForResponseIfProvided(final String commaSeparatedParameters, Set fields) { - if (StringUtils.isNotBlank(commaSeparatedParameters)) { - fields.removeAll(new HashSet<>(Arrays.asList(commaSeparatedParameters.split("\\s*,\\s*")))); // NOSONAR + if (StringUtils.isNotBlank(commaSeparatedParameters) && fields != null) { + fields.removeAll(new HashSet<>(Arrays.asList(COMMA_SEPARATOR.split(commaSeparatedParameters)))); } } - public static void excludeAssociationsForResponseIfProvided(final MultivaluedMap queryParams, Set fields) { - if (queryParams.getFirst("exclude") != null) { + public static void excludeAssociationsForResponseIfProvided(final MultivaluedMap queryParams, + Set fields) { + if (queryParams != null && queryParams.getFirst("exclude") != null) { excludeAssociationsForResponseIfProvided(queryParams.getFirst("exclude"), fields); } } + // ---------------- LOCALE ---------------- + public static Locale extractLocale(final MultivaluedMap queryParams) { - Locale locale = null; - if (queryParams.getFirst("locale") != null) { + if (queryParams != null && queryParams.getFirst("locale") != null) { final String localeAsString = queryParams.getFirst("locale"); - locale = JsonParserHelper.localeFromString(localeAsString); + if (StringUtils.isNotBlank(localeAsString)) { + try { + return JsonParserHelper.localeFromString(localeAsString); + } catch (Exception e) { + return null; + } + } } - return locale; + return null; } - public static boolean parameterType(final MultivaluedMap queryParams) { - boolean parameterType = false; - if (queryParams.getFirst("parameterType") != null) { - final String parameterTypeValue = queryParams.getFirst("parameterType"); - parameterType = "true".equalsIgnoreCase(parameterTypeValue); + // ---------------- PAGINATION ---------------- + + public static Integer offset(final MultivaluedMap params) { + if (params != null && params.getFirst("offset") != null) { + try { + return Math.max(0, Integer.parseInt(params.getFirst("offset"))); + } catch (NumberFormatException e) { + return 0; + } } - return parameterType; + return 0; } - public static boolean template(final MultivaluedMap queryParams) { - boolean template = false; - if (queryParams.getFirst("template") != null) { - final String prettyPrintValue = queryParams.getFirst("template"); - template = "true".equalsIgnoreCase(prettyPrintValue); + public static Integer limit(final MultivaluedMap params) { + if (params != null && params.getFirst("limit") != null) { + try { + int limit = Integer.parseInt(params.getFirst("limit")); + return limit > 0 ? limit : 200; // Standard Fineract default + } catch (NumberFormatException e) { + return 200; + } } - return template; + return 200; + } + + // ---------------- BOOLEAN FLAGS ---------------- + + public static boolean parameterType(final MultivaluedMap queryParams) { + return isTrue(queryParams, "parameterType"); + } + + public static boolean template(final MultivaluedMap queryParams) { + return isTrue(queryParams, "template"); } public static boolean makerCheckerable(final MultivaluedMap queryParams) { - boolean makerCheckerable = false; - if (queryParams.getFirst("makerCheckerable") != null) { - final String prettyPrintValue = queryParams.getFirst("makerCheckerable"); - makerCheckerable = "true".equalsIgnoreCase(prettyPrintValue); - } - return makerCheckerable; + return isTrue(queryParams, "makerCheckerable"); } public static boolean includeJson(final MultivaluedMap queryParams) { - boolean includeJson = false; - if (queryParams.getFirst("includeJson") != null) { - final String includeJsonValue = queryParams.getFirst("includeJson"); - includeJson = "true".equalsIgnoreCase(includeJsonValue); - } - return includeJson; + return isTrue(queryParams, "includeJson"); } public static boolean genericResultSet(final MultivaluedMap queryParams) { - boolean genericResultSet = false; - if (queryParams.getFirst(GENERIC_RESULT_SET) != null) { - final String genericResultSetValue = queryParams.getFirst(GENERIC_RESULT_SET); - genericResultSet = "true".equalsIgnoreCase(genericResultSetValue); - } - return genericResultSet; + return isTrue(queryParams, GENERIC_RESULT_SET); } public static boolean genericResultSetPassed(final MultivaluedMap queryParams) { - return queryParams.getFirst(GENERIC_RESULT_SET) != null; + return queryParams != null && queryParams.getFirst(GENERIC_RESULT_SET) != null; + } + + // ---------------- HELPER ---------------- + + private static boolean isTrue(final MultivaluedMap queryParams, String key) { + if (queryParams != null && queryParams.getFirst(key) != null) { + return "true".equalsIgnoreCase(queryParams.getFirst(key)); + } + return false; } -} +} \ No newline at end of file diff --git a/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelperTest.java b/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelperTest.java new file mode 100644 index 00000000000..2f2731d5473 --- /dev/null +++ b/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/api/ApiParameterHelperTest.java @@ -0,0 +1,220 @@ +/** + * 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.infrastructure.core.api; + +import static org.junit.jupiter.api.Assertions.*; + +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.MultivaluedMap; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class ApiParameterHelperTest { + + // ---------------- COMMAND ID ---------------- + + @Test + void shouldReturnCommandId_whenValid() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("commandId", "123"); + + assertEquals(123L, ApiParameterHelper.commandId(params)); + } + + @Test + void shouldReturnNullCommandId_whenMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + + assertNull(ApiParameterHelper.commandId(params)); + } + + @Test + void shouldReturnNullCommandId_whenInvalid() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("commandId", "abc"); + + assertNull(ApiParameterHelper.commandId(params)); + } + + // ---------------- FIELDS ---------------- + + @Test + void shouldExtractFields_whenValid() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("fields", "id,name,description"); + + Set fields = ApiParameterHelper.extractFieldsForResponseIfProvided(params); + + assertEquals(3, fields.size()); + assertTrue(fields.contains("id")); + assertTrue(fields.contains("name")); + assertTrue(fields.contains("description")); + } + + @Test + void shouldReturnEmptyFields_whenEmpty() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("fields", ""); + + Set fields = ApiParameterHelper.extractFieldsForResponseIfProvided(params); + + assertTrue(fields.isEmpty()); + } + + @Test + void shouldReturnEmptyFields_whenMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + + Set fields = ApiParameterHelper.extractFieldsForResponseIfProvided(params); + + assertTrue(fields.isEmpty()); + } + + // ---------------- BOOLEAN FLAGS ---------------- + + @Test + void shouldReturnTrue_whenTemplateTrue() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("template", "true"); + + assertTrue(ApiParameterHelper.template(params)); + } + + @Test + void shouldReturnFalse_whenTemplateFalse() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("template", "false"); + + assertFalse(ApiParameterHelper.template(params)); + } + + @Test + void shouldReturnFalse_whenTemplateMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + + assertFalse(ApiParameterHelper.template(params)); + } + + @Test + void shouldReturnFalse_whenBooleanInvalid() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("template", "random"); + + assertFalse(ApiParameterHelper.template(params)); + } + + @Test + void shouldHandleMakerCheckerableFlag() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("makerCheckerable", "false"); + + assertFalse(ApiParameterHelper.makerCheckerable(params)); + } + + // ---------------- LOCALE ---------------- + + @Test + void shouldExtractLocale_whenValid() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("locale", "en"); + + assertNotNull(ApiParameterHelper.extractLocale(params)); + } + + @Test + void shouldReturnNullLocale_whenMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + + assertNull(ApiParameterHelper.extractLocale(params)); + } + + // ---------------- INTEGRATION SCENARIO ---------------- + + @Test + void shouldHandleMultipleParametersTogether() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("commandId", "999"); + params.add("template", "true"); + params.add("fields", "id,name"); + + assertEquals(999L, ApiParameterHelper.commandId(params)); + assertTrue(ApiParameterHelper.template(params)); + + Set fields = ApiParameterHelper.extractFieldsForResponseIfProvided(params); + assertEquals(2, fields.size()); + } + + // ---------------- PAGINATION (OFFSET) ---------------- + + @Test + void shouldReturnDefaultOffset_whenMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + assertEquals(0, ApiParameterHelper.offset(params)); + } + + @Test + void shouldReturnValidOffset_whenProvided() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("offset", "10"); + assertEquals(10, ApiParameterHelper.offset(params)); + } + + @Test + void shouldHandleNegativeOffset() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("offset", "-5"); + assertEquals(0, ApiParameterHelper.offset(params)); + } + + @Test + void shouldHandleInvalidOffset() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("offset", "abc"); + assertEquals(0, ApiParameterHelper.offset(params)); + } + + // ---------------- LIMIT ---------------- + + @Test + void shouldReturnDefaultLimit_whenMissing() { + MultivaluedMap params = new MultivaluedHashMap<>(); + assertEquals(200, ApiParameterHelper.limit(params)); + } + + @Test + void shouldReturnValidLimit_whenProvided() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("limit", "50"); + assertEquals(50, ApiParameterHelper.limit(params)); + } + + @Test + void shouldHandleNegativeLimit() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("limit", "-10"); + assertEquals(200, ApiParameterHelper.limit(params)); + } + + @Test + void shouldHandleInvalidLimit() { + MultivaluedMap params = new MultivaluedHashMap<>(); + params.add("limit", "xyz"); + assertEquals(200, ApiParameterHelper.limit(params)); + } +} \ No newline at end of file