参数化 ${参数名}

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 valueMap) throws CustomException{
        if(json==null){
            return "";
        }
        if(valueMap==null){
            throw new NullPointerException("储值map is null");
        }
        try {
            Set keys = json.keySet();
            Iterator 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 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 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 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());
                    }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:
     * 
    *
  • text)
  • *
  • text,text)
  • *
  • *
* @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 parseParams(StringReader reader, Map params) { LinkedList 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; } }

你可能感兴趣的:(参数化 ${参数名})