Clarification of using collections as facts
by Bagwell, Allen F
I'm going through the Drools documentation regarding the use of lists and other collections. I want to make sure my understanding is correct.
So if I have a class:
public class Foo {
private int x;
private int y;
private List<String> names = ArrayList<String>();
public List<String> getNames() {return names;}
// appropriate getters/setters for the int fields ...
}
With this I can insert a Foo object into working memory. I can even make the int fields dynamic facts with the appropriate addition of "bean-ifying" code.
For the List, however, I need to insert it separately into working memory in order to make use of Drools' rule language ('contains' ,etc.)? I'm assuming that doesn't come free because I have to insert my own custom class objects if they are included via composition in a larger fact!
Also, I'm guessing the Collection type classes cannot be dynamic facts? Meaning if I modify my List with add, remove, clear, etc., I must explicitly call update in my code on the List fact in order to alert Drools to a change in the List, correct?
So then the question also comes up as to how I would write a rule that looks for all instances of Strings in the List that match against a given regex expression. I've not been successful at figuring this out...
Rule "when a Foo List is modified, get all Strings in it that start with 'error'"
when
$foo : Foo($names : names)
$foundThese : ArrayList() from collect(??? matches "error.*" from $names)
then
// act on $foo and $foundThese
I know that rule is NOT correct, but I'm not sure how I'm supposed to access an immutable object inside a collection. The examples in the documentation show how to get at mutable class objects.
Thanks!
-Allen
16 years, 5 months
[Drools 4.0.7] JBRMS package dependencies and RuleAgent
by Jones, Alan R
Hi,
When compiling and deploying a package in JBRMS, it uses a bunch of jar
files in the JBRMS model. I have an axis2 web service that calls
RuleAgent in order to create a rulebase->working memory from this jbrms
package. However, though I do have all the classes that were in the
JBRMS model loaded in the lib of my web service, exceptions are thrown
during creation of the rulebase about those classes not being found.
Why is it not enough for the RuleAgent to have these classes loaded by
the web service? The only way to get this to work is to put the jars
used by jbrms model into the Axis2/lib, which is not right. I would like
RuleAgent to be able to use the jars loaded when the web service is
loaded from the service's (archive) /lib directory.
Suggestions?
Thanks,
aj
16 years, 5 months
Re: [rules-users] Using from
by Aziz Boxwala
Marcus,
Thank you very much. I am trying that out.
--Aziz
----- Original Message ----
From: Marcus Ilgner <marcus.ilgner(a)gmail.com>
To: Rules Users List <rules-users(a)lists.jboss.org>
Sent: Thursday, July 17, 2008 2:35:55 PM
Subject: Re: [rules-users] Using from
Hi Aziz,
On Thu, Jul 17, 2008 at 8:26 PM, Aziz Boxwala <boxwala(a)yahoo.com> wrote:
> I have the following class structure.
>
> Class GrandFather {
> List<Father> fathers;
> public List<Father> getFathers() {return fathers;}
> }
>
> Class Father {
> int age;
> List<Son> sons;
> public int getAge() {return age;}
> public List<Son> getSons() {return sons;}
> }
>
> Class Son {
> int age;
> public int getAge() {return age;}
> }
>
> I'd like to write a rule that finds all the Fathers who have age > 45 and
> have Sons where the son's age is greater than 5. But I can't figure out how
> to use "from" to iterate over father first and then over son.
>
> Any help will be greatly appreciated.
>
> Thanks,
> --Aziz
Something like this?
rule "FatherAndSon
when
$father : Father(age > 45)
$son : Son(age > 5) from $father.sons
then
// do something
end
Best regards
Marcus
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
16 years, 5 months
Mvel compilation error
by John Squire
Hi All,
We are intermittently getting mvel compilation errors with the following:
Caused by: java.lang.IllegalArgumentException: object is not an instance of
declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at
org.mvel.optimizers.impl.refl.MethodAccessor.getValue(MethodAccessor.java:61
)
... 148 more
The rules compile ok and the application will run normally (rules processing
successfully) for a few days then this error will occur. Tried to replicate
but once the application is restarted the last action before the failure is
repeated and always processes successfully.
Any help would be appreciated.
Regards
JS
16 years, 5 months
Using from
by Aziz Boxwala
I have the following class structure.
Class GrandFather {
List<Father> fathers;
public List<Father> getFathers() {return fathers;}
}
Class Father {
int age;
List<Son> sons;
public int getAge() {return age;}
public List<Son> getSons() {return sons;}
}
Class Son {
int age;
public int getAge() {return age;}
}
I'd like to write a rule that finds all the Fathers who have age > 45 and have Sons where the son's age is greater than 5. But I can't figure out how to use "from" to iterate over father first and then over son.
Any help will be greatly appreciated.
Thanks,
--Aziz
16 years, 5 months
Alternate approaches of using OR operator (to avoid sub-rule generation)
by Jaikiran Pai
We are using Drools-3.0.6. In one of our scenarios, we are trying to use the OR operator as follows:
rule Testing
when
person : (Person (interests contains "Golf") or Person (interests contains "Soccer") )
then
System.out.println("I am interested");
end
Based on one of my earlier posts in this forum (long time back), this rule will result in
"The OR CE will cause subrule generation, meaning the rule will fire twice if both conditions are true".
One of the ways, i was planning to change this is as follows:
rule Testing
when
person : Person()
then
if (person.getInterests().contains("Golf") || person.getInterests().contains("Soccer")) {
System.out.println("I am interested");
}
end
I don't think this is the best solution, though. Anyone has any better ways of implementing this? I know that Drools - 4 has a better support for this, but right now we don't have plans of migrating.
Thank you.
regards,
-Jaikiran
---------------------------------
Did you know? You can CHAT without downloading messenger. Click here
16 years, 5 months
Re: variable 'or' constraints with a DSL
by Matt Geis
Hi Reid,
>>The user has to be able to specify any of the attributes or any combination thereof and not necessarily in any order or all of them.
[snip]
>>I think answer is adding constraints with the dash syntax
No, dash syntax is not the answer. Clever construction of the DSL mapping will get you what you need.
Allow me to take your example and modify it.
[condition][File]file_name = fileName
[condition][File]dir_name = dirName
[condition][File]group_name = gName
[condition][File]user_name = uName
[condition][]file where {constraints}=$f: File(where {constraints})
[condition][]where {attr} matches {value}={attr} matches {value}
[condition][]and {attr} matches {value}=,{attr} matches {value}
[condition][]or {attr} matches {value}= || {attr} matches {value}
So if the user requests specifies jpg's owned by Bob, you can generate:
file where file_name matches "*.jpg" and user_name matches "Bob"
Which generates appropriate 'when' syntax in DRL:
$f : File(fileName matches "*.jpg", uName matches "bob")
A good way to get ORs with the dash syntax to get something like this:
file where file_name matches "*.jpg" or user_name matches "Bob"
which expands to
$f : File(fileName matches "*.jpg" || uName matches "bob")
Now, I mentioned that you *might* have to use the variable typing feature new to Drools 5.0, but you may not.
If you do, the attribute lines might look a bit like this...
[condition][File](?i:where)\s+{attr:[A-Za-z0-9]+}\s+matches\s+{value:".*?"}={attr} matches {value}
[condition][File](?i:and)\s+{attr:[A-Za-z0-9]+}\s+matches\s+{value:".*?"}=,{attr} matches {value}
[condition][File](?i:or)\s+{attr:[A-Za-z0-9]+}\s+matches\s+{value:".*?"}= || {attr} matches {value}
What you're seeing here is a few things.
The "?i" at the start of any literals makes it case-insensitive. This, of course, is up to you.
The \s+ instead of a space matches on one or more whitespace characters.
The pattern after the variable name contstrains the match rather tightly. I have found that you need this if you're trying to allow a user to enter an arbitrary number of constraints in whatever order they please.
Good luck!
Matt
16 years, 5 months
Design Question (hashCode/equals/fact maintenance)
by Fenderbosch, Eric
I'm just looking for a bit of verification that this is a reasonable
solution. This just feels like a hack and there's probably a better way
that I'm just not seeing. Alternate ideas are welcome and appreciated.
Thanks in advance.
The objective is to find the best workers for a job:
Jobs have a location.
Workers have a location.
Scores are calculated based on miles and minutes of a route from the
worker to a job.
When a job or worker location changes, then the route should be
recalculated so that scores can be recalculated. It is possible for a
location to get re-inserted that might be the functionally the same as a
previous location for a job/worker, but a different instance. In this
case, the route should not be recalculated and the old scores should
remain.
assert behavior = equality
logical override = discard
maintain tms = true
remove identies = true
shadow proxies are enabled
public class JobLatitudeLongitude {
private String jobId;
private double latitude;
private double longitude;
private long timestamp = System.currentTimeMillis();
// getters & setters omitted for brevity
public int hashCode() {
return jobId.hashCode();
}
public boolean equals(Object obj) {
// not null or type safe, just simple version for
brevity
JobLatitudeLongitude other = (JobLatitudeLongitude) obj;
return this.jobId.equals(other.jobId) && this.timestamp
== other.timestamp;
// would "return false;" work ???
}
}
rule "retract redundant job latitude/longitude facts"
// if more than one lat/long with same position for a job, keep the
oldest
salience 600
when
older : JobLatitudeLongitude()
newer : JobLatitudeLongitude(jobId == older.jobId,
latitude == older.latitude, longitude == older.longitude, timestamp >=
older.timestamp)
then
retract(newer);
end
rule "retract old job latitude/longitude facts"
// if more than one lat/long with different position for a job, keep the
newest
salience 600
when
older : JobLatitudeLongitude()
newer : JobLatitudeLongitude(jobId == older.jobId,
latitude != older.latitude, longitude != older.longitude, timestamp >=
older.timestamp)
then
retract(older);
end
rule "add Route fact"
salience 450
when
jobLatitudeLongitude : JobLatitudeLongitude()
workerLatitudeLongitude : WorkerLatitudeLongitude()
then
// calculateRoute is an imported function
Route route = calculateRoute(workerLatitudeLongitude,
jobLatitudeLongitude);
insertLogical(route);
end
16 years, 5 months
Map using from constraint
by Paul Ryan
Hi all,
Is there a way using the 'from' constraint to get the values of a map(the implementations of java.lang.Map eg HashMap, TreeMap, etc) into a constraint parameter, and if so can someone please give an example. Below is the way I've been trying, without success, to get a value based on a key.
import my.package.MyFact
import java.util.Map.Entry
rule "Find with map"
when
$fact : MyFact($paramMap : paramMap)
$myValue : Entry(key == "mykey1") from $paramMap
Then
// Sudo code...
<use $myValue.getValue()>
end
Paul Ryan
Software Architect
Product Engineering
InfoTrust Group, Inc.
[cid:image001.jpg@01C8E75E.F8448000]
500 Discovery Parkway, Suite 200
Superior, CO 80027
Office (303) 627-6528
Fax (303) 666-6711
Email pryan(a)infotrustgroup.com<mailto:pryan@infotrustgroup.com>
WEB www.infotrustgroup.com<http://www.infotrustgroup.com/>
This e-mail and all information included herein do not constitute a legal agreement accorded by INFOTRUST GROUP and its affiliates and subsidiaries. All legal agreements must be formulated in writing by a legal representative of INFOTRUST GROUP. This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this e-mail by mistake, please inform us and destroy this e-mail and any documents it might contain. Please note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of the company. Finally, the recipient should check this email and any attachments for the presence of viruses. The company accepts no liability for any damage caused by any virus transmitted by this email. Thank you for your cooperation.
16 years, 5 months