Inference not working - drools

I'm relatively new to Drools. I have those rules :
import models.Demarche;
declare IsMarque
demarche : Demarche
end
rule "Add type Marque taxe"
salience 2
no-loop true
lock-on-active true
when
$d : Demarche( typeDemarche == "Marque" )
then
modify($d){
listTaxes.put(14, 1)
}
insert( new IsMarque( $d ) );
System.out.println("infer marque");
end
And :
rule "Add Marque Polynesie extention taxe"
no-loop true
lock-on-active true
when
$d : Demarche( extPolynesie == true)
IsMarque(demarche == $d)
then
$d.listTaxes.put(17, 1);
System.out.println("marque");
end
rule "Add Not Marque Polynesie extention taxe"
no-loop true
lock-on-active true
when
$d : Demarche( extPolynesie == true)
not(IsMarque(demarche == $d))
then
System.out.println("not marque");
end
For the rules 2 or 3, nothing happens. One of them should be true, but nothing is printed, as if the infered IsMarque cannot be evaluated. If I comment the IsMaqrue evaluation this is working, i can see the messages printed in the console.
Any idea?

This rule needs to be rewritten as
rule "Add type Marque taxe"
when
$d : Demarche( typeDemarche == "Marque", $t: listTaxes) // I AM GUESSING HERE
not IsMarque(demarche == $d)
then
modify($t){
put(14, 1)
}
insert( new IsMarque( $d ) );
System.out.println("infer marque");
end
And no no-loop true and lock-on-active true if you have shown everything there is.
Note that you could write the first rule also as
rule "Add type Marque taxe"
when
$d : Demarche( typeDemarche == "Marque")
then
$d.getListTaxes().put(14, 1);
insert( new IsMarque( $d ) );
System.out.println("infer marque");
end
if (and only if) no other rule as CEs referring to the listTaxes property. Since you have used this "dirty update" in rule "Add Marque Polynesie extention taxe", it seems to be OK.
Please post complete rules - #1 doesn't compile.

Related

How to check for null value in accumulate Drools

