您的位置:首页 > 编程语言 > Java开发

简单drools规则java代码自动生成

2017-05-21 22:10 260 查看

简单drools规则自动生成

  规则自动生成,drools也提供了支持,比如:
1.决策表(decision table)https://docs.jboss.org/drools/release/6.5.0.Final/drools-docs/html_single/index.html#d0e5713

2.规则模板(Rule Templates)https://docs.jboss.org/drools/release/6.5.0.Final/drools-docs/html_single/index.html#d0e6464

3. 流式API http://docs.jboss.org/drools/release/5.2.0.Final/droolsjbpm-introduction-docs/html/ch02.html#d0e124

  不过由于现实环境中,我们会根据Excel 文件提供规则描述,解析动态生成规则,如果产品给的是决策表,那就很容易了,不过产品一般会根据自己的喜好,制定自己的"决策表".

  比如:(一行放不下,截取了两种图)





      博文http://blog.csdn.net/doctor_who2004/article/details/72600232介绍了如何读取Excel文件转换为java类,此不复述。
    文件中的内容对应的java类:

package com.beaver.drools.exampl.travel.rule;

import org.javafunk.excelparser.annotations.ExcelField;
import org.javafunk.excelparser.annotations.ExcelObject;
import org.javafunk.excelparser.annotations.ParseType;

/**
* Created by beaver on 2017/5/20.
*/
@ExcelObject(parseType = ParseType.ROW, start = 2, end = 61)
public class TravelRule {

//公司名称
@ExcelField(position = 1)
private String companyName;

//费用类型
@ExcelField(position = 2)
private String expenseType;

//规则应用场景
@ExcelField(position = 3)
private String applyPoint;

//规则结果
@ExcelField(position = 4)
private String ruleAction;

//规则内容
@ExcelField(position = 7)
private String rule;

//提示信息
@ExcelField(position = 9)
private String alertMessage;

//规则ID
@ExcelField(position = 11)
private String ruleId;

//解析出的drools规则内容
private String droolsRule;

public String getCompanyName() {
return companyName;
}

public void setCompanyName(String companyName) {
this.companyName = companyName;
}

public String getExpenseType() {
return expenseType;
}

public void setExpenseType(String expenseType) {
this.expenseType = expenseType;
}

public String getRule() {
return rule;
}

public void setRule(String rule) {
this.rule = rule;
}

public String getApplyPoint() {
return applyPoint;
}

public void setApplyPoint(String applyPoint) {
this.applyPoint = applyPoint;
}

public String getRuleAction() {
return ruleAction;
}

public void setRuleAction(String ruleAction) {
this.ruleAction = ruleAction;
}

public String getAlertMessage() {
return alertMessage;
}

public void setAlertMessage(String alertMessage) {
this.alertMessage = alertMessage;
}

public String getRuleId() {
return ruleId;
}

public void setRuleId(String ruleId) {
this.ruleId = ruleId;
}

public String getDroolsRule() {
return droolsRule;
}

public void setDroolsRule(String droolsRule) {
this.droolsRule = droolsRule;
}

@Override
public String toString() {
return "TravelRule{" +
"companyName='" + companyName + '\'' +
", expenseType='" + expenseType + '\'' +
", applyPoint='" + applyPoint + '\'' +
", ruleAction='" + ruleAction + '\'' +
", rule='" + rule + '\'' +
", alertMessage='" + alertMessage + '\'' +
", ruleId='" + ruleId + '\'' +
", droolsRule='" + droolsRule + '\'' +
'}';
}
}

   规则内when条件的匹配对象一般我们使用java中自定义的类最好,此类为:

package com.beaver.drools.exampl.travel.rule;

import com.beaver.drools.common.model.RuleResult;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
* Created by beaver on 2017/5/20.
*/
@Data
public class MatchInvoiceTravelRuleRequestDto {
//规则ID
private String ruleOID;

//出差申请ID
private String invoiceOID;

//出差信息-人员级别、出差地点、出差费用等等
private Map<String, String> data = new HashMap<>();

//规则执行结果
private RuleResult result = RuleResult.OK;

//备注-规则明细
private String remarkMessage;

}


   本博文只是实现简单drools规则的自动生成,一个简单的规则的定义如下:

