开发背景:
我们在开发过程中,可能需要将某数据动态从配置文件中读取。且需要根据用户的输入,来动态判断决定某布尔值。
例如:
我们有一个配置,称为配置一,需要在配置文件中写好,该配置有3个子配置(姑且这么叫吧),3个子配置是否选择,需要根据用户的页面输入。
我们又有一个配置,称为配置二,需要在配置文件中写好,该配置有2个子配置,2个子配置是否选择,需要根据配置二中的其他配置项来决定是否需要选择。
(可能以上例子表述并不完整,但并不影响本文的继续进行)
有时候,我们需要在配置文件中添加一个字段,通过该字段来确认一个动态的布尔值,这个字段是一个逻辑的表达式。(例:a==b && student.id == stusdent .num)
但是,配置文件拿到的只能是字符串。因此需要解析字符串,返回布尔值。
输入(参数):
除了要输入字符串外,还需要输入字符串中需要用到的数据集。
例如student.id == stusdent .num 这个表达式,就需要student对象
输出(返回值):
布尔值:true 或者 false
代码:
package com.dacheng.kyc.com.dacheng.kyc;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import org.springframework.util.StringUtils;
public class getEnableService {
private static final String AND ="&&";
private static final String OR ="||";
private static final String UNEQUAL = "!=";
private static final String EQUAL = "==";
private Mapmap;
private Mapparams;
public boolean isEnable(String enable, Mapmap,
Mapparams){
this.map = map;
this.params = params;
if(StringUtils.isEmpty(enable)){
return true;
}
Stackoperation = new Stack();
int tmpEnd = enable.length();
for(int i = enable.length();i>1 ; i--){
String twoChatter = enable.substring(i-2,i);
if (twoChatter.equals(AND)||twoChatter.equals(OR)) {
operation.add(enable.substring(i, tmpEnd).trim().replaceAll(" ", ""));
operation.add(twoChatter);
tmpEnd = i-2;
}
}
operation.add(enable.substring(0,tmpEnd).replaceAll(" ", ""));
System.out.println(operation);
return judge(operation);
}
private boolean judge(Stackoperation) {
if(operation.size()==1) {
return isTrue(operation.pop());
}else {
boolean value1 = isTrue(operation.pop());
String releation = operation.pop();
boolean value2 = isTrue(operation.pop());
if (releation.equals(AND)) {
boolean operationResult = value1 && value2;
operation.add(String.valueOf(operationResult));
return judge(operation);
}
else if(releation.equals(OR)) {
boolean operationResult = value1 || value2;
operation.add(String.valueOf(operationResult));
return judge(operation);
}
else {
//LOG.error("the logical is wrong")
return true;
}
}
}
private boolean isTrue(String condition) {
if(condition.toLowerCase().equals("true")) {
return true;
}else if(condition.toLowerCase().equals("false")) {
return false;
}else {
if(condition.contains(EQUAL)) {
int index = condition.indexOf(EQUAL);
String stringOfValue1 = condition.substring(0, index);
String stringOfValue2 = condition.substring(index+2,condition.length());
Object value1 = getValuFromString(stringOfValue1,params,map);
Object value2 = getValuFromString(stringOfValue2,params,map);
System.out.println(stringOfValue1+":"+value1);
System.out.println(stringOfValue2+":"+value2);
if(value1==null || value2 ==null) {
//LOG.error();
return false;
}
return value1.equals(value2);
}
else if (condition.contains(UNEQUAL)) {
int index = condition.indexOf(UNEQUAL);
String stringOfValue1 = condition.substring(0, index);
String stringOfValue2 = condition.substring(index+2,condition.length());
Object value1 = getValuFromString(stringOfValue1,params,map);
Object value2 = getValuFromString(stringOfValue2,params,map);
System.out.println(stringOfValue1+":"+value1);
System.out.println(stringOfValue2+":"+value2);
if(value1==null || value2 ==null) {
//LOG.error();
System.out.println("wrong");
return false;
}
return !value1.equals(value2);
}
else {
System.out.println("wrong");
return false;
}
}
}
private Object getValuFromString(String configString, Mapparams,
Mapmap) {
// TODO 这个函数主要是根据configString的知道,从其他参数里面获取想要的Value
String POINT ="\\.";
String PARAMS ="params";
String MAP ="map";
String result = null;
if (!StringUtils.isEmpty(configString) && configString.split(POINT).length == 1) {
result = configString;
} else if (!StringUtils.isEmpty(configString) &&
configString.split(POINT).length == 2) {
String source = configString.split(POINT)[0];
String value = configString.split(POINT)[1];
if (source.equals(PARAMS)) {
result = params.get(value);
} else if (source.equals(MAP)) {
result = map.get(value);
}
}
return result;
}
public static void main(String[] args) {
Mapmap =new HashMap<>();
Mapparams =new HashMap<>();
map.put("name", "kangyucheng");
params.put("name", "kangyucheng");
map.put("id", "https://blog.csdn.net/kangyucheng");
params.put("id", "https://blog.csdn.net/kangyucheng");
getEnableService getEnableService =new getEnableService();
String string1 ="params.name == map.name || params.id != map.id";
System.out.println(getEnableService.isEnable(string1,map,params));
String string2 ="params.name == map.id || params.id != map.id";
System.out.println(getEnableService.isEnable(string2,map,params));
String string3 ="params.name == map.id || params.id != true";
System.out.println(getEnableService.isEnable(string3,map,params));
}
}
结果:
[params.id!=map.id, ||, params.name==map.name]
params.name:kangyucheng
map.name:kangyucheng
params.id:https://blog.csdn.net/kangyucheng
map.id:https://blog.csdn.net/kangyucheng
true
[params.id!=map.id, ||, params.name==map.id]
params.name:kangyucheng
map.id:https://blog.csdn.net/kangyucheng
params.id:https://blog.csdn.net/kangyucheng
map.id:https://blog.csdn.net/kangyucheng
false
[params.id!=true, ||, params.name==map.id]
params.name:kangyucheng
map.id:https://blog.csdn.net/kangyucheng
params.id:https://blog.csdn.net/kangyucheng
true:true
true
分析:
该实现方式采用栈来实现,首先遍历一次整个字符串,将字符串切分,将切分结果入栈。
然后开始对栈进行遍历,每次拿出一个符号和两个表达式,将结果计算好之后再放回栈中。如此递归到栈中只有一个元素。
缺陷:
1、并没有实现对括号的处理。
2、没有对>= ,<= ,< ,>等等等关系进行处理,只处理了== 和 != 。
之所以没有对上述两个进行处理,是因为我觉得配置文件是自己来编写,且无需太复杂,以上代码可以完成需要。
(换一种说法:我有点懒)