001package top.cenze.rulepolicy.frame.utils;
002
003import cn.hutool.core.io.FileUtil;
004import cn.hutool.core.io.resource.ResourceUtil;
005import cn.hutool.core.util.ObjectUtil;
006import cn.hutool.core.util.StrUtil;
007import com.alibaba.fastjson.JSON;
008import lombok.SneakyThrows;
009import top.cenze.rulepolicy.frame.entity.dto.RuleDTO;
010
011import java.io.File;
012import java.io.FileWriter;
013import java.io.UnsupportedEncodingException;
014import java.util.ArrayList;
015import java.util.List;
016
017/**
018 * @desc: 规则文件工具
019 * @author: chengze
020 * @createByDate: 2023/8/7 15:17
021 */
022public class RuleFileUtil {
023//    private static final String DIR_NAME = "rules";             // 规则文件目录
024//    private static final String RELATIVE_PATH = "src/main/resources/rules";  // 规则文件相对目录
025//    private static final String EXT_NAME = ".drl";              // 规则文件扩展名
026//    private static final String PACKAGE_PREFIX = "package ";    // 规则包名前缀
027//    private static final String IMPORT_PREFIX = "import ";      // 规则引入前缀
028//    private static final String RULE_NAME_PREFIX = "rule ";      // 规则名称前缀
029//    private static final String RULE_WHEN = "when";      // 规则WHEN标识
030//    private static final String RULE_THEN = "then";      // 规则THEN标识
031//    private static final String RULE_END = "end";      // 规则END标识
032//
033//    private static final String EVAL_TRUE = "eval(true)";   // 默认条件
034//
035    // 文件内容写入器
036//    private static FileWriter fw;
037//
038//    // 文件内容叠加器
039//    private static StringBuilder sb;
040
041    /**
042     * 获取规则文件全路径
043     * @param ruleFileName
044     * @return
045     */
046//    public static String getRuleFileFullPath(String ruleFileName) {
047//        String dir = getRuleFileDir();
048//
049////        return dir + File.separator + ruleFileName + EXT_NAME;
050//        String filePath = dir + "\\" + ruleFileName + EXT_NAME;
051//
052//        return filePath;
053//    }
054//
055//    /**
056//     * 获取规则文件存储目录
057//     * @return
058//     */
059//    public static String getRuleFileDir() {
060//        // 获取项目资源文件根目录
061//        String dir = ResourceUtil.getResource("").getPath();
062//        // 去除每一个“/”字符(win系统)
063//        dir = StrUtil.sub(dir, 1, dir.length());
064//        // 获取最后一个字符
065//        String lastChar = StrUtil.sub(dir, dir.length() - 1, dir.length());
066//        // 拼接规则文件目录
067//        if (File.separator.equals(lastChar)) {
068//            dir = dir + DIR_NAME;
069//        } else if ("/".equals(lastChar)) {
070//            dir = dir + DIR_NAME;
071//        } else {
072//            dir = dir + File.separator + DIR_NAME;
073//        }
074//
075//        return "D:\\Projects\\cenze\\cenze-rule-policy-engine\\src\\test\\resources\\rules";
076//    }
077//
078//    @SneakyThrows
079//    public static void writeRuleFile(String ruleFileFullPath, String ruleFileContent) {
080//        FileUtil.del(ruleFileFullPath);
081//        File file = FileUtil.touch(ruleFileFullPath);
082//
083//        // 新增文件写入器
084//        FileWriter fw = new FileWriter(file);
085//        fw.write(ruleFileContent);
086//        fw.close();
087//    }
088
089    /**
090     * 重载规则
091     * @param rule
092     */
093    public static void readRuleContent(RuleDTO rule) {
094        if (ObjectUtil.isNull(rule) || StrUtil.isEmpty(rule.getRuleName()) || StrUtil.isEmpty(rule.getRuleContent())) {
095            new NullPointerException("规则对象、名称、内容不能为空");
096        }
097
098        List<RuleDTO> lstRule = new ArrayList<>();
099        lstRule.add(rule);
100
101        KieUtil.reloadRule(lstRule);
102    }
103
104    /**
105     * 重载规则文件
106     * @param ruleFileFullPath
107     * @return
108     * @throws UnsupportedEncodingException
109     */
110    public static void readRuleFile(String ruleFileFullPath) {
111        File file = new File(ruleFileFullPath);
112
113        readRuleFile(file);
114    }
115
116    /**
117     * 重载规则文件
118     * @param file
119     * @return
120     */
121    @SneakyThrows
122    public static void readRuleFile(File file) {
123        byte[] bytes = FileUtil.readBytes(file);
124        String ruleContent = new String(bytes, "UTF-8");
125
126        RuleDTO rule = new RuleDTO();
127        rule.setRuleName(file.getName());
128        rule.setRuleContent(ruleContent);
129
130        System.out.println("rule: " + JSON.toJSONString(rule));
131
132        List<RuleDTO> lstRule = new ArrayList<>();
133        lstRule.add(rule);
134
135        KieUtil.reloadRule(lstRule);
136    }
137
138//    /**
139//     * 初始化规则文件对象(创建一个测试规则文件对象)
140//     * @return
141//     */
142//    public static RuleFile initRuleFile() {
143//        RuleFile ruleFile = new RuleFile();
144//        ruleFile.setFileName("rule");
145//        ruleFile.setPackageName("top.cenze.rule");
146//
147//        List<String> imports = new ArrayList<>();
148//        imports.add("top.cenze.rulepolicy.pojo.UserInfo");
149//        imports.add("top.cenze.rulepolicy.utils.TestUtil");
150//        ruleFile.setImports(imports);
151//
152//        List<String> lstRuleName = new ArrayList<>();
153//
154//        RuleHeader header = new RuleHeader();
155//        header.setRuleName("test_rule");
156//        header.setAttributes(null);
157//        lstRuleName.add(header.getRuleName());
158//
159//        RuleBodyWhenLhs lhs = new RuleBodyWhenLhs();
160//        lhs.setLhsObjBindName("userInfo");
161//        lhs.setLhsObjName("UserInfo");
162//        List<RuleBodyWhenSubLhs> lstSubLhs = new ArrayList<>();
163//        RuleBodyWhenSubLhs subLhs = new RuleBodyWhenSubLhs();
164//        subLhs.setLVal("age");
165//        subLhs.setCmpOps(RuleCompOperatorEnum.LT.getVal());
166//        subLhs.setRVal(50);
167//        lstSubLhs.add(subLhs);
168//        lhs.setLstSubLhs(lstSubLhs);
169//        List<RuleBodyWhenLhs> lstLhs = new ArrayList<>();
170//        lstLhs.add(lhs);
171//
172//        RuleBodyWhen rWhen = new RuleBodyWhen();
173//        rWhen.setLhs(lstLhs);
174//
175//        RuleBodyThenRhs rhs = new RuleBodyThenRhs();
176//        rhs.setRhs("$userInfo.setUserName(\"chengze\")");
177//        List<RuleBodyThenRhs> lstRhs = new ArrayList<>();
178//        lstRhs.add(rhs);
179//
180//        RuleBodyThen rThen = new RuleBodyThen();
181//        rThen.setRhs(lstRhs);
182//
183//        RuleBody body = new RuleBody();
184//        body.setRWhen(rWhen);
185//        body.setRThen(rThen);
186//
187//        Rule rule = new Rule();
188//        rule.setHeader(header);
189//        rule.setBody(body);
190//        List<Rule> lstRule = new ArrayList<>();
191//        lstRule.add(rule);
192//
193//        ruleFile.setRules(lstRule);
194//        ruleFile.setRuleNames(lstRuleName);
195//
196//        return ruleFile;
197//    }
198//
199//    /**
200//     * 创建规则文件
201//     * @param ruleFile
202//     */
203//    @SneakyThrows
204//    public static void createRuleFile(RuleFile ruleFile) {
205//        // 获取规则文件全路径
206//        String ruleFileFullPath = getRuleFileFullPath(ruleFile.getFileName());
207//
208//        // 规则引入
209//        List<String> imports = ruleFile.getImports();
210//        // 规则名称集合
211//        List<String> ruleNames = ruleFile.getRuleNames();
212//        // 规则集合
213//        List<Rule> rules = ruleFile.getRules();
214//
215//        // =======================> 创建规则文件
216//        FileUtil.touch(ruleFileFullPath);
217//    }
218//
219//    /**
220//     * 写入规则文件
221//     * @param ruleFile  规则文件对象
222//     * @param fwMode    写入方式(0叠加,1直接写入,默认为0)
223//     */
224//    @SneakyThrows
225//    private static void fwRuleFile(RuleFile ruleFile, Integer fwMode) {
226//        if (ObjectUtil.isNull(fwMode)) {
227//            fwMode = 0;
228//        }
229//
230//        // 获取规则文件全路径
231//        String ruleFileFullPath = getRuleFileFullPath(ruleFile.getFileName());
232//
233//        // 规则引入
234//        List<String> imports = ruleFile.getImports();
235//        // 规则名称集合
236//        List<String> ruleNames = ruleFile.getRuleNames();
237//        // 规则集合
238//        List<Rule> rules = ruleFile.getRules();
239//
240//        // =======================> 创建规则文件
241//        File file = FileUtil.touch(ruleFileFullPath);
242//
243//        // 新增文件写入器
244//        fw = new FileWriter(file);
245//
246//        // 写入规则package
247//        if (fwMode != 0) {
248//            fwNewLine(PACKAGE_PREFIX + ruleFile.getPackageName());
249//        } else {
250//            appendNewLine(PACKAGE_PREFIX + ruleFile.getPackageName());
251//        }
252//
253//        // 写入规则imports
254//        if (CollectionUtil.isNotEmpty(imports)) {
255//            for (String imp : imports) {
256//                if (StrUtil.isEmpty(imp)) {
257//                    continue;
258//                }
259//
260//                if (fwMode != 0) {
261//                    fwNewLine(IMPORT_PREFIX + imp);
262//                } else {
263//                    appendNewLine(IMPORT_PREFIX + imp);
264//                }
265//            }
266//        }
267//
268//        // -------------------------> 循环写入规则
269//        for (Rule rule: rules) {
270//            RuleHeader header = rule.getHeader();
271//            RuleBody body = rule.getBody();
272//            RuleBodyWhen rWhen = body.getRWhen();
273//            List<RuleBodyWhenLhs> lstLhs = rWhen.getLhs();
274//            RuleBodyThen rThen = body.getRThen();
275//            List<RuleBodyThenRhs> lstRhs = rThen.getRhs();
276//
277//            // 写入规则名称
278//            if (fwMode != 0) {
279//                fwNewLine(RULE_NAME_PREFIX + RuleSymbolEnum.DQUOTE.getVal() + header.getRuleName() + RuleSymbolEnum.DQUOTE.getVal());
280//            } else {
281//                appendNewLine(RULE_NAME_PREFIX + RuleSymbolEnum.DQUOTE.getVal() + header.getRuleName() + RuleSymbolEnum.DQUOTE.getVal());
282//            }
283//
284//            // 写入规则属性
285//            fwRuleAttrs(header.getAttributes(), fwMode);
286//
287//            // 写入WHEN
288//            fwRuleWhen(body.getRWhen(), fwMode);
289//
290//            // 写入THEN
291//            fwRuleThen(body.getRThen(), fwMode);
292//
293//            // 规则END标识
294//            if (fwMode != 0) {
295//                fwNewLine(RULE_END);
296//            } else {
297//                appendNewLine(RULE_END);
298//            }
299//        }
300//
301//        if (0 == fwMode) {
302//            fw.write(sb.toString());
303//        }
304//
305//        fw.close();
306//    }
307//
308//    /**
309//     * 删除规则文件
310//     * @param ruleFileName
311//     */
312//    public static void delRuleFile(String ruleFileName) {
313//        String ruleFileFullPath = getRuleFileFullPath(ruleFileName);
314//
315//        FileUtil.del(ruleFileFullPath);
316//    }
317//
318//    /**
319//     * 清除规则文件
320//     * @param ruleFileName
321//     */
322//    public static void cleanRuleFile(String ruleFileName) {
323//        String ruleFileFullPath = getRuleFileFullPath(ruleFileName);
324//
325//        FileUtil.clean(ruleFileFullPath);
326//    }
327//
328//    /**
329//     * 写入规则属性
330//     * @param attr
331//     */
332//    @SneakyThrows
333//    private static void fwRuleAttrs(RuleHeaderAttributes attr, Integer fwMode) {
334//        if (ObjectUtil.isNull(attr)) {
335//            return;
336//        }
337//
338//        // 写入当前规则是否启用属性
339//        if (ObjectUtil.isNotNull(attr.getEnabled())) {
340//            fwNewLine(RuleAttributesEnum.ENABLED.getVal() + " " + attr.getEnabled());
341//        }
342//
343//        // 写入规则使用的语言类型(取值为java和mvel,默认值为java)属性
344//        if (StrUtil.isNotEmpty(attr.getDialect())) {
345//            fwNewLine(RuleAttributesEnum.DIALECT.getVal() + " " + attr.getDialect());
346//        }
347//
348//        // 写入规则的执行优先级(数值越大越优先执行)属性
349//        if (ObjectUtil.isNotNull(attr.getSalience())) {
350//            fwNewLine(RuleAttributesEnum.SALIENCE.getVal() + " " + attr.getSalience());
351//        }
352//
353//        // 写入是否不允许多次循环执行(默认为false,为true则只允许被执行一次)属性
354//        if (ObjectUtil.isNotNull(attr.getLockOnActive())) {
355//            fwNewLine(RuleAttributesEnum.LOCK_ON_ACTIVE.getVal() + " " + attr.getLockOnActive());
356//        }
357//
358//        // 写入激活分组属性
359//        if (StrUtil.isNotEmpty(attr.getActivationGroup())) {
360//            fwNewLine(RuleAttributesEnum.ACTIVATION_GROUP.getVal() + " " + attr.getActivationGroup());
361//        }
362//
363//        // 写入议程分组属性
364//        if (StrUtil.isNotEmpty(attr.getAgendaGroup())) {
365//            fwNewLine(RuleAttributesEnum.AGENDA_GROUP.getVal() + " " + attr.getAgendaGroup());
366//        }
367//
368//        // 写入自动获取焦点(默认为false)属性
369//        if (ObjectUtil.isNotNull(attr.getAutoFocus())) {
370//            fwNewLine(RuleAttributesEnum.AUTO_FOCUS.getVal() + " " + attr.getAutoFocus());
371//        }
372//
373//        // 写入规则定时(单位:毫秒)属性
374//        if (ObjectUtil.isNotNull(attr.getDuration())) {
375//            fwNewLine(RuleAttributesEnum.DURATION.getVal() + " " + attr.getDuration());
376//        }
377//
378//        // 写入定时器的方式指定规则执行的时间属性
379//        if (StrUtil.isNotEmpty(attr.getTimer())) {
380//            fwNewLine(RuleAttributesEnum.TIMER.getVal() + " " + attr.getTimer());
381//        }
382//
383//        // 写入规则的生效时间属性
384//        if (StrUtil.isNotEmpty(attr.getDateEffective())) {
385//            fwNewLine(RuleAttributesEnum.DATE_EFFECTIVE.getVal() + " " + attr.getDateEffective());
386//        }
387//
388//        // 写入规则的失效时间属性
389//        if (StrUtil.isNotEmpty(attr.getDateExpires())) {
390//            fwNewLine(RuleAttributesEnum.DATE_EXPIRES.getVal() + " " + attr.getDateExpires());
391//        }
392//    }
393//
394//    /**
395//     * 写入规则条件
396//     * @param rWhen
397//     */
398//    @SneakyThrows
399//    private static void fwRuleWhen(RuleBodyWhen rWhen, Integer fwMode) {
400//        // 写入WHEN标识
401//        fwNewLine(RULE_WHEN);
402//
403//        // 如果条件集合为空,则写入默认条件
404//        if (CollectionUtil.isEmpty(rWhen.getLhs())) {
405//            fwNewLine(EVAL_TRUE);
406//
407//            return;
408//        }
409//
410//        // 循环写入规则条件
411//        for (RuleBodyWhenLhs lhs: rWhen.getLhs()) {
412//            if (ObjectUtil.isNull(lhs)) {
413//                continue;
414//            }
415//
416//            // 写入条件对象绑定变量名
417//            if (StrUtil.isNotEmpty(lhs.getLhsObjBindName())) {
418//                fw.write(RuleSymbolEnum.DOLLAR.getVal() + lhs.getLhsObjBindName() + RuleSymbolEnum.COLON.getVal());
419//            }
420//
421//            // 写入条件对象
422//            if (StrUtil.isNotEmpty(lhs.getLhsObjName())) {
423//                fw.write(lhs.getLhsObjName());
424//            }
425//
426//            // 写入对象左括号
427//            fw.write(RuleSymbolEnum.LPAREN.getVal());
428//
429//            // 如果自定义条件不为空,写入自定义条件
430//            if (StrUtil.isNotEmpty(lhs.getLhs())) {
431//                fw.write(lhs.getLhs());
432//            }
433//            // 否则,写入拼接条件
434//            else if (CollectionUtil.isNotEmpty(lhs.getLstSubLhs())) {
435//                for (RuleBodyWhenSubLhs subLhs : lhs.getLstSubLhs()) {
436//                    if (ObjectUtil.isNull(subLhs)) {
437//                        continue;
438//                    }
439//
440//                    // 写入左符号
441//                    if (StrUtil.isNotEmpty(subLhs.getOpenSymbol())) {
442//                        fw.write(subLhs.getOpenSymbol());
443//                    }
444//
445//                    fw.write(subLhs.getLVal() + RuleSymbolEnum.SPACE.getVal());
446//                    fw.write(subLhs.getCmpOps() + RuleSymbolEnum.SPACE.getVal());
447//                    if (subLhs.getRVal() instanceof String) {
448//                        fw.write(RuleSymbolEnum.DQUOTE.getVal() + (String)subLhs.getRVal() + RuleSymbolEnum.DQUOTE.getVal());
449//                    } else {
450//                        fw.write(Convert.toStr(subLhs.getRVal()));
451//                    }
452//
453//                    // 写入右符号
454//                    if (StrUtil.isNotEmpty(subLhs.getCloseSymbol())) {
455//                        fw.write(subLhs.getCloseSymbol());
456//                    }
457//
458//                    // 写入逻辑运算符
459//                    if (StrUtil.isNotEmpty(subLhs.getLogicalOperator())) {
460//                        fw.write(RuleSymbolEnum.SPACE.getVal() + subLhs.getLogicalOperator() + RuleSymbolEnum.SPACE.getVal());
461//                    }
462//                }
463//            }
464//
465//            // 写入对象右括号
466//            fw.write(RuleSymbolEnum.RPAREN.getVal());
467//
468//            // 写入换行
469//            fwNewLine(RuleSymbolEnum.NEWLINE.getVal());
470//        }
471//    }
472//
473//    /**
474//     * 写入THEN
475//     * @param rThen
476//     */
477//    @SneakyThrows
478//    private static void fwRuleThen(RuleBodyThen rThen, Integer fwMode) {
479//        // 写入THEN标识
480//        fwNewLine(RULE_THEN);
481//
482//        // 如果事务集合为空,则返回
483//        if (CollectionUtil.isEmpty(rThen.getRhs())) {
484//            return;
485//        }
486//
487//        // 循环写入规则事务
488//        for (RuleBodyThenRhs rhs : rThen.getRhs()) {
489//            if (ObjectUtil.isNull(rhs)) {
490//                continue;
491//            }
492//
493//            // 写入事务
494//            if (StrUtil.isNotEmpty(rhs.getRhs())) {
495//                fwNewLine(rhs.getRhs());
496//            }
497//        }
498//    }
499//
500//    /**
501//     * 写入新的一行
502//     * @param contant
503//     * @throws IOException
504//     */
505//    private static void fwNewLine(String contant) throws IOException {
506//        fw.write(contant + RuleSymbolEnum.NEWLINE.getVal());
507//    }
508//
509//    // 追加新的一行
510//    private static void appendNewLine(String contant) {
511//        sb.append(contant + RuleSymbolEnum.NEWLINE.getVal());
512//    }
513}