Drools MVEL Dialect - Semi-Colon Requirement - drools

I am just curious as to why my Eclipse Drools compiler (6.5.0) requires semi-colons at the end of statements in the For loop, as below:
Map businessRulesRequest = $root.containsKey("BusinessRulesRequest") ? $root.get("BusinessRulesRequest") : null
Map quoteRequest = businessRulesRequest!=null && businessRulesRequest.containsKey("QuoteRequest") ? businessRulesRequest.get("QuoteRequest") : null
List resultsByKey = quoteRequest!=null && quoteRequest.containsKey("resultsByKey") ? quoteRequest.get("resultsByKey") : new ArrayList()
for (Map search : resultsByKey) {
Map searchInfo = (search.containsKey("searchInfo") ? search.get("searchInfo") : null);
String searchName = searchInfo!=null && searchInfo.containsKey("searchName") ? searchInfo.get("searchName").toString() : "";
List results = (searchName=="quotesMotor" && search.containsKey("results") ? search.get("results") : new ArrayList());
}
If I remove the semi-colons from the first or second lines in the For loop, I get an "unexpected token" error, but not if I remove it from the last line in the loop.
Is it due to Drools evaluating RHS lines as a single statement and so they must be separated inside any loops?
Note: I understand it is not best practice to code assuming semi-colons are not required, however I came across this issue while experimenting and am just interested to know the reason for the compiler error. Thanks.

I guess the answer is because of MVEL itself. Drools may be delegating the entire chunk of code to MVEL to evaluate and execute.
According to this guide, in MVEL the use of a semi-colon is not mandatory in cases where you have 1 statement, or in the last statement of a script.
Hope it helps,

Related

how to prevent logging warning in a .get(true , false) statement to appear even though it is true and not false

I am making an application which rarely uses the terminal for output. So, I found that the logging library was a great way to help debug faulty code as supposed to the print statement.
But, for this code, specifically the .get() statement at the bottom...
def process_variables(self, argument):
data = pd.read_excel(self.url, sheet_name=self.sheet)
data = pd.concat([data.iloc[2:102], data.iloc[107:157]]).reset_index()
fb = data.loc[0:99, :].reset_index()
nfb = data.loc[100:155, :].reset_index()
return {'fb': data.loc[0:99, :].reset_index(),
'nfb': data.loc[100:155, :].reset_index(),
'bi': data.loc[np.where(data['Unnamed: 24'] != ' ')],
'uni': data.loc[np.where(data['Unnamed: 25'] != ' ')],
'fb_bi': fb.loc[np.where(fb['Unnamed: 24'] != ' ')],
'fb_uni': fb.loc[np.where(fb['Unnamed: 25'] != ' ')],
'nfb_bi': nfb.loc[np.where(nfb['Unnamed: 24'] != ' ')],
'nfb_uni': nfb.loc[np.where(nfb['Unnamed: 25'] != ' ')],
}.get(argument, f"{logging.warning(f'{argument} not found in specified variables')}")
...returns this...
output
The output returns the default argument even though the switch-case argument was successful, given that it did return the pandas Data frame.
So how can I make it so it only appears when it wasn't found, as it should if it were just a string and not a logging-string method.
Thank you for your help in advance :)
Python evaluates the arguments for the arguments to a function before it calls the function. That's why your logging function will get called regardless of the result of get(). Another thing is your f-string is probably going to evaluate to "None" every time since logging.warning() doesn't return anything, which doesn't seem like what you intended. You should just handle this with a regular if statement like
variables = {
'fb': data.loc[0:99, :].reset_index(),
...
}
if argument in variables:
return variables[argument]
else:
logging.warning(f'{argument} not found in specified variables')

Drool DRL contains

