Drools AndDescr (and OrDescr) inside PatternDescr

StrongJoshua :

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?

Luca Molteni :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=307704&siteId=1