I create rules files programmatically. Here is a dumbed down example:
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);
This generates the following DRL rule:
rule "null"
when
test.Product( [OR [productId.id == null, operation == 5] ] )
then
System.out.println("Hi");
end
Then when creating the KieContainer using this rule I have an exception:
[ERR 101] Line 7:53 no viable alternative at input 'OR' in rule "null"
Is it invalid to have AndDescr or OrDescr within a PatternDescr?
If so, could I just overwrite the toString method (this is what is being printed here) within the AndDescr and OrDescr to be a valid syntax or is there a better way to handle this situation?
If it's not invalid, then what am I missing to have the KieContainer build successfully?
You're using an internal API to build rules that is not really user friendly.
Even if we answer this question you'll find many problems like this. Also the internal structure is eventually bound to change so I suggest you not to use it.
Instead, start building rules programmatically using the executable model, a Java DSL created exactly for what you need. In this way you don't have to worry about the internal structure of the descriptors.
Take a look at org.drools.modelcompiler.PatternDSLTest
or org.drools.model.FlowDSLTest
, you can find some examples really similar to what you're doing such as this
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());
}
Hope this helps