Iam first time user of Drools. In accumulate function I have a scenario to check for the (!= null) feature of java. But in Drools I find that != doesn't work .
when
$addr : String(length > 0) from accumulate(
$person : Person(),
action(
$addresses : $person.getAddresses();
// i want to check whether $addresses is not
null.
if($addresses !=null) is what i want to achieve
)
Any help is really appreciated.
Edit the rule as Below :
Person(adresses !=null) && $addr : String(length > 0) from accumulate(
$person : Person(),
action(
$addresses : $person.getAddresses();
)

mismatched input '.' in rule

I am new to drools .I am writing a new rule.But i am getting Error as follow:
mismatched input '.' in rule "StopTextRule" in pattern
My rule is
package com.******.*****;
import java.lang.Number;
rule "StopTextRule"
dialect "mvel"
salience 20
lock-on-active true
when
RoutingData( messageBody != null && (
(messageBody.trim().equalsIgnoreCase("stop") || messageBody.trim().equalsIgnoreCase("\"stop\"") || messageBody.trim().equalsIgnoreCase("stop.") || messageBody.trim().equalsIgnoreCase("\"stop.\""))
|| (messageBody.trim().equalsIgnoreCase("quit")|| messageBody.trim().equalsIgnoreCase("\"quit\"") || messageBody.trim().equalsIgnoreCase("quit.")|| messageBody.trim().equalsIgnoreCase("\"quit.\""))
|| (messageBody.trim().equalsIgnoreCase("cancel")|| messageBody.trim().equalsIgnoreCase("\"cancel\"") || messageBody.trim().equalsIgnoreCase("cancel.")|| messageBody.trim().equalsIgnoreCase("\"cancel.\""))
|| (messageBody.trim().equalsIgnoreCase("UNSUBSCRIBE")|| messageBody.trim().equalsIgnoreCase("\"UNSUBSCRIBE\"") || messageBody.trim().equalsIgnoreCase("UNSUBSCRIBE.")|| messageBody.trim().equalsIgnoreCase("\"UNSUBSCRIBE.\"")))
&& incomingMessageProtocol != null && incomingMessageProtocol.trim().equalsIgnoreCase("X"))
routingResp : RoutingRuleResponse( isStop == false )
then
modify( routingResp ) {
setIsStop( true )
}
end
This compiles using Drools 6.4.0. I think that you are using an older version where Java expressions had to be enclosed in eval.
It would be simpler in any case to rewrite this pattern like so:
rule x
when
X( messageBody != null &&
messageBody matches "\\s*(\"?)(?i:stop|quit|cancel|unsubscribe)\\.?\\1\\s*" &&
incomingMessageProtocol != null &&
incomingMessageProtocol matches "\\s*(?i:X)\\s*") )
then
// ...
end

Union link rule

I have problems codify this rule in drools which unites the link to the same destination exists and if the inveso then does the union of the latter also.
class Node {
List <Link> out;
List <Link> in;
}
class Link {
Source node;
Target node;
}
they are inserted as facts in working memory.
example.
A - link1 -> B
A - link2 -> B
A - link3 -> C
C - link4 -> D
B - link5 -> A
result
A - link1 + link2 +link5 -> B
A - link3 -> C
C - link4 -> D
Can anyone help me?
To remove all redundant Link objects and assuming that class Link is declared as
class Link {
Node source;
Node target;
}
(and not as given in the original post), the rule:
rule "kill redundant links"
when
$l1: Link( $s: source, $t: target )
$l2: Link( this != $l1,
source == $s && target == $t
||
source == $t && target == $s )
$n1: Node( out contains $l2 )
$n2: Node( in contains $l2 )
then
retract( $l2 );
modify( $n1 ){ getOut().remove( $l2 ) }
modify( $n2 ){ getIn().remove( $l2 ) }
end
removes all redundant Link facts and updates the out and in fields of
the Nodes at either end of these links.

Drools updating same object at the same time

I have two .drl files:
.dlr file one
rule "Lower Elementary Level"
no-loop
when
$m: MockBean ( overAllScore >= 40.51 && overAllScore < 60.76 )
$s : StudentMockBean()
then
$s.setKnowledgeLevel( "Lower Elementary Level" );
update( $s );
end
// some other condition
.drl file two
rule "Concept Lower Elementary Level"
no-loop
when
$m: MockBean ( mockOneScore >= 40.51 && mockOneScore < 60.76 )
$s : StudentMockBean()
then
$s.setMockOneKnowledgeLevel( "Lower Elementary Level" );
update( $s );
end
// some other condition
I'm reading both of them through this:
...
for( String fileName : aRuleFileName )
{
kbuilder.add( ResourceFactory.newClassPathResource( fileName, getClass() ), ResourceType.DRL );
}
// get error
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
return kbase;
I fired both rules and both .drl file met the condition but they are updating same object.
My question is why does my web app keep on loading infinitely?
You are having an infinite loop caused by the combination of your rules.
I.e. rule A activates -> rule A fires -> modifies $s -> rule B activates -> rule B fires -> modifies $s -> rule A activates -> rule A fires -> modifies $s -> rule B activates -> rule B fires -> ...
no-loop is not enough solution for this situation.
For a better explanation on what's going on and possible ways to solve your problem please read this blog entry.
Hope it helps,

Drools get facts from database at runtime

I need a little help with Drools eval and variable assigning.
rule "check that no previously submitted requests exist"
when
$user : UserFormField( name == 'employeeId', value != null )
$repository : Repository( )
$activeRequests : List( ) from $repository.findActiveRequestsByEmployee( $user.getValue() ) # call to repository
eval( $activeRequests.size() > 0 )
then
System.err.println(' You have active requests: ' + ((Request)$activeRequests.get(0)).getTitle);
insert(Boolean.TRUE);
end
In this rule I try to access repository and get active requests for current user. Rule compiles and executes without any exceptions or warnings. In debug mode it can be seen that repository returns non empty list and I expect to see console message 'You have active requests' but this doesn't happen. I think the problem is in this line
$activeRequests : List( ) from $repository.findActiveRequestsByEmployee( $user.getValue() )
because this rule works fine
rule "check that no previously submitted requests exist"
when
$user : UserFormField( name == 'employeeId', value != null )
$repository : Repository( )
eval( $repository.findActiveRequestsByEmployee($user.getValue()).size() > 0 )
then
System.err.println(' You have active requests !' );
insert(Boolean.TRUE);
end
So could someone point me how to solve this problem?
Thanks!
I was helped to find a solution. I should use from collect expression instead simple from to bundle facts into collection :
$activeRequests : ArrayList() from collect ( Request() from $repository.findActiveRequestsByEmployee( $user.getValue() ) )
You have to distinguish (i.e., read the fine print in the
documentation) between "from" and "from collect". If you want the rule
to fire individually for each collection element produced by the
expression after "from", then use "from". If, however, you want to
have it all bundled into a collection you must used "from collect".
$activeRequests : ArrayList() from collect ( Request() from
$repository.findActiveRequestsByEmployee( $user.getValue() ) )
Note that the separate eval isn't necessary. You can put this
constraint into the ArrayList pattern:
ArrayList( size > 0 )