Drools Rules: How can I use a method on "when" section? - java

I need to execute a method on "when" section of a DSLR file and I´m not sure if it´s possible. Example:
rule "WNPRules_10"
when
$reminder:Reminder(source == "HMI")
$user:User(isInAgeRange("30-100")==true)
Reminder(clickPercentual >= 10)
User(haveAtLeastOptIns("1,2,3,4") == true)
then
$reminder.setPriority(1);update($reminder);
end
(note: isInAgeRange() and haveAtLeastOptIns() are methods of User)
I tried with eval() and no errors appeared, but it didn´t execute. Like this:
rule "WNPRules_10"
when
$reminder:Reminder(source == "HMI")
$user:User(eval($user.isInAgeRange("30-100")==true))
Reminder(clickPercentual >= 10)
User(eval($user.haveAtLeastOptIns("1,2,3,4") == true))
then
$reminder.setPriority(1);update($reminder);
end
How can I resolve this problem?

Your second attempt looks fairly confused - also - do you have so User patterns - do you want them to refer to the same instance of user? or can they be separate instances (or must they be separate?) - that will change things a bit in some cases depending on your intent.
In terms of the simplest rewrite I can think of:
rule "WNPRules_10"
when
$reminder:Reminder(source == "HMI")
$user:User()
eval($user.isInAgeRange("30-100") && $user.haveAtLeastOptIns("1,2,3,4"))
Reminder(clickPercentual >= 10)
then
$reminder.setPriority(1);update($reminder);
end
Note the use of the eval() top level element - it also uses only one user pattern - and then applies the constraints to it. (In a future version inline evals will work without having to write eval !).

Related

Is !(~A && ~B) better than (A||B) in programming?

I am developing in Java and I am using IntelliJ as my IDE. I wrote an if statement as follows.
if( list1.size() >= 1 || list2.contains(itemX) ) {
//do something
}
IntelliJ suggested a transformation (DeMorgan's Law) and it transformed it to:
if( ! ( list1.size() < 1 && !( list2.contains(itemX) ) ) ) {
//do something
}
So it applied a very common discrete mathematics theory on simplifying boolean expressions. What I am wondering is how does this optimize anything?
|| operator anyways does not execute the whole condition if the first part is itself true, and only executes the RHS only if the first part is false.
Is the transformed condition effective? How?
This is somewhat subjective, but a good general rule of thumb is to remove as much complexity as possible. By complexity, I mean the number of operations you need to perform in order to obtain the desired result.
In this sense, !a && !b is worse than !(a || b) because in one case you're negating a and b, then performing the OR and operator resulting in 3 operations whereas in the latter case, you're only performing 2. Of course this is vacuous when you're talking about two conditions, but when you're dealing with many, this can make a big difference.
But in your scenario it doesn't make any sense for your IDE to change it as the later has lower number of operations. Probably its the IDE trying to desperately woo you :)
Hope this makes sense !!
Both are exactly the same statements.
I agree that OR operator does not evaluate the second part if the first part is TRUE, however, it is also true that the AND operator does not evaluate the second part if the first part is FALSE.
In fact, it will take more time and space to evaluate the ~(~A && ~B) as opposed to A||B.
Hope this helps :)

How allow less indent for closing parentheses inside a method with checkstyle?

Check style is telling me the closing parentheses has too low (8) of an indent level and that it should be 12. But I want it to be at the outer level as visually, it makes it much clearer that the checks are one "block" or collective result.
How do I do this (only for closing parentheses)?
private boolean someMethod()
{
return (
someCheck() &&
anotherCheck() &&
aThirdCheck()
); //This is the line it complains about
}
The error I get:
'method def' child has incorrect indentation level 8, expected level should be 12
Your indentation is not really standard.
Besides, the parentheses are not required for a series of && with method invocations.
It may even make the reading harder.
Personally, I find it :
private boolean someMethod()
{
return (
someCheck() &&
anotherCheck() &&
aThirdCheck()
); //This is the line it complains about
}
less clear than that :
private boolean someMethod(){
return someCheck() && anotherCheck() && aThirdCheck();
}
'method def' child has incorrect indentation level 8, expected level should be 12
How do I do this (only for closing parentheses)?
There is no way to do this for IndentationCheck. It is very narrow how much you can customize this check, see http://checkstyle.sourceforge.net/config_misc.html#Indentation . You can submit a change request to Checkstyle to support this case, but Indentation is one of the most complicated checks and not many people want to work on it.
You can suppress the violation using suppressions, or like someone else mentioned, you can remove/disable the check. I myself disable it because my group uses Eclipse and we enforce Eclipse to format the code on any save.

