Skip to content
鼓励作者:欢迎打赏犒劳

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

如有转载或 CV 的请标注本站原文地址