12-流程条件控制
测试
java
package com.example.bootdemo.flow;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import com.example.bootdemo.flow.dto.RuleDO;
import com.example.bootdemo.flow.handle.RuleEqualsOperatorHandle;
import com.example.bootdemo.flow.handle.RuleLessThanEqualsOperatorHandle;
import com.example.bootdemo.flow.handle.RuleLessThanOperatorHandle;
import com.example.bootdemo.flow.handle.RuleMoreThanEqualsOperatorHandle;
import com.example.bootdemo.flow.handle.RuleMoreThanOperatorHandle;
import com.example.bootdemo.flow.handle.RuleNotEqualsOperatorHandle;
import com.example.bootdemo.flow.handle.RuleOperatorHandle;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class RuleTest {
public static Map<String, RuleOperatorHandle> ruleOperatorHandleList = getRuleOperatorHandleList();
@Test
public void test1() {
List<RuleDO> ruleDOList = new ArrayList<RuleDO>(){{
add(new RuleDO(1L,0L,"normal",1, "color","红色","and","=",1,"string"));
add(new RuleDO(2L,0L,"normal",1, "weight","10","and",">",2,"int"));
add(new RuleDO(3L,0L,"normal",1, "weight","100","and","<",2,"int"));
// add(new RuleDO("size","10",null,"<=",3,"double"));
}};
Map<String, Object> valMap = new HashMap<>();
valMap.put("color","红色");
valMap.put("weight",18);
valMap.put("size",12.4);
Boolean pass = isPass(ruleDOList,valMap);
System.out.println(pass);
}
@Test
public void test2() {
List<RuleDO> ruleDOList = new ArrayList<RuleDO>();
RuleDO ruleDO1 = new RuleDO(1L,0L,"virtually",1, null,null,"and",null,1,null);
RuleDO ruleDO2 = new RuleDO(2L,0L,"normal", 1,"producer","中国",null,"=",2,"string");
RuleDO ruleDO1_1 = new RuleDO(3L,1L,"virtually", 2,null,null,"or",null,1,null);
RuleDO ruleDO1_2 = new RuleDO(4L,1L,"virtually", 2,null,null,null,null,2,null);
RuleDO ruleDO1_1_1 = new RuleDO(5L,3L,"normal", 3,"color","蓝色","and","=",1,"string");
RuleDO ruleDO1_1_2 = new RuleDO(6L,3L,"normal", 3,"weight","10",null,"<",2,"int");
RuleDO ruleDO1_2_1 = new RuleDO(7L,4L,"normal", 3,"color","红色","and","=",1,"string");
RuleDO ruleDO1_2_2 = new RuleDO(8L,4L,"normal", 3,"weight","10",null,">",2,"int");
ruleDOList.add(ruleDO1);
ruleDOList.add(ruleDO2);
ruleDOList.add(ruleDO1_1);
ruleDOList.add(ruleDO1_2);
ruleDOList.add(ruleDO1_1_1);
ruleDOList.add(ruleDO1_1_2);
ruleDOList.add(ruleDO1_2_1);
ruleDOList.add(ruleDO1_2_2);
List<RuleDO> ruleDOS = convertTreeNode(ruleDOList,0L);
System.out.println(ruleDOS);
Map<String, Object> valMap = new HashMap<>();
valMap.put("color","红色");
valMap.put("weight",18);
valMap.put("producer","中国");
Boolean pass2 = isPass2(ruleDOS,valMap);
System.out.println(pass2);
}
public static Boolean isPass2(List<RuleDO> ruleDOList, Map<String,Object> valMap){
Boolean resultByLevel = null;
for (int i = 0; i < ruleDOList.size(); i++) {
Boolean exec = null;
String relationOuter = null;
if (i > 0){
relationOuter = ruleDOList.get(i - 1).getRelationOuter();
}
RuleDO ruleDO = ruleDOList.get(i);
List<RuleDO> childRuleDOList = ruleDO.getChildRuleDOList();
if (CollectionUtils.isNotEmpty(childRuleDOList)){
exec = isPass2(childRuleDOList,valMap);
}else{
String attrCode = ruleDO.getAttrCode();
String relationInner = ruleDO.getRelationInner();
//规则的val
String rule_val_original = ruleDO.getAttrVal();
//规则的val 类型
String attrValType = ruleDO.getAttrValType();
// 商品的val
Object product_val_original = valMap.get(attrCode);
exec = ruleOperatorHandleList.get(relationInner).exec(product_val_original, rule_val_original, attrValType);
}
if (resultByLevel == null){
resultByLevel = exec;
}else{
resultByLevel = relationExec(exec,resultByLevel,relationOuter);
}
}
return resultByLevel;
}
private static List<RuleDO> convertTreeNode(List<RuleDO> list, Long parentId){
List<RuleDO> children = list.stream().filter(x -> x.getParentRuleId().equals(parentId)).collect(Collectors.toList());
List<RuleDO> successor = list.stream().filter(x -> !x.getParentRuleId().equals(parentId)).collect(Collectors.toList());
//排序
children = children.stream().sorted(Comparator.comparingInt(RuleDO::getSort)).collect(Collectors.toList());
children.forEach(x ->
{
convertTreeNode(successor, x.getId()).forEach(
y -> x.getChildRuleDOList().add(y)
);
}
);
return children;
}
public static Boolean isPass(List<RuleDO> ruleDOList, Map<String,Object> valMap){
if (CollectionUtils.isEmpty(ruleDOList)){
return true;
}
//排序
ruleDOList = ruleDOList.stream().sorted(Comparator.comparingInt(RuleDO::getSort)).collect(Collectors.toList());
Boolean resultByLevel = null;
for (int i = 0; i < ruleDOList.size(); i++) {
RuleDO ruleDO = ruleDOList.get(i);
String attrCode = ruleDO.getAttrCode();
String relationOuter = null;
if (i > 0){
relationOuter = ruleDOList.get(i - 1).getRelationOuter();
}
String relationInner = ruleDO.getRelationInner();
//规则的val
String rule_val_original = ruleDO.getAttrVal();
//规则的val 类型
String attrValType = ruleDO.getAttrValType();
// 商品的val
Object product_val_original = valMap.get(attrCode);
Boolean exec = ruleOperatorHandleList.get(relationInner).exec(product_val_original, rule_val_original, attrValType);
if (resultByLevel == null){
resultByLevel = exec;
}else{
resultByLevel = relationExec(exec,resultByLevel,relationOuter);
}
}
return resultByLevel;
}
public static Boolean relationExec(Boolean r1,Boolean r2,String relationType){
if (RuleOperatorConstant.and.equalsIgnoreCase(relationType)){
return r1 && r2;
}else if (RuleOperatorConstant.or.equalsIgnoreCase(relationType)){
return r1 || r2;
}
return true;
}
public static Map<String, RuleOperatorHandle> getRuleOperatorHandleList(){
Map<String, RuleOperatorHandle> map = new HashMap<>();
map.put("=",new RuleEqualsOperatorHandle());
map.put(">",new RuleMoreThanOperatorHandle());
map.put(">=",new RuleMoreThanEqualsOperatorHandle());
map.put("<",new RuleLessThanOperatorHandle());
map.put("<=",new RuleLessThanEqualsOperatorHandle());
map.put("!=",new RuleNotEqualsOperatorHandle());
return map;
}
}
实体
java
package com.example.bootdemo.flow.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
public class RuleDO {
/**
* 主键
*/
private Long id;
/**
* 父级规则ID
*/
private Long parentRuleId;
/**
* 规则类型;normal=正常节点,virtually=虚拟节点
*/
private String ruleType;
/**
* 层级;层级越高执行优先级越高, default 1
*/
private int level;
private String attrCode;
private String attrVal;
private String relationOuter;
private String relationInner;
private Integer sort;
private String attrValType;
private List<RuleDO> childRuleDOList = new ArrayList<>();
public RuleDO(long id, Long parentRuleId, String ruleType, int level, String attrCode, String attrVal, String relationOuter, String relationInner, Integer sort, String attrValType) {
this.id = id;
this.parentRuleId = parentRuleId;
this.ruleType = ruleType;
this.level = level;
this.attrCode = attrCode;
this.attrVal = attrVal;
this.relationOuter = relationOuter;
this.relationInner = relationInner;
this.sort = sort;
this.attrValType = attrValType;
}
}
常量
java
package com.example.bootdemo.flow.constant;
public class RuleOperatorConstant {
public static final String equals_operator = "=";
public static final String more_than_operator = ">";
public static final String less_than_operator = "<";
public static final String less_than_equal_operator = "<=";
public static final String more_than_equal_operator = ">=";
public static final String not_equals_operator = "!=";
public static final String int_type = "int";
public static final String string_type = "string";
public static final String double_type = "double";
public static final String and = "and";
public static final String or = "or";
}
接口
java
public interface RuleOperatorHandle {
/**
* 操作类型
* @return
*/
String operatorType();
/**
* 执行计算
* @return
*/
Boolean exec(Object product_val_original,Object rule_val_original,String attrValType);
}
RuleEqualsOperatorHandle
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleEqualsOperatorHandle implements RuleOperatorHandle {
@Override
public String operatorType() {
return RuleOperatorConstant.equals_operator;
}
@Override
public Boolean exec(Object product_val_original, Object rule_val_original, String attrValType) {
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)) {
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.equals(rule_val);
} else if (RuleOperatorConstant.string_type.equalsIgnoreCase(attrValType)) {
String product_val = product_val_original.toString();
String rule_val = rule_val_original.toString();
result = product_val.equals(rule_val);
} else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)) {
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) == 0;
}
log.info(product_val_original + RuleOperatorConstant.equals_operator + rule_val_original + "; --> " + result);
return result;
}
}
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleLessThanEqualsOperatorHandle implements RuleOperatorHandle{
@Override
public String operatorType() {
return RuleOperatorConstant.less_than_equal_operator;
}
@Override
public Boolean exec(Object product_val_original,Object rule_val_original,String attrValType){
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)){
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.compareTo(rule_val) <= 0;
}else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)){
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) <= 0;
}
log.info(product_val_original + RuleOperatorConstant.less_than_equal_operator + rule_val_original + "; --> " + result);
return result;
}
}
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleLessThanOperatorHandle implements RuleOperatorHandle{
@Override
public String operatorType() {
return RuleOperatorConstant.less_than_operator;
}
@Override
public Boolean exec(Object product_val_original,Object rule_val_original,String attrValType){
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)){
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.compareTo(rule_val) < 0;
}else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)){
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) < 0;
}
log.info(product_val_original + RuleOperatorConstant.less_than_operator + rule_val_original + "; --> " + result);
return result;
}
}
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleMoreThanEqualsOperatorHandle implements RuleOperatorHandle{
@Override
public String operatorType() {
return RuleOperatorConstant.more_than_equal_operator;
}
@Override
public Boolean exec(Object product_val_original,Object rule_val_original,String attrValType){
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)){
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.compareTo(rule_val) >= 0;
}else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)){
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) >= 0;
}
log.info(product_val_original + RuleOperatorConstant.more_than_equal_operator + rule_val_original + "; --> " + result);
return result;
}
}
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleMoreThanOperatorHandle implements RuleOperatorHandle{
@Override
public String operatorType() {
return RuleOperatorConstant.more_than_operator;
}
@Override
public Boolean exec(Object product_val_original,Object rule_val_original,String attrValType){
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)){
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.compareTo(rule_val) > 0;
}else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)){
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) > 0;
}
log.info(product_val_original + RuleOperatorConstant.more_than_operator + rule_val_original + "; --> " + result);
return result;
}
}
java
package com.example.bootdemo.flow.handle;
import com.example.bootdemo.flow.constant.RuleOperatorConstant;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@Slf4j
public class RuleNotEqualsOperatorHandle implements RuleOperatorHandle{
@Override
public String operatorType() {
return RuleOperatorConstant.not_equals_operator;
}
@Override
public Boolean exec(Object product_val_original,Object rule_val_original,String attrValType){
Boolean result = true;
if (RuleOperatorConstant.int_type.equalsIgnoreCase(attrValType)){
Integer product_val = Integer.valueOf(product_val_original.toString());
Integer rule_val = Integer.valueOf(rule_val_original.toString());
result = product_val.compareTo(rule_val) != 0;
}else if (RuleOperatorConstant.double_type.equalsIgnoreCase(attrValType)){
BigDecimal product_val = new BigDecimal(product_val_original.toString());
BigDecimal rule_val = new BigDecimal(rule_val_original.toString());
result = product_val.compareTo(rule_val) != 0;
}
log.info(product_val_original + RuleOperatorConstant.not_equals_operator + rule_val_original + "; --> " + result);
return result;
}
}