参数化 ${参数名}

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;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值