From: <jbo...@li...> - 2006-05-24 08:40:37
|
Author: mic...@jb... Date: 2006-05-24 04:40:11 -0400 (Wed, 24 May 2006) New Revision: 4400 Added: labs/jbossrules/trunk/documentation/training/developers-course/Module 6 - rule formats.odp labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Approve.java labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/launcher/PolicyApprovalLauncher.java labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme.dsl labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approval.drl labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/archive/ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/archive/raw.drl labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/technical.drl Removed: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme_insure.dsl labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approve.drl labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/raw.drl Modified: labs/jbossrules/trunk/documentation/training/developers-course/course_outline.odt labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/Instructions.txt labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Policy.java labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Rejection.java Log: lab 4 finished Added: labs/jbossrules/trunk/documentation/training/developers-course/Module 6 - rule formats.odp =================================================================== (Binary files differ) Property changes on: labs/jbossrules/trunk/documentation/training/developers-course/Module 6 - rule formats.odp ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: labs/jbossrules/trunk/documentation/training/developers-course/course_outline.odt =================================================================== (Binary files differ) Modified: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/Instructions.txt =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/Instructions.txt 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/Instructions.txt 2006-05-24 08:40:11 UTC (rev 4400) @@ -5,6 +5,7 @@ Instructions: This excercise is a self contained Eclipse project. + There are 2 parts, decision tables, and DSLs. FOR DECISION TABLES: @@ -34,19 +35,41 @@ techie folk to edit in relative safety. (http://support.microsoft.com/?kbid=214081) - - NOTE: when you make a change to the spreadsheet, you will need to refresh the eclipse project to pick up the latest (of course, if you change it to load direct from a file system, not the classpath, then you won't need to do this). DSLs: - Step 11: + Step 11: Locate the src/rules/approval package. Open the approval rules. + Step 12: Locate the PolicyApprovalLauncher class. + Step 13: Run the PolicyApprovalLauncher class as a java application, note the console output. + Step 14: open the acme.dsl and examine the mappings for the domain language. + Add a mapping for the "then" section to log some debug message. + Open the approval.drl and add the log expression to a rule that you think + will fire. Then re-run the launcher. + Step 15: Modify or add a constraint to a rule, re-launch and observe + Step 16: open the technical.drl file, and change APPROVAL or REJECTED messages. Relaunch. + Step 17: Right click on the .dsl file, and open as a text file, note the format of the mappings. + Step 18: Open the approval.drl file, make a "typo" and save, observe an error showing up on the appropriate line + (errors may be parse errors, or an "expand" error). + Step 18: (optional) - store rules from approval in seperate files. Modify the launcher to load them all up from + the seperate files. + Step 19: (optional - advanced) - note the way that multiple patterns + are added to the "d : Driver(..)" construct. + Discuss alternative ways, perhaps more mappings for combinations + that capture all constraints on a line. + + Add a mapping like: "Set Driver to 'd'" which will simply + bind a Driver instance to a "d" variable. + Then add mappings to add constraints in the form of + "eval( /* java code with 'd' */)" - this is less efficient + but can provide more flexibility. + Step 20: Open the archive/raw.drl file, to see what the rules would look like + without a DSL. Note the use of little facts like "Approve" and "Rejection" + to control the behaviour. - - Pre-requisites: Eclipse 3.2 must be installed JBoss Rules plug in installed into Eclipse Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Approve.java =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Approve.java 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Approve.java 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,24 @@ +package org.acme.insurance; + +/** + * This is a simple fact class to mark something as approved. + * @author Michael Neale + * + */ +public class Approve { + + private String reason; + + public Approve(String reason) { + this.reason = reason; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + +} Property changes on: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Approve.java ___________________________________________________________________ Name: svn:eol-style + native Modified: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Policy.java =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Policy.java 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Policy.java 2006-05-24 08:40:11 UTC (rev 4400) @@ -11,7 +11,7 @@ public class Policy { private String type = "COMPREHENSIVE"; - private boolean approved = true; + private boolean approved = false; private int discountPercent = 0; private int basePrice; Modified: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Rejection.java =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Rejection.java 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/Rejection.java 2006-05-24 08:40:11 UTC (rev 4400) @@ -1,5 +1,9 @@ package org.acme.insurance; +/** + * + * @author Michael Neale + */ public class Rejection { private String reason; Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/launcher/PolicyApprovalLauncher.java =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/launcher/PolicyApprovalLauncher.java 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/launcher/PolicyApprovalLauncher.java 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,147 @@ +package org.acme.insurance.launcher; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +import org.acme.insurance.Driver; +import org.acme.insurance.Policy; +import org.drools.RuleBase; +import org.drools.RuleBaseFactory; +import org.drools.WorkingMemory; +import org.drools.compiler.DroolsParserException; +import org.drools.compiler.PackageBuilder; + +/** + * Sample file for launching rules with a DSL. + * @author Michael Neale + */ +public class PolicyApprovalLauncher { + + public static void main(String[] args) throws Exception { + PolicyApprovalLauncher launcher = new PolicyApprovalLauncher(); + launcher.executeExample(); + } + + private void executeExample() throws Exception { + + RuleBase ruleBase = loadRuleBase(); + + testUnsafeDriver(ruleBase); + testSafeMature(ruleBase); + testUnsafeAreaAndPriors(ruleBase); + + } + + /** + * This shows how rules are loaded up from multiple files. + * Some are technical, and some are DSL based. + */ + private RuleBase loadRuleBase() throws DroolsParserException, IOException, Exception { + PackageBuilder builder = new PackageBuilder(); + + //this loads the DSL business rules + builder.addPackageFromDrl(getMainRules(), getDSL()); + + //loads the technical rules + builder.addPackageFromDrl(getTechnicalRules()); + + //package it all up + RuleBase ruleBase = RuleBaseFactory.newRuleBase(); + ruleBase.addPackage(builder.getPackage()); + return ruleBase; + + //note there is a utlity class called + //'RuleBaseLoader' which can do the above in one hit, but only + //for 1 file per rulebase. + } + + + /////////////////////////////////////////////////// + // The trial scenarios follow below + /////////////////////////////////////////////////// + + + private void testUnsafeDriver(RuleBase ruleBase) { + WorkingMemory wm = ruleBase.newWorkingMemory(); + + Driver driver = new Driver(); + driver.setPriorClaims(new Integer(4)); + Policy policy = new Policy(); + policy.setType("COMPREHENSIVE"); + policy.setApproved(false); + + wm.assertObject(driver); + wm.assertObject(policy); + + wm.fireAllRules(); + + System.out.println("Policy approved: " + policy.isApproved()); + } + + private void testSafeMature(RuleBase ruleBase) { + WorkingMemory wm = ruleBase.newWorkingMemory(); + + Driver driver = new Driver(); + driver.setPriorClaims(new Integer(0)); + driver.setAge(new Integer(45)); + + Policy policy = new Policy(); + policy.setType("COMPREHENSIVE"); + policy.setApproved(false); + + wm.assertObject(driver); + wm.assertObject(policy); + + wm.fireAllRules(); + + System.out.println("Policy approved: " + policy.isApproved()); + } + + private void testUnsafeAreaAndPriors(RuleBase ruleBase) { + WorkingMemory wm = ruleBase.newWorkingMemory(); + + Driver driver = new Driver(); + driver.setPriorClaims(new Integer(2)); + driver.setAge(new Integer(22)); + driver.setLocationRiskProfile("MED"); + + Policy policy = new Policy(); + policy.setType("COMPREHENSIVE"); + policy.setApproved(false); + + wm.assertObject(driver); + wm.assertObject(policy); + + wm.fireAllRules(); + + System.out.println("Policy approved: " + policy.isApproved()); + } + + + //////////////////////////////////////////////////////////// + // Loading from classpath, for convenience. + // Feel free to change it to the file system if you like. + //////////////////////////////////////////////////////////// + + private Reader getMainRules() { + InputStream stream = this.getClass() + .getResourceAsStream("/approval/approval.drl"); + return new InputStreamReader(stream); + } + + private Reader getTechnicalRules() { + InputStream stream = this.getClass() + .getResourceAsStream("/approval/technical.drl"); + return new InputStreamReader(stream); + } + + private Reader getDSL() { + InputStream stream = this.getClass() + .getResourceAsStream("/approval/acme.dsl"); + return new InputStreamReader(stream); + } + + +} Property changes on: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/java/org/acme/insurance/launcher/PolicyApprovalLauncher.java ___________________________________________________________________ Name: svn:eol-style + native Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme.dsl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme.dsl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme.dsl 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,13 @@ +#ACME Discount insurance rule language +[then]Log "{message}"=System.out.println("{message}"); +[when]The Driver is less than {age} years old=d : Driver(age < {age}) +[when]The Driver is greater than {age} years old=d : Driver(age > {age}) +[when]The Driver has had more than {prior} prior claims=d : Driver(priorClaims > {prior}) +[when]The Policy type is '{type}'=Policy(type == "{type}") +[then]Reject the policy with explanation : '{reason}'=assert(new Rejection("{reason}")); +[when]The Driver has a location risk profile of '{risk}'=d : Driver(locationRiskProfile == "{risk}") +[when]The Driver has an age of at least {age}=d : Driver(age >= {age}) +[when]The Driver is between {lower} and {upper} years old=d : Driver(age >= {lower}, age <= {upper}) +[when]Policy has not been rejected=not Rejection() +[when]Driver has had {number} prior claims=d : Driver(priorClaims == {number}) +[then]Approve the policy with the reason : '{reason}'=assert(new Approve("{reason}")); Property changes on: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme.dsl ___________________________________________________________________ Name: svn:eol-style + native Deleted: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme_insure.dsl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme_insure.dsl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/acme_insure.dsl 2006-05-24 08:40:11 UTC (rev 4400) @@ -1,4 +0,0 @@ -#place your comments here - this is just a description for your own purposes. -[when]There is a Person with name of "{name}"=Person(name=="{name}") -[when]Person is at least {age} years old and lives in "{location}"=Person(age > {age}, location=="{location}") -[then]Log "{message}"=System.out.println("{message}"); Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approval.drl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approval.drl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approval.drl 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,82 @@ +#created on: 23/05/2006 +package org.acme.insurance +expander acme.dsl + +# +# These rules are mostly "negative" in the sense that +# a driver has to not be rejected. There is +# one rule that allows immediate approval however. +# + +rule "Driver has had too many accidents" + + when + The Driver has had more than 3 prior claims + then + Reject the policy with explanation : 'Too many accidents' + +end + +rule "Driver is underage" + + when + The Driver is less than 18 years old + then + Reject the policy with explanation : 'Driver is underage. Try another insurer' + +end + +rule "Driver is in marginal age" + #remember, don't leave any blank lines in between expressions + when + The Driver is between 18 and 24 years old + The Driver has had more than 1 prior claims + The Policy type is 'COMPREHENSIVE' + then + Reject the policy with explanation : 'No accidents allowed if in marginal age group' +end + +rule "Driver in unsafe area for marginal age" + when + The Policy type is 'COMPREHENSIVE' + The Driver is less than 25 years old + The Driver has a location risk profile of 'HIGH' + then + Reject the policy with explanation : 'Marginal age driver in high risk area' +end + +rule "Driver in unsafe area with priors" + when + The Driver has a location risk profile of 'MED' + The Policy type is 'COMPREHENSIVE' + The Driver is less than 25 years old + The Driver has had more than 1 prior claims + then + Reject the policy with explanation : 'Driver in that area is too risky - given past accidents and age.' +end + +rule "Driver unsafe for third party" + when + The Policy type is 'THIRD_PARTY' + The Driver has had more than 2 prior claims + then + Reject the policy with explanation : 'Too many priors for third party' +end + +rule "Driver in bad area for theft" + when + The Policy type is 'FIRE_THEFT' + The Driver has a location risk profile of 'HIGH' + then + Reject the policy with explanation : 'Unsafe area for theft' +end + +rule "Quick approval - safe driver, any policy type" + when + Policy has not been rejected + The Driver has an age of at least 30 + Driver has had 0 prior claims + then + Approve the policy with the reason : 'Driver is safe and mature.' +end + Deleted: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approve.drl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approve.drl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/approve.drl 2006-05-24 08:40:11 UTC (rev 4400) @@ -1,23 +0,0 @@ -#created on: 23/05/2006 -package org.acme.insurance - -expander acme_insure.dsl - - -rule "Your First Rule" - - when - #conditions - then - #actions - -end - -rule "Your Second Rule" - #include attributes such as "salience" here... - when - #conditions - then - #actions - -end Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/archive/raw.drl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/archive/raw.drl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/archive/raw.drl 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,107 @@ +#created on: 23/05/2006 +package org.acme.insurance + + +rule "Driver underage" + + when + Driver(age < 18) + then + assert(new Rejection("Driver is underage")); + +end + +rule "Driver in marginal age bracket" + when + Driver(age > 18, age < 25, priorClaims > 1) + Policy(type == "COMPREHENSIVE") + then + assert(new Rejection("No accidents accepted if in marginal age group")); +end + +rule "Driver unsafe - accident history" + when + Driver(priorClaims > 3) + then + assert(new Rejection("Too many accidents")); +end + +rule "Driver in unsafe area for comprehensive" + when + d: Driver(locationRiskProfile == "HIGH") + d: Driver(age < 25) + Policy(type == "COMPREHENSIVE") + then + assert(new Rejection("Driver in that area is too risky")); +end + +rule "Driver in unsafe area for comprehensive and priors" + when + d : Driver(locationRiskProfile == "MED") + d : Driver(priorClaims > 1) + d : Driver(age < 25) + Policy(type == "COMPREHENSIVE") + then + assert(new Rejection("Driver in that area is too risky - given past accidents and age.")); +end + +rule "Driver unsafe for third party" + when + Policy(type == "THIRD_PARTY") + Driver(priorClaims > 2) + then + assert(new Rejection("Too many priors for third party")); +end + +rule "Driver in bad area for theft" + + when + Policy(type == "FIRE_THEFT") + d : Driver(locationRiskProfile == "HIGH") + then + assert(new Rejection("Unsafe area for theft")); +end + +rule "Quick approval - safe driver, any policy type" + when + not Rejection() + d: Driver(age >= 30) + d: Driver(priorClaims == 0) + then + assert(new Approve("Driver is safe, and mature")); +end + +rule "Approve policy affirmative" + salience 100 #this can short circuit any processing + when + a : Approve() + p : Policy() + then + p.setApproved(true); + System.out.println("APPROVED: " + + a.getReason()); + drools.clearAgenda(); #stop processing (bit of a hack ;) +end + +rule "Approve if not rejected" + salience -100 #approve if there are no objections + when + not Rejection() + p : Policy(approved == false) + then + System.out.println("APPROVED: due to no objections."); + p.setApproved(true); +end + +rule "Reject application" + salience 100 #this can short circuit any other processing + when + r : Rejection() + d : Driver() + p : Policy() + then + System.out.println("REJECTED: " + r.getReason()); + p.setApproved(false); + retract(d); +end + Deleted: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/raw.drl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/raw.drl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/raw.drl 2006-05-24 08:40:11 UTC (rev 4400) @@ -1,67 +0,0 @@ -#created on: 23/05/2006 -package org.acme.insurance - - -rule "Driver underage" - - when - Driver(age < 18) - then - assert(new Rejection("Driver is underage")); - -end - -rule "Driver in margina age bracket" - when - Driver(age > 18, age < 25, priorClaims > 1) - Policy(type == "COMPREHENSIVE") - then - assert(new Rejection("No accidents accepted if in marginal age group")); -end - -rule "Driver unsafe" - when - Driver(priorClaims > 3) - then - assert(new Rejection("Too many accidents")); -end - -rule "Driver in unsafe area for comprehensive" - when - Policy(type == "COMPREHENSIVE") - Driver(locationRiskProfile == "HIGH") - or - Driver(locationRiskProfile == "MED", priorClaims > 2) - - then - assert(new Rejection("Driver in that area is too risky")); -end - -rule "Driver unsafe for third party" - when - Policy(type == "THIRD_PARTY") - Driver(priorClaims > 2) - then - assert(new Rejection("Too many priors for third party")); -end - -rule "Driver in bad area for theft" - - when - Policy(type == "FIRE_THEFT") - d : Driver(locationRiskProfile == "HIGH") - then - assert(new Rejection("Unsafe area for theft")); -end - -rule "Handle Reject of application" - - when - r : Rejection() - d : Driver() - then - #may also notify at this point, send an email etc - retract(d); - #call some utility or a method on "d" -end - Added: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/technical.drl =================================================================== --- labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/technical.drl 2006-05-24 08:38:59 UTC (rev 4399) +++ labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/technical.drl 2006-05-24 08:40:11 UTC (rev 4400) @@ -0,0 +1,44 @@ +package org.acme.insurance + +#NOTE: This is designed to be used +# with the approval.drl rules. This +# just shows how you can span files, and keep +# technical rules, like the ones below, seperate. +# +# The rules below handle updating of the approval status, +# and controlling the operation of the rules using salience (priority) + + +rule "Approve policy affirmative" + salience 100 #this can short circuit any processing + when + a : Approve() + p : Policy() + then + p.setApproved(true); + System.out.println("APPROVED: " + + a.getReason()); + drools.clearAgenda(); #stop processing (bit of a hack ;) +end + +rule "Approve if not rejected" + salience -100 #approve if there are no objections + when + not Rejection() + p : Policy(approved == false) + then + System.out.println("APPROVED: due to no objections."); + p.setApproved(true); +end + +rule "Reject application" + salience 100 #this can short circuit any other processing + when + r : Rejection() + d : Driver() + p : Policy() + then + System.out.println("REJECTED: " + r.getReason()); + p.setApproved(false); + retract(d); #effectively halts the rules +end Property changes on: labs/jbossrules/trunk/documentation/training/developers-course/lab-4-rule-formats/src/rules/approval/technical.drl ___________________________________________________________________ Name: svn:eol-style + native |