This my When condition
$cla : cashliquidassets(
entity == "AU001",
asset_liability_indicator == "A",
product_group.contains('Loans','Bankofindia'),
product.contains("DS"),
counterparty_resident_indicator == "AU",
counterparty_type.contains("DS"),
related_entity == "Y"
)
I am getting an error at
Unable to Analyse Expression product_group.contains("Loans","Bankofindia")
Any Suggestions
Without your class model is hard to tell, but assuming that cashliquidassets.product_group is a String, you are trying to use an unexisting method String.contains(String, String).
One option would be to use an OR or and AND between 2 contains:
...
(product_group.contains('Loans') || product_group.contains('Bankofindia')),
...
or
...
product_group.contains('Loans'),
product_group.contains('Bankofindia'),
...
Another option could be to use the matches operator with a regular expression.
Hope it helps,

Why does my ternary operator give a different result to an if else?

The problem I am having is I am trying to use ternary operators over if else for smaller code but when using it in my case it is returning a different result than if I use an if else.
The problem code is below;
If Else
if(string.IsNullOrEmpty(jn["LARM"].Value))
pm.ItemLeftArm = null;
else
pm.ItemLeftArm = jn["LARM"];
Ternary
pm.ItemLeftArm = string.IsNullOrEmpty(jn["LARM"].Value) ? null : jn["LARM"];
The jn["LARM"] is a json node from simpleJSON and it is either a number e.g. "0" or nothing e.g. "".
It returns null form the if else but it returns the jn object which transforms from "" into 0.
Im not sure why Im getting this issue.
The code is ok, the problem must be in the JSON. Have you tried logging the jn["LARM"].Value just before the terniary operator in order to be sure that the value is null/empty or not?
BTW, why are you using simpleJSON instead of the new Unity integrated JsonUtility?

Error in drool file: input mismatch

I am working on a drool file with the below code:
rule "test rule"
#RuleNumber(1)
#RuleMessage("data mismatch")
when
$myObj : MyObj($localVal1: val1)
$dataMismatch: Boolean() from ($localVal1 == null)
eval $dataMismatch
then
//do something
end
I keep getting the error mismatched input '$dataMismatch' in rule, Parser returned a null Package
Does anyone know where am I going wrong?
Thanks!
Unless you get paid by lines of code written, you should use:
rule "test rule"
#RuleNumber(1)
#RuleMessage("data mismatch")
when
$myObj : MyObj(val1 == null)
then
//do something
end
(Looking into syntax errors cannot be done reliably without knowing the Drools version, which you haven't provided.)

Entity Framework: combining exact and wildcard searching conditional on search term

I'm creating a query to search the db using EF. TdsDb being the EF context.
string searchValue = "Widget";
TdsDb tdsDb = new TdsDb();
IQueryable<Counterparty> counterparties;
I can do exact match:
counterparties = tdsDb.Counterparties.Where(x => x.CounterpartyName == searchValue);
or wildcard match:
counterparties = tdsDb.Counterparties.Where(x => x.CounterpartyName.Contains(searchValue));
But I want to be able to do both i.e. (psudo code)
counterparties = tdsDb.Counterparties.Where(x =>
if (searchValue.EndsWith("%"))
{
if (searchValue.StartsWith("%"))
{x.CounterpartyName.Contains(searchValue)}
else
{x.CounterpartyName.StartsWith(searchValue)}
}
else
{x => x.CounterpartyName == searchValue}
);
Now clearly I can't put an if statement in the where clause like that. But I also can't duplicate the queries: shown here they are hugely dumbed down. The production query is far longer, so having multiple versions of the same long query that vary on only one clause seems very unhealthy and unmaintainable.
Any ideas?
You should be able to use the ternary operator:
bool startsWithWildCard = searchValue.StartsWith("%");
bool endsWithWildCard = searchValue.EndsWith("%");
counterparties = tdsDb.Counterparties.Where(x =>
endsWithWildCard
? (startsWithWildCard
? x.CounterpartyName.Contains(searchValue)
: (x.CounterpartyName.StartsWith(searchValue)))
: (x.CounterpartyName == searchValue));
Did you test btw if querying by a searchValue that has an % at the beginning or end works as you expect? It might be possible that % will be escaped as a character to query for because StartsWith and Contains will prepend/append % wildcards to the generated SQL search term anyway. In that case you need to cut off the % from the searchValue before you pass it into StartsWith or Contains.