How do we assign an object to a newly created object in drool - drools

I am new to drools and have a scenario where I have to assign an object1 to object2 and change one of the field value of object2 and pass it further so that I don't loose object1 and can use object1 accordingly. I have the below code but it throws an exception. Please can someone let me know how we can assign an object to newly created Object.
rule "example"
when
$customerObject : Customer(nameOfBank=="AXIS",salary>=70000);
$newObject:Customer()
$newObject:$customerObject;
then
$customerObject.setIsAligibleforLoan("Yes");
$customerObject.setRateOfInterest(12);
$newObject.setDocumentNeeded("Yes");
DocumentCheck($newObject);
halt();
end;

Your rule, as written, doesn't make much sense. What is $newObject:$customerObject supposed to be doing?
Variables that you declare in your when clause are only scoped to the rule, there's no "passing it along."
If you want to create a copy of an object in working memory, modify it, and then have other rules key off of the values in the copy, then you want to use insert.
rule "Example 1"
when
$original: Example( name == "something", value < 0 )
then
// make a copy
$copy = new Example( $original.getName(), original.getValue() );
// make some modifications
$copy.setOtherField( "X" );
// insert into working memory
insert( $copy );
end
Now you will have 2 items in working memory (the original and the copied-and-modified). insert will reevaluate all subsequent rules to figure out if they are still valid / are now valid for firing. Previous rules will not be reevaluated.
If you want to refire all rules, use update instead of insert. You can remove an object from working memory with retract.

Related

How to access common declared types from a function in Drools?

