How to pass and read the vlaues from map in Drools DRT template? - drools

I am trying to pass a map in DRT template of the of the drools like this
TEMPLATE
template "another map"
rule "test map_2"
no-loop true
dialect "java"
when
namedmap:Map(map:"${namedTags}")
review:FactNew(
(compareNamedTags(namedmap,namedTags))
)
then
System.out.println("Value is present in the list: "+ namedmap.get("objective"));
modify(review){setComment("accepted")}
end
end template
DRL GENERATED
rule "test map_2"
no-loop true
dialect "java"
when
namedmap:Map(map:"{key1=value1, key2=value2}")
review:FactNew(
(compareNamedTags(namedmap,namedTags))
)
then
System.out.println("Value is present in the list: "+ namedmap.get("key2"));
modify(review){setComment("accepted")}
end
FUNCTION TO CHECK THE MAP
function Boolean compareNamedTags(Map namedTagsMap, Map namedTags){
System.out.println("Comparing the named Tags map");
System.out.println("namedTag -->"+namedTagsMap );
System.out.println("namedTagsMap -->"+namedTags );
System.out.println("equality -->"+namedTagsMap.keySet().equals(namedTags.keySet()) );
boolean flag = false;
flag = namedTagsMap.equals(namedTags);
return true;
}
While firing the rule there is no error but no output is printed. Also there is no call to the function why? Is this the right to pass the map in DRT and use it in the when condition of the rule.
Please provide some guidance on how one can pass a map in the DRT template and use it.

Related

Get expression value from drools

I want to get expression value from drools.The drl like this.
global java.util.Map $globalVar;
global java.lang.Object $result;
import java.util.Map;
function myFunc(Map map){
return "hello";
}
rule "onlyone"
when
$factMap: Map($tmpResult:(myFunc($globalVar)), eval(true))
then
$result = $tmpResult;
end
When the rule get exception,like this
Caused by: org.mvel2.PropertyAccessException: [unable to resolve method: java.util.Map.$globalVar() [argslength=0]]
The global variable $globarVar has no relation with the fact.
It is likely drools can't recognize the global variable.Is there any grammar error in my drl?
Your syntax is so wrong I can't even figure out what you're trying to do.
Functions are very simple, they're just like methods in Java. They even look like methods in Java -- yours is missing a return type.
function String myFunc(Map map) {
return "hello";
}
function String greeting(String name) {
return "Hello, " + name + ". How are you?"
}
You can invoke them in your rules as you would any other function, either on the left hand side ("when") or on the right hand side ("then").
rule "Apply Greeting and Send Memo"
when
$memo: Memo( $recipient: recipient, sent == false )
$greeting: String() from greeting($recipient)
then
MemoSender.send($greeting, $memo);
modify( $memo ) {
setSent(true)
};
end
rule "Apply Greeting and Send Memo - v2"
when
$memo: Memo( $recipient: recipient, sent == false )
then
String $greeting = greeting($recipient);
MemoSender.send( $greeting, $memo );
modify( $memo ) {
setSent(true)
}
end
The bits with the globals in your question are red herrings. Yes, they're not working and throwing errors, but the syntax is so wrong that I'm not sure how it was supposed to work in the first place.
One way you might interact with a global in a function would possibly be something like ...
global Float taxRate; // passed in as a global because it's an external constant value
global Float freeShippingThreshold;
function float calculateTotal(float subtotal) {
// some math here that references taxRate
return calculatedTotal
}
rule "Apply free shipping"
when
Cart( $subtotal: subtotal )
Float( this >= freeShippingThreshold) from calculateTotal($subtotal)
then
// you get free shipping
end

RuleBook returns empty result

I am using rule Book to create rules a chain of rule as follows:
RuleBookBuilder.create()
.withResultType(Boolean.class)
.addRule(
RuleBuilder.create()
.withFactType(Double.class)
.withResultType(Boolean.class)
.when(facts -> facts.get("amount_gt").getValue() > new Double(600))
.then((facts, result) -> {
result.setValue(true);
System.out.println(result.getValue()); //1st print statement
})
.addRule()
....
.build())
NameValueReferableMap facts = new FactMap();
facts.setValue("amount_gt", new Double(700));
rule.run(facts);
System.out.println(rule.getResult()); //2nd print statement
The fist print statement prints true (as excepted), but the 2nd statement gives Optional.empty
Can some one tell me what could be wrong ?
You seem to chain the rules and the return of the outer rule you are not showing.
If you are trying to access the return on an inner rule, then you need to similarly chain the get() calls.
I would try to "unchain" the rules and see what that yields.

