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