001package top.cenze.rule.utils;
002
003import cn.hutool.core.collection.CollectionUtil;
004import lombok.extern.slf4j.Slf4j;
005import org.drools.core.base.RuleNameStartsWithAgendaFilter;
006import org.kie.api.KieBase;
007import org.kie.api.KieServices;
008import org.kie.api.builder.*;
009import org.kie.api.runtime.KieContainer;
010import org.kie.api.runtime.KieSession;
011import top.cenze.rule.dto.RuleBaseData;
012
013import java.util.List;
014import java.util.Map;
015
016/**
017 * @desc: 规则管理工具
018 * @author: chengze
019 * @createByDate: 2023/8/8 17:30
020 */
021@Slf4j
022public class KieUtil {
023    // 规则文件虚拟加载目录路径
024    private static final String KIE_PACKAGE_PATH = "src/main/resources/rules/";
025
026    private static final KieServices kieServices = KieServices.Factory.get();
027    // 创建kie文件系统
028    private static final KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
029    private static KieContainer kieContainer;
030    private static KieBase kieBase;
031
032    public static KieFileSystem getKieFileSystem() {
033        return kieFileSystem;
034    }
035
036    public static KieContainer getKieContainer() {
037        return kieContainer;
038    }
039
040    public static void setKieContainer(KieContainer kieContainer) {
041        KieUtil.kieContainer = kieContainer;
042    }
043
044    public static KieServices getKieServices() {
045        return kieServices;
046    }
047
048    public static KieBase getKieBase() {
049        return kieBase;
050    }
051
052    public static void setKieBase(KieBase kieBase) {
053        KieUtil.kieBase = kieBase;
054    }
055
056    /**
057     * 批量重载规则
058     * @param lstRule
059     */
060    public static void reloadRules(List<RuleBaseData> lstRule) {
061        if (CollectionUtil.isEmpty(lstRule)) {
062            return;
063        }
064
065        for (RuleBaseData rule : lstRule) {
066            log.info("rule name: {}", rule.getRuleName());
067            String drlFile = KIE_PACKAGE_PATH + rule.getRuleName() + ".drl";
068            kieFileSystem.delete(drlFile);
069            kieFileSystem.write(drlFile, rule.getRuleContent());
070        }
071
072        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
073        kieBuilder.buildAll();
074        Results results = kieBuilder.getResults();
075        if (results.hasMessages(Message.Level.ERROR)) {
076            throw new IllegalStateException("### load rules error ###");
077        }
078
079        kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
080        kieBase = kieContainer.getKieBase();
081    }
082
083//    /**
084//     * 重载规则
085//     * @param lstRule
086//     */
087//    public static void reloadRule(List<RuleDTO> lstRule) {
088//        // 借助 kieHelper 添加规则
089//        KieHelper kieHelper = new KieHelper();
090//        // 从数据库中获取所有的规则
091//        if (CollectionUtil.isNotEmpty(lstRule)) {
092//            // 循环加载所有的规则
093//            for (RuleDTO rule : lstRule) {
094//                String content = rule.getRuleContent();
095//                kieHelper.addContent(content, ResourceType.DRL);
096//            }
097//        }
098//        // 校验规则是否异常
099//        Results results = kieHelper.verify();
100//        System.out.println("results: " + JSON.toJSONString(results));
101//        if (results.hasMessages(Message.Level.ERROR)) {
102//            System.out.println(results.getMessages());
103//            throw new IllegalStateException("### errors ###");
104//        }
105//        // 重置容器
106//        KieContainer kieContainer = kieHelper.getKieContainer();
107//        KieUtil.setKieContainer(kieContainer);
108//
109//        // 重置规则库
110//        KieBase kieBase = kieContainer.getKieBase();
111//        KieUtil.setKieBase(kieBase);
112//    }
113
114    /**
115     * 执行所有规则
116     * @param obj
117     */
118    public static void execAll(Object obj) {
119        KieSession kieSession = KieUtil.getKieBase().newKieSession();
120        kieSession.insert(obj);
121        kieSession.fireAllRules();
122        kieSession.dispose();
123    }
124
125    /**
126     * 执行所有规则
127     * @param obj           待插入的Fact
128     * @param mapGlobal     待传入的全局变量
129     */
130    public static void execAll(Object obj, Map<String, Object> mapGlobal) {
131        KieSession kieSession = KieUtil.getKieBase().newKieSession();
132        kieSession.insert(obj);
133        if (CollectionUtil.isNotEmpty(mapGlobal)) {
134            for (Map.Entry<String, Object> entry : mapGlobal.entrySet()) {
135                kieSession.setGlobal(entry.getKey(), entry.getValue());
136            }
137        }
138        kieSession.fireAllRules();
139        kieSession.dispose();
140    }
141
142    /**
143     * 执行指定名称的规则
144     * drl规则文件中 rule 项对应的值
145     * @param obj           待插入的Fact
146     * @param ruleName      规则名(用于匹配包含此字符串的规则)
147     */
148    public static void execByRuleName(Object obj, String ruleName) {
149        KieSession kieSession = KieUtil.getKieBase().newKieSession();
150        kieSession.insert(obj);
151        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter(ruleName));
152        kieSession.dispose();
153    }
154
155    /**
156     * 执行指定名称的规则
157     * drl规则文件中 rule 项对应的值
158     * @param obj           待插入的Fact
159     * @param ruleName      规则名(用于匹配包含此字符串的规则)
160     * @param mapGlobal     待传入的全局变量
161     */
162    public static void execByRuleName(Object obj, String ruleName, Map<String, Object> mapGlobal) {
163        KieSession kieSession = KieUtil.getKieBase().newKieSession();
164        kieSession.insert(obj);
165        if (CollectionUtil.isNotEmpty(mapGlobal)) {
166            for (Map.Entry<String, Object> entry : mapGlobal.entrySet()) {
167                kieSession.setGlobal(entry.getKey(), entry.getValue());
168            }
169        }
170        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter(ruleName));
171        kieSession.dispose();
172    }
173}