Using Ruta, get a data present in next line of annotated keyword

How to get data below/above annotated keyword present in other line? I am able to annotate keyword but not able to get information
Sample text:
Underwriter's Name Appraiser's Name Appraisal Company Name
Alice Wheaton Cooper Bruce Banner Stark Industries
Code
TYPESYSTEM utils.PlainTextTypeSystem;
ENGINE utils.PlainTextAnnotator;
EXEC(PlainTextAnnotator, {Line});
ADDRETAINTYPE(WS);
Line{->TRIM(WS)};
REMOVERETAINTYPE(WS);
Document{->FILTERTYPE(SPECIAL)};
DECLARE UnderWriterKeyword, NameKeyword, UnderWriterNameKeyword;
DECLARE UnderWriterName(String label, String value);
CW{REGEXP("\\bUnderwriter") -> UnderWriterKeyword};
CW{REGEXP("Name")->NameKeyword};
(UnderWriterKeyword SW NameKeyword){->UnderWriterNameKeyword};
ADDRETAINTYPE(SPACE);
Line{CONTAINS(UnderWriterNameKeyword)} Line -> {
(CW SPACE)+ {-> MARK(UnderWriterName)};
};
REMOVERETAINTYPE(SPACE)
Expected Output :
Underwriter's Name: Alice Wheaton Cooper
Appraiser's Name: Bruce Banner
Appraisal Company Name: Stark Industries
Please suggest if it is possible in RUTA ? If true, how to get data?
TYPESYSTEM utils.PlainTextTypeSystem;
ENGINE utils.PlainTextAnnotator;
DECLARE Header;
DECLARE ColumnDelimiter;
DECLARE Cell(INT column);
DECLARE Keyword (STRING label);
DECLARE Keyword UnderWriterNameKeyword, AppraiserNameLicenseKeyword,
AppraisalCompanyNameKeyword;
"Underwriter's Name" -> UnderWriterNameKeyword ( "label" = "UnderWriter
Name");
"Appraiser's Name/License" -> AppraiserNameLicenseKeyword ( "label" =
"Appraiser Name");
"Appraisal Company Name" -> AppraisalCompanyNameKeyword ( "label" =
"Appraisal Company Name");
DECLARE Entry(Keyword keyword);
EXEC(PlainTextAnnotator, {Line,Paragraph});
ADDRETAINTYPE(WS);
Line{->TRIM(WS)};
Paragraph{->TRIM(WS)};
SPACE[3,100]{-PARTOF(ColumnDelimiter) -> ColumnDelimiter};
Line -> {ANY+{-PARTOF(Cell),-PARTOF(ColumnDelimiter) -> Cell};};
REMOVERETAINTYPE(WS);
INT index = 0;
BLOCK(structure) Line{}{
ASSIGN(index, 0);
Line{STARTSWITH(Paragraph) -> Header};
c:Cell{-> c.column = index, index = index + 1};
}
Header<-{hc:Cell{hc.column == c.column}<-{k:Keyword;};}
# c:#Cell{-PARTOF(Header) -> e:Entry, e.keyword = k};
DECLARE Entity (STRING label, STRING value);
DECLARE Entity UnderWriterName, AppraiserNameLicense, AppraisalCompanyName;
FOREACH(entry) Entry{}{
entry{ -> CREATE(UnderWriterName, "label" = k.label, "value" =
entry.ct)}<-{k:entry.keyword{PARTOF(UnderWriterNameKeyword)};};
entry{ -> CREATE(AppraiserNameLicense, "label" = k.label, "value" =
entry.ct)}<-{k:entry.keyword{PARTOF(AppraiserNameLicenseKeyword)};};
entry{ -> CREATE(AppraisalCompanyName, "label" = k.label, "value" =
entry.ct)}<-{k:entry.keyword{PARTOF(AppraisalCompanyNameKeyword)};};
}
The most important rule is the following:
Header<-{hc:Cell{hc.column == c.column}<-{k:Keyword;};}
# c:#Cell{-PARTOF(Header) -> e:Entry, e.keyword = k};
It contains three rule element, Header,# and Cell, and works this way:
The rule starts to match with the Cell rule element because it is tagged as anchor with #.
This rule element matches on all Cell annotations that or not part of a Header annotation. It starts with the first Cell annotation that fulfills this condition and calls it "c".
The next rule element is # which matches until the next rule element is able to match.
The next rule element matches on a Header annotation if the inlined rule is able to match within the span of the Header annotation. The inlined rule matches on the Cell annotations remembered as "hc" within this span that have the same value for the feature column. The match is successful, if it contains a Keyword remembered as "k".
If these three rule elements matched successfully, then the actions are applied.
The first action creates an Entry annotation called "e" on the span of the Cell annotation.
The second action assigns the keyword to the Entry feature keyword.
As a summary, the rule creates an Entry annotation for each Cell annotation that is not part of the header and assigns the header keyword of the corresponding column in order to define the type of the entry.
Take a look at inlined rules in Ruta.
You could define your condition for one line and annotate the needed info inside the next one:
Line{CONTAINS(UserName)} Line -> { //your logic here };

Drools rules categorization

I am looking for a way to categorize rules in my drl files and determine which category/ categories of rules fired.
I see that the Drools Guvnor documentation has something about categorization http://docs.jboss.org/drools/release/5.2.0.Final/drools-guvnor-docs/html/ch03.html#d0e228. However, it is unclear to me if this is metadata maintained by Guvnor or if it is part of the drl file/ rules execution. I have not been able to find a sample DRL file with category mentioned in it. And, a way to determine the category/ categories of rules that got fired.
I am aware of activation-group but that doesn't quite fit my need since once a rule in the activation-group fires the other rules in the group are not evaluated.
Thanks
The best way to classify rules is to do it via metadata. A metadata entry is added to the rule:
rule metademo
#meta2( 123 )
#meta3( foo )
#meta4( "foo" )
when...then...end
You access the metadata via a Rule, obtained from a package or some event:
for( Rule rule: kPackage.getRules() ){
Map<String,Object> key2meta = rule.getMetaData();
for( Map.Entry<String,Object> entry: key2meta.entrySet() ){
System.out.print( " #" + entry.getKey() + "( " );
Object value = entry.getValue();
System.out.print( "[" + value.getClass().getSimpleName() + "] "
+ value.toString() );
System.out.println( " ) " );
}
}
Output:
#meta2( [Integer] 123 )
#meta4( [String] foo )
#meta3( [String] foo )
There was a plan to permit Maps as value so you might use
#meta7( foo = "foo", bar = "bar" )
This didn't work in 5.5, and I never tried it again.

Drools attributes explanations

I have a question about 2 Drools attributes - salience and no-loop
salience:
rule "Hello World"
salience -10
when
$m : Message( status == Message.HELLO, $myMessage : message )
then
System.out.println( $myMessage );
$m.setMessage( "Goodbye cruel world" );
$m.setStatus( Message.GOODBYE );
update( $m );
end
rule "GoodBye"
when
Message( status == Message.GOODBYE, $myMessage : message )
then
System.out.println( $myMessage );
end
We should expect the "GoodBye" rule to be fired first(since its salience is higher) however that doesn't happen and instead the "Hello World" rule gets fired up first and only then "GoodBye"
no-loop:
I understand that this attribute prevent from a rule to be executed to the same fact which will cause an infinite loop. My question is about an example about this attribute that I don't quite understand:
rule "interest calculation"
no-loop
when
$account : Account( )
then
modify($account) {
setBalance((long)($account.getBalance() * 1.03));
}
end
If there wasn't "no-loop" why that will cause an infinite loop?
Re salience: Logic always beats salience. If Message.status is initially set to Message.HELLO, the other rule doesn't qualify and "Hello World" is executed.
Re no-loop: A modify/update simply means that re-evaluation of everything begins from scratch as far as the modified fact is concerned. So, Account is updated, goes back to square one, and reevaluation creates another activation of this trivially matching rule.