| The OpenRulesTM Tutorials Home |
|
User's Guide |
Decision Tables
OpenRules supports several ways to represent business rules inside Excel tables. A decision table is the most popular way to present sets of related business rules. Decision tables are used to describe and analyze decision situations, where the state of a number of conditions determines the execution of a set of actions. OpenRules allows a user to configure different types of decision tables directly in Excel. The user also may use simple IF-THEN-ELSE statements to describe rules logic inside tables of type "Method".
Introducing Simple Rules Table ►top
Let's consider a simple set of HelloWorld rules that can be used to generate a string like "Good Morning, World!" based on the actual time of the day. How one understands such concepts as "morning", "afternoon", "evening", and "night" is defined in this simple decision table:
Hopefully, this decision table is self explanatory. It states that if the current hour is between 0 and 11, the greeting should be "Good Morning", etc. You may change Hour From or Hour To if you want to customize the definition of "morning" or "evening". This decision table is oriented to a business user. However, its first row already includes some technical information (a table signature):
Rules void helloWorld(int hour)
Here "Rules" is the OpenRules keyword to recognize a table type as a decision table; "helloWorld" is a name of this particular decision table. It tells an external program or other rules how to launch this rule table. Actually, this is a typical description of a programming method (its signature) that has one integer parameter and returns nothing (the type "void"). The integer parameter "hour" is expected to contain the current time of the day. While you always can hide this information from a business user, it is an important specification of this decision table.
You may wonder where is the implementation logic for this decision table? All decision tables include additional hidden rows (usually password protected) that you can see if you click on the buttons "+" or open the Technical view. For example, click on the button "+" in the opened HelloWorld.xls file, and you will see the following additional rows:
This part of the rule table is oriented to a technical user, who is not expected to be a programming guru but rather a person with a basic knowledge of the "C" family of languages which includes Java. Let's walk through these rows step by step:
The Row "Condition and Action Headers" (see row 4 in the table above). The initial columns with conditions should start with the letter "C", for example "C1", "Condition 1". The columns with actions should start with the letter "A", for example "A1", "Action 1".
The Row "Code" (see row 5 in the table above). The cells in this row specify the semantics of the condition or action associated with the corresponding columns. For example, the cell B5 contains the code min <= hour. This means that condition C1 will be true whenever the value for min in any cell in the column below in this row is less than or equals to the parameter hour. If hour is 15, then the C1-conditions from rows 8 and 9 will be satisfied. The code in the Action-columns defines what should be done when all conditions are satisfied. For example, cell D5 contains the code: System.out.println(greeting + ", World!"). This code will print a string composed of the variable greeting and ", World!", where greeting will be chosen from a row where all conditions are satisfied. Again, if hour is 15, then both conditions C1 and C2 will be satisfied only for row 9 (because 9 <= 15 <= 17). As a result, the words "Good Afternoon, World!" will be printed. If the rules table does not contain a row where all conditions have been satisfied, then no actions will be executed. Such a situation can be diagnosed automatically.
The Row "Parameters" (see row 6 in the table above). The cells in this row specify the types and names of the parameter used in the previous row.
The Row "Display Values" (see row 7 in the table above). The cells in this row contain a natural language description of the column content.
The same table can be defined a little bit differently using one condition code for both columns "min" and "max":
![]()
How Decision Tables Are Organized [T] ►top
As you have seen in the previous section, decision tables have the following structure:
Row # Content Description 1 Signature Rules void tableName(Type1 par1, Type2 par2, ..) - Multi-Hit Rules Table
Rules <JavaClass> tableName(Type1 par1, Type2 par2, ..) - Single-Hit Rules Table2 Condition/Action Indicators The condition column indicator is a word starting with “C”.
The action column indicator is a word starting with “A”.
All other starting characters are ignored and the whole column is considered as a comment3 Code The cells in each column (or merged cells for several columns) contain Java Snippets in the language defined in the table Environment (the default language configuration is openrules.java).
Condition codes should contain expressions that return Boolean values..
If an action code contains any correct Java snippet, the return type is irrelevant.4 Parameters Each condition/action may have from 0 to N parameters. Usually there is only one parameter description and it consists of two words:
parameterType parameterName (for example: int min)
parameterName is a standard one word name that corresponds to Java identification rules.
parameterType can be represented using the following Java types:
- Basic Java types: boolean, char, int, long, double, String, Date
- Standard Java classes: java.lang.Boolean, java.lang.Integer, java.lang.Long, java.lang.Double, java.lang.Character, java.lang.String, java.util.Date
- Any custom Java class with a public constructor that has a String parameter
- One-dimensional arrays of the above types. Multiple parameters can be used in the situations when one code is used for several columns. See the standard example Loan1.xls
5 Columns Display Values Text is used to give the column a definition that would be meaningful to another reader (there are no restrictions on what text may be used) 6 and below Rules with concrete values in cells Cells in these rows usually contain literals that correspond to the parameter types.
For Boolean parameters you may enter the values "TRUE" or "FALSE" (or equally "Yes" or "No") without quotations.Empty cells inside rules means "whatever" and the proper condition is automatically considered satisfied. An action with an empty value will be ignored. If the parameter has type String and you want to enter a space character, you must explicitly enter one of the following expressions: :=" " or '=" " or { " "; }
Cells with Dates can be specified using java.util.Date. OpenRules uses java.text.DateFormat.SHORT to convert a text defined inside a cell into java.util.Date. Before OpenRules 4.1 we recommended our customers not to use Excel's Date format and define Date fields in Excel as Text fields. The reason was the notorious Excel problem inherited from a wrong assumption that 1900 was a leap year. As a result, a date entered in Excel as 02/15/2004 could be interpreted by OpenRules as 02/16/2004. Starting with release 4.1 OpenRules correctly interprets both Date and Text Excel Date formats.
Valid Java expression (Java snippets) may be put inside table cells by one of two ways:
- by surrounding the expression in curly brackets, for example: { driver.age+1; }
- by putting ":=" in front of your Java expression, for example: :=driver.age+1
Make sure that the expression's type corresponds to the parameter type.
How Decision Tables Are Executed ►top
Basic Execution Logic ►top
The rules inside decision tables are executed one-by-one in the order they are placed in the table. The execution logic of one rule (row in the vertical table) is the following:
IF ALL conditions are satisfied THEN execute ALL actions.
If at least one condition is violated (evaluation of the code produces false), all other conditions in the same rule (row) are ignored and are not evaluated. The absence of a parameter in a condition cell means the condition is always true. Actions are evaluated only if all conditions in the same row evaluated to be true and the action has non-empty parameters. Action columns with no parameters are ignored.
For the default vertical decision tables, all rules are executed in top-down order. There could be situations when all conditions in two or more rules (rows) are satisfied. In that case, the actions of all rules (rows) will be executed, and the actions in the rows below can override the actions of the rows above.
For horizontal decision tables, all rules (columns) are executed in left-to-right order.
Multi-Hit and Single-Hit Decision Tables ►top
Let's consider how the OpenRulesEngine executes some very simple rules that define a salutation "Mr.", "Mrs.", or "Ms." based on a customer's gender and marital status:
Rules void defineSalutation(Customer customer, Response response) Gender Marital Status Set Salutation Male Mr. Female Married Mrs. Female Single Ms. If a customer is a married female the conditions of the second rules are satisfied and the salutation "Mrs." will be selected. This is only a business view of the rules table. The complete view including the hidden implementation details ("Java snippets") are presented below:
Rules void defineSalutation(Customer customer, Response response) C1 C2 A1 customer.gender.equals(gender) customer.maritalStatus.equals(status) response.map.put("salutation",salutation); String gender String status String salutation Gender Marital Status Set Salutation Male Mr. Female Married Mrs. Female Single Ms. The OpenRulesEngine will execute rules (all 3 "white" rows) one after another. For each row if conditions C1 and C2 are satisfied then the action A1 will be executed with the selected "salutation".
Please note that for this table conditions for all 3 rules will be examined before executing any actions. This is an example of so-called "multi-hit" rules table that executes all rules it may "hit". We may add one more rules at the very end of this table:
Rules void defineSalutation(Customer customer, Response response) Gender Marital Status Set Salutation Male Mr. Female Married Mrs. Female Single Ms. ??? In this case, after executing the second rule OpenRulesEngine will also execute the new 4th rule and will override a salutation "Mrs." with "???". Obviously this is not a desirable result. However, sometimes it may have a positive effect by avoiding undefined values in cases when the previous rules did not cover all possible situations. What if our customer is a Divorced Female?!
How can this multi-hit effect be avoided? What if we want to produce "???" only when no other rules have been satisfied. To achieve this you may use a so-called "single-hit" table that is specified by putting any return type except "void" after the keyword "Rules". The following is an example of a single-hit rules table that will do exactly what we need:
Rules String defineSalutation(Customer customer, Response response) Gender Marital Status Set Salutation Male Mr. Female Married Mrs. Female Single Ms. ??? Another positive effect of such "single-hitness" may be observed in connection with large tables with say 1000 rows: if the OpenRulesEngine obtains a hit on rule #10 it would not bother to check the validity of the remaining 990 rules.
Having rules tables with a return value may also simplify your interface. For example, we do not really need the special object Response in which we used to write our defined salutation. Our simplified rules table produces a salutation without an additional special object:
Rules String defineSalutation(Customer customer) C1 C2 A1 customer.gender.equals(gender) customer.maritalStatus.equals(status) return salutation; String gender String status String salutation Gender Marital Status Set Salutation Male Mr. Female Married Mrs. Female Single Ms. ??? Please note that the last action in the table should return a value that has the same type as the entire single-hit table. The single-hit table may return any standard or custom Java class such as String or Customer. Instead of basic Java types such as "int" you should use the proper Java classes such as Integer in the table signature.
Here is an example of Java code that creates an OpenRulesEngine and executes the latest rules table "defineSalutation":
public static void main(String[] args) {
String fileName = "file:rules/main/HelloCustomer.xls";
OpenRulesEngine engine = new OpenRulesEngine(fileName);
Customer customer = new Customer();
customer.setName("Robinson");
customer.setGender("Female");
customer.setMaritalStatus("Married");
String salutation = (String) engine.run("defineSalutation", customer);
System.out.println(salutation);
}
To learn more about OpenRules execution logic click here. The standard OpenRules's installation contains many examples that demonstrate how to invoke OpenRulesEngine from regular Java applications (see projects HelloJava, HelloJsr94, HelloXMLCustomer) as well as from web-based applications (see projects HelloJsp, HelloForms, and HelloWS).
Simple AND and OR Conditions ►top
All conditions inside the same row (rule) are considered from left to right using the AND logic. For example, to express
if (A>5 && B >10) {do something}
you may use the rules table:
Rules void testAND(int a, int b)
C1
C2
A1
a > 5 b>10 System.out.println(text)
String x
String x
String text
A > 5
B > 10
Do
X
X
Something
To express the OR logic
if (A>5 || B >10) {do something}
you may use the rules table:
Rules void testOR(int a, int b)
C1
C2
A1
a > 5 b>10 System.out.println(text)
String x
String x
String text
A > 5
B > 10
Do
X
Something
X
Instead you always may execute directly a simple method:
Method void testOR(int a, int b)
If (a > 5 || b>10) System.out.println("Something");
Using Templates ►top
Rule Templates introduced in the OpenRules-5 allow rule designers to completely hide implementation details from business users. Rule templates are regular decision tables such as the "defineGreeting" table described above. However, if we want to use this table as a template for many other tables with the same structure but different rules, it is enough to use only the first 5 rows:
Rules void defineGreeting(App app, int hour) - Signature with parameters C1 A1 - Conditions and Actions identifiers min <= hour && hour <= max app.greeting = greeting;
- Java snippets describe condition/action semantics int min int max String greeting - Parameter types and names Hour From Hour To Set Greeting - Business names for conditions and actions We may use this decision table as a template to define different greeting rules for summer and winter time. An actual decision table implements the template table with particular rules:
Rules summerGreeting implements defineGreeting Hour From Hour To Set Greeting 0 10 Good Morning 11 18 Good Afternoon 19 22 Good Evening 23 24 Good Night and
Rules winterGreeting implements defineGreeting Hour From Hour To Set Greeting 0 11 Good Morning 12 17 Good Afternoon 18 22 Good Evening 23 24 Good Night Note that Rules tables "summerGreeting" and "winterGreeting" do not have technical information at all - Java snippets and a signature are defined only once and reside in the template-table "defineGreeting".
Click here to learn more about Rule Templates.
Using Expressions Inside Decision Tables ►top
OpenRules allows a rules designer to use two types of expressions inside decision table cells:
- Natural Language Expressions
- Java Expressions
Natural Language Expressions ►top
Starting with OpenRules release 4, a rules designer may use plain English expressions to define possible values of different decision variables inside rule tables. Instead of creating multiple columns for defining different ranges for integer and real values, a business user may define from-to intervals in practically unlimited English using such phrases as: "500-1000", "between 500 and 1000", "Less than 16", "More or equals to 17", "17 and older", "< 50", ">= 10,000", "70+", "from 9 to 17", "[12;14)", etc. Here is a simple example of a condition that specifies different credit scores:
Condition-2 interval.contains(c.outsideCreditScore) FromToInt interval AND
Outside Credit Score<= 100 (100;550] more than 550 and less or equal to 900 greater than 550 but less than 901 551 - 900 551-900 551-900 551-900 from 551 to 900 between 551 and 900 To read a detailed tutorial wit examples that describes how to apply natural language inside rule tables please click here.
Java Expressions ►top
The use of Java expressions provides a powerful ability to perform calculations and test for complex logical conditions. While the writing of expressions requires some technical knowledge, it does not require the skills of a programmer. Real-world experience shows that business analysts frequently have a need to write these expressions themselves. It is up to the decision table designer to decide whether to show the expressions to business people or to hide them from view. Let's consider a decision table for "Income Validation" from the provided example Loan1.xls:
Rules void ValidateIncomeRules(LoanRequest loan, Customer customer) C1 A1 customer.monthlyIncome * 0.8 - customer.monthlyDebt > loan.amount/loan.term loan.incomeValidationResult = result; boolean condition String result IF
Income is Sufficient for the LoanTHEN
Set Income Vaidation Result