[rules-users] determining what field changed

2009-09-16 Thread Chris Richmond
Is it possible to determine what fields from an object changed within a
rule.  

 

So I am using this to determine if any DataObject has changed: 

 

//IDENTIFY ANY DATAOBJECT CHANGES

rule identify any DATAOBJECT

  

when

  

  $do : DataObject();

 

then

 

  System.err.println(ANY DataObject change detected: + $do);

End

 

 

However this also fires when any new DataObject() is injected into the
system and the rules are fired.  I would like to be able to only have a rule
fire when  an object is first created

Vs. when it is modified and is there a way to detect what values of an
object have changed if I don't explicitly know what fields of DataObject
changed ahead of time?

 

Thanks,


Chris

 

___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] determining what field changed

2009-09-16 Thread Greg Barton
Not really.  Without modifying the objects you could do this outside the rules 
using a WorkingMemoryEventListener, which has objectInserted() and 
objectUpdated() methods.  Event if you can modify the DataObject to add an I'm 
a new object flag, and set it immediately on insertion, then you could do 
differentiate with two rules:

rule identify new DATAOBJECT 
when 
  do : DataObject(n00b == true); 
then
  do.setN00b(false);
  update(do);
  System.err.println(DataObject assertion detected:  + do);
end 

rule identify modified DATAOBJECT 
when 
  do : DataObject(n00b == false); 
then
  System.err.println(DataObject modification detected:  + do);
end 

Which would still catch a spurious modification notification on assert!  At 
that point the semi-risky alternative is to not call update() in the identify 
new DATAOBJECT rule action.  That way, the identify modified DATAOBJECT is 
not immediately activated, but it would be activated the next time update() is 
called on the object.  I say semi-risky because it's not often a good idea to 
put a WM object into a state that the rete is not aware of, but in this case it 
would do what you want.

--- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote:

 From: Chris Richmond crichm...@referentia.com
 Subject: [rules-users] determining what field changed
 To: 'Rules Users List' rules-users@lists.jboss.org
 Date: Wednesday, September 16, 2009, 2:41 PM
 
 Is it possible
 to determine what fields from an object
 changed within a rule.   
 
 So I am using
 this to determine if any DataObject has
 changed:  
 
 //IDENTIFY ANY DATAOBJECT
 CHANGES 
 
 rule
 identify any DATAOBJECT 
 when 
   $do :
 DataObject(); 
 then    
 System.err.println(ANY
 DataObject change detected: + $do);
 End 
 
 However this
 also fires when any new DataObject() is
 injected into the system and the rules are fired.  I
 would like to be able to
 only have a rule fire when  an object is first
 created 
 
 Vs. when it is
 modified and is there a way to detect what
 values of an object have changed if I don’t
 explicitly know what fields
 of DataObject changed ahead of time? 
 
 Thanks,
 Chris 
 
 -Inline Attachment Follows-
 
 ___
 rules-users mailing list
 rules-users@lists.jboss.org
 https://lists.jboss.org/mailman/listinfo/rules-users
 


  

___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] determining what field changed

2009-09-16 Thread Chris Richmond
In general do you have any suggestions for getting around multiple update
detects being made?  In other words I have a rule to detect if my DataObject
has fieldA  X and if so, then modify fieldB.  Then another rule that checks
if fieldB = value and then updates field C.

So something like:

rule identify modified DATAOBJECT 
when 
  do : DataObject(FieldA  x); 
then
  modify(do.fieldB = value)
end

So something like:

rule identify modified DATAOBJECT 
when 
  do : DataObject(fieldB == value); 
then
  modify(do.fieldC = someValue)
end


rule identify modified DATAOBJECT 
when 
  do : DataObject(fieldC == someValToMatchForC); 
then
  modify(do.fieldA = someNewValueForA)
end



But of course this leads to some sort of cross product execution as each one
is run all over again after another makes a change and ramps out of control

One question.  I have been using modify() and I notice you had explicit:
  do.setN00b(false);
  update(do);

What is the difference and will that matter to my scenario?

Thanks,

Chris