Here am having multiple Rules in a .drl file. They are updating 6 different JSONArray. These updates are happening in the "then" section of the Drools. Rather than having the similar logic inside the rule, am trying to write a function which will update the 6 JSONArray. How would that be possible ?
declare USER1_LIST
querysetUser1 :JSONArray
end
declare USER2_LIST
querysetUser2 :JSONArray
end
......
......
......
The initialization is happening in a "Set Up" rule with highest Salience -
rule "setUp"
salience 25
when
then
USER1_LIST user1_list = new USER1_LIST();
user1_list.setQuerysetUser1(new JSONArray());
insert(user1_list);
....
In the rule am using one of the list based on the logic -
rule "RULE_XYZ"
salience 5
when
USER1_LIST($querysetUser1 :querysetUser1)
...<Some code>
then
...<Some code>
$querysetUser1.add(...);
Here I want to perform the operation "$querysetUser1.add(...);" inside a function. These JSONArray are updated by different rules. So my aim is to move the logic of selecting the JSONArray and updating it in a function, so that only this function would be called from different rules.
Declared types can be accessed in declared functions. However, from your example, it sounds like you just need to be able to do work against the JSONArray objects contained within the declared types.
The function would look something like this:
function void addToQuerySet(JSONArray querySet, JSONObject object) {// I have guessed the type of 'object'
querySet.add(object);
}
And you would invoke it from the then clause:
rule "RULE_XYZ"
when
USER1_LIST($querysetUser1 :querysetUser1)
// ...<Some code>
someObject: JSONObject() // the thing to insert
then
addToQuerySet($querysetUser1, someObject);
end
What you cannot do is write a generic method that will take any of your USER1_LIST, USER2_LIST, etc declared types because they're all unique and unrelated types, even if they all share the same structure.
Note that the fact that your declared types sharing the same structure is indicative of poor design -- it is likely they should all be instances of a single type, with somet other way of identifying which user it belongs to. For example, something like this:
declare UserList
querySet: JSONArray
userNum: int
end
Where userNum would indicate which user this is for. Then you could write a function that takes a UserList and a JSONObject (or whatever the type is of that thing is you're adding to the query set) like so:
function void addToQuerySet(UserList userList, JSONObject object) {
userList.getQuerySet().add(object);
}
And invoke it in a then clause like so:
rule "RULE XYZ version 2"
when
$user1List: UserList( userNum == 1, querySet != null)
// more code
$someObject: JSONObject() // to insert
then
addToQuerySet( $user1List, $someObject );
end
Please refer to the documentation here. I have linked to the Drools 7.11.0.Final documentation, specifically the section on functions; the section on declared types is the following section and quite extensive.

When does Chapel pass by reference and when by constant?

I am looking for examples of Chapel passing by reference. This example works but it seems like bad form since I am "returning" the input. Does this waste memory? Is there an explicit way to operate on a class?
class PowerPuffGirl {
var secretIngredients: [1..0] string;
}
var bubbles = new PowerPuffGirl();
bubbles.secretIngredients.push_back("sugar");
bubbles.secretIngredients.push_back("spice");
bubbles.secretIngredients.push_back("everything nice");
writeln(bubbles.secretIngredients);
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
bubbles = kickAss(bubbles);
writeln(bubbles.secretIngredients);
And it produces the output
sugar spice everything nice
sugar spice everything nice Chemical X
What is the most efficient way to use a function to modify Bubbles?
Whether Chapel passes an argument by reference or not can be controlled by the argument intent. For example, integers normally pass by value but we can pass one by reference:
proc increment(ref x:int) { // 'ref' here is an argument intent
x += 1;
}
var x:int = 5;
increment(x);
writeln(x); // outputs 6
The way that a type passes when you don't specify an argument is known as the default intent. Chapel passes records, domains, and arrays by reference by default; but of these only arrays are modifiable inside the function. ( Records and domains pass by const ref - meaning they are passed by reference but that the function they are passed to cannot modify them. Arrays pass by ref or const ref depending upon what the function does with them - see array default intent ).
Now, to your question specifically, class instances pass by "value" by default, but Chapel considers the "value" of a class instance to be a pointer. That means that instead of allowing a field (say) to be mutated, passing a class instance by ref just means that it could be replaced with a different class instance. There isn't currently a way to say that a class instance's fields should not be modifiable in the function (other than making them to be explicitly immutable data types).
Given all of that, I don't see any inefficiencies with the code sample you provided in the question. In particular, here:
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
the argument accepting b will receive a copy of the pointer to the instance and the return b will return a copy of that pointer. The contents of the instance (in particular the secretIngredients array) will remain stored where it was and won't be copied in the process.
One more thing:
This example works but it seems like bad form since I am "returning" the input.
As I said, this isn't really a problem for class instances or integers. What about an array?
proc identity(A) {
return A;
}
var A:[1..100] int;
writeln(identity(A));
In this example, the return A in identity() actually does cause a copy of the array to be made. That copy wasn't created when passing the array in to identity(), since the array was passed by with a const ref intent. But, since the function returns something "by value" that was a reference, it's necessary to copy it as part of returning. See also arrays return by value by default in the language evolution document.
In any case, if one wants to return an array by reference, it's possible to do so with the ref or const ref return intent, e.g.:
proc refIdentity(ref arg) ref {
return arg;
}
var B:[1..10] int;
writeln(refIdentity(B));
Now there is no copy of the array and everything is just referring to the same B.
Note though that it's currently possible to write programs that return a reference to a variable that no longer exists. The compiler includes some checking in that area but it's not complete. Hopefully improvements in that area are coming soon.

How to change Class object name in a loop

So I have Class
class MyClass
....do things...
and I add objects to it with
ObjName = MyClass(things)
and my problem is that when I add ObjName to MyClass in a loop, I can't figure out a way to create a new object name each loop so it keeps overwriting the only Obj this ends up creating. I tried adding a list as in
ObjName[i] = MyClass(things)
but it wouldn't work.
Here is what I'm trying to do specifically (edited for clarity):
So when I add objects to MyClass, the name of the object added should be callable with input, like so:
somename = input("objname: ") # User input decides how the object values can be called
TempObjName = MyClass(things) # Values of the specific object, will contain more than one unique object
*...*
somename.someattribute() ## 2 different
somename2.someattribute() ## values, sets or etc
Try this:
ObjList = []
for i in whatever:
temp = MyClass(things)
ObjList.extend(temp)
I wasn't able to create the function I wanted per-say, but because my code had a dictionary that saved the obj name and obj value in it, I was able to do what I initially wanted to do by rerunning the requested name from the dictionary in the Class.

Activate Rules on child objects in Drools

I have two Facts named OptionalCover and OptionalPremiumComponent and OptionalCover has a reference of OptionalPremiumComponent in it. So this is what I'm inserting into working memory.
private static OptionalCover getOptionalCover(Double sumAssured, Double premiumRate) {
OptionalPremiumComponent premiumComponent = new OptionalPremiumComponent();
premiumComponent.setSumAssured(sumAssured);
premiumComponent.setPremiumRate(premiumRate);
OptionalCover optionalCover = new OptionalCover();
optionalCover.setPremiumComponent(premiumComponent);
return optionalCover;
}
kieSession.insert(getOptionalCover(1000000.0, 0.02));
I have created the following rule in drools
import java.lang.Number;
rule "OptionalCoverCalculation"
dialect "java"
when
opc : OptionalPremiumComponent( sumAssured > 1I && sumAssured != null && premiumRate != null && premiumRate > 0.0 )
then
opc.setPremium( opc.getSumAssured() * 0.001 * opc.getPremiumRate() );
System.out.println("Here");
end
The problem is, the above rule is not being fired when I insert the parent object. Do I have to do anything else to enable this behaviour? Is it supported?
Thank you.
The Drools engine has no way of telling that your Cover contains a Component. (Well, it has, as it might use reflection - but where should it stop?)
So, you'll have to insert the OptionalPremiumComponent as well.
To reduce the amount of clutter in your code you might write a sorts of clever methods so that you can insert Cover and Component with a single call.
For instance, if you have many similar "contains" relationships and if you want to reason freely, you might implement s.th. like
interface FactContainer {
List<Object> factChildren(); -- return all contained fact objects
-- OR --
void insertAll( KieSession ks );
}
where factChildren would return a List with the premiumComponent or an empty List, or, alternatively, one method insertAll that handles everything internally.

Supporting "recursive objects" in lua

I'm fairly new to lua and have the following problem with an assignment from a class:
We currently extend lua to support objects and inheritance. The Syntax for that is
Class{'MyClass',
attribute1 = String,
attribute2 = Number
}
Class{'MySubClass', MyClass,
attribute3 = Number
}
This works perfectly fine. The real problem lies within the next task: We should support "recursive types", that means a call like
Class{'MyClass', attribute = MyClass}
should result in an class with a field of the same type as the class. When this "class-constructor" is called the variable MyClass is nil, thats why the parameter table doesnt't have an entry attribute. How is it possible to access this attribute?
My first thought was using some kind of nil-table which gets returned every time the global __index is called with an unset key. This nil-table should behave like the normal nil, but can be checked for in the "class-constructor". The problem with this approach are comparisons like nil == unknown. This should return true, but as the __eq meta method of the nil-table is never called we cannot return true.
Is there another approach I'm currently just ignoring? Any hint is greatly appreciated.
Thanks in advance.
Edit:
Here the relevant part of the "testfile". The test by which the code is rated in class is another one and gets published later.
three = 3
print( three == 3 , "Should be true")
print( unknown == nil , "Should be true" )
Class{'AClass', name = String, ref = AClass}
function AClass:write()
print("AClass:write(), name of AClass:", self.name)
end
aclass = AClass:create("A. Class")
aclass:write()
Since MyClass is just a lookup in the global table (_G), you could mess with its metatable's __index to return a newly-defined MyClass object (which you would later need to fill with the details).
However, while feasible, such an implementation is
wildly unsafe, as you could end up with an undefined class (or worse, you may end up inadvertantly creating an infinite lookup loop. Trust me, I've been there)
very hard to debug, as every _G lookup for a non-existing variable will now return a newly created class object instead of nil (this problem could somewhat be reduced by requiring that class names start with an uppercase character)
If you go that route, be sure to also override __newindex.
How about providing the argument in string form?
Class{'MyClass', attribute = 'MyClass'}
Detect strings inside the implementation of Class and process them with _G[string] after creating the class
Or alternatively, use a function to delay the lookup:
Class{'MyClass', attribute = function() return MyClass end}