Reuse of conditions (when) in Drool DSL statements - drools

Is it possible to reuse a when/condition statement into another when/condition statement in a DSL file?
For example, I have two conditions:
[condition][]The client is invalid = Client( name == null || email == null )
[condition][]All the clients are invalid = forall( Client( name == null || email == null ) )
Note that the second condition just diff the first for the forall command, but the statement inside is equals. In these case, I want to reuse the first condition into the second.
Is it possible? How?
Thank you.

even the most recent version of drools will only let you substitute values into a template from pojo's or a corresponding map as per their documentation here.
This won't work for your use case though.
Since drool files are simply text files, there is nothing preventing you from considering a more powerful templating toolkit.
Possibilities include Apache Velocity, ANTLR or Scala!

Related

Drools filtering stream within DRL

I would like to create a rule with lamba expression like below:
when
rule_id: String() from "784acba8-32e5-41de-bd73-04f9ce2bfaff"
$: DroolsEventWrapper(Arrays.stream("testing".split("")).filter(element->(element!=null && element.contains("e"))).findFirst().isPresent())
then
System.out.println("Qualified for "+rule_id);
end
just a simple check "testing" will be given as a parameter also; however when I use it drl. It gave error like:
mismatched input '.' in rule "784acba8-32e5-41de-bd73-04f9ce2bfaff" in pattern
When I check the location of that dot; it belongs to filter(element->(element!=null && element.contains("e"))) when I omit it, it is working.
I am using the latest version of Drools: 7.55.0.Final. I found some tickets which say that lambda expressions somehow buggy at previous versions but not the latest ones.
Do I missing something, or is there any way to run this within DRL ?

Filtering column strings that contain substring

I am working on an if else in the Tmap, and one of the conditions is if a column contains a substring.
I am unsure exactly how to go about this being fairly new to talend.
This is the current syntax that I am using.
row16.Location.contains("clos")?"Pending":""
I have not been able to find any good examples of the correct way to go about this, other than the one above.
Talend uses Java as an underlying language, so you need to use the ternary operator of Java:
row16.Location.contains("clos") ? "Pending" : ""
But make sure you first check row16.Location for null, otherwise you'll get a NullPointerException if Location is null :
row16.Location != null && row16.Location.contains("clos") ? "Pending" : ""

Boolean flags handing in Drools conditions

We are working on a monitoring application in which we follow the processing of a task in a set of applications.
We have a set of drools rules matching our needs but we have some performance issues (we may have easily up to 50k objects in session).
We are looking for best pactices
This question is about bloolean flag usage.
We are working to remove most of org.drools.core.rule.constraint.MvelConstraint: Exception jitting: ... warns.
We have often such warn on boolean flags.
for example in:
rule "PropagateDeprecation"
when
$parent:BaseChainStep( $parent.Deprecated )
$child:BaseChainStep( $parent.Id == $child.Parent, !$child.Deprecated )
then
modify($child){
setDeprecated(true)
}
end
we have warn on both $parent.Deprecated and !$child.Deprecated.
We would like to understand why there is such warn on boolean flags.
We would like to know also the impacts of the warn on composed conditions.
For example in:
rule "App1_TriggerExpected"
when $chainStep:App1ChainStep(
HasChain
, HasParent
, !$chainStep.Deprecated
, Status in ("error", "closed")
, Places != null
, Analysis != null)
then
..
end
if we have the warn on the first condition HasChain, how is resolved the when clause ?
Does other conditions are evaluated too (with iteration on all App1ChainStep objects) or some "index" are still used to help ?
If its matter, we are using flags as boolean (and not Boolean) to ensure false value as default.
Edit:
The problem may be linked to extended classes. In our use case we have something like:
declare BaseChainStep
parent : GUID
deprecated : boolean
end
declare App1ChainStep extends BaseChainStep
// specific App1 fields
end
BaseChainStep fields may be manipulated in rules using App1ChainStep objects or BaseChainStep objects.
rule "deprecateApp1"
when $app1:App1ChainStep( BusinessLogicCondition )
then
modify($app1) {
setDeprecated(true)
}
end
Then the deprecated flag is propagated to App1 children using "PropagateDeprecation" rule.
Boolean flag causing warn are declared in BaseChainStep class.
Although you are deviating from the conventional way of accessing attributes, this should not trigger the warning you have reported. I can't reproduce this using 6.3.0. You should add (a) the Drools version (b) the Java code for a class BaseChainStep with which the problem can be reproduced with the rule as shown.
This is another (much simpler) way of writing rules combining boolean attributes:
rule bool1
when
X( big, fast )
then
System.out.println( "big fast X" );
end
You may even use boolean operators:
rule bool2
when
X( big && ! fast )
then
System.out.println( "big slow X" );
end
Note the simple use of field name, assuming conventional naming, e.g., big for the field, isBig and setBig for the accessors.

Make an object that can be compared and hashed with variable attributes, in Python

I am working on a package that deals with citations and most of them are of the form
Author, Year, Journal, Volume, Page, DOI
So a a string with series of fields separated by commas.Unfortunately some (~5%) are missing one (or often more than one) of these fields.
To do useful things with them I need to be able to check if two are the same ignoring a field if it is missing. I have an __eq__(self, other) defined that does this with a series of if statements like this:
elif hasattr(self, 'V') and hasattr(other, 'V') and getattr(self, 'V') != getattr(other, 'V'):
return False
The one constant about the citations is that author is present and at least one of year or journal is too.
I feel like there should be a much faster way of doing this, but have not been able to come up with one. Is there a faster way of doing this as that would really help with processing?
Rather than using a long if/elif chain and explicitly returning Fase if a condition finds a mismatch, you can chain together the comparisons directly in a Boolean expression with and:
return (self.author == other.author and
self.year == other.year and
self.journal == other.journal
...)
You can keep using your getattr calls if you want, but I'd suggest moving the logic to fill in None for missing values into the initialization code, rather than needing to repeat it anywhere you check the attributes. That way you'll always have the attributes you expect, ones that don't have meaningful data will simply have None as their value.
Note that the current behavior of your getattr code doesn't quite match the description you give of your desired behavior ("check if two are the same ignoring a field if it is missing"). The current code will return False if an attribute is present in one citation and not in another, even if the rest of the values match up. If you want the behavior to match your description, use something like this:
not (hasattr(self, "year") and (hasattr(other, "year")) or self.year == other.year
Or (if you do year = None in __init__ if there's no year specified):
None in (self.year, other.year) or self.year == other.year

drools rule for fact with list values and multiple conditions

i am attempting to write a rule that will compare a fact list values to a multiple condition rule
rule: only valid legislations
when
fact:Fact (legislationList == ('L1' && 'L2') OR 'L3')
then
fact.printMessage();
end
ie. if fact.legislationList={'L1', 'L2') then fire
if fact.legislationList={'L1', 'L4') then dont fire
i looked at the 'from' clause but wasnt clear how that would solve my issue.
is there some voodoo method/solution that will help me?
thanks
-lp
Assuming that legislationList is a List<String>, then you could use Drools' 'contains' operator:
rule: only valid legislations
when
fact:Fact ((legislationList contains "L1" && legislationList contains "L2") || legislationList contains "L3" )
then
fact.printMessage();
end
You can abbreviate the syntax a bit, but I wanted to be explicit.
Hope it helps,