This post originated from an RSS feed registered with Java Buzz
by Geoffrey Wiseman.
Original Post: Types and Semantics in Drools
Feed Title: Furious Purpose
Feed URL: http://www.jroller.com/diathesis/feed/entries/rss
Feed Description: Thoughts and experiences on technology and software.
As you compose complicated rule sets, you may find that you need to
assert simple facts, normally handled by Java primitives, with different
meanings. Because drools uses the type of the fact to determine which
rules to examine, these primitives may overlap in confusing ways.
For instance, imagine that you're processing a pet food shopping cart
using drools and, in so doing, want the option of supplying a discretionary
discounts, based on the customer's shopping history and your own excess
inventory. You decide to capture these as Float objects, one for the
customer's relationship discretionary discount and another for the inventory
discretionary discount.
If you simply assert both of these facts into memory, drools will be
unable to determine which is which -- they're both Float objects with
no additional semantics associated with them. That leaves several
available options:
Send the float objects in as application data.
Subclass float to add semantic meaning by the names of the new classes.
Use the semaphore mechanism.
Application Data
The application data mechanism is a useful way to
parameterize rules, but application data is not treated as a fact assertion, and will not activate
rules. This makes it applicable in some, but not all rule design scenarios.
e.g.:
ruleBase.newWorkingMemory();
// ... assert facts here
memory.setApplicationData( "relationshipDiscretionaryDiscount", new Float( 0.1f ) );
memory.setApplicationData( "inventoryDiscretionaryDiscount", new Float( 0.05f ) );
memory.fireAllRules();
Subclassing
By subclassing the float, you can create a class that has domain-specific semantic
meaning and which can be used directly in your rules. For this example, you might
create a generalized Discount class which can represent both kinds of discount as
well as a type.
If this class has meaning in your domain, and by using it, you will make your
application design more intention-revealing, and possibly add further functionality
to the class, then this may well be the best way to go. However, if you're going to
create a meaningless wrapper class, or several of them, this can be tiresome.
e.g.:
ruleBase.newWorkingMemory();
// ... assert facts here
memory.assertObject( new RelationshipDiscretionaryDiscount( 0.1f ) );
memory.assertObject( new InventoryDiscretionaryDiscount( 0.05f ) );
memory.fireAllRules();
Semaphores
As of Drools 2.0B19, Drools supplies semaphore classes that can be used for much of
the same purpose. In essence, these are simple wrappers for Java primitives that
are also named. This allows you to submit two facts with the same primitive type
but with different names. The rules are aware of semaphores and can use these names
to make distinctions between the supplied facts.
e.g.:
ruleBase.newWorkingMemory();
// ... assert facts here
// This FloatSemaphore constructor doesn't yet exist: See DROOLS-280
memory.assertObject( new FloatSemaphore( "relationshipDiscretionaryDiscount", 0.1f ) );
memory.assertObject( new FloatSemaphore( "inventoryDiscretionaryDiscount", 0.05f ) );
memory.fireAllRules();