Files
timi-utils/src/main/java/com/imyeyu/utils/StringInterpolator.java
T
Timi 8c5abdb149
CI/CD / build-deploy (pull_request) Successful in 38s
v0.0.3
2026-03-21 18:00:03 +08:00

169 lines
4.8 KiB
Java

package com.imyeyu.utils;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArgReturn;
import com.imyeyu.java.ref.Ref;
import lombok.Getter;
import lombok.Setter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 字符串插值器
*
* @author 夜雨
* @version 2022-12-01 00:41
*/
public class StringInterpolator {
public static final String DOLLAR_OBJ = "\\$\\{(.+?)\\}";
public static final String SIMPLE_OBJ = "\\{(.+?)\\}";
/** 缓存解析过的嵌套属性路径 */
private final Map<String, String[]> deepKeyCache = new ConcurrentHashMap<>();
/** 正则匹配器 */
private final Pattern pattern;
/** 过滤器映射 */
private final Map<String, CallbackArgReturn<String, String>> filterMap = new HashMap<>();
/** 空值处理策略 */
@Setter
@Getter
private boolean nullable = false;
public StringInterpolator(String regex) {
this.pattern = Pattern.compile(regex);
}
/**
* 注入变量
*
* @param template 字符串
* @param argsMap 变量表
* @return 插值结果
*/
public String inject(String template, Map<String, Object> argsMap) {
if (TimiJava.isEmpty(template) || TimiJava.isEmpty(argsMap)) {
return template;
}
Matcher matcher = pattern.matcher(template);
StringBuilder result = new StringBuilder();
while (matcher.find()) {
String replacement = processReplacement(matcher.group(1), argsMap);
matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(result);
return result.toString();
}
/** 处理单个替换项 */
private String processReplacement(String expression, Map<String, Object> argsMap) {
// 解析表达式:变量名和过滤器
ExpressionParts parts = parseExpression(expression);
// 获取变量值
Object value = getVariableValue(parts.variable, argsMap);
// 应用过滤器
value = applyFilters(value, parts.filters);
// 处理空值
return handleNullValue(value, parts.variable);
}
/** 解析表达式为变量名和过滤器数组 */
private ExpressionParts parseExpression(String expression) {
if (!expression.contains("|")) {
return new ExpressionParts(expression.trim(), new String[0]);
}
String[] parts = expression.split("\\|");
String variable = parts[0].trim();
String[] filters = new String[parts.length - 1];
for (int i = 1; i < parts.length; i++) {
filters[i - 1] = parts[i].trim();
}
return new ExpressionParts(variable, filters);
}
/** 获取变量值,支持嵌套属性 */
private Object getVariableValue(String variable, Map<String, Object> argsMap) {
Object value = argsMap.get(variable);
if (variable.contains(".")) {
value = getNestedPropertyValue(variable, argsMap);
}
return value;
}
/** 获取嵌套属性值 */
private Object getNestedPropertyValue(String deepKey, Map<String, Object> argsMap) {
String[] keyPath = deepKeyCache.computeIfAbsent(deepKey, k -> k.split("\\."));
try {
Object value = argsMap.get(keyPath[0]);
for (int i = 1; i < keyPath.length && value != null; i++) {
value = Ref.getFieldValue(value, keyPath[i], Object.class);
}
return value;
} catch (IllegalAccessException e) {
throw new RuntimeException("ref field error: " + e.getMessage(), e);
}
}
/** 应用过滤器链 */
private Object applyFilters(Object value, String[] filters) {
if (TimiJava.isEmpty(filters) || TimiJava.isEmpty(filterMap) || value == null) {
return value;
}
String currentValue = String.valueOf(value);
for (String filterName : filters) {
CallbackArgReturn<String, String> filter = filterMap.get(filterName);
if (filter == null) {
throw new IllegalArgumentException("not found %s filter for".formatted(filterName));
}
currentValue = filter.handler(currentValue);
}
return currentValue;
}
/** 处理空值情况 */
private String handleNullValue(Object value, String variable) {
if (value == null) {
if (!nullable) {
throw new NullPointerException("not found %s value".formatted(variable));
}
return "";
}
return String.valueOf(value);
}
public void putFilter(String name, CallbackArgReturn<String, String> callback) {
filterMap.put(name, callback);
}
public void putAllFilter(Map<String, CallbackArgReturn<String, String>> filters) {
filterMap.putAll(filters);
}
public void removeFilter(String name) {
filterMap.remove(name);
}
public void clearFilter() {
filterMap.clear();
}
/** 表达式部分内部类 */
private record ExpressionParts(String variable, String[] filters) {
}
public static StringInterpolator createDollarInterpolator() {
return new StringInterpolator(DOLLAR_OBJ);
}
public static StringInterpolator createSimpleInterpolator() {
return new StringInterpolator(SIMPLE_OBJ);
}
}