package com.beaver.drools.exampl.travel.rule;

import com.beaver.drools.common.model.RuleResult;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Created by beaver on 2017/5/20.<br>
* 简单规则组成,并不不包含drools复杂的语法规则
*/
public class TravelRuleGenerate {
//规则包名
private String packageName;
//规则需要外部类的包
private List<String> importPackages = new ArrayList<>();
//规则名字
private String ruleName;

//规则匹配的类型,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem
private String objectType;

//规则匹配类型的变量名,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem中$o
private String objectVar;

//规则信息
private TravelRule travelRule;

//规则执行动作结果赋值属性名,如 $invoice.setResult(RuleResult.REJECT); 中的resultr;
private String resultPropertyName;
//规则执行动作结果的提示信息赋值属性名,如   $invoice.setRemarkMessage("您的房费高于公司标准 ");中的remarkMessage.
private String alertMessagePropertyName;

//规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),
// 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下
//不过key为正则表达式
private Map<String, String> rulePropertyNameAlias = new HashMap<>();

public String getPackageName() {
return packageName;
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}

public List<String> getImportPackages() {
return importPackages;
}

public void setImportPackages(List<String> importPackages) {
this.importPackages = importPackages;
}

public String getRuleName() {
return ruleName;
}

public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}

public TravelRule getTravelRule() {
return travelRule;
}

public void setTravelRule(TravelRule travelRule) {
this.travelRule = travelRule;
}

public String getObjectType() {
return objectType;
}

public void setObjectType(String objectType) {
this.objectType = objectType;
}

public String getObjectVar() {
return objectVar;
}

public void setObjectVar(String objectVar) {
this.objectVar = objectVar;
}

public String getResultPropertyName() {
return resultPropertyName;
}

public void setResultPropertyName(String resultPropertyName) {
this.resultPropertyName = resultPropertyName;
}

public String getAlertMessagePropertyName() {
return alertMessagePropertyName;
}

public void setAlertMessagePropertyName(String alertMessagePropertyName) {
this.alertMessagePropertyName = alertMessagePropertyName;
}

public Map<String, String> getRulePropertyNameAlias() {
return rulePropertyNameAlias;
}

public void setRulePropertyNameAlias(Map<String, String> rulePropertyNameAlias) {
this.rulePropertyNameAlias = rulePropertyNameAlias;
}
}


其中,
//规则信息
private TravelRule travelRule;


是我们解析Excel文件得到的原生规则,我们需要对其处理,生成drools规则描述。

下面的定义主要是为业务和代码需求定制,Excel文件中规则属性名多个对应一个意思,后者和我们java代码定义的不一样,所以类似mybatis,做个映射。

//规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),
// 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下
//不过key为正则表达式
private Map<String, String> rulePropertyNameAlias = new HashMap<>();


下面代码是对
private TravelRule travelRule;


及本类提供的规则信息产生drools规则,实现是比较笨重的方法,因为规则比较简单,复杂的规则如何实现呢?

package com.beaver.drools.exampl.travel.rule;

import com.beaver.drools.common.model.RuleResult;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Created by beaver on 2017/5/20.<br>
* 简单规则组成,并不不包含drools复杂的语法规则
*/
public class TravelRuleGenerate {
//规则包名
private String packageName;
//规则需要外部类的包
private List<String> importPackages = new ArrayList<>();
//规则名字
private String ruleName;

//规则匹配的类型,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem
private String objectType;

//规则匹配类型的变量名,如 $o: OrderItem( $p : price, $code : custCode )中的OrderItem中$o
private String objectVar;

//规则信息
private TravelRule travelRule;

//规则执行动作结果赋值属性名,如 $invoice.setResult(RuleResult.REJECT); 中的resultr;
private String resultPropertyName;
//规则执行动作结果的提示信息赋值属性名,如   $invoice.setRemarkMessage("您的房费高于公司标准 ");中的remarkMessage.
private String alertMessagePropertyName;

//规则匹配属性别名,如data["EXPENSE_LEVEL"] not in ("总裁"),
// 中的EXPENSE_LEVEL在travelRule中droolsRule中的名不一样,类似mybatis映射一下
//不过key为正则表达式
private Map<String, String> rulePropertyNameAlias = new HashMap<>();

public String getPackageName() {
return packageName;
}

public void setPackageName(String packageName) {
this.packageName = packageName;
}

public List<String> getImportPackages() {
return importPackages;
}

public void setImportPackages(List<String> importPackages) {
this.importPackages = importPackages;
}

public String getRuleName() {
return ruleName;
}

public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}

