import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
public class FunctionVariable {
private static Logger log = LoggerFactory.getLogger(FunctionVariable.class);
/**
* 替换json数据中value的参数化
* @param json json数据
* @param valueMap 储值map
* @return
* @throws CustomException
*/
public static String compileJson(JSONObject json, Map<String, String> valueMap) throws CustomException{
if(json==null){
return "";
}
if(valueMap==null){
throw new NullPointerException("储值map is null");
}
try {
Set<String> keys = json.keySet();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String key = it.next();
String value = json.getString(key);
String result = compileString(value, valueMap);
json.put(key, result);
}
return json.toJSONString();
}catch (Exception e) {
log.error("data:"+json.toJSONString());
throw new CustomException(e.getMessage(), e);
}
}
/**
* 替换字符串中的参数化
*
* Compile a general string into a list of elements for a CompoundVariable.
*
* Calls {@link #makeFunction(StringReader)} if it detects an unescaped "${".
*
* Removes escapes from '$', ',' and '\'.
*
* @param value string containing the function / variable references (if any)
*
* @return list of Strings or Objects representing functions
* @throws InvalidVariableException when evaluation of variables fail
*/
public static String compileString(String value, Map<String, String> params) {
StringReader reader = new StringReader(value);
StringBuilder result = new StringBuilder();
StringBuilder buffer = new StringBuilder();
char previous = ' '; // TODO - why use space?
char[] current = new char[1];
try {
while (reader.read(current) == 1) {
if (current[0] == '\\') { // 处理转义
previous = current[0];
if (reader.read(current) == 0) {
break;
}
// 保存'\',除非它是一个可撤销的字符'$'','或'\'
// 注: 此方法用于解析函数参数,因此必须将“,”作为特殊处理
if (current[0] != '$' && current[0] != ',' && current[0] != '\\') {
buffer.append(previous); // 即 '\\'
}
previous = ' ';
buffer.append(current[0]);
} else if (current[0] == '{' && previous == '$') {// 找到 "${"
buffer.deleteCharAt(buffer.length() - 1);
if (buffer.length() > 0) {// 保存前面的文本
result.append(buffer.toString());
buffer.setLength(0);
}
result.append(makeFunction(reader, params));
previous = ' ';
} else {
buffer.append(current[0]);
previous = current[0];
}
}
if (buffer.length() > 0) {
result.append(buffer.toString());
}
} catch (IOException e) {
log.error("解析函数错误: {}", value, e);
result.setLength(0);
result.append(value);
}
return result.toString();
}
/**
* 获取参数的值或者调用函数
* Compile a string into a function or SimpleVariable.
*
* Called by {@link #compileString(String)} when that has detected "${".
*
* Calls {@link CompoundVariable#getNamedFunction(String)} if it detects:
* '(' - start of parameter list
* '}' - end of function call
*
* @param reader points to input after the "${"
* @return the function or variable object (or a String)
* @throws InvalidVariableException when evaluation of variables fail
*/
static String makeFunction(StringReader reader, Map<String, String> params) {
char[] current = new char[1];
char previous = ' '; // TODO - why use space?
StringBuilder buffer = new StringBuilder();
try {
while (reader.read(current) == 1) {
if (current[0] == '\\') {
if (reader.read(current) == 0) {
break;
}
previous = ' ';
buffer.append(current[0]);
} else if (current[0] == '(' && previous != ' ') {
String funcName = buffer.toString();
if (GenerationParamsEnum.check(funcName)) {//函数,有参数
LinkedList<String> functionParams = parseParams(reader, params);//获取参数
if (reader.read(current) == 0 || current[0] != '}') {
reader.reset();// 设置为开始字符串
char []cb = new char[100];
int nbRead = reader.read(cb);
throw new CustomException("函数 "+funcName+" 缺少 },调用字符串 "+new String(cb, 0, nbRead));
}
//调用函数
return DataGenerator.genneratorValue(funcName, functionParams);
} else { // 函数不存在,因此按照缺失变量进行处理
buffer.append(current[0]);
}
} else if (current[0] == '}') {// 变量或函数,无参数
String key = buffer.toString();
if (GenerationParamsEnum.check(key)){// 确认是否存在该函数
return DataGenerator.genneratorValue(key, new LinkedList<String>());
}else if(params.containsKey(key)) {//不是函数,查找参数是否存在
return params.get(key);
}else {
throw new CustomException("找不到参数值:"+key);
}
} else {
buffer.append(current[0]);
previous = current[0];
}
}
} catch (IOException e) {
log.error("解析函数错误: {}", buffer, e);
return null;
}
log.warn("可能是一个无效的函数字符串:{}", buffer);
return buffer.toString();
}
/**
* 获取函数的参数
* Compile a String into a list of parameters, each made into a
* CompoundVariable.
*
* Parses strings of the following form:
* <ul>
* <li>text)</li>
* <li>text,text)</li>
* <li></li>
* </ul>
* @param reader a StringReader pointing to the current input location, just after "("
* @return a list of CompoundVariable elements
* @throws InvalidVariableException when evaluation of variables fail
*/
static LinkedList<String> parseParams(StringReader reader, Map<String, String> params) {
LinkedList<String> result = new LinkedList<>();
StringBuilder buffer = new StringBuilder();
char[] current = new char[1];
char previous = ' ';
int parenRecursion = 0;
try {
while (reader.read(current) == 1) {
if (current[0] == '\\') { // 处理转义的字符
buffer.append(current[0]); // 存储 \
if (reader.read(current) == 0) {
break; // 缓冲区结束
}
previous = ' ';
buffer.append(current[0]); // 存储以下字符
} else if (current[0] == '|' && previous == '|') {//找到 '||'
buffer.deleteCharAt(buffer.length()-1);
result.add(buffer.toString());
buffer.setLength(0);
} else if (current[0] == ')' && parenRecursion == 0) {
// 检测函数名,因此不会生成空字符串作为参数
if (buffer.length() == 0 && result.isEmpty()){
return result;
}
// 正常退出在这里
result.add(buffer.toString());
buffer.setLength(0);
return result;
} else if (current[0] == '{' && previous == '$') {
buffer.deleteCharAt(buffer.length()-1);
buffer.append(makeFunction(reader, params));
previous = current[0];
}else if (current[0] == ')' && parenRecursion > 0) {
buffer.append(current[0]);
previous = current[0];
parenRecursion--;
} else if (current[0] == '(') {
buffer.append(current[0]);
previous = current[0];
parenRecursion++;
}else {
buffer.append(current[0]);
previous = current[0];
}
}
} catch (IOException e) {// Should not happen with StringReader
log.error("解析函数错误: {}", buffer, e);
}
// 退出,没有找到关闭的')'
log.warn("可能是一个无效的函数字符串:{}", buffer);
result.add(buffer.toString());
return result;
}
}
参数化 ${参数名}
最新推荐文章于 2024-06-21 10:02:08 发布