PatternDescr 内的 Drools AndDescr(和 OrDescr)
Drools AndDescr (and OrDescr) inside PatternDescr
我以编程方式创建规则文件。这是一个简单的例子:
PackageDescr pkg = DescrFactory.newPackage()
.name(Constants.DRL_FILE_PACKAGE)
.newImport().target(Product.class.getName()).end()
.getDescr();
RuleDescr testRule = new RuleDescr();
RelationalExprDescr expr1 = new RelationalExprDescr("==", false, null, new ExprConstraintDescr("productId.id"), new ExprConstraintDescr(null));
RelationalExprDescr expr2 = new RelationalExprDescr("==", false, null, new ExprConstraintDescr("operation"), new ExprConstraintDescr("5"));
OrDescr or = new OrDescr();
PatternDescr patternDescr = new PatternDescr();
AndDescr and = new AndDescr();
or.addDescr(expr1);
or.addDescr(expr2);
patternDescr.setObjectType(Product.class.getName());
patternDescr.addConstraint(or);
and.addDescr(patternDescr);
testRule.setLhs(and);
testRule.setConsequence("System.out.println(\"Hi\");");
pkg.addRule(testRule);
String drl = new DrlDumper().dump(pkg);
这会生成以下 DRL 规则:
rule "null"
when
test.Product( [OR [productId.id == null, operation == 5] ] )
then
System.out.println("Hi");
end
然后在使用此规则创建 KieContainer 时出现异常:
[ERR 101] Line 7:53 no viable alternative at input 'OR' in rule "null"
在 PatternDescr 中包含 AndDescr 或 OrDescr 是否无效?
如果是这样,我是否可以只覆盖 AndDescr 和 OrDescr 中的 toString 方法(这是此处打印的内容)使其成为有效语法,或者是否有更好的方法来处理这种情况?
如果它不是无效的,那么我缺少什么才能成功构建 KieContainer?
您正在使用内部 API 来构建对用户不友好的规则。
即使我们回答了这个问题,您也会发现很多这样的问题。而且内部结构终究是要变的,建议大家不要用。
相反,开始使用可执行模型以编程方式构建规则,Java DSL 正是根据您的需要创建的。这样你就不用担心描述符的内部结构了。
看看 org.drools.modelcompiler.PatternDSLTest
或 org.drools.model.FlowDSLTest
,您可以找到一些与您正在做的事情非常相似的例子,比如这个
public void testOr() {
Result result = new Result();
Variable<Person> personV = declarationOf( Person.class );
Variable<Person> markV = declarationOf( Person.class );
Variable<String> nameV = declarationOf( String.class );
Rule rule = rule( "or" )
.build(
or(
pattern( personV ).expr("exprA", p -> p.getName().equals("Mark")),
and(
pattern( markV ).expr("exprA", p -> p.getName().equals("Mark")),
pattern( personV ).expr("exprB", markV, (p1, p2) -> p1.getAge() > p2.getAge())
)
),
pattern( nameV ).expr("exprC", personV, (s, p) -> s.equals( p.getName() )),
on(nameV).execute( result::setValue )
);
Model model = new ModelImpl().addRule( rule );
KieBase kieBase = KieBaseBuilder.createKieBaseFromModel( model );
KieSession ksession = kieBase.newKieSession();
ksession.insert( "Mario" );
ksession.insert(new Person("Mark", 37));
ksession.insert(new Person("Edson", 35));
ksession.insert(new Person("Mario", 40));
ksession.fireAllRules();
assertEquals("Mario", result.getValue());
}
希望对您有所帮助
我以编程方式创建规则文件。这是一个简单的例子:
PackageDescr pkg = DescrFactory.newPackage()
.name(Constants.DRL_FILE_PACKAGE)
.newImport().target(Product.class.getName()).end()
.getDescr();
RuleDescr testRule = new RuleDescr();
RelationalExprDescr expr1 = new RelationalExprDescr("==", false, null, new ExprConstraintDescr("productId.id"), new ExprConstraintDescr(null));
RelationalExprDescr expr2 = new RelationalExprDescr("==", false, null, new ExprConstraintDescr("operation"), new ExprConstraintDescr("5"));
OrDescr or = new OrDescr();
PatternDescr patternDescr = new PatternDescr();
AndDescr and = new AndDescr();
or.addDescr(expr1);
or.addDescr(expr2);
patternDescr.setObjectType(Product.class.getName());
patternDescr.addConstraint(or);
and.addDescr(patternDescr);
testRule.setLhs(and);
testRule.setConsequence("System.out.println(\"Hi\");");
pkg.addRule(testRule);
String drl = new DrlDumper().dump(pkg);
这会生成以下 DRL 规则:
rule "null"
when
test.Product( [OR [productId.id == null, operation == 5] ] )
then
System.out.println("Hi");
end
然后在使用此规则创建 KieContainer 时出现异常:
[ERR 101] Line 7:53 no viable alternative at input 'OR' in rule "null"
在 PatternDescr 中包含 AndDescr 或 OrDescr 是否无效?
如果是这样,我是否可以只覆盖 AndDescr 和 OrDescr 中的 toString 方法(这是此处打印的内容)使其成为有效语法,或者是否有更好的方法来处理这种情况?
如果它不是无效的,那么我缺少什么才能成功构建 KieContainer?
您正在使用内部 API 来构建对用户不友好的规则。
即使我们回答了这个问题,您也会发现很多这样的问题。而且内部结构终究是要变的,建议大家不要用。
相反,开始使用可执行模型以编程方式构建规则,Java DSL 正是根据您的需要创建的。这样你就不用担心描述符的内部结构了。
看看 org.drools.modelcompiler.PatternDSLTest
或 org.drools.model.FlowDSLTest
,您可以找到一些与您正在做的事情非常相似的例子,比如这个
public void testOr() {
Result result = new Result();
Variable<Person> personV = declarationOf( Person.class );
Variable<Person> markV = declarationOf( Person.class );
Variable<String> nameV = declarationOf( String.class );
Rule rule = rule( "or" )
.build(
or(
pattern( personV ).expr("exprA", p -> p.getName().equals("Mark")),
and(
pattern( markV ).expr("exprA", p -> p.getName().equals("Mark")),
pattern( personV ).expr("exprB", markV, (p1, p2) -> p1.getAge() > p2.getAge())
)
),
pattern( nameV ).expr("exprC", personV, (s, p) -> s.equals( p.getName() )),
on(nameV).execute( result::setValue )
);
Model model = new ModelImpl().addRule( rule );
KieBase kieBase = KieBaseBuilder.createKieBaseFromModel( model );
KieSession ksession = kieBase.newKieSession();
ksession.insert( "Mario" );
ksession.insert(new Person("Mark", 37));
ksession.insert(new Person("Edson", 35));
ksession.insert(new Person("Mario", 40));
ksession.fireAllRules();
assertEquals("Mario", result.getValue());
}
希望对您有所帮助