public TravelRule getTravelRule() {
return travelRule;
}

public void setTravelRule(TravelRule travelRule) {
this.travelRule = travelRule;
}

public String getObjectType() {
return objectType;
}

public void setObjectType(String objectType) {
this.objectType = objectType;
}

public String getObjectVar() {
return objectVar;
}

public void setObjectVar(String objectVar) {
this.objectVar = objectVar;
}

public String getResultPropertyName() {
return resultPropertyName;
}

public void setResultPropertyName(String resultPropertyName) {
this.resultPropertyName = resultPropertyName;
}

public String getAlertMessagePropertyName() {
return alertMessagePropertyName;
}

public void setAlertMessagePropertyName(String alertMessagePropertyName) {
this.alertMessagePropertyName = alertMessagePropertyName;
}

public Map<String, String> getRulePropertyNameAlias() {
return rulePropertyNameAlias;
}

public void setRulePropertyNameAlias(Map<String, String> rulePropertyNameAlias) {
this.rulePropertyNameAlias = rulePropertyNameAlias;
}

//规则生成
public String Generate() {
StringBuilder sb = new StringBuilder();

//规则头部
sb.append("package ").append(packageName).append("\n").append("\n");

importPackages.stream().forEach(t -> sb.append("import ").append(t).append("\n"));

sb.append("\n\n");

//规则名称
sb.append("rule  \"").append(generateRuleName()).append("\n\n");

//规则条件
sb.append("when").append("\n");
sb.append("  ").append(objectVar).append(" : ").append(objectType).append("(").append("\n");

//规则条件内容
List<String> rules = generateWhenContent();
rules.stream().forEach(t -> {
sb.append("  ").append(t).append(",\n");
});

int lastIndexOf = sb.lastIndexOf(",");
if (lastIndexOf > 0) {
sb.deleteCharAt(lastIndexOf);
}

sb.append(" ) \n");

//规则执行动作
sb.append("then \n");

//规则执行结果
sb.append("  ").append(objectVar).append(".set").append(StringUtils.capitalize(resultPropertyName)).append("(");
RuleResult ruleResult = RuleResult.valueOf(travelRule.getRuleAction());
sb.append(RuleResult.class.getSimpleName()).append(".").append(ruleResult.name()).append("); \n");

//规则执行提示信息
sb.append("  ").append(objectVar).append(".set").append(StringUtils.capitalize(alertMessagePropertyName)).append("(\"");
sb.append(travelRule.getAlertMessage()).append(" \");");

sb.append("\n").append("end");
return sb.toString();
}

//{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300
private List<String> generateWhenContent() {
String rule = travelRule.getRule().trim();
if (rule.contains("OR") || rule.contains("or")) {
throw new UnsupportedOperationException("请知悉drools 的基本使用:复杂的规则拆成简单的规则执行,or的规则请拆分");
}

if (rule.contains("and")) {
throw new UnsupportedOperationException("AND条件单词大写");
}

List<String> ruelList = Splitter.on(Pattern.compile("AND")).trimResults().splitToList(rule);

List<String> rules = ruelList.stream().map(this::generateARule).collect(Collectors.toList());
return rules;
}

