表达式解析工具



import com.krls.simulator.system.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Matches1 {

    private static final String TRUE = " true ";
    private static final String FALSE = " false ";

    public static boolean getMatches(String matches, Object... args) {

        matches = matchesFormat(matches);
        if (!checks(matches)) {
            return false;
        }
        matches = replace$(matches, args);
        matches = replaceEqual(matches);
        matches = replaceBracket(matches);
        matches = replaceAndOr(matches);
        return !matches.contains("false");
    }

    public static String matchesFormat(String str) {
        return str.replaceAll("\\|\\|", " || ").replaceAll("&&", " && ");
    }

    private static int bracketNum = 0;

    public static boolean checks(String matches) {
        if (matches.contains("&|") || matches.contains("|&")) {
            return false;
        }
        matches = matches.replaceAll("\\\\\\(", "").replaceAll("\\\\\\)", "");
        int left = 0;
        char[] chars = matches.toCharArray();
        for (char c : chars) {
            String aChar = String.valueOf(c);
            if (Objects.equals("(", aChar)) {
                left++;
            }
            if (Objects.equals(")", aChar)) {
                if (left > 0) {
                    bracketNum++;
                    left--;
                } else {
                    return false;
                }
            }
        }
        return left == 0;
    }

    public static String replaceBracket(String matches) {
        matches = matches.replaceAll("\\\\\\(", "").replaceAll("\\\\\\)", "");
        int left = 0, right = 0;
        char[] chars = matches.toCharArray();
        int[] leftArray = new int[bracketNum];

        for (int i = 0; i < chars.length; i++) {
            String aChar = String.valueOf(chars[i]);
            if (Objects.equals("(", aChar)) {
                leftArray[left] = i;
                left++;
            }
        }
        for (int i = bracketNum - 1; i >= 0; i--) {
            int end = getCloseSubscript(leftArray[i], matches);
            if (end == -1) {
                return matches;
            }
            String val = replaceAndOr(matches.substring(leftArray[i] + 1, end).trim());
            String start = leftArray[i] - 1 < 0 ? "" : matches.substring(0, leftArray[i] - 1);
            String last = end + 1 > matches.length() ? "" : matches.substring(end + 1);
            matches = start + val + last;
        }
        return matches;
    }

    public static String replaceAndOr(String source) {
        String reg = "\\w+\\s*[&|]{2}\\s*\\w+";
        Matcher matcher = Pattern.compile(reg).matcher(source);
        while (matcher.find()) {
            String group = matcher.group();
            String val = functionAndOr(group);
            source = source.replace(group, val);
        }
        return source;
    }

    public static String functionAndOr(String str) {
        if (str.contains("&&")) {
            String left = str.substring(0, str.indexOf("&&")).trim();
            String right = str.substring(str.indexOf("&&") + 2).trim();
            if (left.equals("true") && right.equals("true")) {
                str = TRUE;
            } else {
                str = FALSE;
            }
        } else if (str.contains("||")) {
            String left = str.substring(0, str.indexOf("||")).trim();
            String right = str.substring(str.indexOf("||") + 2).trim();
            if (left.equals("true") || right.equals("true")) {
                str = TRUE;
            } else {
                str = FALSE;
            }
        }
        return str;
    }

    public static int getCloseSubscript(int start, String str) {
        if (start >= str.length() - 1) {
            return -1;
        }
        char[] chars = str.toCharArray();
        for (int i = start; i < chars.length; i++) {
            String s = String.valueOf(chars[i]);
            if (Objects.equals(s, ")")) {
                return i;
            }
        }
        return -1;
    }

    public static String replaceEqual(String source) {
        String reg = "\\w+\\s*[><!=]=\\s*\\w+";
        Matcher matcher = Pattern.compile(reg).matcher(source);
        while (matcher.find()) {
            String group = matcher.group();
            String val = functionEqual(group);
            source = source.replace(group, val);
        }
        reg = "\\w+\\s*[><]\\s*\\w+";
        matcher = Pattern.compile(reg).matcher(source);
        while (matcher.find()) {
            String group = matcher.group();
            String val = functionUnEqual(group);
            source = source.replace(group, val);
        }
        return source;
    }

    public static String functionUnEqual(String str) {
        if (str.contains(">")) {
            String left = str.substring(0, str.indexOf(">")).trim();
            String right = str.substring(str.lastIndexOf(">") + 1).trim();
            if (Integer.parseInt(left) > Integer.parseInt(right)) {
                return TRUE;
            }
        }
        if (str.contains("<")) {
            String left = str.substring(0, str.indexOf("<")).trim();
            String right = str.substring(str.lastIndexOf("<") + 1).trim();
            if (Integer.parseInt(left) < Integer.parseInt(right)) {
                return TRUE;
            }
        }
        return FALSE;
    }

    public static String functionEqual(String str) {
        String right = str.substring(str.lastIndexOf("=") + 1).trim();
        if (str.contains("==")) {
            String left = str.substring(0, str.indexOf("=")).trim();
            if (Objects.equals(left, right)) {
                return TRUE;
            }
        }
        if (str.contains(">=")) {
            String left = str.substring(0, str.indexOf(">")).trim();
            if (Integer.parseInt(left) >= Integer.parseInt(right)) {
                return TRUE;
            }
        }
        if (str.contains("<=")) {
            String left = str.substring(0, str.indexOf("<")).trim();
            if (Integer.parseInt(left) <= Integer.parseInt(right)) {
                return TRUE;
            }
        }
        if (str.contains("!=")) {
            String left = str.substring(0, str.indexOf("!")).trim();
            if (!Objects.equals(left, right)) {
                return TRUE;
            }
        }
        return FALSE;
    }

    public static String replace$(String source, Object... args) {
        String reg = "\\$[0-9]+\\.\\w+";
        Matcher matcher = Pattern.compile(reg).matcher(source);
        while (matcher.find()) {
            String group = matcher.group();
            int size = Integer.parseInt(group.substring(1, group.indexOf(".")));
            Object val = getVal(args[size],
                    group.substring(group.indexOf(".") + 1));
            if (val != null) {
                source = source.replace(group, val.toString());
            }
        }
        return source;
    }

    public static Object getVal(Object obj, String paramName) {
        if (obj == null || StringUtils.isNull(paramName)) {
            return null;
        }
        try {
            Method method = obj.getClass().getMethod(getGetName(paramName));
            return method.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getGetName(String key) {
        return "get" + key.substring(0, 1).toUpperCase() + key.substring(1);
    }

}

以上代码主要是利用正则表达式实现对一些字符表达式的解析,是为了别的系统专门适配写的一个工具类,但是泛用性很高,共享出来交流。

额外声明:

        1、该代码是本人独立开发,仅供个人学习参考,请勿商用

        2、该代码是几个月前的0.1版本,并且删掉了部分功能(目前已经0.3版本)

        3、该文章可能后续会删除,可能不会更新工具类的版本。

以下是测试代码

    public static void main(String[] args) {
        String ss = "( $0.id like $2% ) && ( ($1.id==34)|| $1.name!=cui  )";
        SS ss1 = new SS() {{
            setId("321");
            setName("ka");
        }};
        SS ss2 = new SS() {{
            setId("34");
            setName("cui");
        }};
        System.out.println(getMatches(ss, ss1, ss2, 32));
        ss = "($1.id in (34,35,36) || $1.id>$0.id) && ( 1==1 )";
        System.out.println(getMatches(ss, ss1, ss2));
//        System.out.println(matchesFormat(" asda||asd&&ds"));
    }

以下是SS代码,该类只是测试时使用,随手写的。

@Data
class SS {
    private String name;
    private String id;

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof SS)) return false;
        if (((SS) obj).name == name) return true;
        return false;
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值