Several string inputs for one variable

Is there any other way to shorten this condition?
if (oper.equals("add") || oper.equals("Add") || oper.equals("addition") ||
oper.equals("Addition") || oper.equals("+"))
I was just wondering if there's something I can do to 'shortcut' this. The user will type a string when prompted what kind of operation is to be performed in my simple calculator program. Our professor said our program should accept whether the user enters "add", or "Add", you know, in lowercase letters or not... Or is the only way I should do it?
You can use String#equalsIgnoreCase(String) for 1st four strings: -
if (oper.equalsIgnoreCase("add") ||
oper.equalsIgnoreCase("addition") ||
oper.equals("+"))
If number of strings increases, you would be better off with a List, and use its contains method. But just for these inputs, you can follow this approach only.
Another way to approach this is to use String#matches(String) method, which takes a regex: -
if (oper.matches("add|addition|[+]")
But, you don't really need a regex for this. Specially, this method can become ugly for greater inputs. But, it's just a way for this case. So, you can choose either of them. 1st one is more clear to watch on first go.
Alternatively, you can also use enum to store operators, and pass it's instance everywhere, rather than a string. It would be more easy to work with. The enum would look like this:
public enum Operator {
ADD,
SUB,
MUL,
DIV;
}
You can enhance it to your appropriate need. Note that, since you are getting user input, you would first need to identify the appropriate enum instance based on it, and from there-on you can work on that enum instance, rather than String.
In addition to #Rohit's answer, I would like to add this.
In case of comparison of strings, if oper is null a NullPointerException could be thrown. SO its always better to write
"addition".equalsIgnoreCase(oper)
instead of
oper.equalsIgnoreCase("addition")
If aDD is considered as invalid input, you can consider following approach:
ArrayList<String> possibleInputs = new ArrayList<String>();
possibleInputs.add("Add");
possibleInputs.add("add");
possibleInputs.add("Addition");
possibleInputs.add("addition");
possibleInputs.add("+");
if(possibleInputs.contains(oper))
{
// ...
}
throw that whole bit of code inside a function called: isOperationAddition(String s){...} that returns a boolean.
So this:
if (oper.equals("add") || oper.equals("Add") || oper.equals("addition") ||
oper.equals("Addition") || oper.equals("+")){...}
Changes to this
if (isOperationAddition(operation)){...}
Then inside that method, don't use Strings as branch material for your if statements. Have a variable that defines which kind of operation it is and "Keep the barbarians (confusion/ambiguous users) out at the moat". You should not be always iterating against a list to remember what operation we are dealing with.
You can take the input, and convert in to lower case then compare.
str.toLowerCase()
then pass to your if() statement
if(str.equals("add") || str.equals("addition") || str.equals("+"))

What is better: multiple "if" statements or one "if" with multiple conditions?

For my work I have to develop a small Java application that parses very large XML files (~300k lines) to select very specific data (using Pattern), so I'm trying to optimize it a little. I was wondering what was better between these 2 snippets:
if (boolean_condition && matcher.find(string)) {
...
}
OR
if (boolean_condition) {
if (matcher.find(string)) {
...
}
}
Other details:
These if statements are executed on each iteration inside a loop (~20k iterations)
The boolean_condition is a boolean calculated on each iteration using an external function
If the boolean is set to false, I don't need to test the regular expression for matches
Thanks for your help.
One golden rule I follow is to "Avoid Nesting" as much as I can. But if it is at the cost of making my single if condition too complex, I don't mind nesting it out.
Besides you're using the short-circuit && operator. So if the boolean is false, it won't even try matching!
So,
if (boolean_condition && matcher.find(string)) {
...
}
is the way to go!
The following two methods:
public void oneIf(boolean a, boolean b)
{
if (a && b)
{
}
}
public void twoIfs(boolean a, boolean b)
{
if (a)
{
if (b)
{
}
}
}
produce the exact same byte code for the method body so there won't be any performance difference meaning it is purely a stylistic matter which you use (personally I prefer the first style).
Both ways are OK, and the second condition won't be tested if the first one is false.
Use the one that makes the code the more readable and understandable. For just two conditions, the first way is more logical and readable. It might not be the case anymore with 5 or 6 conditions linked with &&, || and !.
I recommend extracting your expression to a semantically meaningful variable and then passing that to your evaluation. Instead of:
if (boolean_condition && matcher.find(string)) { ... }
Assign the expression to a variable, then evaluate the variable:
const hasItem = boolean_condition && matcher.find(string)
if (hasItem) { ... }
With this method, you can keep even the most complex evaluations readable:
const hasItem = boolean_condition && matcher.find(string)
const hasOtherThing = boolean_condition || boolean_condition
const isBeforeToday = new Date(string) < new Date()
if (hasItem && hasOtherThing && isBeforeToday) { ... }
Java uses short-circuiting for those boolean operators, so both variations are functionally identical. Therefore, if the boolean_condition is false, it will not continue on to the matching
Ultimately, it comes down to which you find easier to read and debug, but deep nesting can become unwieldy if you end up with a massive amount of braces at the end
One way you can improve the readability, should the condition become longer is to simply split it onto multiple lines:
if(boolean_condition &&
matcher.find(string))
{
...
}
The only choice at that point is whether to put the && and || at the end of the previous line, or the start of the current.
I tend to see too many && and || strung together into a logic soup and are often the source of subtle bugs.
It is too easy to just add another && or || to what you think is the right spot and break existing logic.
Because of this as a general rule i try not to use either of them to avoid the temptation of adding more as requirements change.
If you like to be compliant to Sonar rule squid:S1066 you should collapse if statements to avoid warning since it states:
Collapsible "if" statements should be merged
The first one. I try to avoid if nesting like that, i think it's poor style/ugly code and the && will shortcircuit and only test with matcher.find() if the boolean is true.
In terms of performance, they're the same.
But even if they weren't
what's almost certain to dominate the time in this code is matcher.find(string) because it's a function call.
Most would prefer to use the below one, because of "&&".
if (boolean_condition && matcher.find(string)) {
...
}
We normally called these as "short-circuit (or minimum evaluation)". It means the 2nd argument (here it is "matcher.find(string)") is only evaluated only if the 1st argument doesn't have sufficient information to determine the value of the expression. As an example, if the "boolean_condition" is false, then the overall condition must be false (because of here logical AND operator). Then compiler won't check the 2nd argument which will cause to reduce the running time of your code.

Does Java check all arguments in "&&" (and) operator even if one of them is false?

I have such code:
if(object != null && object.field != null){
object.field = "foo";
}
Assume that object is null.
Does this code result in nullPointerException or just if statement won't be executed?
If it does, how to refactor this code to be more elegant (if it is possible of course)?
&& does short circuit while & would not.
But with simple questions like this, it is best to just try it (ideone can help when you don't have access to a machine).
&& - http://ideone.com/LvV6w
& - http://ideone.com/X5PdU
Finally the place to check for sure would be the JLS §15.23. Not the most easy thing to read, the relevent section states:
The && operator is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
Java does have short circuit evaluation, i.e. your code should be ok
One way to know it! Test it! How? Well, make a method which prints out something:
public static boolean test(int i)
{
System.out.println(i);
return false;
}
...
if (test(1) && test(2) && test(3))
{
// not reached
}
This prints:
1
So the answer on your question is "no".
Best way to find out would be try it, especially for a single line question. Would have been faster, too.
The answer is that Java will not execute the body of the "if".
This will not throw any NullPointerException . The condition will be evaluated from left to right and the moment first false expression is found it will not evaluate remaining expression.
Maybe this other question helps you:
Differences in boolean operators: & vs && and | vs ||
Java has short circuit evaluation, so it will be fine.
The code looks ok to me, but do you actually need to check object.field != null? I think that test can be omitted as you never use the variable, just set it.
On a side-note, most programmers wouldn't access fields directly (object.field) but rather through getters/setters (object.setField(x);). Without any more context to go on, I can't say if this is appropriate in your case.
&& and || conditions stops at the point they can decide whether the condition is true/false, in your case, the condition will stop right after object != null and I think that your code is just fine for this case
If you want all of your boolean expressions evaluated regardless of the truth value of each, then you can use & and | instead of && and ||. However make sure you use these only on boolean expressions. Unlike && and ||, & and | also have a meaning for numeric types which is completely different from their meaning for booleans.
http://ibiblio.org/java/course/week2/46.html
Although short circuiting would work here, its not a guarantee that (like I have done many times) you'll get the order wrong when writing another, it would be better practice to nest those if statements and define the order you want the boolean checks to break:
if(object != null)
{
if(object.field != null)
{
object.field = "foo";
}
}
This does exactly the same as you're essentially saying, if the first boolean check fails don't do the second; it is also nullPointerException safe as object.field will not be checked unless object is not null
Using short-circuiting on booleans can become annoying later on as when you have a multiple bool if statement it becomes trickier to efficiently debug which part short circuited.

Categories