//去除AND条件的一条简单规则
private String generateARule(final String rule) {
if (StringUtils.deleteWhitespace(rule).contains("NOTIN")) {
Pair<String, String> pair = getRulePropertyNameAliasAndValuesForIn(rule, "NOT");
return pair.getKey() + " not in " + pair.getValue();
}

if (rule.contains("IN")) {
Pair<String, String> pair = getRulePropertyNameAliasAndValuesForIn(rule, "IN");
return pair.getKey() + " in " + pair.getValue();
}

if (rule.contains(">")) {
return getRulePropertyNameAliasAndValuesForCompare(rule, ">");
}

throw new UnsupportedOperationException();
}

//{EXP_LEVEL}IN[一般员工] , {ER_LOCATION}NOT IN[北京/上海/深圳]  to
//data["EXPENSE_LEVEL"] in ("一般员工"),	data["city"] not in ("上海","北京","深圳","广州"),
private Pair<String, String> getRulePropertyNameAliasAndValuesForIn(final String rule, final String separators) {
String name = StringUtils.splitByWholeSeparator(rule, separators)[0];
name = getRulePropertyNameAlias(name).getValue();

name = "data[\"" + name + "\"]";

String value = StringUtils.substring(rule
, StringUtils.lastIndexOf(rule, "[") + 1
, StringUtils.lastIndexOf(rule, "]"));

List<String> values = Splitter.on("/").trimResults().splitToList(value);
value = values.stream().map(t -> "\"" + t + "\"").collect(Collectors.joining(","));
value = "(" + value + ")";
return Pair.of(name, value);
}

//{ER_EXP_FEE}>{ER_DAYS}*300     to
// BigDecimal.valueOf(Double.valueOf(data.["INVOICE_AMOUNT"])) > 300 * Double.valueOf(data["days"])
private String getRulePropertyNameAliasAndValuesForCompare(final String rule, final String separator) {
if (!Arrays.asList(">", "<", "=").contains(separator.trim())) {
throw new UnsupportedOperationException();
}

List<String> list = Splitter.on(separator.trim()).trimResults().splitToList(rule);
String express1 = list.get(0);
String express2 = list.get(1);
String template1 = "BigDecimal.valueOf(Double.valueOf(data[\"%s\"]))";
String tempalte2 = "Double.valueOf(data[\"%s\"])";

Pair<String, String> rulePropertyNameAlias1 = getRulePropertyNameAlias(express1);
express1 = String.format(template1, rulePropertyNameAlias1.getValue());

Pair<String, String> rulePropertyNameAlias2 = getRulePropertyNameAlias(express2);

express2 = String.format(tempalte2, rulePropertyNameAlias2.getValue());

String replace = rule.replace(rulePropertyNameAlias1.getKey(), express1);
replace = replace.replace(rulePropertyNameAlias2.getKey(), express2);
return replace;
}

private Pair<String, String> getRulePropertyNameAlias(final String content) {
for (Entry<String, String> entry : rulePropertyNameAlias.entrySet()) {
Pattern compile = Pattern.compile(entry.getKey());
Matcher matcher = compile.matcher(content);
if (matcher.find()) {
String name = content.substring(matcher.regionStart(), matcher.regionEnd());
String aliasName = entry.getValue();
return Pair.of(name, aliasName);
}
}

throw new UnsupportedOperationException(content);
}

private String generateRuleName() {
StringBuilder sb = new StringBuilder();
sb.append(travelRule.getCompanyName())
.append("-")
.append(travelRule.getExpenseType())
.append("-")
.append(ruleName).append("\"");

return sb.toString();
}

}

其中
 //规则生成

    public String Generate() {。。。}

方法主要是drools规则组装的实现。

我们测试一下:

package com.beaver.drools.exampl.travel.rule;

