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