[jboss-svn-commits] JBL Code SVN: r15350 - labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Sep 24 17:30:42 EDT 2007
Author: mark.proctor at jboss.com
Date: 2007-09-24 17:30:41 -0400 (Mon, 24 Sep 2007)
New Revision: 15350
Added:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/1-PetStore-Start-Screen.png
labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/2-stock-added-to-order-list.png
labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/3-purchase-suggestion.png
labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/4-Petstore-final-screen.png
Modified:
labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/Section-Examples.xml
Log:
-added petstore example, curtesy of Paul Brown.
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/1-PetStore-Start-Screen.png
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/1-PetStore-Start-Screen.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/2-stock-added-to-order-list.png
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/2-stock-added-to-order-list.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/3-purchase-suggestion.png
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/3-purchase-suggestion.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/4-Petstore-final-screen.png
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/4-Petstore-final-screen.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/Section-Examples.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/Section-Examples.xml 2007-09-24 20:34:47 UTC (rev 15349)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Examples/Section-Examples.xml 2007-09-24 21:30:41 UTC (rev 15350)
@@ -1479,15 +1479,747 @@
</section>
<section>
- <title>PetStore Example</title>
+ <section>
+ <title>Pet Store Example</title>
- <programlisting><emphasis role="bold">Name:</emphasis> PetStore
-<emphasis role="bold">Main class:</emphasis> org.drools.examples.PetStoreExample
-<emphasis role="bold">Type:</emphasis> java application
+ <programlisting><emphasis role="bold">Name:</emphasis> Pet Store
+<emphasis role="bold">Main class:</emphasis> org.drools.examples.PetStore
+<emphasis role="bold">Type:</emphasis> Java application
<emphasis role="bold">Rules file:</emphasis> PetStore.drl
-<emphasis role="bold">Objective:</emphasis> Demonstrates 'accumulate', 'collect' and 'from'</programlisting>
+<emphasis role="bold">Objective:</emphasis> Demonstrate use of Agenda Groups, Global Variables and integration with a GUI (including callbacks from within the Rules)
+</programlisting>
- <para></para>
+ <para>The Pet Store example shows how to integrate Rules with a GUI (in
+ this case a Swing based Desktop application). Within the rules file, it
+ shows how to use agenda groups and auto-focus to control which of a set
+ of rules is allowed to fire at any given time. It also shows mixing of
+ Java and MVEL dialects within the rules, the use of accumulate functions
+ and calling of Java functions from within the ruleset.</para>
+
+ <para>Like the rest of the the samples, all the Java Code is contained
+ in one file. The PetStore.java contains the following principal classes
+ (in addition to several minor classes to handle Swing Events)</para>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis role="italic"> Petstore</emphasis> - containing
+ the main() method that we will look at shortly.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">PetStoreUI</emphasis> - responsible
+ for creating and displaying the Swing based GUI. It contains
+ several smaller classes , mainly for responding to various GUI
+ events such as mouse and button clicks.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">TabelModel</emphasis> - for holding
+ the table data. Think of it as a JavaBean that extends the Swing
+ AbstractTableModel class.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">CheckoutCallback</emphasis> - Allows
+ the GUI to interact with the Rules.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">Ordershow </emphasis> - the items
+ that we wish to buy.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">Purchase</emphasis> - Details of the
+ order and the products we are buying.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">Product</emphasis> - JavaBean
+ holding details of the product available for purchase, and it's
+ price.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Much of the Java code is either JavaBeans (simple enough to
+ understand) or Swing based. We will touch on some Swing related points
+ in the this tutorial , but a good place to get more Swing component
+ information is <ulink
+ url="???"><uri>http://java.sun.com/docs/books/tutorial/uiswing/</uri>available
+ at the Sun Swing website.<citebiblioid /></ulink></para>
+
+ <para>There are two important Rules related pieces of Java code in
+ <emphasis role="italic">Petstore.java</emphasis>.</para>
+
+ <para>
+ <example>
+ <title>Creating the PetStore RuleBase - extract from PetStore.java
+ main() method</title>
+
+ <programlisting>PackageBuilder builder = new PackageBuilder();
+builder.addPackageFromDrl( new InputStreamReader(
+PetStore.class.getResourceAsStream( "PetStore.drl" ) ) );
+RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ruleBase.addPackage( builder.getPackage() );
+
+//RuleB
+Vector stock = new Vector();
+stock.add( new Product( "Gold Fish",5 ) );
+stock.add( new Product( "Fish Tank", 25 ) );
+stock.add( new Product( "Fish Food", 2 ) );
+
+//The callback is responsible for populating working memory and
+// fireing all rules
+PetStoreUI ui = new PetStoreUI( stock, new CheckoutCallback( ruleBase ) );
+ui.createAndShowGUI();
+</programlisting>
+ </example>
+ </para>
+
+ <para>This code above loads the rules (drl) file from the classpath.
+ Unlike other examples where the facts are asserted and fired straight
+ away, this example defers this step to later. The way it does this is
+ via the second last line where the PetStoreUI is created using a
+ constructor the passes in the Vector called stock containing products ,
+ and an instance of the CheckoutCallback class containing the RuleBase
+ that we have just loaded.</para>
+
+ <para>The actual Javacode that fires the rules is within the <emphasis
+ role="italic">CheckoutCallBack.checkout()</emphasis> method. This is
+ triggered (eventually) when the 'Checkout' button is pressed by the
+ user.</para>
+
+ <example>
+ <title>Firing the Rules - extract from the CheckOutCallBack.checkout()
+ method</title>
+
+ <programlisting>public String checkout(JFrame frame, List items) throws FactException {
+ Order order = new Order();
+
+ //Iterate through list and add to cart
+ for ( int i = 0; i < items.size(); i++ ) {
+ order.addItem( new Purchase( order, (Product) items.get( i ) ) );
+ }
+
+ //add the JFrame to the ApplicationData to allow for user interaction
+ WorkingMemory workingMemory = ruleBase.newStatefulSession();
+ workingMemory.setGlobal( "frame", frame );
+ workingMemory.setGlobal( "textArea", this.output );
+
+ workingMemory.insert( new Product( "Gold Fish", 5 ) );
+ workingMemory.insert( new Product( "Fish Tank", 25 ) );
+ workingMemory.insert( new Product( "Fish Food", 2 ) );
+ workingMemory.insert( new Product( "Fish Food Sample", 0 ) );
+
+ workingMemory.insert( order );
+ workingMemory.fireAllRules();
+
+ //returns the state of the cart
+ return order.toString();
+}
+</programlisting>
+ </example>
+
+ <para>Two items get passed into this method; A handle to the JFrame
+ Swing Component surrounding the output text frame (bottom of the GUI if
+ / when you run the component). The second item is a list of order items;
+ this comes from the TableModel the stores the information from the
+ 'Table' area at the top right section of the GUI.</para>
+
+ <para>The <emphasis role="italic">for()</emphasis> loop transforms the
+ list of order items coming from the GUI into the Order JavaBean (also
+ contained in the PetStore.java file). Note that it would be possible to
+ refer to the Swing dataset directly within the rules, but it is better
+ coding practice to do it this way (using Simple Java Objects). It means
+ that we are not tied to Swing if we wanted to transform the sample into
+ a Web application.</para>
+
+ <para>It is important to note that <emphasis role="bold">all state in
+ this example is stored in the Swing components, and that the rules are
+ effectively stateless. </emphasis>Each time the 'Checkout' button is
+ pressed, this code copies the contents of the Swing
+ <emphasis>TableModel</emphasis> into the Session / Working
+ Memory.</para>
+
+ <para>Within this code, there are nine calls to the working memory. The
+ first of these creates a new workingMemory (statefulSession) from the
+ Rulebase - remember that we passed in this Rulebase when we created the
+ CheckoutCallBack class in the <emphasis role="italic">main()</emphasis>
+ method. The next two calls pass in two objects that we will hold as
+ Global variables in the rules - the Swing text area and Swing frame that
+ we will use for writing messages later.</para>
+
+ <para>More inserts put information on products into the working memory,
+ as well as the order list. The final call is the standard e <emphasis
+ role="italic">fireAllRules()</emphasis>. Next, we look at what this
+ method causes to happen within the Rules file.</para>
+
+ <para>
+ <example>
+ <title>Package, Imports , Globals and Dialect - extract (1) from
+ PetStore.drl</title>
+
+ <programlisting>package org.drools.examples
+
+import org.drools.WorkingMemory
+import org.drools.examples.PetStore.Order
+import org.drools.examples.PetStore.Purchase
+import org.drools.examples.PetStore.Product
+import java.util.ArrayList
+import javax.swing.JOptionPane;
+
+import javax.swing.JFrame
+
+global JFrame frame
+global javax.swing.JTextArea textArea
+
+dialect "mvel"
+</programlisting>
+ </example>
+ </para>
+
+ <para>The first part of the <emphasis
+ role="italic">PetStore.drl</emphasis> file contains the standard package
+ and import statement to make various Java classes available to the
+ rules. We've seen the dialect been defaulted to "mvel" before in other
+ examples. What is new are the two globals <emphasis>frame and textArea.
+ </emphasis>These hold references to the Swing JFrame and Textarea
+ components that were previous passed by the Java code calling the
+ <emphasis>setGlobal() </emphasis>method. Unlike normal variables in
+ Rules , which expire as soon as the rule has fired, Global variables
+ retain their value for the lifetime of the (Stateful in this case)
+ Session.</para>
+
+ <para>The next extract (below) is from the <emphasis
+ role="bold">end</emphasis> of the PetStore.drl file. It contains two
+ functions that are referenced by the rules that we will look at
+ shortly.</para>
+
+ <para>
+ <example>
+ <title>Java Functions in the Rules - extract (2) from
+ PetStore.drl</title>
+
+ <programlisting>function void doCheckout(JFrame frame, WorkingMemory workingMemory) {
+ Object[] options = {"Yes",
+ "No"};
+
+ int n = JOptionPane.showOptionDialog(frame,
+ "Would you like to checkout?",
+ "",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+
+ if (n == 0) {
+ workingMemory.setFocus( "checkout" );
+ }
+}
+
+function boolean requireTank(JFrame frame, WorkingMemory workingMemory, Order order, Product fishTank, int total) {
+ Object[] options = {"Yes",
+ "No"};
+
+ int n = JOptionPane.showOptionDialog(frame,
+ "Would you like to buy a tank for your " + total + " fish?",
+ "Purchase Suggestion",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE,
+ null,
+ options,
+ options[0]);
+
+ System.out.print( "SUGGESTION: Would you like to buy a tank for your "
+ + total + " fish? - " );
+
+ if (n == 0) {
+ Purchase purchase = new Purchase( order, fishTank );
+ workingMemory.insert( purchase );
+ order.addItem( purchase );
+ System.out.println( "Yes" );
+ } else {
+ System.out.println( "No" );
+ }
+ return true;
+}
+</programlisting>
+ </example>
+ </para>
+
+ <para>Having these functions in the rules file makes the PetStore sample
+ more compact - in real life you probably have the functions in a file of
+ their own (within the same rules package), or as a static method on a
+ standard Java class (and import them using the <emphasis
+ role="bold">import function my.package.Foo.hello
+ </emphasis>syntax).</para>
+
+ <para>The above functions are</para>
+
+ <para><itemizedlist>
+ <listitem>
+ <para><emphasis role="italic">doCheckout()</emphasis> - Displays a
+ dialog asking the user if they wish to checkout. If they do, focus
+ is set to the <emphasis role="italic">checkOut</emphasis>
+ agenda-group, allowing rules in that group to (potentially)
+ fire.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="italic">requireTank()</emphasis> - Displays
+ a dialog asking the user if they wish to buy a tank. If so, a new
+ FishTank <emphasis role="italic">Product</emphasis> added to the
+ orderlist in working memory.</para>
+ </listitem>
+ </itemizedlist>We'll see later the rules that call these functions.The
+ next set of examples are from the PetStore rules themselves. The first
+ extract is the one that happens to fire first (partly because it has the
+ <emphasis role="italic">auto-focus</emphasis> attibute set to
+ true).<example>
+ <title>Putting each (individual) item into working memory - extract
+ (3) from PetStore.drl</title>
+
+ <programlisting>// insert each item in the shopping cart into the Working Memory
+rule "Explode Cart"
+ agenda-group "init"
+ auto-focus true
+ salience 10
+ dialect "java"
+when
+ $order : Order( grossTotal == -1 )
+ $item : Purchase() from $order.items
+then
+ insert( $item );
+ drools.setFocus( "show items" );
+ drools.setFocus( "evaluate" );
+end
+
+</programlisting>
+ </example></para>
+
+ <para>This rule matches against all orders that do not yet have an
+ Order.grossTotal calculated . It loops for each purchase item in that
+ order. Some of the <emphasis role="italic">Explode Cart</emphasis> Rule
+ should be familiar ; the rule name, the salience (suggesting of the
+ order that the rules should be fired in) and the dialect set to
+ <emphasis role="italic">java</emphasis>. There are three new
+ items:</para>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para role="bold"><emphasis role="bold">agenda-group "init"
+ </emphasis>- the name of the agenda group. In this case, there is
+ only one rule in the group. However, nothing in Java code / nor a
+ rule sets the focus to this group , so it relies on the next
+ attibute for it's chance to fire.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">auto-focus true - </emphasis>This is
+ the only rule in the sample, so when <emphasis
+ role="italic">fireAllRules()</emphasis> is called from within the
+ Java code, this rule is the first to get a chance to fire.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">drools.setFocus() </emphasis>This sets
+ the focus to the <emphasis role="italic">show items </emphasis>and
+ <emphasis role="italic">evaluate</emphasis> agenda groups in turn
+ , giving their rules a chance to fire. In practice , we loop
+ through all items on the order, inserting them into memory, then
+ firing the other rules after each insert.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>The next two listings shows the rules within the <emphasis
+ role="italic">show items </emphasis>and <emphasis
+ role="italic">evaluate</emphasis> agenda groups. We look at them in the
+ order that they are called.<example>
+ <title>Show Items in the GUI extract (4) from PetStore.drl</title>
+
+ <programlisting>rule "Show Items"
+ agenda-group "show items"
+ dialect "mvel"
+when
+ $order : Order( )
+ $p : Purchase( order == $order )
+then
+ textArea.append( $p.product + "\n");
+end
+
+</programlisting>
+ </example></para>
+
+ <para>The <emphasis role="italic">show items</emphasis> agenda-group has
+ only one rule, also called <emphasis role="italic">Show Items</emphasis>
+ (note the difference in case). For each purchase on the order currently
+ in the working memory (session) it logs details to the text area (at the
+ bottom of the GUI). The <emphasis role="italic">textArea</emphasis>
+ variable used to do this is one of the Global Variables we looked at
+ earlier.</para>
+
+ <para>The <emphasis role="italic">evaluate</emphasis> Agenda group also
+ gains focus from the <emphasis role="italic">explode cart
+ </emphasis>rule above. This Agenda group has two rules (below) <emphasis
+ role="italic">Free Fish Food Sample </emphasis> and <emphasis
+ role="italic">Suggest Tank</emphasis>.</para>
+
+ <para>
+ <example>
+ <title>Evaluate Agenda Group extract (5) from PetStore.drl</title>
+
+ <programlisting>// Free Fish Food sample when we buy a Gold Fish if we haven't already bought
+// Fish Food and dont already have a Fish Food Sample
+rule "Free Fish Food Sample"
+ agenda-group "evaluate"
+ dialect "mvel"
+when
+ $order : Order()
+ not ( $p : Product( name == "Fish Food") && Purchase( product == $p ) )
+ not ( $p : Product( name == "Fish Food Sample") && Purchase( product == $p ) )
+ exists ( $p : Product( name == "Gold Fish") && Purchase( product == $p ) )
+ $fishFoodSample : Product( name == "Fish Food Sample" );
+then
+ System.out.println( "Adding free Fish Food Sample to cart" );
+ purchase = new Purchase($order, $fishFoodSample);
+ insert( purchase );
+ $order.addItem( purchase );
+end
+
+// Suggest a tank if we have bought more than 5 gold fish and dont already have one
+rule "Suggest Tank"
+ agenda-group "evaluate"
+ dialect "java"
+when
+ $order : Order()
+ not ( $p : Product( name == "Fish Tank") && Purchase( product == $p ) )
+ ArrayList( $total : size > 5 ) from collect( Purchase( product.name == "Gold Fish" ) )
+ $fishTank : Product( name == "Fish Tank" )
+then
+ requireTank(frame, drools.getWorkingMemory(), $order, $fishTank, $total);
+end
+
+</programlisting>
+ </example>
+ </para>
+
+ <para>The <emphasis role="italic">Free Fish Food Sample</emphasis> rule
+ will only fire if</para>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>We <emphasis role="italic">don't </emphasis>already have any
+ fish food.</para>
+ </listitem>
+
+ <listitem>
+ <para>We <emphasis role="italic">don't</emphasis> already have a
+ free fish food sample.</para>
+ </listitem>
+
+ <listitem>
+ <para>We <emphasis role="italic">do</emphasis> have a Gold Fish in
+ our order.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If the rule does fire, it creates a new product (Fish Food
+ Sample), and adds it to the Order in working memory.</para>
+
+ <para>The <emphasis role="italic">Suggest Tank</emphasis> rule will only
+ fire if</para>
+
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>We <emphasis role="italic">don't </emphasis>already have a
+ Fish Tank in our order</para>
+ </listitem>
+
+ <listitem>
+ <para>If we <emphasis role="italic">can</emphasis> find more than
+ 5 Gold Fish Products in our order.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If the rule does fire, it calls the <emphasis
+ role="italic">requireTank</emphasis>() function that we looked at
+ earlier (showing a Dialog to the user, and adding a Tank to the order /
+ working memory if confirmed). When calling the <emphasis
+ role="italic">requireTank</emphasis>() function the rule passes the
+ global <emphasis role="italic">frame</emphasis> variable so that the
+ function has a handle to the Swing GUI.</para>
+
+ <para>The next rule we look at is <emphasis role="italic">do
+ checkout.</emphasis><example>
+ <title>Doing the Checkout - extract (6) from PetStore.drl</title>
+
+ <programlisting>rule "do checkout"
+ dialect "java"
+ when
+ then
+ doCheckout(frame, drools.getWorkingMemory());
+end
+
+</programlisting>
+ </example></para>
+
+ <para>The <emphasis role="italic">do checkout</emphasis> rule has
+ <emphasis role="bold">no agenda-group set and no auto-focus
+ attribute</emphasis>. As such, is is deemed part of the default (MAIN)
+ agenda-group - the same as the other non PetStore examples where agenda
+ groups are not used. This group gets focus by default when all the
+ rules/agenda-groups that explicity had focus set to them have run their
+ course.</para>
+
+ <para>There is no LHS to the rule, so the RHS will always call the
+ <emphasis role="italic">doCheckout</emphasis>() function. When calling
+ the <emphasis role="italic">doCheckout</emphasis>() function the rule
+ passes the global <emphasis role="italic">frame</emphasis> variable so
+ the function has a handle to the Swing GUI. As we saw earlier, the
+ <emphasis role="italic">doCheckout</emphasis>() function shows a
+ confirmation dialog to the user. If confirmed, the function sets the
+ focus to the <emphasis role="italic">checkout</emphasis> agenda-group,
+ allowing the next lot of rules to fire.</para>
+
+ <para>
+ <example>
+ <title>Checkout Rules- extract (7) from PetStore.drl</title>
+
+ <programlisting>rule "Gross Total"
+ agenda-group "checkout"
+ dialect "mvel"
+when
+ $order : Order( grossTotal == -1)
+ Number( total : doubleValue ) from accumulate( Purchase( $price : product.price ),
+ sum( $price ) )
+then
+ modify( $order ) { grossTotal = total };
+ textArea.append( "\ngross total=" + total + "\n" );
+end
+
+rule "Apply 5% Discount"
+ agenda-group "checkout"
+dialect "mvel"
+when
+ $order : Order( grossTotal >= 10 && < 20 )
+then
+ $order.discountedTotal = $order.grossTotal * 0.95;
+ textArea.append( "discountedTotal total=" + $order.discountedTotal + "\n" );
+end
+
+
+rule "Apply 10% Discount"
+ agenda-group "checkout"
+dialect "mvel"
+when
+ $order : Order( grossTotal >= 20 )
+then
+ $order.discountedTotal = $order.grossTotal * 0.90;
+ textArea.append( "discountedTotal total=" + $order.discountedTotal + "\n" );
+end
+
+
+
+</programlisting>
+ </example>
+ </para>
+
+ <para>There are three rules in the <emphasis
+ role="italic">checkout</emphasis> agenda-group</para>
+
+ <para><itemizedlist>
+ <listitem>
+ <para><emphasis role="bold">Gross Total </emphasis> - if we
+ haven't already calculated the gross total, accumulates the
+ product prices into a total, puts this total into working memory,
+ and displays it via the Swing TextArea (using the <emphasis
+ role="italic">textArea </emphasis>global variable yet
+ again).</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">Apply 5% Discount</emphasis> - if our
+ gross total is between 10 and 20, then calculate the discounted
+ total and add it to working memory / display in the text
+ area.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">Apply 10% Discount</emphasis> - if our
+ gross total is equal to or greater than 20, calculate the
+ discounted total and add it to working memory / display in the
+ text area.</para>
+ </listitem>
+ </itemizedlist>Now we've run through what happens in the code, lets
+ have a look at what happens when we run the code for real. The <emphasis
+ role="italic">PetStore.java </emphasis>example contains a <emphasis
+ role="italic">main()</emphasis> method, so it can be run as a standard
+ Java application (either from the command line or via the IDE). This
+ assumes you have your classpath set correctly (see the start of the
+ examples section for more information).s.</para>
+
+ <para>The first screen that we see is the Pet Store Demo. It has a List
+ of available products (top left) , an empty list of selected products
+ (top right), checkout and reset buttons (middle) and an empty system
+ messages area (bottom).</para>
+
+ <para><figure>
+ <title>Figure 1 - PetStore Demo just after Launch</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="1-PetStore-Start-Screen.png" />
+ </imageobject>
+ </mediaobject>
+ </figure>To get to this point, the following things have
+ happened:</para>
+
+ <para><orderedlist>
+ <listitem>
+ <para>The <emphasis role="italic">main()</emphasis> method has run
+ and loaded the RuleBase <emphasis role="bold">but not yet fired
+ the rules</emphasis>. This is the only rules related code to run
+ so far.</para>
+ </listitem>
+
+ <listitem>
+ <para>A new <emphasis role="italic">PetStoreUI</emphasis> class is
+ created and given a handle to the RuleBase (for later use).</para>
+ </listitem>
+
+ <listitem>
+ <para>Various Swing Components do their stuff, and the above
+ screen is shown and <emphasis role="bold">waits for user
+ input</emphasis>.</para>
+ </listitem>
+ </orderedlist>Clicking on various products from the list might give
+ you a screen similar to the one below.</para>
+
+ <para><figure>
+ <title>Figure 2 - PetStore Demo with Products Selected</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="2-stock-added-to-order-list.png" />
+ </imageobject>
+ </mediaobject>
+ </figure>Note that <emphasis role="bold">no rules code has been fired
+ here</emphasis>. This is only swing code, listening for the mouse click
+ event, and added the clicked product to the
+ <emphasis>TableModel</emphasis> object for display in the top right hand
+ section (as an aside , this is a classic use of the Model View
+ Controller - MVC - design pattern).</para>
+
+ <para>It is only when we press the <emphasis
+ role="bold">Checkout</emphasis> that we fire our business rules, in
+ roughly the same order that we walked through the code earlier.</para>
+
+ <para>
+ <orderedlist>
+ <listitem>
+ <para>The <emphasis
+ role="italic">CheckOutCallBack.checkout()</emphasis> method is
+ called (eventually) by the Swing class waiting for the click on
+ the checkout button. This inserts the data from the
+ <emphasis>TableModel</emphasis> object (top right hand side of the
+ GUI), and handles from the GUI into the session / working memory.
+ It then fires the rules.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <emphasis role="italic">Explode Cart</emphasis> rule is
+ the first to fire, given that has <emphasis
+ role="italic">auto-focus </emphasis>set to true. It loops through
+ all the products in the cart, makes sure the products are in the
+ working memory, then gives the <emphasis role="italic">Show
+ Items</emphasis> and <emphasis role="italic">Evaluation</emphasis>
+ agenda groups a chance to fire. The rules in these groups, add the
+ contents of the cart to the text area (bottom), decide whether or
+ not to give us free fish food and whether to ask if we want to buy
+ a fish tank (Figure 3 below).</para>
+ </listitem>
+ </orderedlist>
+
+ <figure>
+ <title>Figure 3 - Do we want to buy a fish tank?</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="3-purchase-suggestion.png" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <orderedlist>
+ <listitem>
+ <para>The <emphasis role="italic">Do Checkout</emphasis> rule is
+ the next to fire as it (a) No other agenda group currently has
+ focus and (b) it is part of the default (MAIN) agenda group. It
+ always calls the<emphasis role="italic"> doCheckout() function
+ </emphasis>which displays a 'Would you like to Checkout?' Dialog
+ Box.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <emphasis role="italic">doCheckout() function</emphasis>
+ sets the focus to the <emphasis role="italic">checkout
+ </emphasis>agenda-group, giving the rules in that group the option
+ to fire.</para>
+ </listitem>
+
+ <listitem>
+ <para>The rules in the the <emphasis
+ role="italic">checkout</emphasis> agenda-group, display the
+ contents of the cart and apply the appropriate discount.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis role="bold">Swing then waits for user
+ input</emphasis> to either checkout more products (and to cause
+ the rules to fire again) or to close the GUI - Figure 4
+ below.</para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ <figure>
+ <title>Figure 4 - Petstore Demo after all rules have fired.</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="4-Petstore-final-screen.png" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+ </para>
+
+ <para>Should we choose, we could add more System.out calls to
+ demonstrate this flow of events. The current output of the console fo
+ the above sample is as per the listing below.</para>
+
+ <para>
+ <example>
+ <title>Console (System.out) from running the PetStore GUI</title>
+
+ <programlisting>Adding free Fish Food Sample to cart
+SUGGESTION: Would you like to buy a tank for your 6 fish? - Yes
+
+</programlisting>
+ </example>
+ </para>
+
+ <para>Todo : Add Audit and Agenda Views for this sample.</para>
+ </section>
</section>
<section>
More information about the jboss-svn-commits
mailing list