-Original Message-
From: rules-users-boun...@lists.jboss.org
[mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Greg Barton
Sent: Wednesday, September 16, 2009 10:14 AM
To: Rules Users List
Subject: Re: [rules-users] determining what field changed

Not really.  Without modifying the objects you could do this outside the
rules using a WorkingMemoryEventListener, which has objectInserted() and
objectUpdated() methods.  Event if you can modify the DataObject to add an
I'm a new object flag, and set it immediately on insertion, then you could
do differentiate with two rules:

rule identify new DATAOBJECT 
when 
  do : DataObject(n00b == true); 
then
  do.setN00b(false);
  update(do);
  System.err.println(DataObject assertion detected:  + do);
end 

rule identify modified DATAOBJECT 
when 
  do : DataObject(n00b == false); 
then
  System.err.println(DataObject modification detected:  + do);
end 

Which would still catch a spurious modification notification on assert!  At
that point the semi-risky alternative is to not call update() in the
identify new DATAOBJECT rule action.  That way, the identify modified
DATAOBJECT is not immediately activated, but it would be activated the next
time update() is called on the object.  I say semi-risky because it's not
often a good idea to put a WM object into a state that the rete is not aware
of, but in this case it would do what you want.

--- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote:

 From: Chris Richmond crichm...@referentia.com
 Subject: [rules-users] determining what field changed
 To: 'Rules Users List' rules-users@lists.jboss.org
 Date: Wednesday, September 16, 2009, 2:41 PM
 
 Is it possible
 to determine what fields from an object
 changed within a rule.   
 
 So I am using
 this to determine if any DataObject has
 changed:  
 
 //IDENTIFY ANY DATAOBJECT
 CHANGES 
 
 rule
 identify any DATAOBJECT 
 when 
   $do :
 DataObject(); 
 then    
 System.err.println(ANY
 DataObject change detected: + $do);
 End 
 
 However this
 also fires when any new DataObject() is
 injected into the system and the rules are fired.  I
 would like to be able to
 only have a rule fire when  an object is first
 created 
 
 Vs. when it is
 modified and is there a way to detect what
 values of an object have changed if I don’t
 explicitly know what fields
 of DataObject changed ahead of time? 
 
 Thanks,
 Chris 
 
 -Inline Attachment Follows-
 
 ___
 rules-users mailing list
 rules-users@lists.jboss.org
 https://lists.jboss.org/mailman/listinfo/rules-users
 


  

___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users




___
rules-users mailing list
rules-users@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users


Re: [rules-users] determining what field changed

2009-09-16 Thread Greg Barton
There is no functional difference between modify and update.  update is the 
new syntax.  See section 3.3.3.1.3 of the expert doc:

https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-expert/html_single/index.html#d0e1264

(scroll down a bit)

As for general suggestions to prevent rule re-firing, there are several 
options.  The most general is make your conditions the negation of your 
action.  In other words, the conditions say the objects are in state A, and 
not in state B yet and state B is what you do to them in the action.  So, to 
modify your example:

rule Rule1 
when 
  do : DataObject(FieldA  x, fieldB != value); 
then
  modify(do.fieldB = value)
end

So something like:

rule Rule2 
when 
  do : DataObject(fieldB == value, fieldC != someValue); 
then
  modify(do.fieldC = someValue)
end

rule Rule3 
when 
  do : DataObject(fieldC == someValToMatchForC, do.fieldA != 
someNewValueForA); 
then
  modify(do.fieldA = someNewValueForA)
end

So you're always telling the engine to fire the rule if the objects are in some 
state, and NOT in the state you're about to put them in.

Another general pattern is to have the objects hold some artificial state (or 
match them with an object that holds the artificial state) that restricts rule 
firing to transitions in a certain logical path.  One simple way to do this is 
to have a String (or preferably an Enum) value in the object that informs the 
rules what artificial state the object is in.

rule Rule1 
when 
  do : DataObject(FieldA  x, state == StageA); 
then
  do.setFieldB(value);
  do.setStage(StageB);
  update(do);
end

So something like:

rule Rule2 
when 
  do : DataObject(fieldB == value, state == StageB); 
then
  do.setFieldC(someValue)
  do.setStage(StageC);
  update(do);
end

rule Rule3 
when 
  do : DataObject(fieldC == someValToMatchForC, state == StageC);
then
  do.setFieldA(someNewValueForA);
  do.setStage(StageD);
  update(do);
end

This isn't as restrictive as you might think.

There are also the flow control mechanisms available for rule flow and agenda 
grouping, but they don't reach down to the object level.  However, mattering on 
how many conflicting objects you have in memory at once, they can be quite 
useful for this purpose as well. (Basically, you force the entire engine into 
limited processing states, instead of individual objects.)

--- On Wed, 9/16/09, Chris Richmond crichm...@referentia.com wrote:

 From: Chris Richmond crichm...@referentia.com
 Subject: Re: [rules-users] determining what field changed
 To: 'Rules Users List' rules-users@lists.jboss.org
 Date: Wednesday, September 16, 2009, 3:52 PM
 In general do you have any
 suggestions for getting around multiple update
 detects being made?  In other words I have a rule to
 detect if my DataObject
 has fieldA  X and if so, then modify fieldB.  Then
 another rule that checks
 if fieldB = value and then updates field C.
 
 So something like:
 
 rule identify modified DATAOBJECT 
 when 
       do : DataObject(FieldA  x); 
 then    
   modify(do.fieldB = value)
 end
 
 So something like:
 
 rule identify modified DATAOBJECT 
 when 
       do : DataObject(fieldB == value); 
 then    
   modify(do.fieldC = someValue)
 end
 
 
 rule identify modified DATAOBJECT 
 when 
       do : DataObject(fieldC ==
 someValToMatchForC); 
 then    
   modify(do.fieldA = someNewValueForA)
 end
 
 
 
 But of course this leads to some sort of cross product
 execution as each one
 is run all over again after another makes a change and
 ramps out of control
 
 One question.  I have been using modify() and I notice
 you had explicit:
   do.setN00b(false);
   update(do);
 
 What is the difference and will that matter to my
 scenario?
 
 Thanks,
 
 Chris
 
 
 -Original Message-
 From: rules-users-boun...@lists.jboss.org
 [mailto:rules-users-boun...@lists.jboss.org]
 On Behalf Of Greg Barton
 Sent: Wednesday, September 16, 2009 10:14 AM
 To: Rules Users List
 Subject: Re: [rules-users] determining what field changed
 
 Not really.  Without modifying the objects you could
 do this outside the
 rules using a WorkingMemoryEventListener, which has
 objectInserted() and
 objectUpdated() methods.  Event if you can modify the
 DataObject to add an
 I'm a new object flag, and set it immediately on
 insertion, then you could
 do differentiate with two rules:
 
 rule identify new DATAOBJECT 
 when 
       do : DataObject(n00b == true); 
 then    
   do.setN00b(false);
   update(do);
   System.err.println(DataObject assertion detected: 
 + do);
 end 
 
 rule identify modified DATAOBJECT 
 when 
       do : DataObject(n00b == false); 
 then    
   System.err.println(DataObject modification
 detected:  + do);
 end 
 
 Which would still catch a spurious modification
 notification on assert!  At
 that point the semi-risky alternative is to not call
 update() in the
 identify new DATAOBJECT rule action.  That way