import com.beaver.drools.util.KieSessionUtil;
import com.google.gson.Gson;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.javafunk.excelparser.SheetParser;
import org.kie.api.io.ResourceType;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
* Created by beaver on 2017/5/20.
*/
public class TravleRuelTest {

static String packageName = "com.beaver.drools.exampl.travel.rule";
static List<String> importPackages = Arrays.asList(
"java.math.*"
, "com.beaver.drools.common.model.*");

static String sheetName = "工作表1";
static String fileName = "腾讯差标规则1.xlsx";

static String objectType = "MatchInvoiceTravelRuleRequestDto";
static String objectVar = "$invoice";

static String resultPropertyName = "result";
static String alertMessagePropertyName = "remarkMessage";

//规则内容属性别名,如{EXP_LEVEL}IN[一般员工],EXP_LEVEL 可以起别名
static Map<String, String> rulePropertyNameAlias = new HashMap<>();

static {
rulePropertyNameAlias.put("\\{.*LEVEL.*\\}", "EXPENSE_LEVEL");
rulePropertyNameAlias.put("\\{.*LOCATION.*\\}", "city");
rulePropertyNameAlias.put("\\{.*FEE.*\\}", "INVOICE_AMOUNT");
rulePropertyNameAlias.put("\\{.*DAYS.*\\}", "days");
}

public static void main(String[] args) throws IOException {
//Get the sheet using POI API.
SheetParser parser = new SheetParser();
InputStream inputStream = TravleRuelTest.class.getClassLoader().getResourceAsStream(fileName);
Sheet sheet = new XSSFWorkbook(inputStream).getSheet(sheetName);
//Invoke the Sheet parser.
List<TravelRule> entityList = parser.createEntity(sheet, TravelRule.class, t -> t.printStackTrace());

//
entityList = entityList.stream()
.filter(t -> t.getCompanyName() != null && !t.getCompanyName().isEmpty())
.collect(Collectors.toList());

System.out.println(new Gson().toJson(entityList));

Set<String> set = entityList.stream().map(TravelRule::getRuleId).collect(Collectors.toSet());
if (set.size() != entityList.size()) {
throw new IllegalArgumentException("id 有重复");
}

entityList.stream()
.map(TravleRuelTest::travelRuleGenerate)
.forEach(t -> {
System.out.println(t);
});
}

public static TravelRule travelRuleGenerate(TravelRule travelRule) {
TravelRuleGenerate travelRuleGenerate = new TravelRuleGenerate();
travelRuleGenerate.setPackageName(packageName);
travelRuleGenerate.setImportPackages(importPackages);
travelRuleGenerate.setRuleName(travelRule.getRule());
travelRuleGenerate.setObjectType(objectType);
travelRuleGenerate.setObjectVar(objectVar);
travelRuleGenerate.setTravelRule(travelRule);
travelRuleGenerate.setResultPropertyName(resultPropertyName);
travelRuleGenerate.setAlertMessagePropertyName(alertMessagePropertyName);
travelRuleGenerate.setRulePropertyNameAlias(rulePropertyNameAlias);
String generate = travelRuleGenerate.Generate();

KieSessionUtil kieSessionUtil = new KieSessionUtil();
kieSessionUtil.addContent(generate, ResourceType.DRL);
kieSessionUtil.verifyRules();
travelRule.setDroolsRule(generate);
return travelRule;
}

}


输出:

