|
Rule Project "ExternalRulesFromXML"
Step 1.
Setting Up Rule Templates
Step 2. Defining Rule
Tables in XML
Step 3. Reading XML rules
in Java
Step
4. Creating and Executing Rules from a Java Program
OpenRules allows you to keep your business rules in
XML files that correspond to the columns
(conditions and actions) of Excel's templates based on which the proper
rule tables will be executed. While you may use any XML processing
software, this sample project demonstrate how to use a simple XML
interface provided by OpenRules.This project intends to produce
greetings like "Good Morning, Mrs. Robinson!" based on the current time
and different customer's attributes such as gender and marital status.
In a way it is similar to the standard project "HelloJavaTemplates" but
instead of using Excel-based rule tables it is using XML-based rule
tables.
Step 1. Setting Up Rule
Templates
►top
The business logic for producing greetings and
salutations is presented in the Excel file HelloTemplates.xls. The first
template
| Rules void defineGreeting(App
app, int hour) |
| C1 |
C2 |
A1 |
| min <= hour |
hour <= max |
app.greeting = greeting; |
| int min |
int max |
String greeting |
| Hour From |
Hour To |
Set Greeting |
| |
|
Unknown Greeting |
specifies how to define different greetings (Good
Morning, Good Afternoon, etc.) based on the hour of the day. If the
parameter "hour" belongs to the interval [min;max] defined by a concrete
rule then the attribute "greeting" of the parameter "app" will be set to
the proper greeting. If no rules are satisfied, this multi-hit table
will use the default greeting "Unknown Greeting".
The second template
| Rules void defineSalutation(App
app, Customer c) |
| C1 |
C2 |
C3 |
A1 |
| c.gender.equals(gender) |
c.maritalStatus.equals(status) |
c.age < age |
app.salutation = salutation; |
| String gender |
String status |
int age |
String salutation |
| Gender |
Marital Status |
Age Less Than |
Set Salutation |
| |
|
|
Unknown Salutation |
specifies how to define different salutations (Mr.,
Mrs., etc.) based on customer attributes Gender, Marital Status, and
Age. If no rules are satisfied, this multi-hit table will use the
default salutation "Unknown Salutation".
Step 2.
Defining Rule Tables in XML ►top
You may create a subdirectory "xml" in the directory
"rules" and place different xml-files into it. The first file
"GreetingRules.xml" defines a rule table with the name "greetingRules"
that will be based on the template with the name "defineGreeting":
<?xml version="1.0" encoding="UTF-8"?>
<GreetingRules ruleTableName="greetingRules" templateName="defineGreeting" type="Array of Rule(s)">
<Rule from="0" to="11" greeting="Good Morning" />
<Rule from="12" to="16" greeting="Good Afternoon" />
<Rule from="17" to="21" greeting="Good Evening" />
<Rule from="22" to="24" greeting="Good Night" />
</GreetingRules> |
Similarly we create the second file "SalutationRules.xml":
<?xml version="1.0" encoding="UTF-8"?>
<SalutationRules ruleTableName="salutationRules" templateName="defineSalutation">
<Rule
gender="Female"
maritalStatus="Married"
salutation="Mrs."
/>
<Rule
gender="Female"
maritalStatus="Single"
salutation="Ms."
/>
<Rule
gender="Male"
maritalStatus=""
salutation="Mr."
/>
<Rule
gender="Male"
maritalStatus="Single"
maxAge="5"
salutation="Little"
/>
</SalutationRules>
|
Please note that the last rule contains an extra
attribute "maxAge". OpenRules does not require any specification of the
XML document and will dynamically recognize its structure.
Step 3. Reading XML
rules in Java
►top
To inform an OpenRulesEngine about external rules, you
to create an object of the type ExternalRules and add to it all external
RuleTables. Each instance of the class RuleTable consists of:
- rule table name (String)
- template name (String)
- a grid of objects that represent the content of a
rule tables (Object[][])
In this project, we will create an instance of the class
External Rules directly in the Excel method "getExternalRules":
| Method ExternalRules createExternalRules() |
ExternalRules externalRules = new ExternalRules();
addGreetingRules(externalRules);
addSalutationRules(externalRules);
return externalRules; |
This method will execute two other methods "addGreetingRules"
and "addSalutationRules" that will read the above xml-files and will add
the proper rule tables to the newly create ExternalRules object.
Before reading the xml files we have to specify the
proper xml schemas in the Environment table placed in the main Excel
file HelloXMLRules.xls:
| Environment |
| import.java |
com.openrules.table.external.Objects |
| import.schema |
file:rules/xml/GreetingRules.xml |
| file:rules/xml/SalutationRules.xml |
OpenRules dynamically defines the Java classes
GreetingRules and SalutationRules that will be used to read the
proper XML files.
Now we may specify the method "addGreetingRules":
| Method ExternalRules addGreetingRules(ExternalRules
externalRules) |
GreetingRules greetings = GreetingRules.load("file:rules/xml/GreetingRules.xml");
Objects[] grid = new Objects[greetings.Rule.length];
for(int i = 0; i < greetings.Rule.length; ++i) {
GreetingRules.Rule r = greetings.Rule[i];
Objects row = new Objects(3);
row.set(0,r.from); row.set(1,r.to); row.set(2,r.greeting);
grid[i] = row;
}
externalRules.addRuleTable(greetings.ruleTableName,
greetings.templateName, grid ); |
First we load the rules from the xml-file defining its
relative path using the standard OpenRules URL notation:
file:rules/xml/GreetingRules.xml
All objects specified in the file GreetingRules.xml
becomes available to the Java code through the object "greetings" of the
dynamically defined type GreetingRules. In particular, the object
"greetings.Rule" points to the array of objects of the dynamic type
"Rule" as it was defined in the xml-file.
Then we create a "grid" as an array of the predefined
type Objects that is used by OpenRules to simplify handling of
multi-dimensional array. Looping through all elements of the array
greetings.Rules we are adding new rows to the object "grid". Data
elements inside each rule are available through their names defined in
the xml-file: r.from, r.to, r.greeting.
Similarly we specify the method "addSalutationRules":
| Method ExternalRules addSalutationRules(ExternalRules
externalRules) |
SalutationRules salutations = SalutationRules.load("file:rules/xml/SalutationRules.xml");
Objects[] grid = new Objects[salutations.Rule.length];
for(int i = 0; i < salutations.Rule.length; ++i) {
SalutationRules.Rule r = salutations.Rule[i];
Objects row = new Objects(4);
row.set(0,r.gender); row.set(1,r.maritalStatus);
row.set(2,r.maxAge); row.set(3,r.salutation);
grid[i] = row;
}
externalRules.addRuleTable(salutations.ruleTableName,
salutations.templateName, grid ); |
Step 4. Creating and Executing Rules from a Java Program
►top
All other modules are typical for basic rule projects.
The main Java file RunExternalRulesFromXML.java is used to test the
above
rules:
import com.openrules.ruleengine.ExternalRules;
import com.openrules.ruleengine.OpenRulesEngine;
public class RunExternalRulesFromXML {
public static void main(String[] args)
{
// The first engine reads XML-based rules described at HelloXMLRules.xls
String xlsMainData = "file:rules/main/HelloXMLRules.xls";
OpenRulesEngine engine1 = new OpenRulesEngine(xlsMainData);
ExternalRules externalRules = (ExternalRules) engine1.run("createExternalRules");
// Print External Rules
for (int i = 0; i < externalRules.getRuleTables().size(); i++) {
System.out.println(externalRules.getRuleTables().get(i));
}
// The second engine reads test data and execute external rules created by the first engine
String fileName = "file:rules/main/HelloCustomer.xls";
OpenRulesEngine engine2 = new OpenRulesEngine(fileName,externalRules);
App app = (App) engine2.run("getDefaultApplication");
engine2.run("generateGreeting",app);
System.out.println("\nGenerated Greeting:");
System.out.println(app.getResult());
}
}
|
The first instance 'engine1" of the class OpenRulesEngine
is based on
the main Excel-file HelloXMLRules.xls. We execute the method "createExternalRules"
to create external rules from the xml files:
ExternalRules externalRules = (ExternalRules) engine1.run("createExternalRules");
The secondn instance "engine2" of the OpenRulesEngine
is using
the main Excel-file HelloCustomer.xls and newly created external rules:
OpenRulesEngine engine2 = new OpenRulesEngine(fileName,externalRules);
The main file HelloCustomer.xls defines the
Environment as follows:
| Environment |
| import.java |
hello.* |
| import.static |
com.openrules.tools.Methods |
| include |
../include/HelloTemplates.xls |
| include |
../include/HelloData.xls |
This application uses two simple Java beans:
Customer.java:
String name;
String
maritalStatus;
String gender;
int
age;
App.java:
Customer
customer;
String
greeting;
String
salutation;
String result;
The proper instance of the Customer and App are
created based on the Excel file HelloData.xls using these data tables:
| Data App apps |
| customer.name |
customer.maritalStatus |
customer.gender |
customer.age |
| Customer Name |
Marital Status |
Gender |
Age |
| Robinson |
Married |
Female |
24 |
| Smith |
Single |
Male |
19 |
|
|
|
|
|
|
|
|
| Method App getDefaultApplication() |
|
| return apps[0]; |
|
And finally, the engine2 will execute rules by calling
the method "run":
engine2.run("generateGreeting",app);
The proper method "generateGreeting" is described in
the file HelloCustomer.xls in the following table:
| Method void generateGreeting(App app) |
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
greetingRules(app, hour);
salutationRules(app, app.customer);
app.result = app.greeting + ", " + app.salutation + " " +
app.customer.name + "!";
|
You may validate the entire rule project by
double-clicking on the file "compile.bat". Because the actual
external rule tables "greetingRules" and "salutationRules" will become
known only in run-time the proper OpenRules validator may produce errors
(warnings) about unknown rule tables. You may ignore these errors or you
may explicitly inform OpenRules about this fact by adding an optional
table to the file HelloCustomer.xls:
| ExternalRules |
| greetingRules |
defineGreeting |
| salutationRules |
defineSalutation |
To run the project you may double-click on the file "run.bat".
Here is an expected output:
INITIALIZE OPENRULES ENGINE 5.3.0 (build 03092009) for [file:rules/main/HelloXMLRules.xls]
IMPORT.JAVA=com.openrules.table.external.Objects
IMPORT.SCHEMA=file:rules/xml/GreetingRules.xml
IMPORT.SCHEMA=file:rules/xml/SalutationRules.xml
ExternalRules greetingRules template defineGreeting
0 11 Good Morning
12 16 Good Afternoon
17 21 Good Evening
22 24 Good Night
ExternalRules salutationRules template defineSalutation
Female Married null Mrs.
Female Single null Ms.
Male null Mr.
Male Single 5 Little
INITIALIZE OPENRULES ENGINE 5.3.0 (build 03092009) for [file:rules/main/HelloCustomer.xls]
External rules table: greetingRules
External rules table: salutationRules
IMPORT.JAVA=hello.*
IMPORT.JAVA=com.openrules.tools.Operator
IMPORT.STATIC=com.openrules.tools.Methods
INCLUDE=../include/HelloTemplates.xls
[../include/HelloTemplates.xls] has been resolved to [file:<..>/ExternalRulesFromXML/rules/include/HelloTemplates.xls]
INCLUDE=../include/HelloData.xls
[../include/HelloData.xls] has been resolved to [file:<..>/ExternalRulesFromXML/rules/include/HelloData.xls]
Generated Greeting:
Good Afternoon, Mrs. Robinson!
|
►top
|