/**
* 执行函数脚本
*
* @since author: l00050286 date: 2023/4/10 15:26
* @param scriptStr 函数脚本字符串
* @param functionName 函数名
* @return java.lang.Object
*/
public static Object executeFunctionScript(String scriptStr,String functionName) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval(scriptStr);
Invocable jsInvoke = (Invocable) engine;
return jsInvoke.invokeFunction(functionName);
}
/**
* 获取可执行函数Str
*
* @since author: l00050286 date: 2023/4/10 14:46
* @param sourceFormula 计算规则
* @param endSign 计算规则结束标识
* @param functionName 可执行函数名称
* @param factorValueMap 计算规则计算因子的值
* @return java.lang.String
*/
public static String getScriptStr(String sourceFormula, String endSign, String functionName,
Map<String, String> factorValueMap) {
int length = endSign.length();
String column = StringUtils.trimAllWhitespace(sourceFormula);
String splitStr = "IF|THEN|OTHERWISE|AND|OR|>=|<=|>|<|==|\\+|-|\\*|/|\\?|:";
if (column.indexOf("IF") == 0) {
String logicScript = column.substring(0, column.length() - length); // 去掉结束标记
Map<String, String> factorMap = new HashMap<>();
// 1、设置需要替换的最小计算因数
setFactorMap(factorMap, logicScript, splitStr);
// 2、格式化逻辑脚本
splitStr = "IF|THEN|OTHERWISE|AND|OR|>=|<=|>|<|==|\\+|-|\\*|/|\\;|\\?|:|" + endSign;
String formatFormula = CommonUtil.formatLogicFormula(column, endSign, splitStr);
// 3、格式化逻辑脚本转换成可执行函数
return scriptTransferFunction(formatFormula, factorMap, functionName, endSign, factorValueMap);
} else {
Map<String, String> factorMap = new HashMap<>();
// 1、设置需要替换的最小计算因数
setFactorMap(factorMap, column, splitStr);
// 2、格式化逻辑脚本
splitStr = "IF|THEN|OTHERWISE|AND|OR|>=|<=|>|<|==|\\+|-|\\*|/|\\;|\\?|:|" + endSign;
String formatFormula = CommonUtil.formatLogicFormula(column, endSign, splitStr);
// 3、格式化逻辑脚本转换成可执行函数
return scriptTransferFunction(formatFormula, factorMap, functionName, endSign, factorValueMap);
}
}
/**
* 设置需要替换的最小计算因数
*
* @since author: l00050286 date: 2023/4/10 14:40
* @param factorMap 保存需要替换的最小计算因数Map
* @param logicScript 逻辑脚本
* @param splitStr 分隔符
* @return void
*/
public static void setFactorMap(Map<String,String> factorMap,String logicScript,String splitStr){
String[] elementArray = logicScript.split(";");
int serialIndex=0;
// 解析公式获取需要替换的最小计算因数
for (String tempElement : elementArray) {
String[] split = tempElement.split(splitStr);
for (String minCalculationFactor : split) {
if(!CommonUtil.isEmpty(minCalculationFactor)){
int j = minCalculationFactor.indexOf("[");
int k = minCalculationFactor.indexOf("]");
if (j > -1 && k > -1) {
// 考虑到 ( ) 的情况
int l = minCalculationFactor.indexOf(")");
String element = (l > -1 ? minCalculationFactor.substring(j, l) : minCalculationFactor.substring(j));
if(factorMap.get(element) == null) {
serialIndex++;
factorMap.put(element, "param" + serialIndex);
// 考虑到存在()的情况
int m = minCalculationFactor.indexOf("(");
if (m > -1 || l > -1) {
factorMap.put(minCalculationFactor, element);
}
}else{
// 考虑到(,((,(((...和),)),)))...的情况
if(factorMap.get(minCalculationFactor) == null){
factorMap.put(minCalculationFactor, element);
}
}
}
}
}
}
}
/**
* 格式化逻辑公式
*
* @since author: l00050286 date: 2023/3/31 18:28
* @param column 计算规则公式
* @param endSign 原始字符串结束标识
* @param splitStr 分隔字符串
* "IF|THEN|OTHERWISE|AND|OR|>=|<=|>|<|==|\\+|-|\\*|/|\\;|"
* "IF|THEN|OTHERWISE|AND|OR|>=|<=|>|<|==|\\+|-|\\*|/"
* @return java.lang.String
*/
public static String formatLogicFormula(String column,String endSign,String splitStr) {
List<String> separatorList = new ArrayList<>();
String[] split1 = column.split(splitStr);
int i = 0;
int j = 1;
int length = split1.length;
while (column.length() > 0 && i < length && j < length) {
column = column.substring(split1[i].length());
int i1 = column.indexOf(split1[j]);
separatorList.add(column.substring(0, i1));
column = column.substring(i1);
i++;
j++;
}
StringBuilder stringBuilder = new StringBuilder();
int size = separatorList.size();
for (int i1 = 0; i1 < length; i1++) {
if(!CommonUtil.isEmpty(split1[i1])){
stringBuilder.append(split1[i1]).append(" ");
}
if (i1 < size) {
String tmp = separatorList.get(i1);
if(tmp.length()>1 && tmp.indexOf(";")==0){
stringBuilder.append(";").append(" ").append(tmp.substring(1)).append(" ");
}else{
stringBuilder.append(separatorList.get(i1)).append(" ");
}
}
}
stringBuilder.append(endSign);
return stringBuilder.toString();
}
/**
* 格式化逻辑脚本转换成可执行函数
*
* @since author: l00050286 date: 2023/4/10 15:05
* @param formatFormula 格式化逻辑脚本
* @param factorMap 需要替换的最小计算因数Map
* @param functionName 可执行函数名称
* @param endSign 格式化逻辑脚本结束标识
* @return java.lang.String
*/
public static String scriptTransferFunction(String formatFormula, Map<String, String> factorMap,
String functionName, String endSign,
Map<String, String> factorValueMap) {
String[] elementAllArray = formatFormula.split(" ");
StringBuilder stringBuilderFormula = new StringBuilder();
factorMap.forEach((key, value) -> {
if (key.indexOf("(") == -1 && key.indexOf(")") == -1) {
if (factorValueMap.get(key) == null) {
stringBuilderFormula.append("var ").append(value).append(" = 10;\n");
} else {
stringBuilderFormula.append("var ").append(value).append(" = ").append(factorValueMap.get(key)).append(";\n");
}
}
});
stringBuilderFormula.append("function ");
if (formatFormula.indexOf("IF") == 0) {
stringBuilderFormula.append(functionName).append("(){\n var result = 0;\n");
} else {
stringBuilderFormula.append(functionName).append("(){\n var result = ( \n");
}
for (String element : elementAllArray) {
switch (element) {
case "IF":
stringBuilderFormula.append(" if (");
break;
case "THEN":
stringBuilderFormula.append(") {\n\t result = ");
break;
case "AND":
stringBuilderFormula.append(" && ");
break;
case "OR":
stringBuilderFormula.append(" || ");
break;
case "OTHERWISE":
stringBuilderFormula.append(";\n } else {\n\t result = ");
break;
case ";":
stringBuilderFormula.append(";\n } else");
break;
default:
if (factorMap.get(element) == null) {
if (element.equals(endSign)) {
if(formatFormula.indexOf("IF") == 0){
stringBuilderFormula.append(";\n }\n return result ;\n}");
} else{
stringBuilderFormula.append(" );\n return result ;\n}");
}
} else {
stringBuilderFormula.append(" ").append(element);
}
} else {
String factor = factorMap.get(element);
String parameter = factorMap.get(factor);
if (parameter != null) {
element = element.replace(factor, parameter);
stringBuilderFormula.append(element);
} else {
stringBuilderFormula.append(" ").append(factorMap.get(element));
}
}
break;
}
}
return stringBuilderFormula.toString();
}