..................................
[
{
"companyName": "微民",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}\u003e{ER_DAYS} *600",
"alertMessage": "您的房费高于公司标准",
"ruleId": "8a24ef78-d1c4-4c7c-924f-f199fa3c5eb1"
},
{
"companyName": "微民",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}\u003e{ER_DAYS}*700",
"alertMessage": "您的房费高于公司标准",
"ruleId": "f9b17610-7917-4f71-b369-602224fdd20d"
},
{
"companyName": "微民",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}\u003e{ER_DAYS}*800",
"alertMessage": "您的房费高于公司标准",
"ruleId": "128e621a-832a-4876-81c8-a5a9624b6ca7"
},
{
"companyName": "微民",
"expenseType": "差旅补贴",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}\u003e{ER_DAYS}*140",
"alertMessage": "您的补贴高于公司标准",
"ruleId": "06d1afc9-4a0e-4ad6-b0b1-01af068997fe"
},
{
"companyName": "微民",
"expenseType": "差旅补贴",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",
"alertMessage": "您的补贴高于公司标准",
"ruleId": "922d99ff-c5bc-4f26-a365-d8b6e8a9a999"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",
"alertMessage": "您的房费高于公司标准",
"ruleId": "7c170ce0-080e-499a-9046-0dc7d226b86c"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*300",
"alertMessage": "您的房费高于公司标准",
"ruleId": "6135e677-867b-41ed-8d00-7512b5ec5c2a"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}\u003e{ER_DAYS}*550",
"alertMessage": "您的房费高于公司标准",
"ruleId": "636ebfda-6d78-4ec7-a441-234ff931fa57"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",
"alertMessage": "您的房费高于公司标准",
"ruleId": "b236a113-e547-4f65-9ddc-3b9549efa6ce"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*700",
"alertMessage": "您的房费高于公司标准",
"ruleId": "8bb7e480-bf94-4c24-a46e-963ae60bee7e"
},
{
"companyName": "腾南",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}\u003e{ER_DAYS}*500",
"alertMessage": "您的房费高于公司标准",
"ruleId": "f74d0d7c-d31d-49d9-84ff-c0889bf37771"
},
{
"companyName": "腾南",
"expenseType": "差旅补贴",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{ER_EXP_FEE}\u003e{ER_DAYS}*80",
"alertMessage": "您的补贴高于公司标准",
"ruleId": "154866b0-fdc5-433f-9c3f-640e9a812564"
},
{
"companyName": "腾新",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*600",
"alertMessage": "您的房费高于公司标准",
"ruleId": "e4ece4c7-f9ca-46fc-bb7b-2a4443513daf"
},
{
"companyName": "腾新",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}\u003e{ER_DAYS}*500",
"alertMessage": "您的房费高于公司标准",
"ruleId": "51768055-8a13-4d44-9c61-e261bcb74149"
},
{
"companyName": "腾新",
"expenseType": "住宿费",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}\u003e{ER_DAYS}*400",
"alertMessage": "您的房费高于公司标准",
"ruleId": "0d3f86b6-f937-4544-916d-8fac5061c479"
},
{
"companyName": "腾新",
"expenseType": "差旅补贴",
"applyPoint": "ER_SUBMIT",
"ruleAction": "REJECT",
"rule": "{ER_EXP_FEE}\u003e{ER_DAYS}*100",
"alertMessage": "您的补贴高于公司标准",
"ruleId": "a9c0f423-7880-4f86-a761-ba2f2ec83c66"
}
]

.....................

TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}>{ER_DAYS} *600', alertMessage='您的房费高于公司标准', ruleId='8a24ef78-d1c4-4c7c-924f-f199fa3c5eb1', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "微民-住宿费-{EXP_LEVEL}IN[1] AND {ER_EXP_FEE}>{ER_DAYS} *600"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("1"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}>{ER_DAYS}*700', alertMessage='您的房费高于公司标准', ruleId='f9b17610-7917-4f71-b369-602224fdd20d', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "微民-住宿费-{EXP_LEVEL}IN[2] AND {ER_EXP_FEE}>{ER_DAYS}*700"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("2"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='微民', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}>{ER_DAYS}*800', alertMessage='您的房费高于公司标准', ruleId='128e621a-832a-4876-81c8-a5a9624b6ca7', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "微民-住宿费-{EXP_LEVEL}IN[3] AND {ER_EXP_FEE}>{ER_DAYS}*800"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("3"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='微民', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*140', alertMessage='您的补贴高于公司标准', ruleId='06d1afc9-4a0e-4ad6-b0b1-01af068997fe', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "微民-差旅补贴-{ER_LOCATION_COUNTRY}IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*140"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["city"] in ("中国"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的补贴高于公司标准 ");
end'}
TravelRule{companyName='微民', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的补贴高于公司标准', ruleId='922d99ff-c5bc-4f26-a365-d8b6e8a9a999', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "微民-差旅补贴-{ER_LOCATION_COUNTRY}NOT IN[中国] AND {ER_EXP_FEE}>{ER_DAYS}*400"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["city"] not in ("中国"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的补贴高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='7c170ce0-080e-499a-9046-0dc7d226b86c', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[一般员工] AND {ER_EXP_FEE}>{ER_DAYS}*400"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("一般员工"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300', alertMessage='您的房费高于公司标准', ruleId='6135e677-867b-41ed-8d00-7512b5ec5c2a', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[一般员工] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*300"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("一般员工"),
data["city"] not in ("北京","上海","深圳"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}>{ER_DAYS}*550', alertMessage='您的房费高于公司标准', ruleId='636ebfda-6d78-4ec7-a441-234ff931fa57', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[总监] AND {ER_EXP_FEE}>{ER_DAYS}*550"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("总监"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='b236a113-e547-4f65-9ddc-3b9549efa6ce', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[总监] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*400"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("总监"),
data["city"] not in ("北京","上海","深圳"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*700', alertMessage='您的房费高于公司标准', ruleId='8bb7e480-bf94-4c24-a46e-963ae60bee7e', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*700"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("总裁"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*500', alertMessage='您的房费高于公司标准', ruleId='f74d0d7c-d31d-49d9-84ff-c0889bf37771', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳] AND {ER_EXP_FEE}>{ER_DAYS}*500"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("总裁"),
data["city"] not in ("北京","上海","深圳"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾南', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_EXP_FEE}>{ER_DAYS}*80', alertMessage='您的补贴高于公司标准', ruleId='154866b0-fdc5-433f-9c3f-640e9a812564', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾南-差旅补贴-{ER_EXP_FEE}>{ER_DAYS}*80"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的补贴高于公司标准 ");
end'}
TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*600', alertMessage='您的房费高于公司标准', ruleId='e4ece4c7-f9ca-46fc-bb7b-2a4443513daf', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾新-住宿费-{EXP_LEVEL}IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*600"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] in ("总裁"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*500', alertMessage='您的房费高于公司标准', ruleId='51768055-8a13-4d44-9c61-e261bcb74149', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾新-住宿费-{EXP_LEVEL}NOT IN[总裁] AND {ER_EXP_FEE}>{ER_DAYS}*500"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] not in ("总裁"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾新', expenseType='住宿费', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400', alertMessage='您的房费高于公司标准', ruleId='0d3f86b6-f937-4544-916d-8fac5061c479', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾新-住宿费-{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
data["EXPENSE_LEVEL"] not in ("总裁"),
data["city"] not in ("北京","上海","深圳","成都","广州","杭州"),
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的房费高于公司标准 ");
end'}
TravelRule{companyName='腾新', expenseType='差旅补贴', applyPoint='ER_SUBMIT', ruleAction='REJECT', rule='{ER_EXP_FEE}>{ER_DAYS}*100', alertMessage='您的补贴高于公司标准', ruleId='a9c0f423-7880-4f86-a761-ba2f2ec83c66', droolsRule='package com.beaver.drools.exampl.travel.rule

import java.math.*
import com.beaver.drools.common.model.*

rule  "腾新-差旅补贴-{ER_EXP_FEE}>{ER_DAYS}*100"

when
$invoice : MatchInvoiceTravelRuleRequestDto(
BigDecimal.valueOf(Double.valueOf(data["INVOICE_AMOUNT"]))>Double.valueOf(data["days"])
)
then
$invoice.setResult(RuleResult.REJECT);
$invoice.setRemarkMessage("您的补贴高于公司标准 ");
end'}

Process finished with exit code 0

 每产生一个规则,都用drools引擎校验了一下,以防出错。

 上面只是对简单的规则如:

{EXP_LEVEL}NOT IN[总裁] AND {ER_LOCATION}NOT IN[北京/上海/深圳/成都/广州/杭州] AND {ER_EXP_FEE}>{ER_DAYS}*400
 做了解析,用的是比较笨的解析和组装,复杂的或者本文是不是可以用
https://github.com/antlr/antlr4 https://github.com/antlr/stringtemplate4 http://freemarker.org
这些工具更简单呢,后面学习一下第一个工具,再试试。

本文代码地址:
https://github.com/sdcuike/drools-example/tree/2017-05-21/src/main/java/com/beaver/drools/exampl/travel/rule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: