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}