diff --git a/boot/platform/src/main/java/com/plate/boot/commons/exception/JsonException.java b/boot/platform/src/main/java/com/plate/boot/commons/exception/JsonException.java
index 6f753d61..af39f90e 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/exception/JsonException.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/exception/JsonException.java
@@ -3,18 +3,44 @@
import java.io.IOException;
/**
- * @author Alex bob
+ * Exception class specifically designed to handle JSON processing errors, extending {@link RestServerException}.
+ * This exception is typically thrown when there is an issue with parsing or generating JSON data.
*/
public class JsonException extends RestServerException {
+ /**
+ * Constructs a new {@code JsonException} instance initialized with a default status code of 500 and a predefined error message,
+ * wrapping the provided {@link IOException} which represents a JSON processing error.
+ *
+ * @param jsonProcessingException The {@link IOException} that was encountered during JSON processing, providing specifics about the processing failure.
+ */
public JsonException(IOException jsonProcessingException) {
this(500, "Json processing exception", jsonProcessingException);
}
+ /**
+ * Constructs a new {@code JsonException} with a specified status code, error message, and additional details.
+ * This exception is typically utilized to wrap issues encountered during JSON processing, adding a layer of specificity
+ * over the broader {@link RestServerException}.
+ *
+ * @param status The HTTP status code representing the type of error occurred. This helps in categorizing the exception.
+ * @param message A human-readable description of the error, providing context about what went wrong during JSON processing.
+ * @param msg An optional object containing further information or metadata related to the error, which can assist in diagnosing the issue.
+ */
public JsonException(int status, String message, Object msg) {
super(status, message, msg);
}
+ /**
+ * Constructs and returns a new {@code JsonException} instance wrapping the provided {@link IOException},
+ * which is indicative of a JSON processing error. This method is a convenience factory for creating
+ * {@code JsonException} objects without needing to explicitly reference the constructor arguments.
+ *
+ * @param jsonProcessingException The {@link IOException} that occurred during JSON processing,
+ * providing details about the processing error.
+ * @return A new instance of {@code JsonException} initialized with the given {@code IOException}
+ * as the cause, carrying a default status code and message indicative of a JSON processing failure.
+ */
public static JsonException withError(IOException jsonProcessingException) {
return new JsonException(jsonProcessingException);
}
diff --git a/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java b/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java
index d171366b..e40b4dd8 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/exception/RestServerException.java
@@ -6,25 +6,82 @@
import java.io.Serializable;
/**
- * @author Alex bob
+ * Represents a custom exception class for handling REST server errors, which includes an error message, a status code,
+ * and additional details. This exception extends {@link RuntimeException} and implements {@link Serializable} to support
+ * serialization when transmitted across networks or persisted.
+ *
+ * It provides factory methods to conveniently create instances with predefined or custom error messages and codes,
+ * facilitating standardization of error responses in a RESTful API context.
+ *
+ *
Features:
+ *
+ * - Custom error code to supplement HTTP status codes.
+ * - Holds an arbitrary object ({@code msg}) for detailed error information.
+ * - Convenience static factory methods for instantiation.
+ *
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RestServerException extends RuntimeException implements Serializable {
+ /**
+ * Encapsulates additional metadata or details about the error condition.
+ * This field can hold any type of object, enabling the transmission of structured
+ * information alongside the exception, such as maps, lists, or custom objects that
+ * provide context for the error scenario.
+ */
protected Object msg;
+ /**
+ * The error code associated with this {@link RestServerException}.
+ * This field represents a custom error code that provides more granular information
+ * about the specific error scenario beyond standard HTTP status codes.
+ * It is intended for use in identifying and differentiating between various error conditions.
+ */
protected int code;
+ /**
+ * Constructs a new instance of {@code RestServerException} with specified error code, message, and additional details.
+ * This exception is intended for conveying REST server-side error conditions, providing a more granular error code
+ * alongside a standard exception message and an optional object that can carry detailed contextual information.
+ *
+ * @param code The custom error code associated with the exception. This can be used to differentiate between
+ * various error scenarios beyond the standard HTTP status codes.
+ * @param message The human-readable error message explaining the exception circumstances. Should be concise and informative.
+ * @param msg An optional object containing additional metadata or details about the error. Can be any type,
+ * facilitating the passing of structured error information (e.g., maps, lists, or domain-specific objects).
+ */
public RestServerException(int code, String message, Object msg) {
super(message);
this.msg = msg;
this.code = code;
}
+ /**
+ * Creates a new instance of {@code RestServerException} with a predefined HTTP status code of 500 (Internal Server Error),
+ * a custom message, and additional details encapsulated in the {@code msg} parameter.
+ * This method serves as a convenience factory for generating exceptions that indicate a generic server error
+ * along with specific contextual information.
+ *
+ * @param message A descriptive message explaining the reason for the exception.
+ * @param msg An arbitrary object containing additional details about the error. This can be used to provide more
+ * extensive error context or metadata.
+ * @return A new instance of {@code RestServerException} initialized with the provided message, a status code of 500,
+ * and the additional details object.
+ */
public static RestServerException withMsg(String message, Object msg) {
return withMsg(500, message, msg);
}
+ /**
+ * Creates a new instance of {@code RestServerException} with a specified error code, message, and additional details.
+ * This static factory method allows for customization of the error response by providing a unique error code and
+ * a message along with an arbitrary object that can contain further information about the error condition.
+ *
+ * @param code The custom error code to identify the specific error scenario. This code supplements the HTTP status code.
+ * @param message The error message describing the exception's nature. Should be informative for debugging purposes.
+ * @param msg An optional object holding additional metadata or details related to the error. Can be any type.
+ * @return A new instance of {@code RestServerException} initialized with the provided code, message, and additional details.
+ */
public static RestServerException withMsg(int code, String message, Object msg) {
return new RestServerException(code, message, msg);
}
diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/BeanUtils.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/BeanUtils.java
index defb53da..b23bb329 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/utils/BeanUtils.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/BeanUtils.java
@@ -27,7 +27,9 @@
import java.util.StringJoiner;
/**
- * @author Alex bob
+ * Converts a JavaBean object into a Map representation.
+ * Each property of the bean is represented as a key-value pair in the map,
+ * with the property name as the key and its corresponding value as the value.
*/
@Log4j2
@Component
@@ -46,6 +48,21 @@ public final class BeanUtils implements InitializingBean {
}
}
+ /**
+ * Converts a JSON node at a specified JSON Path into an object of the provided class type.
+ *
+ * This method takes a JsonNode, a JSON Path string, and a target class type, then navigates to the
+ * JSON node located at the specified path within the input JSON. If the node exists, it is converted
+ * into an instance of the target class. If the path does not exist or conversion fails, exceptions are thrown.
+ *
+ * @param The type of the object to be returned.
+ * @param json The JsonNode from which to extract data.
+ * @param path A comma-separated string representing the JSON Path to the desired node.
+ * @param clazz The class of the type that the JSON node should be converted into.
+ * @return An instance of the specified class containing the data from the JSON node at the given path.
+ * @throws JsonException If the JSON Pointer path does not exist in the JSON structure,
+ * or if there is an issue converting the JsonNode to the target class.
+ */
public static T jsonPathToBean(JsonNode json, String path, Class clazz) {
try {
String[] paths = StringUtils.commaDelimitedListToStringArray(path);
@@ -65,6 +82,14 @@ public static T jsonPathToBean(JsonNode json, String path, Class clazz) {
}
}
+ /**
+ * Converts the given object into a byte array using JSON serialization.
+ *
+ * @param The type of the object to be serialized.
+ * @param object The object instance to be converted into bytes.
+ * @return A byte array representing the serialized form of the input object.
+ * @throws JsonException If the object cannot be serialized into JSON.
+ */
public static byte[] objectToBytes(T object) {
try {
return ContextUtils.OBJECT_MAPPER.writeValueAsBytes(object);
@@ -73,11 +98,26 @@ public static byte[] objectToBytes(T object) {
}
}
+ /**
+ * Generates a cache key based on the hash codes of the provided objects.
+ * This method is useful for creating unique keys for caching purposes when the key is derived from multiple parameters.
+ *
+ * @param objects A variable number of objects whose hash codes will be combined to form the cache key.
+ * @return A string representation of the combined hash code, serving as a unique cache key.
+ */
public static String cacheKey(Object... objects) {
int hashCode = Objects.hash(objects);
return String.valueOf(hashCode);
}
+ /**
+ * Inserts an object into the specified cache if its size does not exceed the maximum allowed in-memory size.
+ *
+ * @param cache The cache instance where the object will be stored.
+ * @param cacheKey The key under which the object will be stored in the cache.
+ * @param obj The object to be cached. Its size will be evaluated against the maximum allowed size.
+ * If the object exceeds the limit, it will not be cached and a warning will be logged.
+ */
public static void cachePut(Cache cache, String cacheKey, Object obj) {
DataSize objectSize = getBeanSize(obj);
if (objectSize.toBytes() > MAX_IN_MEMORY_SIZE.toBytes()) {
@@ -88,6 +128,15 @@ public static void cachePut(Cache cache, String cacheKey, Object obj) {
cache.put(cacheKey, obj);
}
+ /**
+ * Calculates the size of the given Java bean by serializing it into a byte array and measuring its length.
+ * This method provides an estimate of the space the object occupies when serialized.
+ *
+ * @param obj The Java bean object whose size is to be calculated. Must not be null.
+ * @return The size of the bean as a {@link DataSize} object, representing the size in a human-readable format.
+ * If the object is empty or serialization fails, returns a DataSize of 0 bytes.
+ * @throws IllegalArgumentException If the provided object is null, since null cannot be sized.
+ */
public static DataSize getBeanSize(Object obj) {
if (ObjectUtils.isEmpty(obj)) {
log.warn("Object is empty,This object not null.");
@@ -104,16 +153,41 @@ public static DataSize getBeanSize(Object obj) {
}
}
+ /**
+ * Copies the properties from the source object to a new instance of the specified target class.
+ * This method utilizes Spring's BeanUtils to perform the deep copy, allowing for copying nested properties as well.
+ *
+ * @param The type of the target class.
+ * @param source The source object from which properties are to be copied.
+ * @param clazz The class of the target object to be instantiated and populated with the source's properties.
+ * @return A new instance of the target class with properties copied from the source object.
+ * @throws IllegalArgumentException If the source is null or the clazz cannot be instantiated.
+ */
public static T copyProperties(Object source, Class clazz) {
T target = org.springframework.beans.BeanUtils.instantiateClass(clazz);
BeanUtils.copyProperties(source, target, true);
return target;
}
+ /**
+ * Copies the properties from the source object to the target object.
+ *
+ * @param source The source object whose properties are to be copied.
+ * @param target The target object where the properties from the source will be set.
+ */
public static void copyProperties(Object source, Object target) {
BeanUtils.copyProperties(source, target, false);
}
+ /**
+ * Copies properties from the source object to the target object.
+ * Optionally, properties with null values can be ignored during the copy process.
+ *
+ * @param source The source object from which properties are to be copied.
+ * @param target The target object to which properties are to be copied.
+ * @param ignoreNullValue If true, properties with null values in the source object will not be copied to the target object.
+ * If false, all properties including those with null values are copied.
+ */
public static void copyProperties(Object source, Object target, boolean ignoreNullValue) {
Map targetMap = BeanUtils.beanToMap(source);
String[] nullKeys = new String[0];
@@ -127,14 +201,41 @@ public static void copyProperties(Object source, Object target, boolean ignoreNu
}
}
+ /**
+ * Converts a JavaBean object into a Map representation.
+ *
+ * @param The type of the bean.
+ * @param bean The JavaBean object to be converted.
+ * @return A Map containing the properties of the JavaBean with keys as String and values as Object.
+ * The returned Map reflects the properties of the input bean including any nested beans.
+ */
public static Map beanToMap(T bean) {
return BeanUtils.beanToMap(bean, false);
}
+ /**
+ * Converts a JavaBean object into a Map, with keys representing the property names
+ * and values representing the corresponding property values.
+ *
+ * @param The type of the bean to convert.
+ * @param bean The JavaBean object to be converted into a Map.
+ * @param ignoreNullValue If true, properties with null values will not be included in the Map.
+ * @return A Map where each key-value pair corresponds to a property name and its value from the input bean.
+ * If ignoreNullValue is true, properties with null values are excluded.
+ */
public static Map beanToMap(T bean, final boolean ignoreNullValue) {
return BeanUtils.beanToMap(bean, false, ignoreNullValue);
}
+ /**
+ * Converts a JavaBean object into a Map, with options to transform field names to snake_case and ignore null values.
+ *
+ * @param The type of the bean to convert.
+ * @param bean The JavaBean object to be converted into a Map.
+ * @param isToUnderlineCase If true, converts camelCase keys in the Map to snake_case. Defaults to false.
+ * @param ignoreNullValue If true, excludes keys with null values from the resulting Map. Defaults to false.
+ * @return A Map representation of the input JavaBean, optionally with keys transformed to snake_case and null values excluded.
+ */
public static Map beanToMap(T bean, final boolean isToUnderlineCase, final boolean ignoreNullValue) {
if (ObjectUtils.isEmpty(bean)) {
return null;
diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/CriteriaUtils.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/CriteriaUtils.java
index fb098c0a..993d3ddc 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/CriteriaUtils.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/CriteriaUtils.java
@@ -14,21 +14,52 @@
import java.util.stream.Collectors;
/**
- * @author Alex bob
+ * Utility class to hold both SQL string segment and its related parameters.
+ * This is particularly useful for dynamically constructing SQL queries
+ * with bind variables in a structured manner.
*/
public final class CriteriaUtils {
public static final Set SKIP_CRITERIA_KEYS = Set.of("extend", "createdTime", "updatedTime");
+ /**
+ * Applies pagination to a SQL query string based on the provided {@link Pageable} object.
+ * This is a convenience overload that delegates to {@link #applyPage(Pageable, String)}
+ * with a null prefix, used primarily when no prefix is needed for generating the SQL LIMIT and OFFSET clauses.
+ *
+ * @param pageable The pagination information, including page size and offset.
+ * @return A string representing the pagination part of the SQL query, i.e., "LIMIT {pageSize} OFFSET {offset}".
+ */
public static String applyPage(Pageable pageable) {
return applyPage(pageable, null);
}
+ /**
+ * Applies pagination to a SQL query string based on the provided {@link Pageable} object and an optional prefix.
+ * Generates a LIMIT and OFFSET clause with the specified page size and offset from the {@link Pageable} instance,
+ * optionally prefixed to align with a specific table alias or column name in the SQL query.
+ *
+ * @param pageable The pagination information containing the desired page size and offset for query pagination.
+ * @param prefix An optional prefix to be applied before the LIMIT and OFFSET placeholders in the SQL query.
+ * This can be useful when addressing specific table aliases or column names.
+ * @return A string appended with the pagination SQL segment, formatted as "LIMIT {pageSize} OFFSET {offset}",
+ * with optional prefixing, ready to be integrated into a larger SQL query.
+ */
public static String applyPage(Pageable pageable, String prefix) {
String orderSql = applySort(pageable.getSort(), prefix);
return String.format(orderSql + " limit %d offset %d", pageable.getPageSize(), pageable.getOffset());
}
+ /**
+ * Applies sorting to a SQL query string based on the provided {@link Sort} object, with an optional prefix for property names.
+ * Transforms the sort orders into SQL-compatible sort clauses, considering case insensitivity and JSON field access notation.
+ * If the sort is unsorted or null, defaults to sorting by 'id' in descending order.
+ *
+ * @param sort The sorting criteria specifying the properties and directions for sorting.
+ * @param prefix An optional prefix to prepend to each sorted property name, useful when dealing with table aliases or nested properties.
+ * @return A string representing the sorting part of the SQL query, starting with "ORDER BY",
+ * followed by comma-separated sort clauses, each in the format "property_name ASC/DESC".
+ */
public static String applySort(Sort sort, String prefix) {
if (sort == null || sort.isUnsorted()) {
return " order by id desc ";
@@ -49,6 +80,22 @@ public static String applySort(Sort sort, String prefix) {
return " order by " + sortSql;
}
+ /**
+ * Constructs a ParamSql instance representing a part of an SQL WHERE clause
+ * and its corresponding parameters extracted from a given Java object, while
+ * providing options to skip certain keys and apply a prefix to the keys.
+ * The method first converts the object into a map and processes a special
+ * "query" key using QueryJson to generate SQL and parameters. It then handles
+ * a "securityCode" key if present and not skipped. Afterward, it filters out
+ * keys that should be skipped, including default ones defined in SKIP_CRITERIA_KEYS
+ * and combines these with additional parameters generated from the remaining object map.
+ * @param object The source object from which SQL conditions and parameters are derived.
+ * @param skipKeys A collection of keys to be excluded from processing, can be null.
+ * @param prefix A prefix to prepend to the keys in the generated SQL, useful for nested queries.
+
+ * @return A ParamSql object containing a StringJoiner with concatenated SQL conditions
+ * (joined by 'and') and a map of parameters for prepared statement binding.
+ */
@SuppressWarnings("unchecked")
public static ParamSql buildParamSql(Object object, Collection skipKeys, String prefix) {
@@ -83,6 +130,23 @@ public static ParamSql buildParamSql(Object object, Collection skipKeys,
return ParamSql.of(sql, params);
}
+ /**
+ * Constructs a ParamSql instance for dynamic SQL WHERE clause generation
+ * based on a provided map of column-value pairs. Supports optional prefixing
+ * for column names to handle table aliases or nested properties. Determines
+ * the SQL condition type (equality, 'like', or 'in') dynamically based on
+ * the value's type, enabling flexible query construction.
+ *
+ * @param objectMap A map where keys represent column names (in camelCase)
+ * and values are the criteria for filtering. Values can be
+ * Strings, Collections, or other types supporting equality checks.
+ * @param prefix An optional string prefix to prepend to each column name,
+ * typically used to reference specific tables or entities in a query.
+ * @return A ParamSql object encapsulating the constructed WHERE clause
+ * conditions joined by 'and', and a map of parameters for prepared
+ * statement binding, where keys correspond to named parameters
+ * and values are the user-provided filter values.
+ */
public static ParamSql buildParamSql(Map objectMap, String prefix) {
StringJoiner whereSql = new StringJoiner(" and ");
for (Map.Entry entry : objectMap.entrySet()) {
@@ -105,6 +169,18 @@ public static ParamSql buildParamSql(Map objectMap, String prefi
return ParamSql.of(whereSql, objectMap);
}
+ /**
+ * Constructs a Criteria instance by converting the provided object into a map,
+ * excluding specified keys, and then further processing this map to create
+ * the Criteria object. The method removes keys listed in the predefined
+ * SKIP_CRITERIA_KEYS set as well as any additional keys specified in the
+ * skipKes collection from the object map before constructing the Criteria.
+ *
+ * @param object The Java object to convert into Criteria. Its properties will form the basis of the Criteria.
+ * @param skipKes A collection of strings representing keys to exclude from the object during conversion.
+ * These are in addition to the default skipped keys predefined in SKIP_CRITERIA_KEYS.
+ * @return A Criteria instance representing the processed object, excluding the specified keys.
+ */
public static Criteria build(Object object, Collection skipKes) {
Map objectMap = BeanUtils.beanToMap(object, true);
if (!ObjectUtils.isEmpty(objectMap)) {
@@ -117,6 +193,18 @@ public static Criteria build(Object object, Collection skipKes) {
return build(objectMap);
}
+ /**
+ * Constructs a Criteria instance from a map of search criteria.
+ * Each entry in the map represents a search criterion where the key is the field name
+ * and the value is the criterion value. The method supports String patterns with 'like',
+ * collections of values with 'in', and direct value matching for other types.
+ *
+ * @param objectMap A map mapping field names to their respective search criterion values.
+ * String values will be treated for 'like' matching,
+ * Collections will be used for 'in' clauses, and all other types for equality.
+ * @return A Criteria instance representing the combined search criteria.
+ * Returns an empty Criteria if the input map is null or empty.
+ */
public static Criteria build(Map objectMap) {
if (ObjectUtils.isEmpty(objectMap)) {
return Criteria.empty();
diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/ParamSql.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/ParamSql.java
index 7f0192e3..a740e467 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/ParamSql.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/ParamSql.java
@@ -5,14 +5,40 @@
import java.util.StringJoiner;
/**
- * @author Alex bob
+ * Represents a SQL parameter structure consisting of a conditional SQL fragment
+ * and a map of parameters to be bound to a PreparedStatement.
+ * This record facilitates the construction of dynamic SQL queries with placeholders
+ * for improved performance and security against SQL injection.
+ *
+ * @param sql A {@link StringJoiner} containing the dynamically built WHERE clause
+ * fragments of a SQL query, joined by 'and'.
+ * @param params A {@link Map} mapping parameter names to their respective values,
+ * which are intended to replace placeholders in the SQL query.
*/
public record ParamSql(StringJoiner sql, Map params) implements Serializable {
+ /**
+ * Creates a new instance of {@link ParamSql} with the provided conditional SQL
+ * fragment and parameters map.
+ *
+ * @param sql A {@link StringJoiner} object containing the dynamically
+ * constructed WHERE clause segments of a SQL query, concatenated by 'and'.
+ * @param params A {@link Map} of parameter names to values, which will be
+ * substituted for placeholders within the SQL query to prevent SQL injection.
+ * @return A new {@link ParamSql} instance encapsulating the given SQL fragment
+ * and parameters map, ready for use in preparing a parameterized SQL statement.
+ */
public static ParamSql of(StringJoiner sql, Map params) {
return new ParamSql(sql, params);
}
+ /**
+ * Constructs a WHERE clause segment for a SQL query based on the accumulated conditions.
+ * If conditions have been added, it prepends the 'WHERE' keyword followed by the conditions;
+ * otherwise, it returns an empty string.
+ *
+ * @return A String representing the WHERE clause with conditions or an empty string if no conditions exist.
+ */
public String whereSql() {
if (this.sql.length() > 0) {
return " where " + this.sql;
diff --git a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryJson.java b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryJson.java
index 8213c976..e37c2be6 100644
--- a/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryJson.java
+++ b/boot/platform/src/main/java/com/plate/boot/commons/utils/query/QueryJson.java
@@ -10,7 +10,8 @@
import java.util.*;
/**
- * @author Alex bob
+ * Searches for a keyword within the provided key and returns the keyword along with its SQL equivalent.
+ * If no keyword match is found, returns null.
*/
public class QueryJson {
@@ -51,6 +52,19 @@ public class QueryJson {
KEYWORDS.put("False", "is false");
}
+ /**
+ * Transforms a Spring Sort object into a new Sort object suitable for sorting based on JSON properties,
+ * considering nested structures denoted by dot-separated keys. Optionally prefixes property keys.
+ *
+ * This method processes each order in the provided Sort object. If a property key represents a nested
+ * JSON path (indicated by containing dots), it constructs a new sorting property that can be used
+ * directly in SQL queries involving JSON data, using the '->>' operator to access nested JSON fields.
+ * Non-nested properties or those not requiring transformation are preserved as is.
+ *
+ * @param sort The original Spring Sort object defining the sorting orders. If null or empty, returns an unsorted Sort.
+ * @param prefix An optional prefix to prepend to each sorting property, useful for aliasing in SQL queries.
+ * @return A new Sort object with transformed sorting properties, ready for sorting queries that involve JSON columns.
+ */
public static Sort sortJson(Sort sort, String prefix) {
if (sort == null || sort.isEmpty()) {
return Sort.unsorted();
@@ -75,6 +89,19 @@ public static Sort sortJson(Sort sort, String prefix) {
return Sort.by(orders);
}
+ /**
+ * Constructs a SQL parameter object based on a JSON-like map structure and an optional prefix for column names.
+ *
+ * This method iterates through the provided map, treating keys as JSON paths to construct
+ * WHERE clause conditions and bind parameters accordingly. Supports complex JSON paths
+ * and keyword-based operations like 'Between' and 'NotBetween'.
+ *
+ * @param params A map where each key represents a JSON path to a value that should be used in query conditions.
+ * The value associated with each key is the target value for comparison or range (for Between/NotBetween).
+ * @param prefix An optional prefix to prepend to column names, useful when querying nested or aliased tables/views.
+ * @return A {@link ParamSql} object containing a {@link StringJoiner} with concatenated WHERE clause conditions
+ * and a map of bind parameters to be used in a prepared statement.
+ */
public static ParamSql queryJson(Map params, String prefix) {
Map bindParams = Maps.newHashMap();
StringJoiner whereSql = new StringJoiner(" and ");
@@ -98,6 +125,17 @@ public static ParamSql queryJson(Map params, String prefix) {
return ParamSql.of(whereSql, bindParams);
}
+ /**
+ * Generates a JSON path key along with the corresponding parameter name for constructing SQL queries.
+ * It supports handling special keywords in the last key segment for operations like 'Between' and 'NotBetween'.
+ *
+ * @param keys An array of strings representing keys in a JSON path, typically derived from a dot-separated string.
+ * @param prefix An optional prefix to be prepended to the first key, used to namespace column names in SQL queries.
+ * @return A Map.Entry containing:
+ * - Key: A string representing the constructed JSON path expression suitable for SQL query with placeholders.
+ * - Value: A list of strings representing the parameter names to bind values to in the SQL prepared statement.
+ * @throws IllegalArgumentException If the keys array is null or empty.
+ */
private static Map.Entry> jsonPathKeyAndParamName(String[] keys, String prefix) {
if (keys == null || keys.length < 1) {
throw new IllegalArgumentException("Keys array cannot be null or empty.");
@@ -147,6 +185,13 @@ private static Map.Entry> jsonPathKeyAndParamName(String[]
}
+ /**
+ * Appends intermediate keys from a given array into a StringBuilder to form a part of a JSON path expression.
+ * Each key is surrounded by '->' to denote nested elements in a JSON structure when used within SQL queries.
+ *
+ * @param joinKeys An array of strings representing intermediate keys in a JSON path.
+ * @return StringBuilder containing the concatenated intermediate keys formatted for a JSON path expression.
+ */
private static StringBuilder appendIntermediateKeys(String[] joinKeys) {
StringBuilder jsonPath = new StringBuilder();
for (String path : joinKeys) {
@@ -155,6 +200,14 @@ private static StringBuilder appendIntermediateKeys(String[] joinKeys) {
return jsonPath;
}
+ /**
+ * Searches for a keyword within a predefined map of keywords and returns the matching entry.
+ * The search prioritizes longer keywords and is case-insensitive, considering the end of the input string.
+ *
+ * @param inputStr The string to search for a matching keyword suffix.
+ * @return An entry containing the matched keyword and its associated value,
+ * or null if no match is found.
+ */
private static Map.Entry findKeyWord(String inputStr) {
return KEYWORDS.entrySet().stream()
.filter(entry -> StringUtils.endsWithIgnoreCase(inputStr, entry.getKey()))