I see no cogent reason for implementing Identifiable for each fact class.<br>The hashCode() any object returns should be distinct enough, especially<br>considering that all the hash codes are munched together, which is<br>
definitely not *guaranteed* to result in different values for *all* rule and<br>fact set combinations. <br><br>But please do as Greg suggested.<br><br>BTW, it's sufficient to end with<br> return alreadyActivatedRules.add(hash);<br>
<br>-W<br><br>On Thu, Oct 8, 2009 at 11:43 PM, Dave Schweisguth <span dir="ltr"><<a href="mailto:dave@schweisguth.org">dave@schweisguth.org</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Greetings fellow Droolers,<br>
<br>
Each of our rules modifies the fact it matches. We'd like to run each of<br>
those rules exactly once, not reactivating them when a fact changes. I see<br>
from the archives that I'm not the first person to discover that no-loop is<br>
too weak and lock-on-activate too strong for my purposes.<br>
<br>
I implemented our requirement with an AgendaListener that remembers hashes<br>
of rules + facts. This works but requires each fact to implement an<br>
interface with a method that returns the hash, and means TWO casts each time<br>
I examine a FactHandle. The whole AgendaFilter is below so you can see what<br>
I mean.<br>
<br>
Can anyone suggest a better way? I'm looking more for a better approach<br>
altogether than I am for critique of the implementation of my current<br>
approach, although the latter would not be unwelcome.<br>
<br>
private static class Once<br>
implements AgendaFilter {<br>
<br>
private final Set<Integer> alreadyActivatedRules = new HashSet<Integer>();<br>
<br>
public boolean accept(Activation activation) {<br>
int hash = activation.getRule().getName().hashCode();<br>
for (FactHandle handle: activation.getFactHandles()) {<br>
Object object = ((DefaultFactHandle) handle).getObject();<br>
hash *= 31;<br>
if (object instanceof Identifiable) {<br>
hash += ((Identifiable) object).getIdentity();<br>
} else if (object instanceof String) {<br>
// We get here when a rule uses from on a string collection<br>
hash += object.hashCode();<br>
} else {<br>
throw new IllegalStateException(<br>
"Don't know what to do with fact class "<br>
+ object.getClass() + ", value " + object);<br>
}<br>
}<br>
boolean accept = !alreadyActivatedRules.contains(hash);<br>
alreadyActivatedRules.add(hash);<br>
return accept;<br>
}<br>
<br>
}<br>
<br>
Thanks & cheers,<br>
<font color="#888888"><br>
--<br>
| Dave Schweisguth <a href="http://schweisguth.org/%7Edave/" target="_blank">http://schweisguth.org/~dave/</a> |<br>
| Home: dave at <a href="http://schweisguth.org" target="_blank">schweisguth.org</a> Work: <a href="http://www.nileguide.com/" target="_blank">http://www.nileguide.com/</a> |<br>
| For compliance with the NJ Right to Know Act: Contents partially unknown |<br>
_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
</font></blockquote></div><br>