PK [EZFoa,mimetypeapplication/epub+zipPK[EZFMETA-INF/container.xml PKYuPK[EZFOEBPS/rules_start.htm Working with Rulesets and Rules

4 Working with Rulesets and Rules

This chapter describes the Oracle Business Rules data model element called ruleset that you use to group one or more rules and Decision Tables. It also discusses how to work with dictionaries, nested tests, and advanced and tree mode rules, and Expression Builder.

The chapter includes the following sections:

For more information, see Section 1.1.5, "What Are Rulesets?".

4.1 Introduction to Working with Rulesets and Rules

You can use business rules to define key decisions and policies for a business, including:

Oracle Business Rules provides two ways to work with rules:

This chapter describes working with IF/THEN rules. For information on Decision Tables, see Chapter 5, "Working with Decision Tables".

4.2 Working with Rulesets

A ruleset provides a unit of execution for rules and for Decision Tables. In addition, rulesets provide a unit of sharing for rules; rules belong to a ruleset. Multiple rulesets can be executed in order. This is called rule flow. The ruleset stack determines the order. The order can be manipulated by rule actions that push and pop rulesets on the stack. In rulesets, the priority of rules applies to specify the order of firing of the rules in the ruleset. Rulesets also provide an effective date specification that identifies that the ruleset is always active, or that the ruleset is restricted based on a time and date range, or a starting or ending time and date.

4.2.1 How to Create a Ruleset

All rules and Decision Tables are created in a ruleset. A ruleset organizes rules and Decision Tables into a unit of execution.

To create a ruleset:

  1. In Rules Designer, go to the Rulesets navigation tab.

  2. Click the Create Ruleset... icon. This displays the Create Ruleset dialog.

  3. Enter a name in the Name field.

  4. Enter a description in the Description field, as shown in Figure 4-1.

    Figure 4-1 Adding a Ruleset

    Description of Figure 4-1 follows

  5. Click OK.

4.2.2 How to Set the Effective Date for a Ruleset

Effective date support provides the ability to specify a start date and an end date for a ruleset, a rule or a Decision Table. For a ruleset the effective date defines the date range in which the rules and Decision Tables within the ruleset are effective. For more information on effective dates, see Section 4.9, "Using Date Facts, Date Functions, and Specifying Effective Dates".

To set the effective date for a ruleset:

  1. Select the ruleset name from the Rulesets navigation tab.

  2. Click the navigation icon next to the ruleset name to expand the ruleset information to show the ruleset Name, Description, and Effective Date fields, as shown in Figure 4-2.

    Figure 4-2 Ruleset Showing Effective Date Field

    Description of Figure 4-2 follows

  3. Select the Effective Date entry. This displays the Set Effective Date dialog, as shown in Figure 4-3.

    Figure 4-3 Using the Set Effective Date Dialog

    Description of Figure 4-3 follows

  4. Use the Set Effective Date dialog to specify the effective dates for the ruleset. Clicking the Set Date icon displays a calendar to assist you in entering the From and To field data.

4.2.3 How to Use a Filter to Display Matching Rules in a Ruleset

As the number of rules in a ruleset increases, it can be difficult to navigate the list of rules. You can instruct Rules Designer to filter the list of rules, to display only rules of interest. For example, you can display only active rules or only rules that have validation warnings.

For more information on creating rules, see Section 4.3, "Working with Rules".

To use a filter to display matching rules in a ruleset:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. To show the rule filter settings, next to the ruleset name, click Show Filter Query as Figure 4-4 shows.

    Figure 4-4 Showing a Filter Query in a Ruleset

    Description of Figure 4-4 follows

  3. In the Filter Query field, click <insert test> to insert a default test as Figure 4-5 shows.

    Figure 4-5 Inserting a Default Filter Query Test

    Surrounding text describes Figure 4-5 .
  4. Configure the default test.

    In this case, as shown in Figure 4-6, when you click an <operand> you can choose from the rule-specific options shown in Table 4-1.

    Table 4-1 Rule Filter Query Operands

    OperandDescription

    name

    Matches against the rule name.

    description

    Matches against the rule description.

    priority

    Matches against the rule priority. For more information, see Section 4.5.5, "How to Set a Priority for a Rule".

    start date

    Matches against the rule start date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule".

    end date

    Matches against the rule end date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule".

    minutes until start date

    Matches against a specified number of minutes until the rule start date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule".

    minutes until end date

    Matches against a specified number of minutes until the rule end date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule".

    days until start date

    Matches against a specified number of days until the rule start date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule"

    days until end date

    Matches against a specified number of days until the rule end date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule"

    years until start date

    Matches against a specified number of years until the rule start date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule"

    years until end date

    Matches against a specified number of years until the rule end date. For more information, see Section 4.9.2, "How to Set the Effective Date for a Rule"

    is active

    Matches against whether the rule is active. For more information, see Section 4.5.3, "How to Select the Active Option".

    is valid

    Matches against whether the rule has validation warnings. For more information, see Section 4.4.2, "Understanding Rule Validation".

    referenced fact types

    Matches against one or more fact types.


    Figure 4-6 Filter Query Operands

    Description of Figure 4-6 follows

    For more information, see Section 4.3.2, "How to Define a Test in a Rule".

  5. Select the operator to choose an operator for the comparison. For example, for the name you can select startsWith from the operand list.

  6. Enter a comparison operand for the right-hand-side of the filter test. For example, enter the string Customer.

  7. When the filter query is complete you can apply the filter to the rules in the ruleset:

    1. To apply the filter, select the Filter On checkbox.

      Rules Designer displays only the rules that match the filter query as Figure 4-7 shows.

      Figure 4-7 Enable Filter Query in a Ruleset with Filter On Option

      Description of Figure 4-7 follows

    2. To disable the filter query, deselect the Filter On checkbox.

      Rules Designer displays all the rules in the ruleset.

    3. To delete the filter query, select it and press Delete or click the Clear Filter icon.

4.2.4 Using Auto Complete when Selecting Component Values from a List

The Rules Designer enables you to easily set values for the following components of a business rule:

  • Expressions

  • Conditions

  • Operands

  • Actions

You can edit these components by clicking them in the Rules Editor and selecting the desired value from a drop down list or tree. You can also enter the name of the desired value in the text area at the top of the list. When you begin entering text, the list of options are filtered as shown in Figure 4-8.

Figure 4-8 Using the Auto Complete Function

Surrounding text describes Figure 4-8 .

In this figure, only the options beginning with the text entered are displayed.

4.3 Working with Rules

You create business rules to process facts and to obtain intermediate conclusions that Oracle Business Rules can process. You create rules in a ruleset, so before working with rules you need to create a ruleset (or use the default ruleset). For more information on creating a ruleset, see Section 4.2, "Working with Rulesets".

You can easily test your rules as you are designing them without having to deploy your application. For more information, see Section 8.1.5, "How to Test a Decision Function Using an Oracle Business Rules Function".

Rules Designer rule validation can assist you when you work with rules. To show the validation log window, click the Validate icon or select View>Log and select the Business Rule Validation tab. This displays warnings for incorrect or incomplete rules. Note that you must correct all warnings before you can test or deploy rules. For more information on rule validation, see Section 4.4.2, "Understanding Rule Validation".

As the number of rules in a ruleset increases, you can configure Rules Designer to filter the list of rules to show only rules of interest. For more information, see Section 4.2.3, "How to Use a Filter to Display Matching Rules in a Ruleset".

4.3.1 How to Add Rules

To create a rule you first add the rule to a ruleset, and then you insert tests and actions. The actions are associated with pattern matches. At runtime when a test in the IF area of a rule matches, the Rules Engine activates the THEN action and prepares to run the actions associated with the rule.

Rules Designer lets you create a rule where by default the rule fires for each matching fact. To enable other options, where the same fact type matches more than once, or never, you select Advanced Mode. For more information on advanced mode and showing advanced settings, see Section 4.5, "Using Advanced Settings with Rules and Decision Tables".

To add rules in a ruleset:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. In the View field, select IF/THEN Rules.

  3. Click Add to add a rule. For example, click Add to add a rule named Rule_1, as shown in Figure 4-9.

    Figure 4-9 Adding a Rule in a Ruleset

    Description of Figure 4-9 follows

4.3.2 How to Define a Test in a Rule

To create a test in a rule you add conditions for facts. For example, with a sample CustomerOrder fact with an annual spending property, you can add a test to determine if a customer order is associated with a high value of spending, based on the annual spending for the customer. Note that you can use bucketsets to limit the values for tests and actions in rules. For more information, see Section 4.11, "Using Bucketsets as Constraints for Options Values in Rules".

Figure 4-10 shows this sample rule.

Figure 4-10 Adding a Test to a Rule

Description of Figure 4-10 follows

At runtime, when this rule is processed the Rules Engine checks the facts against rule pattern tests that you define to find matching facts. For this sample rule, Rule_1, when a fact matches the Rules Engine modifies the fact and then modifies the value property to "High".

To define tests in rules:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. In the View field, select IF/THEN Rules (this is the Rules Designer default).

  3. Add or select the rule you want to use, for example, select Rule_1.

  4. In Rule_1, in the IF area, select <insert test>.

  5. For a test, the IF area of a rule includes a left-hand-side <operand> and a right-hand-side <operand>, as shown in Figure 4-11.

    Figure 4-11 Rule Test with Left-hand-side operand and Right-hand-side operand

    Description of Figure 4-11 follows

  6. In a test, you replace the left-hand-side operand with a value.

    To do this, select the left-hand-side <operand>. This displays a text entry area and a list, as shown in Figure 4-12:

    Figure 4-12 Configuring the Left-hand-side Operand of a Test in a Rule

    Description of Figure 4-12 follows

    1. To enter a value use the list to select an item from the value options.

      You can view the options using a single list, by selecting List View, or using a navigator by selecting Tree View.

    2. To enter a literal value, type the value into the text entry area and press Enter.

      The value you enter must agree with the type of the corresponding operand. For example, in the test IF CustomerOrder.annualSpending > <operand>, valid values for <operand> must agree with the type of CustomerOrder field annualSpending.

  7. In a test, you replace the operator with the desired logical operator or accept the default (==). To do this, select the default == operator. This displays a field and a list. The list may contain additional operators, depending on the datatype of the left operand. For example, to test strings, if you select a String operand on the left hand side, then additional String operators, such as startsWith and equalsIgnoreCase are available as shown in Figure 4-13.

    Figure 4-13 Configuring String Operators in a Rule

    Description of Figure 4-13 follows

    Similarly, to test a logical condition between the left-hand and right-hand operands, select one of the logical operators as shown in Figure 4-14: == (equality), != (not equal), > (greater than), >= (greater than or equal to), < (less than), <= (less than or equal to). For more information on the operators, see Appendix B, "Oracle Business Rules Built-in Classes and Functions.".

    Figure 4-14 Configuring the Operator of a Test in a Rule

    Description of Figure 4-14 follows

  8. In a test, you replace the right-hand-side operand with a value.

    Configure the <operand> placeholder as you would for any operand.

    For example, enter 2000 into the text entry area and press Enter or Return, as shown in Figure 4-15.

    Figure 4-15 Configuring the Right-hand-side Operand of a Test in a Rule

    Description of Figure 4-15 follows

4.3.3 What You Need to Know About Oracle Business Rules Test Variables

Oracle Business Rules test variables provide a way to shorten lengthy expressions that occur in rule and decision table conditions and actions. The variable and its value can be represented as an inline business term definition. The test variables are also called as inline aliases.

The option to insert test variables appears as a list next to <insert test> in the rules condition section. As part of the definition of rule condition, you can define a variable to represent a complex expression, a mathematical expression, or callouts to functions.

For example you have an XML fact called Song that has an attribute as composer having a function called size. When referring to the attribute, instead of using Song.composer.size() every time, you can just define a variable as the following:

lo = Song.composer.size()

Subsequently, in tests, you can use lo as part of your expressions. The expression can be anything from a simple to a complex expression. For example, in the body of a function, if you click <insert action>, you can see expression as a part of the available options.

Figure 4-16 displays a test variable.

Figure 4-16 Rules Test Variable

Description of Figure 4-16 follows

Once you define an inline alias, for subsequent test conditions, the inline alias is available in the list of the operands. The scope of an inline alias is restricted to the subsequent tests in a particular rule, in which the inline alias is defined. In case of a nested test, you can still use the inline alias, because the nested test is a part of the base test where you have defined the alias. This is true even for any test that you define even within the nested test. The scope of the inline alias is not just restricted to the test conditions of the base and its nested test, but also to the actions of that rule. If the inline alias is defined as a part of a nested test condition and not as a part of the main test condition, even then the alias will be available to all the subsequent test conditions and actions within or outside the main nested test.

However, if you define an inline alias inside a not nested test, then the scope of the inline alias is restricted only to the subsequent tests inside the not nested test and not to any tests that are outside the not nested test.

The inline aliases can be used both in If-Then rules as well as Decision Tables. In a Decision Table, in advanced mode, you can show or hide patterns as well as enter a pattern by clicking <insert pattern>. After you insert a pattern, you can insert tests. In normal mode, you can show or hide tests as well as enter a test by clicking <insert test>.

4.3.4 How to Define Range Tests in Rules

To create a range test in a rule, you add conditions for facts. For example, with a sample CustomerOrder fact with an annual spending property, you can add a test to determine if the value of a customer order falls between an upper and lower range.

The following summarizes this sample rule:

IF  
     CustomerOrder.annualSpending between 100 and 2000
THEN
     Modify CustomerOrder.value = "Normal"

At runtime, when this rule is processed the Rules Engine checks the facts against rule pattern tests that you define to find matching facts.

To define range tests in rules:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. In the View field, select IF/THEN Rules (this is the Rules Designer default).

  3. Add or select the rule you want to use, for example, select Rule_1.

  4. In Rule_1, in the IF area, select <insert test>.

  5. The test in the IF area of a rule includes a left-hand side <operand> and a right-hand-side <operand>, as shown in Figure 4-17.

    Figure 4-17 Rule Test with Left-hand-side operand and Right-hand-side operand

    Description of Figure 4-17 follows

  6. In a range test, you replace the left-hand-side operand with a value.

    To do this, select the left-hand-side <operand>. This displays a text entry area and a list, as shown in Figure 4-18:

    Figure 4-18 Adding a Test Left-hand-side Operand to a Rule

    Description of Figure 4-18 follows

    1. To enter a value, use the list to select an item from the value options.

      You can view the options using a single list, by selecting List View, or using a navigator by selecting Tree View.

    2. To enter a literal value, type the value into the text entry area and press Enter. The value you enter must agree with the type of the corresponding operand.

      For example, in the test IF CustomerOrder.annualSpending > <operand>, valid values for <operand> must agree with the type of CustomerOrder field annualSpending.

  7. In a range test, you choose the between operator. To do this, select the default == operator. This displays a text entry area and a list. Select between as shown in Figure 4-19.

    Figure 4-19 Configuring the Operator of a Range Test in a Rule

    Description of Figure 4-19 follows

    This adds two more <operand> placeholders as shown in Figure 4-20.

    Figure 4-20 Between Operator in a Range Test

    Description of Figure 4-20 follows

  8. Configure the <operand> placeholders as you would for any operand as shown in Figure 4-21.

    Figure 4-21 Configuring the Operand of a Range Test in a Rule

    Description of Figure 4-21 follows

    The test is true when the left-most operand (CustomerOrder.annualSpending) is between the values 100 and 2000.

4.3.5 How to Define Set Tests in Rules

To create a set test in a rule, you add conditions for facts. For example, with a sample CustomerOrder fact with a line item property you can add a test to determine if the line item belongs to an arbitrary set of products.

The following summarizes this sample rule:

IF  
     CustomerOrder.lineItem.sku in 12345, 43255, 76348
THEN
     Modify CustomerOrder.value = "High"

At runtime, when this rule is processed the Rules Engine checks the facts against rule pattern tests that you define to find matching facts.

To define set tests in rules:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. In the View field, select IF/THEN Rules (this is the Rules Designer default).

  3. Add or select the rule you want to use, for example select Rule_1.

  4. In Rule_1, in the IF area select <insert test>.

  5. The test in the IF area of a rule includes a left-hand side <operand> and a right-hand-side <operand>, as shown in Figure 4-11.

    Figure 4-22 Rule Test with Left-hand-side operand and Right-hand-side operand

    Description of Figure 4-22 follows

  6. In a set test, you replace the left-hand-side operand with a value.

    To do this, select the left-hand-side <operand>. This displays a text entry area and a list as shown in Figure 4-23:

    Figure 4-23 Adding a Test Left-hand-side Operand to a Rule

    Description of Figure 4-23 follows

    1. To enter a value use the list to select an item from the value options.

      You can view the options using a single list, by selecting List View, or using a navigator by selecting Tree View.

    2. To enter a literal value, type the value into the text entry area and press Enter.

  7. In a set test, you use the in operator. To do this, select the default == operator. This displays a text entry area and a list. Select in as shown in Figure 4-24.

    Figure 4-24 Configuring the Operator of a Set Test in a Rule

    Description of Figure 4-24 follows

    This adds two more <operand> placeholders in a comma separated list and an <insert> placeholder as shown in Figure 4-25.

    Figure 4-25 In Operator in a Set Test

    Description of Figure 4-25 follows

    To add another operand to the list, click <insert>.

    To delete an operand from the list, right-click the operand and select Delete Test Expression.

  8. Configure the <operand> placeholders as you would for any operand as shown in Figure 4-26.

    Figure 4-26 Configuring the Operands of a Set Test in a Rule

    Description of Figure 4-26 follows

    The test is true when the value of the left-most operand (CustomerOrder.lineItem.sku) is any of 12345, 43255, or 76348.

4.3.6 How to Define Actions in Rules

To create a rule you insert tests and you insert actions. The actions are associated with pattern matches. When a test in the IF area of a rule matches, the Rules Engine activates the THEN action and prepares to run the actions associated with the rule.

When you add an action, you use one of the forms of actions shown in Table 4-2. For each form shown in Table 4-2 the options that Rules Designer presents are context sensitive, so the lists and the number of items you work with may be different, depending on which action you add and the choices you make while you enter the action. Table 4-2 shows the basic actions; additional actions are available with Advanced Mode. For more information on advanced mode see Section 4.5, "Using Advanced Settings with Rules and Decision Tables".

Table 4-2 Rule Action Choices

Action FormDescription

Assert New

Assert a new fact

Modify

Modify a data value associated with a matched fact

Retract

Retract a fact

Call

Call a function

If, else, elseif, for, while

Conditional actions


To define actions in rules:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. In a rule, in the THEN area, select <insert action>. This displays the add action list as shown in Figure 4-27.

    Figure 4-27 Adding a Modify Action to a Rule

    Description of Figure 4-27 follows

  3. In the add action list, select the type of action you want to add. For example, select modify. You can also enter the name of the action in the text area. As you begin entering a name, the list of available choices is automatically filters. This is useful when there are a large number of options available.

    You can add any required action ranging from assert, call, modify to even conditional actions such as if, else, elseif, while, for, if (advanced), and while (advanced) as shown in

  4. In the THEN area, select <target> to display the option list. For example, select customerOrder as shown in Figure 4-28.

    Figure 4-28 Adding Modify Action to a Rule and Selecting the Target

    Description of Figure 4-28 follows

  5. Select <add property>. This displays the Properties dialog.

  6. In the Properties dialog, in the Value column, enter "High" (include the double quotation marks) and press Enter or Return as shown in Figure 4-29.

    Figure 4-29 Adding Modify Action Property and Value to a Rule

    Description of Figure 4-29 follows

  7. In the Properties dialog, click Close. This displays the rule as shown in Figure 4-30.

    Figure 4-30 Rule with Test and Action Added

    Description of Figure 4-30 follows

4.3.7 What You Need to Know About Rule Actions

A rule loop occurs when the value for a condition is changed by an action. Loops can occur across rules in a single rule, spread over several Decision Tables, or spread over rules and Decision Tables in the same ruleset. You need to avoid creating rule actions that modify fact properties that are used in rule conditions. At runtime, such rules could cause an infinite loop.

4.3.8 What You Need to Know About Oracle Business Rules Performance Tuning

In most cases, writing of rules should not require a focus on performance. However, there are tips that can that help you to enhance and maximize rule performance.

For more information on Oracle Business Rules performance tuning, see "Oracle Business Rules Performance Tuning" in Oracle Fusion Middleware Performance and Tuning Guide.

4.4 Validating Dictionaries

Rules Designer performs dictionary validation when you make any change to the dictionary. Rules Designer validation can assist you when you work with rules or Decision Tables. To show the validation log window, click the Validate icon or select View>Log and select the Business Rule Validation tab. This displays warnings for incorrect or incomplete rules. Note that you must correct all warnings before you can test or deploy rules.

When a dictionary is invalid, Rules Designer produces a list of warning messages and lists the associated dictionary objects. You can use the validation message information to locate the dictionary object and to correct problems. In addition, Rules Designer flags objects with validation warnings with a validation indicator (a red, wavy underline), as shown in Figure 4-31.

Figure 4-31 Validation Warnings Shown in Log and On Screen with Wavy Underline

Description of Figure 4-31 follows

If a dictionary is invalid, you can save the dictionary. However, you can only generate RL Language for a dictionary that is valid and does not display warnings in the Rules Designer validation log.

In the validation log, each validation message includes the following:

When you are viewing the validation log, if you select an item and then right-click and select from the list Select and Highlight Object in Editor, Rules Designer moves the cursor to select the dictionary object. Note that for some validation warnings this functionality is not possible.

4.4.1 Understanding Data Model Validation

Rules Designer performs dictionary validation when you make any change to the dictionary. When Rules Designer displays a warning message, the validation log includes a message that should assist you in locating the dictionary object that caused the validation warning. For example, the following string indicates that the warning originates from the data model object named RLFact_1. In addition, the problem is in the property named test_int:

CarRental/Data Model/RLFact_1/test_int/Expression

Table 4-3 specifies the parts of the dictionary object name specified in a validation message.

Table 4-3 Data Model Dictionary Property in Validation Log

NameDescription

CarRental

Dictionary Name

Data Model

Data Model component in dictionary.

RLFact_1

Element name in data model

test_int

Property name in the specified element.

Expression

Expression part of property.


For more information, see:

4.4.2 Understanding Rule Validation

When you click the Validate icon Rules Designer displays the validation log. When you first add a rule you see validation warnings similar to those shown in Figure 4-32.

Figure 4-32 Rules Validation Messages

Description of Figure 4-32 follows

The dictionary object name part of a validation message for a rule includes details that help you to identify the ruleset, the rule, and an area in the rule that is associated with the validation warning. For example, the following dictionary object specification indicates a problem:

OracleRules1/Ruleset_2/Rules_1/Pattern[1]

In validation messages, the dictionary object name for a rule uses indexes that start at 1. Thus, the first pattern is Pattern[1].

In addition to validating rules, you can also test them in Rules Designer as you are designing them. For more information, see Section 8.1.5, "How to Test a Decision Function Using an Oracle Business Rules Function".

4.4.3 Understanding Decision Table Validation

When you click the Validate icon Rules Designer displays the validation log. When you first add a Decision Table you see validation warnings similar to those shown in Figure 4-33.

Figure 4-33 Decision Table Validation Messages

Description of Figure 4-33 follows

The dictionary object name part of a validation message for a Decision Table includes details that help you to identify the area of the Decision Table that is associated with the validation warning. For example, the following dictionary object specification indicates a problem in the first action row, and the first action cell of the Decision Table:

OR1/Ruleset_1/DecisionTable_1/Action[1]/Action Cell[1]

In validation messages the dictionary object name for a Decision Table object uses indexes that start at 1. For example, to indicate the first condition cell in the first row in the Conditions area, the message is as follows:

OracleRules1/Ruleset_1/DecisionTable_2/Condition[1]/Condition Cell[1]

This specification indicates the condition cell for the rule with the label R1 in the first row of the Conditions area in a Decision Table as shown in Figure 4-34.

Figure 4-34 Decision Table with Warning on a Condition Cell

Description of Figure 4-34 follows

4.4.4 How to Validate a Dictionary

Rules Designer performs dictionary validation when you make any change to the dictionary.

To validate a dictionary:

  1. In Rules Designer, click the Validate icon (a checkmark).

  2. Select the Business Rule Validation log from the messages area.

  3. When you are viewing the validation log, if you select an item and then right-click and select from the list Select and Highlight Object in Editor, Rules Designer moves the cursor to select the dictionary object. Note that for some validation warnings this functionality is not possible.

4.5 Using Advanced Settings with Rules and Decision Tables

Advanced settings for rules and Decision Tables let you work with features that provide advanced options that not all Oracle Business Rules users need. These features include:

4.5.1 How to Show and Hide Advanced Settings in a Rule or Decision Table

In Rules Designer, next to each rule name and Decision Table name, the show or hide advanced settings icon lets you show and hide advanced settings.

To show and hide advanced settings in a rule or decision table:

  1. Select the ruleset where you want to show advanced settings.

  2. In the View field, from the list, select either IF/THEN Rules or select a Decision Table.

    1. To show the advanced settings, next to the rule name click Show Advanced Settings, as shown in Figure 4-35 (there is a highlighted icon shown next to the rule name, Rule_1).

      Figure 4-35 Showing Rules Advanced Settings

      Description of Figure 4-35 follows

    2. To hide the advanced settings, next to the rule name click Hide Advanced Settings, as shown in Figure 4-36 (there is a highlighted icon shown next to the rule name, Rule_1).

      Figure 4-36 Hiding Advanced Settings in a Rule

      Description of Figure 4-36 follows

4.5.2 How to Select the Advanced Mode Option

Select Advanced Mode to use Rule or Decision Table features that provide additional pattern matching options and additional actions. For more information, see Section 4.7, "Working with Advanced Mode Rules".

To select the advanced mode option:

  1. Select the rule or Decision Table where you want to set Advanced Mode.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Advanced Mode, as shown in Figure 4-37.

    Figure 4-37 Setting Advanced Mode Option

    Description of Figure 4-37 follows

4.5.3 How to Select the Active Option

Oracle Business Rules includes the ability to specify that a rule or a Decision Table is active or inactive. The active option is set independent of the effective dates and may be set without changing or removing previously specified effective dates. When Rule Active is unselected, Rules Designer does not validate the rule.

To select the active option:

  1. Select the rule or Decision Table where you want to set the Rule Active option.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Rule Active.

4.5.4 How to Select the Logical Option

A ruleset or Decision Table with the Logical option selected specifies that rules in the generated RL Language use the logical property. The logical property allows you to enable or disable logical dependence between the facts that trigger a rule and the facts asserted by a rule.

A rule with the logical property enabled makes all facts that are asserted by an action block in the rule dependent on facts matched in the rule condition. Anytime a fact referenced in the rule condition changes, such that the rule's conditions no longer apply, the facts asserted by the rule condition are automatically retracted. For more information on the logical property, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules.

Using the ruleset and Decision Table Logical option you can enable or disable the logical property for the generated RL Language associated with the rules in the ruleset or the Decision Table. By default, the Logical option is not selected.

To select the logical option:

  1. Select the rule or Decision Table where you want to set the Logical option.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Logical.

4.5.5 How to Set a Priority for a Rule

You can set the priority for a rule or a Decision Table. You can select from a predefined named priority list as shown in Table 4-4, or enter a positive or negative integer to specify your own priority level. Higher priority rules run before lower priority rules, within a ruleset. The default priority is medium (with the integer value 0).

Table 4-4 Priority String Value Mapping

Named PriorityInteger Value

highest

3000

higher

2000

high

1000

medium (Default Priority)

0

low

-1000

lower

-2000

lowest

-3000


To set a priority for a rule:

  1. Select the rule or Decision Table where you want to set the priority.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. In the Priority field, specify the priority value:

    1. To specify a named priority, select a named priority from the Priority list as Figure 4-38 shows.

      Figure 4-38 Choosing a Predefined Named Priority

      Description of Figure 4-38 follows

    2. To specify an integer priority, click in the Priority field and enter a positive or negative integer value and press Enter, as Figure 4-39 shows.

      Figure 4-39 Choosing a User Defined Numeric Priority

      Description of Figure 4-39 follows

4.5.6 How to Specify Effective Dates

You can specify effective dates for a ruleset, a rule, or a Decision Table.

To specify effective dates:

  1. Select the rule or Decision Table where you want to set the effective date.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select the Effective Date field. This displays the Set Effective Date dialog.

  4. Use the Set Effective Date dialog to set the effective date.

For more information on using effective dates, see Section 4.9, "Using Date Facts, Date Functions, and Specifying Effective Dates" and Section 4.2.2, "How to Set the Effective Date for a Ruleset".

4.6 Working with Nested Tests

In a rule or a Decision Table you can create more complicated tests using the nested tests feature.

4.6.1 How to Use Nested Tests

To use nested tests:

  1. Select the rule where you want to use a nested test.

  2. In the IF area, select a test. This surrounds the test with a highlighted box.

  3. With a test selected right-click to display the list, as shown in Figure 4-40.

    Figure 4-40 Adding a Nested Test to a Rule

    Description of Figure 4-40 follows

  4. To add the nested test, from the list select either Insert Before or Insert After and then select Nested Test. A nested test is shown in Figure 4-41.

    Figure 4-41 A Nested Test Added to a Rule

    Description of Figure 4-41 follows

4.7 Working with Advanced Mode Rules

Oracle Business Rules provides features that allow you to create advanced rules that add support for the following Oracle Business Rules features:

For more information, see Section 4.7.5, "What You Need to Know About Advanced Mode Rules".

4.7.1 How to Use Advanced Mode Pattern Matching Options

The advanced mode pattern matching options specify when a rule should fire. Table 4-5 shows the available options.

Table 4-5 Advanced Mode Pattern Matching Options

OptionDescription

for each case where

This is the default pattern matching option. A rule should fire each time there is a match (for all matching cases).

there is a case where

This option selects one firing of the rule if there is at least one match.

there is no case where

The value specifies that the rule fires once if there are no such matches.

aggregate

This specifies an aggregate function is applied to all matches. For more information, see Section 4.7.4, "How to Use Advanced Mode Aggregate Conditions".


To use advanced mode pattern matching options:

  1. Select the rule or Decision Table where you want to use pattern matching options.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Advanced Mode.

  4. Right-click a test pattern and select Surround With... as shown in Figure 4-42.

    Figure 4-42 Surrounding With Option

    Description of Figure 4-42 follows

    The Surround With dialog appears as shown in Figure 4-43.

    Figure 4-43 Surround With Dialog

    Description of Figure 4-43 follows

  5. Choose the Pattern Block option from the Surround With dialog and click OK.

    The pattern is surrounded by a nested pattern with the default (for each case where) as shown in Figure 4-44.

    Figure 4-44 Default Pattern Matching Option: for each case where

    Description of Figure 4-44 follows

  6. Select the default (for each case where) option and select the desired pattern matching option from the list as shown in Figure 4-45.

    Figure 4-45 Adding an Advanced Pattern Match Option

    Description of Figure 4-45 follows

4.7.2 How to Use Advanced Mode Matched Fact Naming

The matched fact name field, pattern binding variable, in a rule or a Decision Table lets you test multiple instances of the same type in a single rule. The matched fact name lets you enter a temporary name for the matched fact to use in a test. For example, the rules shown in Figure 4-46 show the use of pattern binding variables in a rule that applies a discount on a shoe item when an order includes at least one "matching" hat item.

Figure 4-46 Rule Using a Pattern Binding Variable

Description of Figure 4-46 follows

For example, you can create the rule, as shown in Figure 4-47 to find duplicate items in a customer order. This example shows the use of matched in a rule.

Figure 4-47 Rule to Find Duplicate Items in an Order

Description of Figure 4-47 follows

To use advanced mode matched fact naming:

  1. Select the rule or Decision Table where you want to add a matched fact name.

  2. Click the Show Advanced Settings icon next to the rule name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Advanced Mode.

  4. Select the <fact type> and enter a fact type from the list.

  5. Select the supplied matched fact name and modify it as needed, as shown in Figure 4-48. For example, enter the matched fact name Order$LineItem1 and then press Enter.

    Figure 4-48 Adding a Matched Fact Variable Name

    Description of Figure 4-48 follows

  6. Create the rule as Figure 4-49 shows. Note that you can choose a matched fact name as an operand. Choose the LineItem1 and LineItem2 operands as needed to create the rule.

    Figure 4-49 Choosing a Matched Fact Variable Name as an Operand

    Description of Figure 4-49 follows

Note in Figure 4-49 that the test checking:

RL.get fact ID(Order$LineItem1) > RL.get fact ID(Order$LineItem2)

Prevents a single instance of an Order$LineItem from matching both patterns that match the Order$LineItem fact type. The ">" is required so that the rule does not fire for different permutations of different instances. For more information, see Appendix C, "How Do I Correctly Express a Self-Join?".

4.7.3 How to Use Advanced Mode Action Forms

When you create a rule with Advanced Mode, Rules Designer presents a list with the available actions shown in Table 4-6. For each form shown in Table 4-6, the options that Rules Designer presents are context sensitive. Thus, the lists and the number of items you see when you work with the action types are context sensitive, depending on which action you add and the choices you make while you enter the action.

Table 4-6 Advanced Mode Action Options

Action FormDescription

Assert

Assert a fact

Assert Tree

Asserts a tree of facts given the root.

Assert New

Assert a new fact.

Assign

Assign a value to a variable.

Assign New

Assign a value to a new variable.

Expression

Perform expression.

Call

Call a function.

For

Oracle RL, like Java, has a for loop. A for loop includes a type with a variable and a collection. The type and variable defines the loop variable that holds the collection value used within the loop. Collection is an expression that evaluates to a collection of the correct type for the loop variable. You can use a for loop to iterate through any collection.

A return, throw, or halt may exit the action block.

If

Using the if else action, if the test is true, execute the first action block, and if the test is false, execute the optional else part, which may be another if action or an action block. Oracle RL, unlike Java, requires action blocks and does not allow a single semicolon terminated action.

Modify

Modify a data value associated with a matched fact.

Retract

Retract a fact.

Return

The return action returns from the action block of a function or a rule. A return action in a rule pops the ruleset stack, so that execution continues with the activations on the agenda that are from the ruleset that is currently at the top of the ruleset stack.

rl

Use an Oracle RL expression that you supply.

synchronized

As in Java, the synchronized action is useful for synchronizing the actions of multiple threads. The synchronized action block lets you acquire the specified object's lock, then execute the action-block, then release the lock.

throw

Throw an exception, which must be a Java object that implements java.lang.Throwable. A thrown exception may be caught by a catch in a try action block.

try

The try, catch, and finally in Oracle RL is like Java both in syntax and in semantics. There must be at least one catch or finally clause.

while

While the test is true, execute the action block. A return, throw, or halt may exit the action block.


To use advanced mode action forms:

  1. In Rules Designer, select a ruleset from the Rulesets navigation tab.

  2. Select or add a rule or a Decision Table.

  3. In the rule or Decision Table click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  4. Select Advanced Mode.

  5. With the insertion areas showing, in a rule in the THEN area select <insert action>. This displays the action list, as shown in Figure 4-50.

    Figure 4-50 Adding an Action to a Rule in Advanced Mode

    Description of Figure 4-50 follows

  6. In the list select the action you want to add.

    For example, select assign new.

  7. In the THEN area, select the context sensitive parameters for the action and enter appropriate values.

4.7.4 How to Use Advanced Mode Aggregate Conditions

When you create a rule with Advanced Mode, Rules Designer supports the pattern matching aggregate option. When you write rule conditions that are based not only on one fact, but on many facts, you can use an aggregate. You use aggregate functions when the conditions have a view spanning multiple facts.

Table 4-7 shows the available aggregate functions.

Table 4-7 Aggregate Functions for Advanced Mode Rules

FunctionDescription

count

Count of matching facts.

average

Average of matching facts.

maximum

Maximum value of matching facts.

minimum

Minimum value of matching facts.

sum

Sum of matching facts.

collection

Builds a list of matching facts.


For example, to write a rule that specifies a special order as follows:

IF 
   an order has more than 5 line items whose price is above a certain value
THEN 
   the order requires manual approval

The five line items may span multiple facts. Thus, you can use the count aggregate function to write this sample special order rule.

When you use an aggregate function, do the following:

  • Select aggregate for the pattern.

  • Enter a function from the list shown in Table 4-7

  • Enter or select values from the context sensitive menus:

    • <variable> A name for the aggregate value.

    • <expression> The value to aggregate, for example driver.age. When the aggregate function you select is the count function the <expression> is not used.

For example, you can compute the sum of the cost all the line items with color "red", as shown in Figure 4-51.

Figure 4-51 Using Aggregate Functions with Rules Red Color Total Cost Rule

Description of Figure 4-51 follows

To use advanced mode aggregates:

  1. Select or create the rule or Decision Table where you want to use an aggregate function.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Select Advanced Mode.

  4. Enter the fact type you want to work with.

  5. Select <insert pattern> to add a pattern.

  6. Select the new pattern.

  7. Right-click the pattern and select Surround With.... This displays the Surround With dialog.

  8. In the Surround With dialog select Pattern Block. For more information, see Section 4.7.1, "How to Use Advanced Mode Pattern Matching Options".

  9. Click OK.

  10. In the pattern select the first field. By default this field contains (for each case where), as shown in Figure 4-52.

    Figure 4-52 Adding an Advanced Pattern Match Option

    Description of Figure 4-52 follows

  11. Select the aggregate option. This adds the context sensitive fields for an aggregate, as shown in Figure 4-53.

    Figure 4-53 Using Aggregate Functions in a Rule

    Description of Figure 4-53 follows

  12. Click <function> and select a function from the list.

  13. In the condition, click <fact type> and select a fact type from the list.

  14. Click <expression> and select an expression from the list.

  15. Rules Designer by default constructs variable names as you create the aggregate pattern. If needed for the rule you are constructing enter variable names to replace the default variable names. Figure 4-54 shows a completed rule using aggregate. In this example, for clarity the rule shows the variable names total_cost and item_x.

    Figure 4-54 Completed Aggregate Function in a Rule

    Description of Figure 4-54 follows

  16. Enter additional tests as required. For this example you enter the test for items with color "red", as Figure 4-55 shows.

Figure 4-55 Using Aggregate Functions with Rules Red Color Total Cost Rule

Description of Figure 4-55 follows

4.7.5 What You Need to Know About Advanced Mode Rules

There are some special cases to keep in mind when you work with Advanced Mode rules, including the following:

  • When you work with aggregates, in actions, you do not see pattern variables. The pattern variables are only shown for action lists when you use (foreach...) patterns. Thus, you cannot see pattern variables in aggregate, "there is a case", or "there is no case patterns".

  • After you select Advanced Mode the Advanced Mode stays selected and inactive (gray), as long as your rule uses advanced options such as advanced pattern matching. To deselect Advanced Mode you must remove or undo the advanced mode features (sometimes it is easier to start over by creating a non-advanced mode rule and then delete the advanced mode rule).

To deselect the advanced mode option:

  1. Select the rule or Decision Table where you want to deselect Advanced Mode.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name (see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table").

  3. Consider the state of the rule:

    • If you can simplify the rule to enable the Advanced Mode option (such that the Advanced Mode icon changes from gray to enabled). Then simplify the rule and when Advanced Mode is enabled, deselect Advanced Mode.

    • If you can use Undo to undo the steps you used to create the Advanced Mode rule, to get to a state where the rule is no longer in Advanced Mode, then use this technique to simplify the rule.

    • If you cannot simplify the rule, then delete the rule and re-create it.

4.8 Working with Tree Mode Rules

Tree Mode rules make it easier to work with a master detail hierarchy, where there are nested elements that map to a parent child relationship.

4.8.1 Introduction to Tree Mode Rules

To introduce tree mode rules, it is instructive to work with an example. Consider the lifecycle of an application fragment that uses business processes and rules to process a retail purchase order (PO). The purchase order has a header with business terms that apply to the entire PO. The PO also contains a list of shipping destinations. Each destination has an address, a list of items to be shipped to the destination's address, and a list of shipments.

Consider the business rule: the status of a PO is "fully shipped" if the status of every item is either "shipped" or "canceled".

Figure 4-56 shows a sample XML schema representation for the PO example. The XML documents for the PO are tree structured. This allows a natural representation for the PO. For example, the PO itself is the top level document element and destinations are nested elements that contain item elements and shipment elements. Shipment elements also contain item elements that reference the ordered items. Status has a list of valid values.

Figure 4-56 PO Schema for Tree Mode Rules Sample

Description of Figure 4-56 follows

Example 4-1 shows the sample purchase order XML schema as represented in Figure 4-56.

Example 4-1 Sample Purchase Order (PO) Schema

<?xml version= '1.0' encoding= 'UTF-8' ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org"
targetNamespace="http://www.example.org"
     elementFormDefault="qualified">
    <xsd:element name="PO">
        <xsd:annotation>
            <xsd:documentation>A sample element</xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="header">
                    <xsd:complexType>
                        <xsd:attribute name="status" type="Status"/>
                        <xsd:attribute name="order-date" type="xsd:date"/>
                        <xsd:attribute name="customer-value"/>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="billing">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="address"/>
                            <xsd:element name="payment"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="destination" maxOccurs="unbounded">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="address"/>
                            <xsd:element name="item" maxOccurs="unbounded">
                                <xsd:complexType>
                                    <xsd:attribute name="ID"/>
                                    <xsd:attribute name="status"/>
                                    <xsd:attribute name="quantity" type="xsd:int"/>
                                    <xsd:attribute name="availability-date" type="xsd:date"/>
                                    <xsd:attribute name="qoh" type="xsd:int"/>
                                    <xsd:attribute name="price"
                                                   type="xsd:decimal"/>
                                </xsd:complexType>
                            </xsd:element>
                            <xsd:element name="shipment" minOccurs="0" maxOccurs="unbounded">
                                <xsd:complexType>
                                    <xsd:sequence>
                                        <xsd:element name="item" maxOccurs="unbounded">
                                            <xsd:complexType>
                                                <xsd:attribute name="ID"/>
                                                <xsd:attribute name="quantity"/>
                                            </xsd:complexType>
                                        </xsd:element>
                                    </xsd:sequence>
                                    <xsd:attribute name="ship-date"/>
                                    <xsd:attribute name="method"/>
                                </xsd:complexType>
                            </xsd:element>
                        </xsd:sequence>
                        <xsd:attribute name="status" type="xsd:string"/>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:simpleType name="Status">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="open"/>
            <xsd:enumeration value="partially shipped"/>
            <xsd:enumeration value="fully shipped"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

Example 4-2 shows part of the XML for an instance of the PO schema. To use tree mode rules you can create a rule that tests one or more business terms and if the tests pass, one or more business terms are added or changed. Oracle Business Rules has special support to enable error-free authoring of rules on fact trees like the sample PO instance.

For example, consider creating a rule for an instance of the PO schema that states:

IF the time between the order date and the date for availability of an item is more than 30 days
THEN cancel the item

Example 4-2 Sample Abbreviated PO XML Instance

<PO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org ../../../../Temp/PO.xsd"
    xmlns="http://www.example.org">
  <header/>
  <billing>
    <address/>
    <payment/>
  </billing>
  <destination>
    <address/>
    <item ID="a01"/>
    <item ID="a02"/>
    <item ID="a03"/>
    <shipment>
      <item ID="a01"/>
      <item ID="a02"/>
    </shipment>
  </destination>
</PO>

4.8.1.1 Understanding Tree Mode Rules (Non-Advanced Mode)

You use non-advanced tree mode, or simple tree mode, when the Advanced Mode option is not selected and Tree Mode is selected. With this mode Rules Designer shows ROOT: <fact type> where you enter the root fact type, as shown in Figure 4-57.

Figure 4-57 Simple Tree Mode Rule with Tree Mode Selected

Description of Figure 4-57 follows

When you create rules with Tree Mode selected and Advanced Mode unselected you can reference properties in the tree using qualified names, for example:

  • PO/destination/item.quantity that is similar to item.quantity but only items that are a destination of PO are matched.

  • PO$Destination$item.quantity that refers to a List<item>. This reference is unchanged from non-tree mode.

With Simple Tree Mode you can only choose terms that do not require many-to-many joins or aggregation.

For more information, see Section 4.8.2, "How to Create Simple Tree Mode Rules".

4.8.1.2 Understanding Advanced Tree Mode Rules

You use advanced tree mode when the Advanced Mode option is selected and the Tree Mode option is selected. With this mode Rules Designer shows ROOT: <fact type> where you enter the root fact type, as shown in Figure 4-58. Rules Designer shows patterns for the tree structured facts but the simple tests that join the parent and child facts are hidden.

Figure 4-58 Advanced Tree Mode

Description of Figure 4-58 follows

In advanced tree mode the tree mode patterns, except for the root, display as:

<operator> <variable> is a <fact path>

Where the <fact path> is an XPath-like path through the 1-to-1 and 1-to-many relationships starting at the root. For example, each fact path has a name like PO/destination, where PO is the root fact type and the destination is a property of type List. A 1-to-many relationship in a fact path is indicated with a "/", as in PO/destination.

A 1-to-1 relationship in a fact path is indicated with "." This unchanged from non-tree mode. For example, item.availabilityDate.

Advanced mode exposes the concept of a pattern, the simplest of which is is a. For example, p is a PO causes p to match, iterate over, all the PO facts, and d is a p/destination causes d to match all the destinations of p. The left side of is a is a variable, and the right side is a fact type or a fact path. By default, Oracle Business Rules sets the variable name equal to the fact type or path. For example, PO is a PO. A pattern can also be a pattern block. A pattern block has a logical quantifier, negation, or aggregation that applies to the patterns and tests nested inside the block.

For more information, see Section 4.8.3, "How to Create Advanced Tree Mode Rules".

When you work with advanced tree mode rules, Rules Designer expects you to use an aggregation pattern, including exists and not exists to combine terms from different child forests into the same rule while avoiding a Cartesian product.

4.8.2 How to Create Simple Tree Mode Rules

Given the XML schema shown in Example 4-1 and the schema instance shown in Example 4-2, the following procedure creates the PO rule to cancel non 30-day availability items.

IF the time between the order date and the date for availability of an item is more than 30 days
THEN cancel the item

To create simple tree mode rules:

  1. Create an IF/THEN rule in your ruleset.

    For more information, see Section 4.3.1, "How to Add Rules".

  2. View advanced settings.

    For more information, see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table".

  3. Select Tree Mode as Figure 4-59 shows.

    Figure 4-59 Simple Tree Mode Advanced Settings

    Description of Figure 4-59 follows

  4. Next to ROOT:, click the <fact type> place holder and select PO from the list as Figure 4-60 shows.

    Figure 4-60 Simple Tree Mode: Configuring the Root

    Description of Figure 4-60 follows

  5. Select <insert test>.

    The IF statement now reads IF <operand> == <operand>.

  6. Select the left-hand <operand>.

  7. In the list, select PO/destination/item.availabilityDate.

  8. Select Expression Builder icon, as shown in Figure 4-61.

    Figure 4-61 Adding Simple Tree Mode Expression

    Description of Figure 4-61 follows

  9. In the Expression Builder dialog, copy and delete the item shown in the Expression area.

  10. In the Expression Builder, select the Functions tab.

  11. In the navigator, expand Duration and double-click the daysbetween function.

  12. Remove the daysbetween argument templates, as shown in Figure 4-62.

    Figure 4-62 Using Expression Builder to Add a Simple Tree Mode Rule

    Description of Figure 4-62 follows

  13. In the daysbetween function, paste the value you previously cut as the second argument.

  14. In the Expression Builder dialog, select the Variables tab.

  15. For the daysbetween function first argument, use the navigator to expand PO and expand header, and double-click orderDate.

  16. In the Expression Builder dialog, click OK.

  17. In the list, in the expression area and press Enter.

  18. Select the operator and enter >.

  19. Select the right-hand <operand> and enter the value 30 and press Enter, as shown in Figure 4-63.

    Figure 4-63 Simple Tree Mode: Right-Hand Operand with Value 30

    Description of Figure 4-63 follows

  20. Click <insert action> and from the list select modify.

    The THEN statement now reads: THEN modify <target>.

  21. Click <target> and from the list select PO/destination/item. The THEN statement now reads:

    THEN modify PO/destination/item ( <add property> )
    
  22. Click <add property>. This displays the properties dialog.

  23. In the properties dialog for the status name, enter the value "canceled", as Figure 4-64 shows.

    Figure 4-64 Simple Tree Mode: Action

    Description of Figure 4-64 follows

  24. In the Properties dialog, click Close.

  25. This displays the finished rule, as shown in Figure 4-65.

    Figure 4-65 Simple Tree Mode Rule Final Rule

    Description of Figure 4-65 follows

Note that in the modify statement, PO/destination/item refers to the particular item instance member.

4.8.3 How to Create Advanced Tree Mode Rules

Given the XML schema shown in Example 4-1 and the instance of these facts shown in Example 4-2, the following procedure creates a free shipping rule that can be summarized as:

IF the total cost of "free shipping eligible" items to a given destination is greater than $40
THEN shipping of those items is free

To create advanced tree mode rules:

  1. Create an IF/THEN rule in your ruleset.

    For more information, see Section 4.3.1, "How to Add Rules".

  2. View advanced settings.

    For more information, see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table".

  3. Select Advanced Mode and select Tree Mode as Figure 4-66 shows.

    Figure 4-66 Advanced Tree Mode Rule for Free Shipping

    Description of Figure 4-66 follows

  4. Select the <fact type> place holder and from the list, select PO.

  5. Complete the free shipping rule, as shown in Figure 4-67.

Figure 4-67 Advanced Tree Mode Free Shipping Rule

Description of Figure 4-67 follows

4.8.4 What You Need to Know About Tree Mode Rules

When you select Tree Mode and select a root fact type, the options lists show all available fact types (not just the children of the root fact type). This allows you to view all available fact types as well as the children of the root fact type. There is no option to limit the option list to only show the children of the selected root fact type.

4.9 Using Date Facts, Date Functions, and Specifying Effective Dates

Oracle Business Rules provides functions that make it easier for you to work with times and dates, and provides effective date features to let you determine when rules are effective, based on times and dates:

Table 4-8 describes the available Effective Date options.

Table 4-8 Effective Date Possible Values

Effective DateDescription

Always Valid

Specifies to set neither "From" nor "To" dates.

From (without To date set)

Valid from a certain date indefinitely into the future.

To (without a From date set)

Valid from now until a certain date.

From Set and To set

Valid only between two dates.


An effective date specification other than Always can be one of the following:

4.9.1 How to Use the Current Date Fact

You can use the current date fact in a rule or a Decision Table.

To use the CurrentDate fact:

  1. Select a ruleset from the Rulesets navigation tab.

  2. Select a rule within the ruleset.

  3. In the IF area, add a condition that uses the CurrentDate fact and the date method of Calendar type, as shown in Figure 4-68.

    Figure 4-68 Rule with Condition Using CurrentDate Fact

    Description of Figure 4-68 follows

4.9.2 How to Set the Effective Date for a Rule

You can specify an effective start date and or an effective end date for a ruleset, a rule, or a Decision Table. For information on specifying the effective date for a ruleset, see Section 4.2.2, "How to Set the Effective Date for a Ruleset".

To set the effective date for a rule:

  1. Select the ruleset name from the Rulesets navigation tab.

  2. Select a rule within the ruleset.

  3. Next to the rule name click Show Advanced Settings, as shown highlighted in Figure 4-69.

    Figure 4-69 Showing Advanced Settings in a Rule

    Description of Figure 4-69 follows

  4. Select the Effective Date field. This displays the Set Effective Date dialog, as shown in Figure 4-70.

    Figure 4-70 Setting the Effective Date for a Rule

    Description of Figure 4-70 follows

  5. Use the Set Effective Date dialog to specify the effective dates for the rule. Clicking the Set Date icon displays a calendar to assist you in entering the From and To field data.

  6. In the Set Effective Date dialog, click OK.

4.9.3 What You Need to Know About Effective Dates

By default, the Oracle Business Rules Engine implicitly manages the clock associated with the CurrentDate fact and the effective date, setting each to the value of the system date. Using the RL Language functions setCurrentDate() and setEffectiveDate() you can explicitly set the current date and the effective date. For more information, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules.

An effective start date is defined as the first point in time at which a rule, Decision Table, or ruleset may actively participate in rule evaluations and fire. Thus, if a rule is effective it may fire if its condition is satisfied and if the rule is not effective, it does not fire whether the condition is satisfied or not.

An effective end date is the first moment in time at which the rule, Decision Table, or ruleset no longer actively participates in rule evaluations (not effective means the rule does not fire).

The effective start and end date can be set on a Decision Table, but these dates cannot be set individually for the rules within a Decision Table.

Rules and Decision Tables also include the Rule Active option. This option is set independent of the effective dates and makes dates effective without changing or removing the specified effective date. For more information on using the Rule Active option, see Section 4.5.3, "How to Select the Active Option".

The precedence of the effective date, when it is defined for both a ruleset and for the rules or Decision Tables within a ruleset, is as follows (with the top precedence being 1):

  1. If the ruleset Rule Active option is unselected, then RL Language is not generated for that entity.

  2. If one or both of the effective date properties are selected for a ruleset, then those effective start dates and effective end dates define the range of effective dates allowable for rules or Decision Tables that are defined within the ruleset (that is, if in the ruleset the From checkbox, the To checkbox, or both checkboxes are selected in the Set Effective Date dialog).

    Thus, the effective dates specified for rules or Decision Tables within a ruleset must not violate the boundaries established by the ruleset that contains the rules or Decision Tables. For example, a rule may not have an effective end date that is later than the effective end date specified for a ruleset.

  3. If any individual rule or Decision Table has Rule Active unselected, then RL Language is not generated for that rule or Decision Table.

  4. If the Set Effective Date dialog for a ruleset includes Time selected or this option is selected on a rule or a Decision Table in the ruleset, then all instances of rules or Decision Tables in the ruleset must have Time selected when effective dates are specified. In this case, if Both or Date is selected then Rules Designer shows a validation warning:

    RUL-05742: Calendar form incompatibility detected with forms Time and DateTime.
    If the calendar form is set to Time on a rule set or any of the rules or
    decision tables within that ruleset then the calendar form for that entire
    rule set is restricted to Time.
    

4.9.4 How to Use Duration, JavaDate, OracleDate, and XMLDate Methods

You can use the Duration, JavaDate, and XMLDate, OracleDate, and OracleDuration extension methods in a rule or a Decision Table. For more information, see Appendix B, "Oracle Business Rules Built-in Classes and Functions".

To use a Duration method:

  1. Select ruleset from the Rulesets navigation tab.

  2. Select a rule within the ruleset (you can also use Duration methods in a Decision Table).

  3. In the IF area, add a condition.

  4. Select an operand in the rule condition.

  5. From the list, select Expression Builder.... For more information, see Section 4.10, "Working with Expression Builder".

  6. In the Expression Builder, select the Functions tab.

  7. In the Expression Builder, in the Navigator, expand the Duration folder.

  8. Double-click to select and insert the appropriate method as needed for your duration test.

  9. Provide the appropriate arguments for the method. For example, see Figure 4-71.

  10. This allows you to create a rule such as that shown in Figure 4-72.

Figure 4-71 Using Duration Methods in a Rule

Description of Figure 4-71 follows

Figure 4-72 Adding a Rule Using Duration Function

Description of Figure 4-72 follows

4.10 Working with Expression Builder

Use the expression builder to create and edit expressions for Oracle Business Rules.

4.10.1 Introduction to the Expression Builder

You can access the expression builder from different parts of Rules Designer, including in the Edit Globals dialog, and in the conditions area when you work with conditions in Decision Tables, and when you enter rules and Decision Tables in advanced mode with free form expressions selected.

Figure 4-73 shows the Rules Designer expression builder.

Figure 4-73 Rules Designer Expression Builder

Description of Figure 4-73 follows

4.10.2 How to Use the Expression Builder

In the expression builder when you double-click items in the Variables or Functions navigation trees, or in the Operators tab, or in the Constants tab, this inserts the item into the expression in the Expression area. You can also create or edit expressions directly by entering text in the Expression area.

When you enter an expression, note that Variables are valid assignment targets and Constants are not valid assignment targets. Thus, you should use both tabs if you are unsure what type of item you want to add to the expression you are building.

Specify an argument for a selected function by placing the cursor inside the function in the Expression field and double-clicking the expression or function to insert. For example, place the cursor inside the parentheses of a function and select a variable. This inserts the variable in the expression at the cursor position.

4.10.3 What You Need to Know About Working with Expressions

XML fact types allow XML Schema types, elements, and attributes to be used when writing rules. Elements and types defined in XML Schema can be imported into the data model and can then be used to create rules and Decision Tables, just as with Java fact types and RL Fact types. The mapping between the XML Schema definition and the XML Fact types uses the Java Architecture for XML Binding (JAXB). By default, Oracle Business Rules uses the JAXB 2.0 shipped with the Oracle Application Server. JAXB as defined in JSR-222 provides a mapping between the types, names, and conventions in an XML Schema definition and the available types, allowed names and conventions in Java. For example, an element named order-id and of type xsd:integer is mapped to a Java Bean property named orderID of type BigInteger (and xsd:int type maps to Java int).

You can use expressions in Oracle Business Rules. Expressions allow arithmetic using the operators *, +, /, %, and other supported operators on primitive numerics, for example double, int, and the numeric types Integer, Long, Short, Float, Double BigDecimal, and BigInteger that are available in the built-in dictionary. For more information on supported primitive numerics, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules.

Expressions allow casting between any two numeric types, for example, (short)((BigInteger)1 + (Long)2). Example 4-3 shows a few additional sample expressions.

The expression processor uses the XPath/Xquery rules for type promotion (XML Path Language (XPath) 2.0). For example, BigDecimal is promoted to float/double; type promotion going the other direction requires a cast, except for literals such as 3.3.

Example 4-3 Sample Expressions in Actions with Types and Casting

assign new double db = 3.3
assign new BigDecimal bd = 3.3  // no cast required
assign db = bd // no cast required
assign bd = (BigDecimal)db // cast is required 

4.11 Using Bucketsets as Constraints for Options Values in Rules

You can use List of Values Bucketsets and List of Ranges Bucketsets to specify constraints for business terms in rules. This allows you to use Rules Designer to produce validation warnings for possible errors where a value supplied is out of range, or not within a set of possible values as specified in a bucketset. Oracle Business Rules also lets you use bucketsets to specify constraints for global initial values, function return values, or function argument values. For more information, see Section 2.3, "Working with Oracle Business Rules Globals" and Section 3.7, "Associating a Bucketset with Business Terms".

4.11.1 How to Use a List of Ranges Bucketset as a Constraint for a Business Term

You can use a list of ranges bucketset as a constraint for any business term other than a function result.

For more information on using a list of values bucket set as a constraint, see Section 4.11.2, "How to Use a List of Values Bucketset as a Constraint for a Fact Property".

To use a List of Ranges bucketset as a constraint for a fact property:

  1. Specify a bucketset that includes the ranges you want to include and select Allowed in Actions for all valid ranges. To include a range, deselect Allowed in Actions for the top and bottom endpoints.

  2. Select Included Endpoint as needed for the application.

  3. Deselect Include Disallowed Buckets in Tests. For example, for a bucketset that defines valid grades and that does not allow values greater than 100, or less than 0, define the bucketset endpoints as shown in Figure 4-74.

    Figure 4-74 Valid Grades Bucketset for Fact Property

    Description of Figure 4-74 follows

  4. Associate this bucketset with a business term. For example, associate the bucketset with test_math1 as shown in Figure 4-75.

    Figure 4-75 Associating a Bucketset with a Fact Property

    Description of Figure 4-75 follows

Now, if you define a rule with a test that uses the fact property you receive a validation warning when a value is out of range. For example if you define a rule with an expression with the value -10, Rules Designer shows a validation warning as shown in Figure 4-76.

Figure 4-76 Using a Fact Property Value that is not in the Allowed in Actions for Associated Bucketset

Description of Figure 4-76 follows

4.11.2 How to Use a List of Values Bucketset as a Constraint for a Fact Property

You can use a list of values bucketset as a constraint for a fact property.

For more information on using a list of ranges bucket set as a constraint, see Section 4.11.1, "How to Use a List of Ranges Bucketset as a Constraint for a Business Term".

To use a List of Values bucketset as a constraint for a fact property:

  1. Specify an LOV bucketset that includes the values you want to include, and select Allowed in Actions for all valid values. For more information, see Section 3.6.1, "How to Define a List of Values Global Bucketset".

  2. Deselect Allowed in Actions for the otherwise bucket.

  3. Deselect Include Disallowed Buckets in Tests.

  4. Associate this bucketset with a fact property.

4.11.3 How to Use Bucketsets to Provide Options for Test Expressions

You can use LOV bucketsets to provide options for expressions and actions.

How to use bucketsets to provide options for rule expressions and actions:

  1. In Rules Designer, define an LOV bucketset of a type corresponding to a fact property. For more information, see Section 3.6.1, "How to Define a List of Values Global Bucketset".

  2. Associate the bucketset with a fact property. For more information, see Section 3.7.1, "How to Associate a Bucketset with a Fact Property".

  3. When you enter expressions, Rules Designer shows the bucket values in the values options. For example, when you associate a fact property Driver.eye_test with an LOV bucketset named eyes, with values: pass, fail, and glasses_required, and then you use Driver.eye_test in a test expression, the bucket values are limited as shown in Figure 4-77.

    Figure 4-77 Using a Bucketset to Provide Options for a Rule Test Expression

    Description of Figure 4-77 follows

4.12 Importing Runtime Rules Changes From Repository Into JDeveloper

This section dicusses how to import changes to a rule implemented in SOA Composer into the JDeveloper.

When you make changes to a dictionary in SOA Composer, you must upload them to MDS repository as described in Section 12.10, "Committing Changes for an Oracle Business Rules Dictionary at Runtime". However, these changes do not get updated in JDeveloper. You need to import the changes from MDS repository into JDeveloper manually.

To import the changes into the JDeveloper,

  1. Select the rule in the application navigator for which changes were made.

  2. Click the Import From MDS button in Rule Editor as shown in Figure 4-78.

    Figure 4-78 Importing Changes from MDS Repository

    Surrounding text describes Figure 4-78 .
  3. Select the MDS Repository in the SOA Resource Browser window that opens.

    Figure 4-79 Select the MDS Repository in SOA Resource Browser

    Surrounding text describes Figure 4-79 .
  4. Click OK.

    Changes are updated in JDeveloper and you can view the changes in the Rule Editor.

PKEbaPK[EZFOEBPS/dcommon/oracle.gifJGIF87aiyDT2F'G;Q_oKTC[ 3-Bq{ttsoGc4I)GvmLZ).1)!ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPK[EZFOEBPS/dcommon/oracle-logo.jpgh[JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222'7" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE!KEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEzE7V%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((_ğ<+F; sU%ԑ >,BH(uSU xþ1Wϲs${wgoQn_swB/'L\ܓFgԏZ ^dj^L^NmH Ҁ6(?nƓjh%ةlΣ /F6}pj2E3HgHЌ(UQR8oX,G8OB]>o9@$xWy'ڹOM=ҼWb"٠9-*r⬻zWokeh͝(F@n~X=q+⟇1b>ƑeIX.~C,o5የ-m;D Nʬ` `+CcE??Ki!R!cxw[ jvc}&Eٱ7T)8&þ/?os$wSn^bo:-4^js4JKm!#rv89>' O59t , \8r,Vk|IgxEv((RmĜ+bkz6,u/}-|.'<VÚ~tk,^cH61¢ !;M;Ėz[#CuAƶ+j_&*/;Q8d ǹHyAsM↷7l-6rò,%Fs;A*',}'f[]tݷs~UWhk?:4JE]WpcY=" ƚw/|_xSw(kycH#r28,X7D5Kh76 mɍ~0H;6194WpGӧգ%8Z&GdPƧo6kcO5Kv`{}fyq \`@?Kv=26OޝyAe Qɼ芍H8͟2敮j#;iѻm؏6+wTx;KYY\-%'Aӣ?|=\-ٴk+٬$ɷlr3S򮆻_eq#T58m]>$W'j41=3[hڵ`Kn 8PI k#ƻ~-5'=1b[0o*|8Q6F:k?{/-<1gun2k7p F]]`#9#/ 8Q\QCߨk:[jhIPq\<+FId wXȰI}$.ӐA9 /0xOo&2`Iâ={:u ặXTeu# 8 sXzgxzK%dǻsrOZ|-%煴i zmuApel&X`1@X,9-B->%A$[$ax9#'ڱSh#m/ݷ~8=RNo߇w^m 6,d1.OqؠHI,2_˟f~g;zk$ׅ-y˩“itqpAq0\x/6%{<8bMp'k,0HQ^'gWwZ ^*mT(v =zo..ͣ^Y^eq%M!$P!Nx(c_|7HAq0B帕XNz8H/?5]/d/'S$lw^Nn5 g}MnU2N[aT{k)bcbػUag9[?_ A<5ۛiC喍|xܜzg5P/?hc—=7Znc$̐ 0g\O 焮|]dKmIr)X$pX?*/9//വA.H,x$ƬP-QZ}˽GB8''$cq޻ (?C O.Y."# vHx+222OĿFcPGGO5Y&o=I 0 vL8ht߷}]<299#xVÚL~"u/w#%2 x;IJ~<P.lv2yr#b޼?7S Fo Yl XHBhwYRvqX]wk&vMDlppAy?!>"rS?'G?~gݷsۭnxzl|SY麥ŭuHp#fS]ĀǎFHz%/H%na_˂#(!aN6HKz5|5s,'z'so [ `Pm7Ϭ>ig;ۛco޹l#f H|Oxzk6$nR{FUp 0$ hP<Bs Q@/c oq3|4H4#izj5ͬo}),+1.t$$2% gO{n(WS2Ia$*d(Nϼy r>Uj~!9ѧWԑ.n+{HgG%wmXc[m-&&H,e3bePrNM\Q{SqwAEE"leyÐ~`al:7_]HY[XZp1̻C~d>f>o/~sl|(cD? 1>}yK`~ҷQl@8댮_m[^wv)A-l&3=H`q$" .tK5|.K1=>{O%ԒUմEu1TuAumGW!5m}`KieYT /0t`õu/>dA8d2f\!y#''wxQLX`9兣Y4$VU&藐xO4ky{NR{M$I0s(`A޹?Ϡw w\i>0_;O8ė$[DƻT8h<υ7 gue;VBێF o< sO+Ko26o{?biZ\2c9Ew)\*a#d49>]q#ԛ\ОO[L2G仹E?1$wZᧂ?.v4^TM֓c#PAS~޳}-sSPleVKFdN7+SU2Ӽ9&:`lgۺzI{T uKZ躮xN+u?Z2b+\yKg5jZxյ):[@q<_|3qcXɫPp-4d̹ݰB Gc1\Huw҈^A?M[hGO 9I6d$Ã:mP; ƷzZ;>DګG<7A "I( 2O5k3Y w\i>0_;O8ė$[DƻT8MWZ>?Z>3 ,hŰH] d6dnj h嗇M }s[ܵJ HcH T6džmGWӤV'%x $^HajxUԗ/|oѻ9#ӐCg (O:oԯ7 ¦\7-d>R@8%O+@$$](Oh#TWq =tAٶ)Kv8\O|mCۿGQV6Zk-,|A?->P 3 uB$ 3dWCOgnoN3xO?iivy^f69+灼/*{6UV $p mIx 2cŗ M _Z.Ťu<N8I7 rm'SK<I2Ŵaw'nН7 `N *y?KcKq%im.M$]Wv;s8#HC~!gB}1ao#YR7kݷÛ/u kYu-B 5V@ߌfSIx^!4Vw5wi>YuFW,#sT*۴?OoyH7#va~K=Ozև s֑}@FP rZfsy'kk3'j(%'ΝoYv4n.&y #?yq½Ğ>P% )@nEy?-/g#b7o۷fqz W<=e:_ygɑB,2@_퍾x?.ķ›ڊ# 2y8uOAkkH BRrr2_<+onMbg)A.OKi~O5A$zCDEX"+Ƞd#=_hDž$7ksy 2wT2)Ea#pk#.o఻_%7Q}L@;ǨP ›߆vמ%)ÍItøR傅 l9マ}O>#xHv݂02ŗf%:/^O95-"]$«pNXI`uqV'Zs:SK!_<"H Jvx?5ψ' Իy'󀤶H6E犼 >41ws8@;)ƍYxDЧ5[$4 %Cx'"lx7Dԯ5HEx9#APm$ fѼMuh[XYRMtI# rp%,#qڵ/v*n3@Zt-VrO,_~9ۜg,Q^oC֟#qڵ/v*n3@; ('U)}G\;HyN23Tgg'+:߁ jWV,dلFPr0r_}VKt=bKSBY[1LS$N@Q@Q@Q@Q@Q@Q@Q@Q@*IKqq%z+v=I'Q@Q@r$ 76xKo(wGMMuPjVOG}+0 {[}DFs﹛(((((((((((((((((h ifw^h-ȷ~b sҽxnV5"H"{6;lmܸX?|;ol.'Gv7}@/$:D|mCۿGZ'sXVtoA˗S>TAȣ[[ڶdݵB8U{[;?wp\yy2_22"1;_ճn۝}1zՈ|-[ڽV{muyf<>k1!r;b9_?=2K--cFIvWQ{mPj(k$eJ jy/$:Dx>}#ۻ jo|9Ai:7n*xg HPQ?+7 Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2015, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in preproduction status:

This documentation is in preproduction status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Oracle Logo

PKMPK[EZFOEBPS/dcommon/blafdoc.cssc@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.8.12 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; text-align: left; } h2 { font-size: 152%; font-weight: bold; text-align: left; } h3 { font-size: 139%; font-weight: bold; text-align: left; } h4 { font-size: 126%; font-weight: bold; text-align: left; } h5 { font-size: 113%; font-weight: bold; display: inline; text-align: left; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; text-align: left; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } li { text-align: left; } dd { text-align: left; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #f00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #f00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKr.hcPK[EZFOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PK[EZF OEBPS/toc.ncx Oracle® Fusion Middleware User's Guide for Oracle Business Rules, 11g Release 1 (11.1.1.7) Cover Title and Copyright Information Contents Preface What's New in This Guide for Release 11.1.1.7 1 Overview of Oracle Business Rules 2 Working with Data Model Elements 3 Working with Facts and Bucketsets 4 Working with Rulesets and Rules 5 Working with Decision Tables 6 Working with Decision Functions 7 Working with Rules SDK Decision Point API 8 Testing Business Rules 9 Creating a Rule-enabled Non-SOA Java EE Application 10 Working with Oracle Business Rules and ADF Business Components 11 Working with Decision Components in SOA Applications 12 Using Oracle SOA Composer with Oracle Business Rules A Oracle Business Rules Files and Limitations B Oracle Business Rules Built-in Classes and Functions C Oracle Business Rules Frequently Asked Questions D Oracle Business Rules Troubleshooting E Working with Oracle Business Rules and JSR-94 Execution Sets F Working with Rule Reporter Index Copyright PKkJ PK[EZFOEBPS/content.opf Oracle® Fusion Middleware User's Guide for Oracle Business Rules, 11g Release 1 (11.1.1.7) en-US E10228-12 Oracle Corporation Oracle Corporation Oracle® Fusion Middleware User's Guide for Oracle Business Rules, 11g Release 1 (11.1.1.7) 2013-06-14T09:30:55Z This guide provides information about using and developing applications for Oracle Business Rules. Oracle Business Rules makes processes and applications more flexible by enabling business analysts and non-developers to easily define and modify business logic without programming. PKtyr֡PK[EZFOEBPS/testing.htm Testing Business Rules

8 Testing Business Rules

This chapter describes how to test rules from Rules Designer of Oracle JDeveloper by using the Rules Test Framework provided by Oracle Business Rules. It also discusses how to test rules and Decision Tables by creating an Oracle Business Rules Function. In addition, it covers at runtime, how to test a SOA Application that uses Oracle Business Rules through a decision service by using Oracle Enterprise Manager Fusion Middleware Control Console.

The chapter includes the following sections:

8.1 Testing Oracle Business Rules at Design Time

Oracle Business Rules provides a test framework that allows you to test rules with complex input parameters. This framework enables you to test rules at the time of designing so that you can validate or refine the rules as per your requirement.

Another way of testing rules is by defining a test function, where you can construct the input, execute rules, and validate the output. Because inputs are constructed and outputs are validated programmatically, test functions are typically used for simple tests, and the test framework is used for comprehensive tests. In addition, this test function is active only for functions that do not take any parameters and only return boolean values.

8.1.1 How to Test Rules Using the Rules Test Framework

Oracle Business Rules provides an 'out-of-the-box' functionality that enables you to test whether the rules you are defining works fine with a given set of inputs at the time of designing. The granularity of testing provided is at the level of decision functions. When you define decision functions in a dictionary, you can define test suites and execute those test suites for each of the decision functions.

Oracle Business Rules supports multiple types of facts, such as Java facts, XML facts, RL facts, and ADFBC facts. The test framework currently only supports XML facts. So, if the decision function, which you have defined, have inputs or outputs referring to non-XML facts, the test framework cannot be used to test the decision function. If you use non-XML facts, a warning or error message is displayed indicating that you cannot use the test feature for that decision function.

To test rules, you need to create a decision function as the prerequisite.

8.1.1.1 Creating a Decision Function

  1. Open Oracle JDeveloper.

  2. From the Application Navigator, open the project file containing the dictionary whose rules you want to test, say BaseDictionary.rules under Business Rules.

  3. In the dictionary section, click Decision Functions to open the list of decision functions.

  4. In the decision functions section, click the Create icon (the plus sign) to display the Edit Decision Function dialog box.

  5. Enter the name of the decision function in the Name field, say TestDF.

  6. In the Input tab, enter the input name under Name and press Enter. In this example, enter songs.

  7. Select the fact type from the Fact Type list. Ensure that you select XML facts. In this example, select Song as the fact type. Similarly, another input variable with the name as artists and fact type as Artist has been added.

  8. Select Tree or List as required. See Section 6.2.1, "How to Add or Edit a Decision Function" for more information on tree or list mode rules.

  9. In the Output tab, enter an output name under Name and press Enter. In this example, enter songs.

  10. Select the fact type from the Fact Type list. Ensure that you select XML facts. In this example, select Song.

  11. Under Rulesets & Decision Functions, select the ruleset that you want to invoke from the Available box, and use the shutter (>) icon to move it to the Selected box. In this example, SongArtistRules has been selected.


    Note:

    This example uses sample schema and corresponding facts.


  12. Click OK to create the decision function. Figure 8-1 displays the Edit Decision Function dialog box.

    Figure 8-1 The Edit Decision Function Dialog

    Description of Figure 8-1 follows

When you create a decision function, two XML schemas (xsd files) get automatically generated to help in testing the decision function. These schemas have suffixes _TestSuite and _Types respectively. Further, these schemas are stored in an xsd folder under the testsuites folder, which can be seen in the Application Navigator as shown in Figure 8-2.

You need to define the test suites, which are created for the decision function, based on the schema with the suffix _TestSuite.

Figure 8-2 Application Navigator Displaying XSDs

Description of Figure 8-2 follows

The generated schema files follows the following naming convention:

  • <DictionaryName>_<DecisionFunctionName>_TestSuite.xsd: This file contains the test suite schema for the decision function. Test Suites created for this decision function should conform to this schema. The following is a sample of the TestSuite.xsd file:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://xmlns.oracle.com/rules/test"
    targetNamespace="http://xmlns.oracle.com/rules/test"
    elementFormDefault="qualified" attributeFormDefault="unqualified"
    xmlns:df="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF">
        <annotation>
          <documentation>
              Decision Function Test Suite Schema
          </documentation>
        </annotation>
       <import namespace="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF" 
        schemaLocation="BaseDictionary_BaseDF_Types.xsd"/>
        <element name="testSuite">
            <complexType>
                <sequence>
                    <element name="decisionFunction" type="string" minOccurs="1"    
                     maxOccurs="1"/>
                    <element name="testCase" type="tns:testCaseType" minOccurs="1" 
                     maxOccurs="unbounded"/>
                </sequence>
            </complexType>
        </element>
    
        <complexType name="testCaseType">
            <sequence>
                <element name="testInput" type="df:parameterList" minOccurs="0"   
                  maxOccurs="1"/>
                <element name="expectedOutput" type="df:resultList" minOccurs="0" 
                  maxOccurs="1"/>
            </sequence>
            <attribute name="name" type="string" use="required"/>
        </complexType>
    </schema>
    

    As you can see in the preceding sample, the schema contains a master testSuite element, which in turn contains an element called decisionFunction that defines to which decision function does this test suite corresponds.The testSuite element also contains one or more testCase elements. Each testCase contains a testInput and expectedOutput elements and a name. The testInput values are the ones that are used as inputs to the test cases and expectedOutput values are the ones against which the actual outputs are matched. The types of testInput and expectedOutput (parameterList and resultList respectively) have been defined in the subsequent XSD.

  • <DictionaryName>_<DecisionFunctionName>_Types.xsd: This schema contains two complexTypes elements, parameterList and resultList. These two types are used in the TestSuite schema but are defined here. The parameterList type corresponds to the decision function input and the resultList type corresponds to the decision function output. This is because a decision function has specific inputs and outputs. When you write a test case for a decision function, then the test case input need to correspond to the inputs accepted by the decision function and the expected output need to correspond to the decision function outputs. paramaterList and the resultList are single complexTypes. For example, a decision function requires 10 inputs and 5 outputs, then the parameterList type will be a single ComplexType that collectively defines 10 different elements that need to be provided as the decision function input.

    The following is a sample of the Types.xsd:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
    attributeFormDefault="unqualified" elementFormDefault="qualified"
    xmlns:tns="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:rules="http://xmlns.oracle.com/bpel/rules"
    xmlns:ns1="http://xmlns.oracle.com/rulestest/datamodel">
    <import namespace="http://xmlns.oracle.com/rulestest/datamodel"
    schemaLocation="../../xsd/XMLFactTypes2.xsd"/>
    <import namespace="http://xmlns.oracle.com/bpel/rules"
    schemaLocation="DecisionFunctionPrimitiveTypes.xsd"/>
       <complexType name="parameterList">
          <sequence>
             <element name="tSongElement" type="ns1:tSong"/>
             <element ref="ns1:Artist"/>
          </sequence>
       </complexType>
       <complexType name="resultList">
          <sequence>
             <element name="tSongElement" type="ns1:tSong"/>
          </sequence>
       </complexType>
    </schema>
    

Every time there is an update to the decision function, the corresponding two schemas get updated. For example, if you change the name of the decision function, then the names of the associated schemas are changed. If you delete the decision functions, the corresponding schemas get deleted.Even changes to the inputs and outputs of the decision function results in the associated schemas getting changed. So a decision function and its corresponding test schemas are always in sync.

In case you make any changes to the decision function, for example delete the decision function, typically the schemas get deleted. When you click the Undo icon on the dictionary toolbar, the decision function is retrieved. However, the corresponding schemas remain deleted. You need to manually regenerate the schemas for the decision function in this case. So the sync between the decision function and its corresponding test schemas is not supported in undo and redo operations.

To manually regenerate the schemas:

Click the Generate test suite schemas for all decision functions icon on the dictionary toolbar as shown in Figure 8-3.

Figure 8-3 Manually Regenerating Test Suite Schemas

Surrounding text describes Figure 8-3 .

When you click the icon to regenerate the test suite schemas, a bulk regeneration activity takes place, and all the test suite schemas pertaining to all the available decision functions in the dictionary gets regenerated. If the schemas already exist, those are overwritten.

This activity is particularly used in the following cases:

  • When you have deleted or modified the decision function and have undone the changes: This results in the decision function and the associated schemas getting out of sync. To get them in sync, you use this option so that the schemas are regenerated to correspond to the decision function.

  • When you migrate old dictionaries: Consider a situation when you already have dictionaries from earlier releases with a number of decision functions defined and you want to use the rules testing feature for defining test suites for those decision functions to test them. In this case, either you have to open each decision function in the editor window after migrating, and then click the OK button. This would generate the corresponding test suite schemas. However, this is time-consuming when you have hundreds of decision functions. In this case, you can use the option of regenerating the schemas at one go.


    Note:

    You need to ensure that the migrated decision functions have XML facts as inputs and outputs, else the inputs and outputs defined in the test suite schema files will be empty.


8.1.1.2 Testing the Rules

Once you have created the decision function for testing the rules, you can test rules.

To test rules:

  1. Select the decision function name, say TestDF in this case, in the dictionary page and then click the Test button to display the Decision Function Test dialog box.

  2. Click the Create icon (the plus sign) to display the Create Test Suite dialog box.

  3. Enter the name for the test suite, say TestDFTestSuite1 and click OK as displayed in Figure 8-4.

    Figure 8-4 Creating a Test Suite

    Description of Figure 8-4 follows

  4. Click Close in the Decision Function test dialog box.

    When you create a test suite, a <test suite name>.xml file gets automatically generated and gets stored in the <base dictionary name> folder under the rules folder inside the testsuites folder. You can view the file in the Application Navigator window. For every test suite that you create, a corresponding XML file gets generated.

    However, the newly created test suite file is empty, which does not contain any test case, input definitions, or output definitions.

  5. Open the <test suite name>.XML and write the required test cases that conform to the test suite XSD file, in this case the TestDF XSDs corresponding to the decision function under test.

    The following is a sample test suite file containing test cases:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <testSuite xmlns="http://xmlns.oracle.com/rules/test"
               xmlns:ns1="http://xmlns.oracle.com/bpel/rules"
               xmlns:ns2="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
               xmlns:ns3="http://xmlns.oracle.com/rulestest/datamodel">
       <decisionFunction>G}-733d3b8f:12f76ddad3a:-7c02</decisionFunction>
       <testCase name="TestDFTestSuite1_TestCase1">
           <testInput>
             <ns2:tSongElement>
                <ns3:Title>Come What May</ns3:Title>
                <ns3:Composer>Artist</ns3:Composer>
                <ns3:Length>PT3M2S</ns3:Length>
                <ns3:Year>2010</ns3:Year>
                <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
                </ns3:Artist>
             </ns2:tSongElement>
             <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
             </ns3:Artist>
          </testInput>
          <expectedOutput>
             <ns2:tSongElement>
                <ns3:Title>Come What May</ns3:Title>
                <ns3:Composer>MJ</ns3:Composer>
                <ns3:Publisher>BMG Music</ns3:Publisher>
                <ns3:Length>PT3M2S</ns3:Length>
                <ns3:Year>2010</ns3:Year>
                <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
                </ns3:Artist>         
             </ns2:tSongElement>
          </expectedOutput>  
       </testCase>
    </testSuite>
    
  6. Save the test suite file.

  7. Open the dictionary page, select the decision function name (say TestDF), and click the Test button to display the Decision Function test dialog box.

  8. Select TestDFTestSuite1 from the Test Suite list and click Run Test as shown in Figure 8-5.

    Figure 8-5 Running the Test

    Description of Figure 8-5 follows

    This executes all the test cases in the test suite file.

You can see the test details for the decision function in a tabular form.

The details contain the test suite name, the overall result, and the test case details, such as:

  • The test case name

  • The result of the test case

  • The trace info such as which are the facts that were asserted, which are the rules that were activated, which are the rules that were fired and the resultant change in facts.

Figure 8-6 displays the test results.

Figure 8-6 The Results Page

Description of Figure 8-6 follows

The Comments section in the Results page displays any error details in case a test case fails.

8.1.2 What You Need to Know About Validation of Test Suites

You may have a situation where your test suite XML file does not conform to the test suite XSD file. In that case when you open the Decision Function Test window, in the Test Suite list, adjacent to the test suite name, a yellow warning triangle appears as shown in Figure 8-7.

Figure 8-7 Invalid Test Suite

Description of Figure 8-7 follows

If you try to run an erroneous test suite, you will get the following error message:

error message

If the test suite XML file is malformed, then the test suite name does not appear in the list of test suites in the Decision Function Test window. In addition, for an invalid dictionary , when you test the Decision Function, the following error message is displayed:

Dictionary is invalid, fix validation errors and try again.

8.1.3 What You Need to Know About Testing Linked Dictionaries

Consider a situation, where you have a base dictionary and a custom dictionary. The custom dictionary has a link to the base dictionary.

Now, navigate to the Decision Functions section of the custom dictionary. Note that the list of decision functions in the custom dictionary includes the decision functions from the linked/base dictionary. You can test the decision functions of the base dictionary from the custom dictionary.

8.1.4 What You Need to Know About Failure of Test Suites

In case your test case fails, the Results page displays the probable reasons of failure in the Comments section.

A test case can fail due to the following reasons:

  • The expected output specified for the test case is different from the actual output as the following:

    unexpected output

    The Comments section clearly states that there is a mismatch between the expected output and the actual output.

  • The test case executes, but no output is generated as the following:

    no output

    You can see that the Comments section displays that the test generated no results and some more details on the probable cause.

  • The test case executes, but multiple outputs are generated as the following:

    multiple outputs

    The Comments section displays that multiple outputs were generated on test execution along with some details on the probable cause.

  • The test case does not fire any rule as the following:

    no rules fired

    This can be because the asserted fact failed to activate any rule resulting in no rules getting fired. So, the Comments section indicates that this may be due to a rule modelling error, because in all probabilities, the provided input failed to match any rule condition.

8.1.5 How to Test a Decision Function Using an Oracle Business Rules Function

You can test rulesets by creating a decision function and calling the decision function from Rules Designer with an Oracle Business Rules function. In the body of the Oracle Business Rules function you create input facts, call a decision function, and validate the facts output from the decision function. For more information, see Section 6.1, "Introduction to Decision Functions" and Section 2.5, "Working with Oracle Business Rules Functions".

To test a decision function using an Oracle Business Rules function:

  1. Confirm that your dictionary is valid.

    For more information on dictionary validation, see Section 4.4.4, "How to Validate a Dictionary"

  2. In Rules Designer, select the Functions navigation tab.

  3. In the Functions area click the Create... icon.

  4. Enter the function name in the Name field, or use the default name.

  5. Select the return type from the Return Type list.

    For a test function, select boolean.

  6. In the Arguments table, confirm that there are no arguments. For a test function, you cannot specify any arguments.

  7. In the Body area, enter the test function body.

    In the body of the test function you can call a decision function using assign new to call and get the return value of the decision function (in the body of the test function you create input facts, call a decision function, and validate the facts output from the decision function).

    A decision function call returns a List. Thus, to test a decision function in a test function you do the following:

    • You create the input data as required for the decision function input arguments.

    • You call the decision function with the arguments you create in the test function.

    • You place results in a List, for example, in the following:

      assign new List resultsList = DecisionFunction_1(testScore)
      

    Figure 8-8 shows a test function that calls a decision function.

    Figure 8-8 Test Function to Call a Decision Function that Returns a List

    Description of Figure 8-8 follows

  8. Select the function and click the Test Function icon.

    The function is executed. The output is shown in a Function Test Result dialog, as Figure 8-9 shows.

    Figure 8-9 Test Function Results for Grade Test

    Description of Figure 8-9 follows

  9. Click OK to dismiss the Function Test Result dialog.

8.1.6 What You Need to Know About Testing Decision Functions

You can use Oracle Business Rules Functions to test decision functions from within Rules Designer. Keep the following points in mind when using a test function:

  • The Test Function icon is gray if the dictionary associated with the test Oracle Business Rules Function contains any validation warnings. The Test Function icon is only shown when the dictionary validates without warnings.

  • To enable logging you can call RL.watch.all(). For more information on RL Language functions, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules. In this guide, RL.watch.all() is an alias for the RL Language function watchAll().

  • As an alternative to the example shown in Figure 8-8, you can enter the function body that is shown in Example 8-1. This function runs and shows the RL.watch.all() output. The dialog shows "Test Passed" when the grade is in the B range as shown in Figure 8-10. The dialog shows "Test Failed" when the grade asserted is not in the B range, as shown in Figure 8-11.

    Example 8-1 Function Body with True or False Return Value

    call RL.watch.all()
    assign new TestScore testScore = new TestScore()
    modify (testScore, name: "Bill Reynolds", testName: "Math Test", testScore: 81)
    assign new TestGrade testGrade = (TestGrade)DecisionFunction_1(testScore).get(0)
    return testGrade.grade == Grade.B
    

    For the testScore value 81, this function returns "Test Passed" as shown in Figure 8-10. For the testScore value 91, this returns "Test Failed", as shown in Figure 8-11.

    Figure 8-10 Test Passed Test Function Output

    Description of Figure 8-10 follows

    Figure 8-11 Test Failed Test Function Output

    Description of Figure 8-11 follows

8.2 Testing Oracle Business Rules at Runtime

In a SOA application that uses Oracle Business Rules with a Decision Service you can test rules at runtime with Oracle Enterprise Manager Fusion Middleware Control Console Test function.

For more information on using the Test function, see Oracle Fusion Middleware Administrator's Guide for Oracle SOA Suite and Oracle Business Process Management Suite.

PKxM̓ÃPK[EZFOEBPS/descfunc.htmP Working with Decision Functions

6 Working with Decision Functions

This chapter describes how to use a decision function to call rules from a Java application, from a composite, or from a BPEL process.

The chapter includes the following sections:

6.1 Introduction to Decision Functions

A decision function is a function that is configured declaratively.

A decision function contains the following declarations:

  • input facts

  • rulesets and nested decision functions

  • output facts

A decision function performs the following operations:

  • Asserts inputs as rule facts into the Oracle Business Rules Engine working memory

  • Runs rulesets configured in the current decision function and in nested decision functions in order

  • Returns output facts from the Oracle Business Rules Engine working memory

You can create a decision function to simplify the use of Oracle Business Rules from a Java application or from a BPEL process. In a decision function the rules you want to use can be organized into several rulesets, and those rulesets can be executed in a prescribed order. Facts may flow to the first ruleset, and this ruleset may assert additional facts that flow to the second and subsequent rulesets until finally facts flow back to the decision function as decision function output.

6.2 Working with Decision Functions

A decision function is a function that is configured declaratively.

6.2.1 How to Add or Edit a Decision Function

You use Rules Designer to add a decision function.

To add a decision function:

  1. In Rules Designer, select the Decision Functions navigation tab.

  2. In the Decision Functions area, click the Create icon.

    A new Decision Function is created and an Edit Decision Function dialog is displayed, as shown in Figure 6-1.

    Figure 6-1 Edit Decision Function Dialog

    Description of Figure 6-1 follows

  3. Enter a name for the Decision Function in Name field.

  4. In the Description field, optionally enter a description.

  5. In the Rule Firing Limit field, select unlimited or a value. In some cases when you are debugging a decision function, you may want to enter a value for the rule firing limit. For more information, see Section 6.3.1, "What You May Need to Know About Rule Firing Limit Option for Debugging Rules".

  6. Select the Rule Firing Limit is Error. The system throws an error when the firing limit is reached.

  7. Select the appropriate decision function options:

    • Will be invoked as a Web Service: select whether the decision function will be invoked as a Web Service and provide the Web Service name.

    • Check Rule Flow: when selected, this option specifies that the rule flow is checked to ensure that facts of the appropriate type are either explicit inputs to the decision function or are asserted by rules in the rule flow. However, when this is selected this does not always produce useful information; there are cases where facts can be asserted in Java code that uses the decision function, but this code might not be available at design time. In this case, validation warnings may produced with Check Rule Flow selected may not be useful.

    • Stateless: when selected specifies the decision function is stateless. For more information, see Section 6.3.3, "What You May Need to Know About the Decision Function Stateless Option".

  8. In the Inputs tab, click Add to add inputs. For each input in the Inputs Table, select the appropriate options:

    • Name - enter an input name and press Enter or accept the default name.

    • Fact Type - select the appropriate fact type from the list.

    • Tree - When unselected, the input is asserted using the assert function. When selected, the input is asserted using the assertTree function. When selected it is expected that the input object or objects are the root of an object tree that is connected in one-to-many relationships with other objects using List properties. For more information, see Section 4.8, "Working with Tree Mode Rules".

    • List - When unselected, the input must be a single object and the assertion applies only to that single input object. When selected, the input must be a List of objects and the assertion applies to each object in the input List (java.util.List).

    • Description - Description of the input.

  9. In the Outputs tab, click Add to add outputs. For each output in the Outputs Table, select the appropriate options:

    • Name - enter an output name and press Enter or accept the default name.

    • Fact Type - select the appropriate fact type from the list.

    • Tree - When selected, this option sets a flag that enables certain design-time decision function argument checking. For an output argument, this option has no effect on runtime behavior. However, at design time in the case where several decision functions are called in a sequence, it is useful to notate explicitly that the output of one decision function is a tree. This implies that the input of another decision function in the sequence is expecting a tree as an input. For more information, see Section 4.8, "Working with Tree Mode Rules".

    • List - When unselected the output is a single object. When selected the output is a group of objects. For more information on the behavior of the List option on an output argument, see Section 6.3.2, "What You May Need to Know to About Decision Function Arguments".

    • Description - Description of the output.

  10. In the Initial Actions tab, you can add actions that could be used to change input facts before they are asserted, change the ruleset stack, set the effective date, or even assert output facts. These actions could be used instead of rules, or to "set up" the environment for running rules.

    Consider a situation where a decision function (DF1) calls another decision function (DF2) using the Initial Actions tab. DF1 is configured to push Ruleset1 to the ruleset stack. DF2 is configured to push Ruleset2. In DF1, before the initial actions are executed, Ruleset1 is pushed to the ruleset stack. Then, when DF2 is called, Ruleset2 is also pushed. So when rules start running, rules from both rulesets fire because of the ruleset stack. If you want to push Ruleset2 (because in the initial actions, you are calling DF2), you can use initial actions in DF1 to clear the ruleset stack before calling DF2, and push Ruleset1 on the stack after calling DF2.

    You can add any required action ranging from assert, call, modify to even conditional actions such as if, else, elseif, while, for, if (advanced), and while (advanced) as shown in Figure 6-2.

    Figure 6-2 Adding Initial Actions

    Description of Figure 6-2 follows


    Note:

    If decision function DF1 contains DF2 in the Rulesets & Decision Functions tab, then DF2 may not have any initial actions.


    The if (advanced) and while (advanced) conditional actions accept only boolean values. For each of the action conditions, you can add different test form types.

  11. In the Rulesets and Decision Functions area, use the shuttle to move items from the Available box to the Selected box.

  12. Select an item in the Selected box, and click Move Up or Move Down as appropriate to order the rulesets and the decision functions.

To edit an existing decision function:

  1. In Rules Designer, select the Decision Functions navigation tab.

  2. Select the decision function to edit and click the Edit icon or double-click the decision function icon.

  3. Edit the appropriate decision function fields in the same manner as you would when you add a decision function.

To change the order of inputs:

  1. In Rules Designer, select the Decision Functions navigation tab.

  2. Select the decision function to edit and click the Edit icon or double-click the decision function icon.

  3. Select the input argument you want to move. Click either Move Up or Move Down to reorder the input argument.

To change the order of outputs:

  1. In Rules Designer, select the Decision Functions navigation tab.

  2. Select the decision function to edit and click the Edit icon or double-click the decision function icon.

  3. Select the output argument you want to move. Click either Move Up or Move Down to reorder the output argument.

To edit a Decision Function

  1. Click on the Decision Function tab.

    Decision Functions are displayed as shown in Figure 6-3.

  2. Select the Decision Function you want to edit and click the Edit icon.

    Edit Decision Function dialog is displayed.

  3. Make necessary changes using the process that you have used for adding a new Decision Function.

Figure 6-3 Editing Decision Function

Surrounding text describes Figure 6-3 .

6.3 What You Need to Know About Decision Functions

A decision function is a function that is configured declaratively.

6.3.1 What You May Need to Know About Rule Firing Limit Option for Debugging Rules

The Rule Firing Limit allows you to set the maximum number of steps (rule firings) that are allowed at runtime. Using this option and specifying a value other than unlimited can help you debug certain rule design problems and in some cases might help prevent java.lang.OutOfMemoryError errors at runtime. This is can be useful when debugging infinitely recursive rule firings.

When you choose a value other than unlimited, and choose Rule Firing Limit is Error, system throws an error once the limit is reached.

6.3.2 What You May Need to Know to About Decision Function Arguments

Oracle Business Rules generates a corresponding RL Language function for each decision function.

The signature of a generated decision function is similar to:

function <name>(InputFactType1 input1, ... InputFactTypeN inputN) returns List

In a decision function, each parameter is generated depending on the List option, with the decision function input, as follows:

  • Input argument, List option unselected: for FactTypei the input must be a single object and the assertion applies only to that single input object.

  • Input List option selected: List<FactTypei> the input must be a List of objects and the assertion applies to each object in the input List (java.util.List).

The generated RL Language function includes calls either to assert or assertTree for each argument, depending on the decision function Input option, Tree. When Tree is unselected the input is asserted using the assert function. When Tree is selected, the input is asserted using the assertTree function. When Tree is selected it is expected that the input object or objects are the root of an object tree that is connected in one-to-many relationships with other objects using List or array type properties.

For the decision function selected rulesets, as specified in the Rulesets and Decision Functions area Selected box, the generated RL Language function includes a call to run() with the selected rulesets in the selected ruleset stack order.

The generated RL Language function returns a list. The list has an element for each decision function output in order. If the output is declared to be a list, then the corresponding element is a list. However, if the output is not declared to be a list, then the corresponding element is the output fact or null (if there is no output fact of the declared type). If an output is not declared to be a list, and more than one output fact of the specified type is found in the working memory of Oracle Business Rules Engine, then an exception is thrown.

After you edit a decision function, for example, to change or add inputs and outputs, the changes are visible in BPEL for new Business Rule activities. However, the changes are not visible to existing Business Rule activities. For more information, see "Getting Started with Oracle Business Rules" in the Oracle Fusion Middleware Developer's Guide for Oracle SOA Suite.

6.3.3 What You May Need to Know About the Decision Function Stateless Option

A decision function supports either stateful or stateless operation. The Stateless checkbox in the Edit Decision Function dialog provides support for these two modes of operation.

By default the Stateless checkbox is selected which indicates stateless operation. With stateless operation, at runtime, the rule session is released after each invocation of the decision function.

When Stateless is deselected the underlying Oracle Business Rules object is kept in the memory of the Business Rules service engine, so that it is not given back to the Rule Session Pool when the operation is finished. A subsequent use of the decision function re-uses the cached RuleSession object, with all its state information from the previous invocation. Thus, when Stateless is deselected the rule session is saved for a subsequent request and a sequence of decision function invocations from the same process should always end with a stateless invocation.

PKPPPK[EZFOEBPS/limits.htm} Oracle Business Rules Files and Limitations

A Oracle Business Rules Files and Limitations

This appendix lists known naming constraints for Rules Designer files and names, and certain Rules SDK limitations.

This appendix includes the following sections:

A.1 Rules Designer Naming Conventions

This section covers Rules Designer naming conventions.

A.1.1 Ruleset Naming

Rules Designer enforces a limitation for ruleset names; a ruleset name must start with a letter and contain only letters, numbers, or the following characters: ".", "-", "_","", ":", "/", and single spaces. Letters include the characters (a to z and A to Z) and numbers (0 to 9).

A.1.2 Dictionary Naming

Rules Designer dictionary names can contain only the following characters, upper and lowercase letters (a to z and A to Z), numbers (0 to 9), and the underscore (_). Special characters are not valid in a dictionary name.

Rules Designer dictionary names are case preserving but case-insensitive. For example, the dictionary names Dictionary and DICT are both valid. If you create a dictionary named Test, then you can create another dictionary named TEST only if you first delete the dictionary named Test.

A.1.3 Alias Naming

Rules Designer alias names must begin with a letter and contain only letters, numbers, ".", "-", "_","", ":", "/", and single spaces.

A.1.4 XML Schema Target Package Naming

The Target Package Name that you specify for an XMLFact on the XML Schema Selector page is limited to ASCII characters, digits, and the underscore character.

PKdPK[EZFOEBPS/jsr2.htmj> Working with Oracle Business Rules and JSR-94 Execution Sets

E Working with Oracle Business Rules and JSR-94 Execution Sets

This appendix describes the Java Rule Engine API (JSR-94) specification that defines a standard Java runtime API to access a rule engine from a Java SE or Java EE client.

The appendix includes the following sections:

For more information, see:

E.1 Introduction to Oracle Business Rules and JSR-94 Execution Sets

Oracle Business Rules provides JSR-94 support. This allows you to create more portable rule-enabled applications.

You can create JSR-94 execution sets from Oracle Business Rules rulesets and you can create JSR-94 rule sessions from these execution sets. For more information, see Section E.2, "Creating JSR-94 Rule Execution Sets from Oracle Business Rules Rulesets".

You can access Oracle Business Rules rulesets and execute them against the Oracle Business Rules Engine using the JSR-94 API. For more information, see Section E.3, "Using the JSR-94 Interface with Oracle Business Rules".

Oracle Business Rules also provides extensions to the JSR-94 API that you may find useful. For more information, see Section E.3.4, "Using Oracle Business Rules JSR-94 Extensions".

E.2 Creating JSR-94 Rule Execution Sets from Oracle Business Rules Rulesets

To use JSR-94 with rules in RL Language text, you must map the rules to a JSR-94 rule execution set.

A JSR-94 rule execution set (rule execution set) is a collection of rules that are intended to be executed together. You also must register a rule execution set before running it. A registration associates a rule execution set with a URI; using the URI, you can create a JSR-94 rule session.


Note:

In Oracle Business Rules, a JSR-94 rule execution set registration is not persistent. Thus, you must register a rule execution set programmatically using a JSR-94 RuleExecutionSetProvider interface.


For more information, see Section E.3.1, "Creating a Rule Execution Set with createRuleExecutionSet".

E.2.1 Creating Rule Execution Set with Oracle Business Rules RL Language Text

You can use JSR-94 with RL Language rulesets saved as text, where the Oracle RL text is directly included in the rule execution set. For more information, see "Using the Extended createRuleExecutionSet to Create a Rule Execution Set" for information about JSR-94 extensions that assist you in including RL Language text.

To create a rule execution set from Oracle Business Rules Oracle RL language text:

  1. Specify the RL Language mapping information in an XML document. Table E-1 shows the mapping elements required to construct a rule execution set. Example E-1 shows a sample XML document for mapping RL Language text to a JSR-94 rule execution set.

  2. You then use the XML document with the JSR-94 administration APIs to create a rule execution set. The resulting rule execution set is registered with a JSR-94 runtime (using a RuleAdministration instance).

Table E-1 Oracle Business Rules Oracle RL Language Text XML Mapping Elements for JSR-94

ElementDescription

<rule-source>

Includes an <rl-text> tag containing explicit RL Language text containing an Oracle Business Rules ruleset. Multiple <rule-source> tags can be used to specify multiple rulesets (specified in the order in which they are interpreted).

<ruleset-stack>

Specifies a list of rulesets that form the initial ruleset stack. The order of the rulesets in the list is from the top of the stack to the bottom of the stack.



Note:

In the <rl-text> element the contents must escape XML predefined entities. This includes the characters '&', '>', '<', '"', and '\''.


Example E-1 XML Mapping File for Rulesets Defined in an Oracle RL Program

<rule-execution-set xmlns="http://xmlns.oracle.com/rules/jsr94/configuration"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
    <name>CarRentalDemo</name>
    <description>The Car Rental Demo</description>
    <rule-source>
        <rl-text>
         ruleset DM {
            fact class carrental.Driver {
               hide property ableToDrive, driverLicNum, licIssueDate, licenceType,
               llicIssueDate, numPreAccidents, numPreConvictions,
               numYearsSinceLicIssued, vehicleType;
            };

               final String DeclineMessage = &quot;Rental declined &quot;;

               public class Decision  supports xpath {
                  public String driverName;
                  public String type;
                  public String message;
              }

               function assertXPath(String package,
                                    java.lang.Object element, String xpath) {
                  //RL literal statement
                  main.assertXPath( package, element, xpath );
               }

               function println(String message) {
                  //RL literal statement
                  main.println(message);
               }

               function showDecision(DM.Decision decision) {
                  //RL literal statement
                  DM.println( &quot;Rental decision is &quot; + decision.type +
                              &quot; for driver &quot; + decision.driverName +
                              &quot; for reason &quot; + decision.message);
               }
         }
        </rl-text>
    </rule-source>
    <rule-source>
        <rl-text>
            ruleset vehicleRent {
                rule UnderAge {
                    priority = 0;
                    if ((fact carrental.Driver v0_Driver &amp;&amp;
                        (v0_Driver.age &lt; 19))) {
                            DM.println( &quot;Rental declined: &quot; + v0_Driver.name +
                            &quot; Under age, age is: &quot; + v0_Driver.age);
                            retract(v0_Driver);
                    }
                }
            }
        </rl-text>
    </rule-source>
    <ruleset-stack>
        <ruleset-name>vehicleRent</ruleset-name>
    </ruleset-stack>
</rule-execution-set>

E.2.2 Creating a Rule Execution Set from Oracle RL Text Specified in a URL

You can use JSR-94 with Oracle RL rulesets specified using a URL. For more information, see "Using the Extended createRuleExecutionSet to Create a Rule Execution Set" for information about JSR-94 extensions that assist you in specifying a URL.

To create a rule execution set from Oracle RL text specified in a URL:

  1. Specify the Oracle RL mapping information in an XML document. Table E-2 shows the mapping elements required to construct a rule execution set. Example E-2 shows a sample XML document for mapping Oracle RL text to a JSR-94 rule execution set.

  2. You then use the XML document with the JSR-94 administration APIs to create a rule execution set. The resulting rule execution set is registered with a JSR-94 runtime (using a RuleAdministration instance).

Table E-2 Oracle Business Rules Oracle RL URL XML Mapping Elements for JSR-94

ElementDescription

<rule-source>

Includes an <rl-url> tag containing a URL that specifies the location of RL Language text. Multiple <rule-source> tags can be used to specify multiple rulesets (in the order in which they are interpreted).

<ruleset-stack>

Specifies a list of rulesets that form the initial ruleset stack. The order of the rulesets in the list is from the top of the stack to the bottom of the stack.


Example E-2 XMP Mapping File for Rulesets Defined in a URL

<?xml version="1.0" encoding="UTF-8"?>
<rule-execution-set xmlns="http://xmlns.oracle.com/rules/jsr94/configuration"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
    <name>CarRentalDemo</name>
    <description>The Car Rental Demo</description>
    <rule-source>
        <rl-url>
            file:rl/DM.r1
        </rl-url>
    </rule-source>
    <rule-source>
        <rl-url>
            file:r1/VehicleRent.r1
        </rl-url>
    </rule-source>
    <ruleset-stack>
        <ruleset-name>vehicleRent</ruleset-name>
    </ruleset-stack>
</rule-execution-set>

E.2.3 Creating Rule Execution Sets with Rulesets from Multiple Sources

A rule execution set may contain rules that are derived from multiple sources and the sources may be a mix of Rules Designer defined rulesets and RL Language rulesets. In this case, the XML element <rule-execution-set> set contains multiple <rule-source> elements, one for each source of rules. You must list each <rule-source> in the order in which they are to be interpreted in Rules Engine.


Note:

For this Oracle Business Rules release, a JSR-94 rule execution set can only reference one Rules Designer dictionary.


E.3 Using the JSR-94 Interface with Oracle Business Rules

This section describes some Oracle Business Rules specific details for JSR-94 interfaces.

E.3.1 Creating a Rule Execution Set with createRuleExecutionSet

The RuleExecutionSetProvider and LocalRuleExecutionSetProvider interfaces in javax.rules.admin include the createRuleExecutionSet to create a RuleExecutionSet object.

For the remaining createRuleExecutionSet methods, the first argument is interpreted as shown in Table E-3.

Table E-3 First Argument Types for createRuleExecutionSet Method

ArgumentDescription

org.w3c.dom.Element

Specifies an instance of the <rule-execution-set> element from the configuration schema.

java.lang.String

Specifies a URL that specifies the location of an XML document that is an instance of the <rule-execution-set> element from the configuration schema.

java.io.InputStream

Specifies an input stream that is used to read an XML document that is an instance of the <rule-execution-set> element from the configuration schema.

java.io.Reader

Specifies a character reader that is used to read an XML document that is an instance of the <rule-execution-set> element from the configuration schema.



Note:

JSR-94 also includes createRuleExecutionSet methods that take a java.lang.Object argument, which is intended to be an abstract syntax tree for the rule execution set. In Oracle Business Rules for Oracle Fusion Middleware 11g Release 1 (11.1.1), using these methods with this argument is not supported. Invoking these methods with a java.lang.Object argument gives a RuleExecutionSetCreateException exception.


The second argument to the createRuleExecutionSet methods is a java.util.Map of vendor-specific properties.

E.3.2 Creating a Rule Session with createRuleSession

Clients create a JSR-94 rule session using the createRuleSession method in the RuleRuntime class. This method takes a java.util.Map argument of vendor-specific properties. This argument can be used to pass in any of the properties defined for the Oracle Business Rules oracle.rules.rl.RuleSession. If a rule execution set contains URL or repository rule sources, the rules from those sources are fetched on the creation of each new RuleSession.

E.3.3 Working with JSR-94 Metadata

JSR-94 allows for metadata for rule execution sets and rules within a rule execution set. The Oracle Business Rules implementation does not add any additional metadata beyond what is in the JSR-94 specification. The rule execution set description is an optional item and thus may not be present. If it is not present, the empty string is returned. For rules, only the rule name is available and the description is initialized with an empty string.

E.3.4 Using Oracle Business Rules JSR-94 Extensions

This section covers the following extensions provided in the JSR-94 implementation classes.

E.3.4.1 Using the Extended createRuleExecutionSet to Create a Rule Execution Set

Oracle Business Rules provides a helper function to facilitate creating the XML control file required as input to create a RuleExecutionSet.

The helper method createRuleExecutionSet is available in the RLLocalRuleExecutionSetProvider class. The createRuleExecutionSet method has the following signature:

RuleExecutionSet createRuleExecutionSet(String name,
                                        String description,
                                        RuleSource[] sources,
                                        String[] rulesetStack,
                                        Map properties)

Table E-4 describes the createRuleExecutionSet arguments.

Table E-4 createRuleExecutionSet Arguments

ArgumentDescription

name

Specifies the name of the rule execution set.

description

Specifies the description of the rule execution set.

sources

Specifies an array of specifications for the sources of rules. The RuleSource is an interface that the following classes implement:

  • RLTextSource: RL Language text for RL Language text.

  • RLUrlSource: RL Language URL for a URL to RL Language text.

For more information, see the oracle.rules.jsr94.admin package in Oracle Fusion Middleware Java API Reference for Oracle Business Rules.

rulesetstack

Specifies the initial contents of the RL Language ruleset stack to be set before each time the rules are executed. The contents of the array should be ordered from the top of stack (0th element) to the bottom of stack (last element).

properties

Oracle specific properties.


E.3.4.2 Invoking an RL Language Function in JSR-94

In a stateful interaction with a JSR-94 rule session, a user may want the ability to invoke an arbitrary RL Language function. The class that implements the JSR-94 StatefulRuleSession interface provides access to the callFunction methods in the oracle.rules.rl.RuleSession class.

Example E-3 shows how you can to invoke an RL Language function with no arguments in a JSR-94 StatefulRuleSession.

Example E-3 Using CallFunction with a StatefulRuleSession

import javax.rules.*;
...
StatefulRuleSession session;
...
((oracle.rules.jsr94.RLStatefulRuleSession) session).callFunction("myFunction");
PK{jjPK[EZFOEBPS/facts.htm Working with Facts and Bucketsets

3 Working with Facts and Bucketsets

This chapter describes the Oracle Business Rules data model element called Facts, which are the objects that rules reason on. It also covers another element called Bucketsets that define groupings of fact property values.

The chapter includes the following sections:

3.1 Introduction to Working with Facts and Bucketsets

In Rules Designer, you make business objects and their methods known to Oracle Business Rules using fact types that are part of a data model.

You can create fact types and bucketsets before you create rules.

In Rules Designer you can work with the following kinds of facts:

  • XML Facts: XML Facts are imported from existing sources by specifying XML Schema. You can add aliases to imported XML Facts or use XML Facts with RL Facts to change the data model according to your business needs.

    For more information, see Section 3.2, "Working with XML Facts".

  • Java Facts: Java Facts are imported from existing sources. You can add aliases to Java Facts or use them with RL Facts to target the data model to business needs. Java Facts are also used to import supporting Java classes for use with the rules or Decision Tables that you create.

    For more information, see Section 3.3, "Working with Java Facts".

  • RL Facts: RL Facts are the only kind of facts that you can create directly and do not have an external source. All other types of Oracle Business Rules facts are imported. An RL Fact is similar to a relational database row or a JavaBean without methods. An RL Fact contains a list of properties of types available in the data model, either RL Facts, Java Facts, or primitive types. You can use RL Facts to extend a Java application object model by providing virtual dynamic types.

    For more information, see Section 3.4, "Working with RL Facts".

  • ADF Business Components Facts: ADF Business Components Facts allow you to use ADF Business Components as Facts in rules and in Decision Tables. By using ADF Business Components Facts you can assert view object graphs representing the business objects upon which rules should be based, and let Oracle Business Rules deal with the complexities of managing the relationships between the various related view objects in the view object graph.

    For more information, see Section 3.5, "Working with ADF Business Components Facts".

You typically use Java fact types and XML fact types to create rules that examine the business objects in a rule-enabled application, or to return results to the application. You use RL Language fact type definitions to create intermediate facts that can trigger other rules in the Rules Engine. ADF Business Components fact types enables you to use ADF Business Components as Facts in rules and in Decision Tables.

In Oracle Business Rules, facts that you can run against the rules are data objects that have been asserted. Each object instance corresponds to a single fact. If an object is re-asserted (whether it has been changed or not), the Rules Engine is updated to reflect the new state of the object. Re-asserting the object does not create a fact. To have multiple facts of a particular fact type, separate object instances must be asserted.

You can create bucketsets to define a list of values or a range of values of a specified type. After you create a bucketset, you can associate the bucketset with a business term of matching type. When a bucketset is associated with a business term, Oracle Business Rules uses the buckets that you define as constraints for the values for the business terms in rules or in Decision Tables.

For more information, see:

3.2 Working with XML Facts

The XML fact type allows XML Schema types, elements, and attributes to be used when writing rules. Elements and types defined in XML Schema can be imported into the data model and can then be used to create rules and Decision Tables, just as with Java fact types and RL Fact types. The mapping between the XML Schema definition and the XML Fact types uses the Java Architecture for XML Binding (JAXB). By default, Oracle Business Rules uses the JAXB 2.0 shipped with the Oracle Application Server. JAXB as defined in JSR-222 provides a mapping between the types, names, and conventions in an XML Schema definition and the available types, allowed names and conventions in Java. For example, an element named order-id and of type xsd:integer is mapped to a Java Bean property named orderID of type BigInteger (and xsd:int type maps to Java int).

Thus, with Oracle Business Rules if you have an XML document that contains data associated with your application and you have the schema associated with the XML document then you can use Rules Designer to define rules based on elements that you specify from the XML Schema.

To create XML fact types, perform the following steps:

  1. Define or obtain an XML Schema.

  2. Use Rules Designer to import the XML Schema into a dictionary. This step uses the JAXB compiler to generate Java classes from the XML Schema. After you compile the XML Schema, you select the desired elements from the schema to add XML Facts in the data model and import the generated JAXB classes into the data model. For more information on these steps, see Section 3.2.1, "How to Import XML Schema and Add XML Facts".

  3. Write rules or create Decision Tables based on these XML Facts that you added to the data model. For more information, see Section 4.3, "Working with Rules" and Section 5.2, "Creating Decision Tables".

Elements and types defined in XML Schema can be imported into the data model so that instances of types can be created, asserted, modified, and retracted by rules. Most XML documents describe hierarchical information, where each element contains subelements. It is common for users to want to write individual rules based on multiple elements in this hierarchy, and the hierarchical relationship among the elements. In Oracle Business Rules the default behavior when you assert a fact is to only assert the single fact instance, and none of the child objects it may reference in the hierarchy of subelements. When you create rules or a Decision Table it is often desirable to assert an entire hierarchy of elements based on a reference to a root element. Oracle Business Rules provides the assertTree action type that allows for a recursive assert for a hierarchy. For more information, see Section 4.8, "Working with Tree Mode Rules".

3.2.1 How to Import XML Schema and Add XML Facts

Before you can use XML Schema definitions in a data model you must import XML schema. This step generates the JAXB classes and makes the generated classes and packages associated with the XML schema visible in Rules Designer.

To import XML schema and add XML facts:

  1. In Rules Designer, select the Facts navigation tab.

  2. Select the XML Facts tab on the Facts navigation tab, as shown in Figure 3-1.

    Figure 3-1 The XML Facts Tab in Rules Designer

    Description of Figure 3-1 follows

  3. In the XML Facts tab, click Create.... This displays the Create XML Fact dialog.

  4. In the Create XML Fact dialog, in the Source Schemas area, click Add Source Schema.... This displays the Add Source Schema dialog, as shown in Figure 3-2.

    Figure 3-2 XML Fact: Add Source Schema Dialog

    Description of Figure 3-2 follows

  5. In the Add Source Schema dialog,

    • Enter the location of the XML Schema you want to import, or click Browse to locate the XML schema in the Schema Location field. During the import the file is copied into the project.


      Note:

      Typically, the XML schema (xsd) file is located inside the xsd folder because any XML schema that is created needs to be stored inside the xsd folder under SOAContent.


    • Accept the default path or enter the directory where you want Rules Designer to store the JAXB-generated Java source and class files in the JAXB Classes Directory field.

    • Enter a target package name or leave this field empty in the Target Package field. If you leave this field empty the JAXB classes package name is generated from the XML target namespace of the XML schema using the default JAXB XML-to-Java mapping rule or explicitly defined package name using annotations, or "generated" if no namespace or annotation is defined. Using the schema namespace is preferred.

      For example, the namespace http://www.oracle.com/as11/rules/demo is mapped to com.oracle.as11.rules.demo.

    • Click OK.

      Rules Designer processes the schema and compiles the JAXB, so depending on the size of the schema this step may take some time to complete. When this step completes Rules Designer displays the Create XML Fact dialog with the Target Classes area updated to include the JAXB classes, as shown in Figure 3-3.

  6. Figure 3-3 XML Fact: Create XML Fact Dialog

    Description of Figure 3-3 follows

  7. In the Create XML Fact dialog, in the Target Classes area, select the classes you want to import as XML fact types.

  8. Click OK.

3.2.2 How to Display and Edit XML Facts

To work with an XML Fact, in Rules Designer open the Edit XML Fact dialog.

To display and edit XML facts:

  1. In Rules Designer, select the Facts navigation tab.

  2. Select the XML Facts tab on the Facts navigation tab.

  3. In the XML Facts table, double-click the icon for the XML Fact you want to edit. This displays the Edit XML Fact dialog, as shown in Figure 3-4.

    Figure 3-4 Edit XML Fact Dialog

    Description of Figure 3-4 follows

The Edit XML Fact dialog includes the fields shown in Table 3-1.

Table 3-1 XML Fact: Edit XML Fact Dialog Fields

FieldDescription

Name

Displays the XML Fact name. You cannot change the name of JAXB generated class.

Alias

Enter the XML Fact alias. You can change this value. This defaults to the unqualified name of the class.

Super Class

Displays Java super class associated with this fact.

Description

Enter the XML Fact description.

XML Name

Displays the XML name associated with the XML Fact.

Generated From

Displays the XML schema file that was the source for the XML Fact when it was copied into the business rules data model.

Visible

Select to show the XML Fact in lists in Rules Designer. XML Facts often reference other XML Facts, forming a tree. You should make all the XML fact types visible that contain properties that you reference in rules.

Support XPath Assertion

Select to enable XPath assertion for the fact. This feature is provided for backward compatibility only. Typically, this option is not used.

Attributes area

Select the available constructors, properties, methods, or fields associated with the JAXB class for the XML Fact to display or edit.


3.2.3 How to Reload XML Facts with Updated Schema

If an XML schema changes in a project, the schema must be reimported into the Oracle Business Rules dictionary. When you reimport the schema, Oracle Business Rules uses JAXB to recompile all source schemas for every XML fact type and updates the XML fact type definitions with the updated XML schema definitions. You should reimport facts if you changed the schema or classes and you want to use the changed schema or classes at runtime.


Note:

When the XML schema on which an XML fact is based changes, on reimporting the schema, the facts are updated and imported into the base dictionary. When working with facts in a linked dictionary, you need to reload the XML facts for the changed schema from the base dictionary instead of the linked dictionary.


To reimport XML facts:

  1. In Rules Designer, select the Facts navigation tab.

  2. Select the XML Facts tab on the Facts navigation tab.

  3. On the XML Facts page, click the Reload XML Facts from Updated Schemas icon.

After the reimport operation you need to correct any validation warnings that may be caused by incompatible changes (for example, the updated schema may include a change that removed a property that is referenced by a rule).

3.2.4 What You Need to Know About XML Facts

Keep the following points in mind when you work with XML Facts:

  • When writing rules, the assertTree action type is available only in advanced mode. For more information on creating rules using assertTree, see Section 4.8, "Working with Tree Mode Rules".

  • When creating a decision function, the tree option for the input types defines whether assert or assertTree is used to put the input facts in working memory. For more information on assertTree, see Section 4.8, "Working with Tree Mode Rules".

  • When XML Schema contain a restriction definition, this allows a user to restrict the types that are valid for use in an element. A common use of restriction is to define an enumeration of strings which can be used for an element, as shown in Example 3-1.

    Example 3-1 XML Schema Restriction Example

    <xs:simpleType name="status-type">
            <xs:restriction base="xs:string">
                <xs:enumeration value="manual"/>
                <xs:enumeration value="approved"/>
                <xs:enumeration value="rejected"/>
            </xs:restriction>
    </xs:simpleType>
    

    Oracle JAXB 2.0 maps a restriction to a Java enum type. When you use Rules Designer to import either a Java enum type or an element with an XML restriction, the static final fields representing the enums are available for use in expressions. Additionally, Oracle Business Rules creates a bucketset for each enum containing all of the enum values and null. For more information on bucketsets, see Section 3.6, "Working with Bucketsets".

  • There is a default version of the JAXB binding compiler supplied with Oracle Application Server. You can use a different JAXB binding compiler. However, to use a different JAXB binding compiler you must manually perform the XML schema processing and then import the generated Java packages and classes into the data model as Java Facts.

    For more information about JAXB, see

    http://java.sun.com/webservices/jaxb/

  • You should reimport facts if you changed the schema or classes and you want to use the changed schema or classes at runtime. You should correct any validation warnings that may be caused by incompatible changes (for example, removing a property that is referenced by a rule). For more information, see Section 3.2.3, "How to Reload XML Facts with Updated Schema".

  • Most users should not need to use the ObjectFactory or import it. If you do need to import and use the ObjectFactory, then use a different package name for every XML Schema that you import; otherwise the different ObjectFactory classes conflict.

  • The use of XML schema with elements that have minOccurs="0" and nillable="true" has special handling in JAXB. For more information, see Section C.12, "Why do XML Schema with xsd:string Typed Elements Import as Type JAXBElement?".

  • The default element naming conventions for JAXB can cause XML schema containing the underscore character in XML-schema element names to fail to compile. For more information, see Section D.7, "Why Does XML Schema with Underscores Fail JAXB Compilation?".

  • There are certain restrictions on the types and names of inputs for the Decision Service. For more information, see Section D.8, "How Are Decision Service Input Output Element Types Restricted?".

  • The built-in dictionary includes support for the Java wrappers Integer, Long, Short, Float, Double, BigDecimal, and BigInteger. These types can appear in XML Fact Types.

3.3 Working with Java Facts

In Rules Designer, importing a Java Fact makes the Java classes and their methods become visible to Rules Designer. Rules Designer does not copy the Java code or bytecode into the data model or into the dictionary.

A Java fact type allows selected properties and methods of a Java class to be imported to the Rules Engine so that rules can access, create, modify, and delete instances of the Java class.

Importing a Java fact type allows the Rules Engine to access and use public attributes, public methods, and bean properties defined in a Java class (bean properties are preferable because they can be modified using the modify action).

3.3.1 How to Import Java Classes and Define Java Facts

Before you can use Java Facts in rules and in Decision Tables, you must make the classes and packages that contain the Java Facts available to Rules Designer. To do this you use Rules Designer to specify the classpath that contains the Java classes, and then you import the Java Facts.

To import and define Java Facts:

  1. In Rules Designer, select the Facts navigation tab.

  2. Select the Java Facts tab on the Facts navigation tab as shown in Figure 3-5.

    Figure 3-5 The Java Facts Table in the Facts Navigation Tab

    Description of Figure 3-5 follows

  3. In the Java Facts tab, click Create.... This displays the Create Java Fact dialog, as shown in Figure 3-6.

    Figure 3-6 Adding a Java Fact

    Description of Figure 3-6 follows

  4. In the Create Java Fact dialog, if the classpath that contains the classes you want to import is not shown in the Classpath area, then click Add to Classpath. This displays the Choose Directory/Jar dialog.

    The default Rules Designer classpath includes three packages, java, javax, and org. These packages contain classes that Rules Designer lets you import from the Java runtime library (rt.jar). Rules Designer does not let you remove these classes from the Classes area (and the associated classpaths are not shown in the Classpaths area).

  5. In the Choose Directory/Jar dialog, browse to select the classpath or jar file to add. By default, the output directory for the project is on the import classpath and any Java classes in the project should appear in the Classes importer. If they do not appear, execute the Build action for the project.

  6. Click Open. This adds the classpath or jar file and updates the Classes area.

  7. In the Create Java Fact dialog, in the Classes area select the packages and classes to import.

  8. Click OK. This updates the Java Facts table in the Java Facts tab.

3.3.2 How to Display and Edit Java Facts

To display or edit Java Facts after you import the Java Facts, use the Edit Java Fact dialog.

To display and edit Java facts:

  1. In Rules Designer, click the Facts navigation tab.

  2. Select the Java Facts tab in the Facts navigation tab.

  3. In the Java Facts table, double-click the Java Fact you want to edit. This displays the Edit Java Fact dialog as shown in Figure 3-7.

    Figure 3-7 Edit Java Fact Dialog

    Description of Figure 3-7 follows

The Edit Java Fact dialog includes the fields shown in Table 3-2.

Table 3-2 Edit Java Fact Dialog Fields

FieldDescription

Class

Displays the Java Fact class for the source associated with the Java Fact.

Alias

Enter the Java Fact alias.

Super Class

Displays Java super class associated with this fact.

Description

Enter the Java Fact description.

Visible

Select to show the Java Fact in lists in Rules Designer.

Attributes area

Select the available class properties, constructors, methods, or fields associated with the Java class for the Java Fact act to display or edit.


3.3.3 What You Need to Know About Java Facts

When you define Java Facts you need to know the following:

  • On Windows systems, you can use a backslash (\) or a slash (/) to specify the classpath in the Classpath area. Rules Designer accepts either path separator.

  • Classes and interfaces that you use in Rules Designer must adhere to the following rules: If you are using a class or interface, only its superclass or one of its implemented interfaces may be made visible.

  • When you specify the classpath you can specify a JAR file, a ZIP file, or a full path for a directory.

  • When you specify a directory name for the classpath, the directory specifies the classpath that ends with the directory that contains the "root" package (the first package in the full package name). Thus, if the classpath specifies a directory, Rules Designer looks in that tree for directory names matching the package name structure.

    For example, to import a class cool.example.Test1 located in c:\myprj\cool\example\Test1.class, specify the classpath value, c:\myprj.

  • You should reimport facts if you change the classes. After the reimport operation you may see validation warnings due to class changes. You should correct any validation warnings that may be caused by incompatible changes (for example, removing a property that is referenced by a rule).

3.4 Working with RL Facts

RL Facts are the only kind of facts that you can create directly and do not have an external source. All other types of Oracle Business Rules facts are imported. An RL Fact is similar to a relational database row or a JavaBean without methods. An RL Fact contains a list of properties of types available in the data model, either RL Fact, Java Fact, or primitive types. You can use an RL Fact to extend a Java application object model by providing virtual dynamic types.

For example:

IF customer spent $500 within past 3 months

THEN customer is a Gold Customer

This rule might use a Java Fact to specify the customer data and also use an action that creates an RL Fact, Gold Customer. A rule might be defined to use a Gold Customer fact, as follows:

IF customer is a Gold customer

THEN offer 10% discount

This rule uses the RL Fact named Gold Customer. This rule then infers, using the Gold Customer fact, that if a customer spent $500 within the past 3 months, then the customer is eligible for a 10% discount. In addition rules could specify other ways that a customer becomes a Gold Customer.

For testing and prototyping with Rules Designer you can create RL Facts and use the RL Facts to write and test rules before you import a schema and switch to XML Facts (you might need to wait for an approved XML schema to be created or to be made available). Switching from RL Facts to corresponding XML Facts involves the following steps:

  1. Delete the RL Facts (this action shows validation warnings in the rules or Decision Tables you created that use these RL Facts).

  2. Import the XML Facts and give the facts and their properties aliases that match the names of the RL Facts and properties you deleted in step 1.

  3. This process should remove the validation warnings if the XML Fact and property aliases and types match those of the RL Facts that you remove.

3.4.1 How to Define RL Facts

You add RL Facts from the Facts navigation tab.

To define RL facts:

  1. In Rules Designer, select the Facts navigation tab.

  2. Select the RL Facts tab in the Facts navigation tab as shown in Figure 3-8.

    Figure 3-8 RL Facts Tab in Rules Designer

    Description of Figure 3-8 follows

  3. In the RL Facts tab, click Create.

  4. In the RL Facts table, in the Name field, enter the name for the RL Fact or accept the default name.

  5. In the RL Facts table, in the Description field, enter a description or accept the default, no description.

3.4.2 How to Display and Edit RL Facts and Add RL Fact Properties

You add properties to RL Facts using the Edit RL Facts dialog.

To display and edit RL facts and add RL fact properties:

  1. In Rules Designer, select the Facts navigation tab.

  2. In the RL Facts tab, double-click the icon for the RL Fact to display or edit the fact. This displays the Edit RL Fact dialog, as shown in Figure 3-9.

    Figure 3-9 Edit RL Fact Dialog

    Description of Figure 3-9 follows

  3. To add RL Fact properties, on the Edit RL Fact dialog in the Properties area, click Create.

    1. In the Name field, enter the property name.

    2. In the Type field, select a type from the list or enter a property type.

    3. To associate a bucketset with the property, from the list in the Bucketset field, select a bucketset.

    4. To associate an initial value with the property enter a value in the Initial Value field.

  4. Add additional properties by repeating these steps, as required.

  5. Click OK.

3.4.3 What You Need to Know About RL Facts

When you add properties to RL Facts using the Edit RL Facts dialog, in the Properties area the Initial Value field provides a list of possible values as shown in Figure 3-10.

Figure 3-10 Setting RL Fact Property Initial Value

Description of Figure 3-10 follows

When you are working with some fields in Rules Designer, the initial values list or other lists may be empty as shown in Figure 3-11. In this case the list is an empty box. Thus, when Rules Designer does not find options to assist you in entering values, you must supply a value directly in the text entry area or click the Expression Builder icon to display the expression builder dialog.

Figure 3-11 RL Fact Empty List Options for Initial Value Field

Description of Figure 3-11 follows

3.5 Working with ADF Business Components Facts

ADF Business Components Facts allow you to use ADF Business Components as Facts in rules and in Decision Tables. By using ADF Business Components Facts you can assert view object graphs representing the business objects upon which rules should be based, and let Oracle Business Rules deal with the complexities of managing the relationships between the various related view objects in the view object graph.

For more information, see Chapter 10, "Working with Oracle Business Rules and ADF Business Components".

3.5.1 How to Import and Define ADF Business Components Facts

When an ADF Business Components view object is imported, an ADF Business Components fact type is created which has a property corresponding to each attribute of the view object.

To add ADF Business Components facts:

  1. Click the Facts navigation tab and select the ADF-BC Facts tab. This displays the ADF-BC Facts table, as shown in Figure 3-12.

    Figure 3-12 ADF Business Components Facts Tab

    Description of Figure 3-12 follows

  2. Click Create.... This displays the ADF Business Components Fact dialog, as shown in Figure 3-13.

    Figure 3-13 Create ADF-BC Fact Dialog

    Description of Figure 3-13 follows

  3. In the Connection field, from the list, select the connection which your ADF Business Components objects use. The Search Classpath area shows a list of classpaths. For more information, see Section 3.5.2, "What You Need to Know About ADF Business Components Fact Classpaths".

  4. In the View Definition field, select the name of the view object to import.

  5. Click OK. This displays the Facts navigation tab, as shown in Figure 3-14. Note that the imported fact includes a validation warning. For information on how to remove this validation warning, see Section 3.5.3, "What You Need to Know About ADF Business Components Circular References".

    Figure 3-14 ADF Business Components Facts in Rules Designer

    Description of Figure 3-14 follows

3.5.2 What You Need to Know About ADF Business Components Fact Classpaths

In the classpath list shown in the Search Classpath area in the Create ADF Business Components Fact dialog one of the listed classpaths allows you to see the view object definitions available in your project. In this dialog you only need to click Add to Classpath when you need to use a classpath that is not available to your project (this case should be very rare).

3.5.3 What You Need to Know About ADF Business Components Circular References

ADF Business Components Facts can include a circular reference, as shown in Figure 3-14. When this warning is shown in the Business Rule validation log you need to manually resolve the circular reference. To do this you must deselect the Visible checkbox for one of the properties that is involved in the circular reference.

3.5.4 What You Need to Know About ADF Business Components Facts

Each ADF Business Components fact type contains a property named ViewRowImpl that references the oracle.jbo.Row instance that the fact instance represents and a property named key_values which points to an oracle.rules.sdk2.decisionpoint.KeyChain object that may be used to retrieve the set of key-values for this row and its parent rows.

When working with ADF Business Components Facts you should know the following:

  • Relationships between view object definitions are determined by introspection of attributes on the View Definition, specifically, those attributes which are View Link Accessors.

    The ADF Business Components fact type importer correctly determines which relationships are 1-to-1 and which are 1-to-many, and generates definitions in the dictionary accordingly. For 1-to-many relationships the type of the property generated is a List, which contains facts of the indicated type at runtime.

  • It is not possible to use ADF Business Components fact types which have cyclic type dependencies. These cycles must be broken by the deselecting the Visible checkbox for at least one property involved in the cycle.

  • ADF Business Components fact types are not Java fact types and do not allow invoking methods on any explicitly created implementation classes for the view object.

    If you need to call such methods then add the view object implementation to the dictionary as a Java fact type instead of as an ADF Business Components fact type. In this case, all getters and setters and other methods become available but the trade-off is that related view objects become inaccessible and, should related view object access be required, these relationships must be explicitly managed.

  • Internally, ADF Business Components fact types are instances of RL fact types.

    Thus, you cannot assert ADF Business Components view object instances directly to a Rule Session, but must instead use the helper methods provided in the MetadataHelper and ADFBCFactTypeHelper classes. For more information, see Oracle Fusion Middleware Java API Reference for Oracle Business Rules.

3.6 Working with Bucketsets

You can create a bucketset to define a list of values or a list of value ranges to limit the acceptable set of values for a fact or a property of a fact in Oracle Business Rules. You can define a bucketset as a Global Bucketset that allows reuse, where a bucketset is named and stored in the data model, or as a Local Bucketset that is specified when you define a Decision Table and only applies to one condition expression. For more information on using a local bucketset, see Section 5.2.2, "How to Add Condition Rows to a Decision Table".

You can use Bucketsets for the following:

  • You can associate fact type properties with bucketsets. This allows you to limit the acceptable set of values for a property of a fact. For more information, see Section 3.7.1, "How to Associate a Bucketset with a Fact Property".

  • In a Decision Table a bucketset defines a list of values or value ranges in the condition expressions that are part of the Decision Table. The bucketset values or ranges determine, for each condition expression in a Decision Table, that it has two or more possibilities. Using a bucketset each possibility in a condition expression is divided into groups or ranges where a cell specifies one Bucket of values from the bucketset (or possibly multiple buckets of values per cell). For example, if a bucketset is defined for colors, then the buckets could include a list of strings: "blue", "red", and "orange". A bucketset that includes integers could have three buckets, less than 1, 1 to 10, and greater than 10. For more information, see Section 5.2.2, "How to Add Condition Rows to a Decision Table".

  • You can associate globals, functions, and function arguments with bucketsets. Associating a bucketset with a global allows for design-time validation that an assigned value is limited to the values specified in the bucketset. Associating a bucketset with a function argument validates that the function is only called with values in the bucketset. Using bucketsets in this manner allows Rules Designer to report validation warnings for global values and function arguments that are assigned or passed a constant argument value that is not allowed. Associating a bucketset with a function automatically sets a Decision Table condition row to use that bucketset when the function is used as the expression for that condition row. This type of bucketset validation is "weak" in the sense that only design-time constant values are validated. No runtime checks are applied based on the globals or function arguments associated with bucketsets. For more information, see Section 3.7.2, "How to Associate a Bucketset with Functions or Function Arguments".

  • In addition to design-time validation you can use an LOV bucketset to provide options that are displayed in lists when entering expressions in IF/THEN rule tests and actions. For more information, see Section 4.11.3, "How to Use Bucketsets to Provide Options for Test Expressions".

There are three forms for bucketsets:

3.6.1 How to Define a List of Values Global Bucketset

A list of values bucketset lets you specify the type and the list of buckets for the bucketset.

For more information, see Section 3.6.5, "What You Need to Know About List of Values Bucketsets".

To define a list of values (LOV) global bucketset:

  1. From Rules Designer select the Bucketsets navigation tab.

  2. From the list next to the Create BucketSet... icon, select List of Values, as shown in Figure 3-15.

    Figure 3-15 Adding a List of Values Bucketset

    Description of Figure 3-15 follows

  3. Double-click the bucket icon for the bucket. This displays the Edit Bucketset dialog.

  4. In the Edit Bucketset dialog, enter the bucketset name in the Name column.

    Ensure that the bucketset name is not the same as the as a fact alias, because this would result in a validation errors as the following:

    RUL-05006: The fact type "Rating" has the same alias as an unrelated bucketset.
    
  5. In the Data Type column select a data type from list.

    For example, select String from the list.

  6. Click the Create icon to add a value.

  7. For each bucket that you add, do the following:

  8. Add additional values by clicking the Create icon as needed for the bucketset, as shown in Figure 3-16.

    Figure 3-16 Create List of Values Bucketset

    Description of Figure 3-16 follows

  9. On the Edit Bucketset window, click OK.

You can control rule ordering in a Decision Table by changing the relative position of the buckets in an LOV bucketset associated with a condition expression in a Decision Table.

To change the order of buckets in a list of values bucketset:

  1. In the Edit Bucketset dialog for the bucketset, select the bucket you want to reorder.

  2. Click the Move Down icon to reorder the bucket down.

  3. Click the Move Up icon to reorder the bucket up.

  4. Click OK.

3.6.2 How to Define a List of Ranges Global Bucketset

A list of ranges bucketset lets you specify the type and the endpoints for buckets in the bucketset.

For more information, see Section 3.6.6, "What You Need to Know About Range Bucketsets".

To define a list of ranges (range) global bucketset:

  1. From Rules Designer select the Bucketsets navigation tab.

  2. From the list next to the Create BucketSet... icon, select List of Ranges.

  3. Double-click in the Data Type field. This displays the Edit Bucketset dialog, as shown in Figure 3-17.

    Figure 3-17 Edit Bucketset: List of Ranges

    Description of Figure 3-17 follows

  4. In the Edit Bucketset dialog, enter the bucketset name in the Name field.

  5. In the Edit Bucketset dialog, in the Data Type field, from the list, select the appropriate data type for the bucketset.

    In this example, select int.

  6. Click the Add Bucket icon repeatedly to add the number of buckets you need in the bucketset as shown in Figure 3-18.

    Figure 3-18 Edit Bucketset: Adding Required Buckets

    Description of Figure 3-18 follows

    In these steps you add three buckets. You start with the default values, as shown in Figure 3-18. After changing the default buckets, the buckets have the following values:

    • greater than 1000

    • between 500 and 1000, inclusive

    • less than 500

    Rules Designer added the buckets with the default values of 50 and 0 and a negative Infinity (-Infinity) bucket.

  7. Starting at the first or top bucket, in the Endpoint field, double-click the default value and enter the top value bucket endpoint, and press Enter.

    In this example, enter 1000 for the first bucket.

  8. In the Included Endpoint field, select the checkbox as appropriate to include or exclude the bucket endpoint.

    In this example, you can leave this checkbox checked to include the bucket endpoint.

  9. In the Allowed in Actions field select the checkbox as appropriate to include the bucket in the bucketset allowable values.

    For more information on the Allowed in Actions field and the Include Disallowed Buckets in Tests field, see Section 3.6.7, "What You Need to Know About Bucketset Allowed in Actions Option".

  10. Optionally, in the Alias field double-click the default value and enter the desired bucket alias, and press Enter.

    The alias appears in Decision Tables that use this bucketset. Use an alias to give a more meaningful name to the bucket than the default value (the range-based Range value).

    Please note that most names and aliases in Oracle Business Rules allow only letters, numbers, embedded single spaces, and the characters $, _, ', ., -, /, and :. However, bucket aliases allow additional characters, such as [0..1]. If a bucket alias contains such additional characters, then you cannot refer to the bucket by the alias in the action cells in a Decision Table. In these cases, you can use the bucket name, which is also known as the bucket value.

    The Range field is read-only: it clearly identifies the actual range associated with the bucket regardless of the Alias value. For more information, see Section 3.6.6, "What You Need to Know About Range Bucketsets").

  11. Moving down the list of buckets, for each subsequent bucket, repeat from Step 7. For the second bucket, enter the endpoint value 500.

    Figure 3-19 shows the completed bucketset.

    Figure 3-19 Edit Bucketset: Completed Range Buckets

    Description of Figure 3-19 follows

  12. In the Edit Bucketset dialog, click OK.

3.6.3 How to Define an Enumerated Type (Enum) Bucketset from XML Types

When you import an XML schema, if the XSD contains enumeration values Rules Designer automatically creates an enumerated type bucketset for each enumeration. Although enumerated type bucketsets are read-only, you can change the order of buckets.

For more information, see Section 3.2.4, "What You Need to Know About XML Facts".

To define an enumerated type (enum) bucketset from XML types:

  1. Obtain an XSD with the desired enumerations.

    Example 3-2 shows the order.xsd schema file which contains the enumeration Status.

    Example 3-2 Order.xsd Schema

    <?xml version="1.0" ?>
    <schema attributeFormDefault="qualified" elementFormDefault="qualified"
            targetNamespace="http://example.com/ns/customerorder"
            xmlns:tns="http://example.com/ns/customerorder"
            xmlns="http://www.w3.org/2001/XMLSchema">
      <element name="CustomerOrder">
        <complexType>
          <sequence>
            <element name="name" type="string" />
            <element name="creditScore" type="int" />
            <element name="annualSpending" type="double" />
            <element name="value" type="string" />
            <element name="order" type="double" />
          </sequence>
        </complexType>
      </element>
      <element name="OrderApproval">
        <complexType>
          <sequZOence>
            <element name="status" type="tns:Status"/>
          </sequence>
        </complexType>
      </element>
      <simpleType name="Status">
        <restriction base="string">
            <enumeration value="manual"/>
            <enumeration value="approved"/>
            <enumeration value="rejected"/>
        </restriction>
      </simpleType>
    </schema>
    
  2. Open a dictionary in Rules Designer and create XML facts using the specified schema that contains the enumeration. For more information, see Section 3.2, "Working with XML Facts".

  3. Click the Bucketsets navigation tab and select the Enum bucketset to see the bucketset, as shown in Figure 3-20. In Figure 3-20, notice that the imported Status enumeration values shown in Example 3-2 are imported as buckets with the XSD-specified values.

    Figure 3-20 Bucketset Showing the Form Enum with Imported Values

    Description of Figure 3-20 follows

You can control rule ordering in a Decision Table by changing the relative position of the buckets in an enum bucketset associated with a condition expression in a Decision Table.

To change the order of buckets in an enum bucketset:

  1. In the Edit Bucketset dialog for the bucketset, select the bucket you want to reorder.

  2. Click the Move Down icon to reorder the bucket down.

  3. Click the Move Up icon to reorder the bucket up.

  4. Click OK.

3.6.4 How to Define an Enumerated Type (Enum) Bucketset from Java Types

When you import a Java enum, Rules Designer automatically creates an enumerated type bucketset for each Java enum. Although enumerated type bucketsets are read-only, you can change the order of buckets.

To define an enumerated type (enum) bucketset from Java facts:

  1. Create or obtain the Java class with the desired enumerations.

    Example 3-3 shows the RejectPurchaseItem.java class which contains enumeration OrderSize.

    Example 3-3 Java Fact with enum OrderSize

    package com.example;
    
    public class Class1
    {
        public enum OrderSize { SMALL, MEDIUM, LARGE };
        public Class1()
        {
        }
    }
    
  2. In Rules Designer open a dictionary and create a Java Fact using the Java class. For more information, see Section 3.3, "Working with Java Facts".

    Figure 3-21 shows a how to create a Java fact for the Java enumeration Class1$OrderSize.

    Figure 3-21 Creating a Java Fact

    Description of Figure 3-21 follows

  3. In Rules Designer click the Bucketsets navigation tab and select the Enum bucketset, as shown in Figure 3-22. Note that the Class1$OrderSize enumeration from the enumeration in Example 3-3 is now a bucketset with the Java enum-specified values.

    Figure 3-22 Edit Bucketset Dialog for Java Enum

    Description of Figure 3-22 follows

You can control rule ordering in a Decision Table by changing the relative position of the buckets in an enum bucketset associated with a condition expression in a Decision Table.

To change the order of buckets in an enumerated type (enum) bucketset:

  1. In the Edit Bucketset dialog for the bucketset, select the bucket you want to reorder.

  2. Click the Move Down icon to reorder the bucket down.

  3. Click the Move Up icon to reorder the bucket up.

  4. Click OK.

3.6.5 What You Need to Know About List of Values Bucketsets

In a Decision Table the order of the buckets in a bucketset associated with a condition expression determines the order of the condition cells, and thus the order of the rules. You can control rule ordering in a Decision Table by changing the relative position of the buckets in a list of values bucketset associated with a condition expression; however, you cannot reorder range buckets.

Figure 3-23 shows a bucketset definition in Rules Designer for a bucketset named colors using a list of values.

Figure 3-23 Bucketset Definition Using List of Values

Description of Figure 3-23 follows

As shown in Figure 3-23, by default with a List of Values bucketset there is a value otherwise included with the list of values (LOV). This value, otherwise, is distinct from all other values and matches all values of the type that have no other bucket. Thus, with otherwise in the list of values a condition expression that uses the bucketset can handle every value and provides a match for every value of the specified type, where a match is either a defined value or the otherwise bucket. The otherwise value cannot be removed from an LOV bucketset but it can be excluded by clearing the Allowed in Actions checkbox (when otherwise is excluded an attempt to assign any value that is not in the list of buckets in the bucketset causes a validation warning).

Table 3-3 shows the bucketset values that Rules Designer supports for LOV bucketsets.

Table 3-3 Supported Types for LOV Bucketsets

TypeDescription

Java primitive types

This includes int, double, boolean, char, byte, short, long, and float

String

Contains String types

Calendar

Contains Calendar types in the current locale



Note:

You are not required to specify an LOV bucketset when you use a boolean type in a Decision Table. For boolean types, Oracle Business Rules provides built-in buckets for the possible values (true and false).


3.6.6 What You Need to Know About Range Bucketsets

When you add a bucket to a List of Ranges bucketset, the value is calculated based on the currently selected bucket value and the next highest bucket value. When you change the endpoint value the value is automatically sorted in the bucketset; thus, it does not matter where a bucket is added. However, it is possible for Rules Designer to not have spaces between the current bucketset endpoint value and the endpoint value. In this case, Rules Designer shows a validation warning of the following form:

RUL-05849: Bucketset has duplicate bucket value "4999"

To correct this problem you must modify bucket endpoints to remove the duplicate bucket.

Figure 3-24 shows the Edit Bucketset window for a bucketset with an integer, int, range.

Figure 3-24 Bucketset Definition Using List of Ranges and Three Endpoints

Description of Figure 3-24 follows

Table 3-4 shows the types Rules Designer supports for Range buckets.

Table 3-4 Supported Types for Range Buckets

TypeDescription

Selected primitive types

This includes: int, double, short, long, and float

Calendar

Contains Calendar types in the current locale


Note the following conventions for the Range field:

  • Logical operator: specifies a range with respect to positive or negative infinity. For example, ">=25" means "from 25 to positive infinity" and "<18" means from negative infinity up to but not including 18.

  • Square bracket "[": specifies a range that includes this end point value. For example, "[18..25)" means "from 18 up to but not including 25".

  • Round bracket ")": specifies a range that excludes this end point value. For example, "(18..25]" means "over 18, not including 18, up to and including 25".

3.6.7 What You Need to Know About Bucketset Allowed in Actions Option

When you define buckets in a bucketset you might define some buckets corresponding to non-permissible values. For example, in a bucketset for driver ages you would typically not allow a bucket that contains values less than 0. Thus, when a fact with driver data includes an age property associated with a driver ages bucketset, then you should not be able to create or modify a fact that has the age property set to a value such as -1. In a bucketset you select Allowed in Actions for valid buckets and deselect this option for invalid buckets.

The bucketset option Include Disallowed Buckets in Tests allows you to include all the buckets, whether Allowed in Actions is selected or not, in Decision Table conditions and in rule tests. By including all buckets you can explicitly test for illegal values. Using the option Include Disallowed Buckets in Tests you can handle two possible cases:

  1. The input data for the Oracle Business Rules Engine is clean and does not contain invalid data (such as a negative age). In this case, you should deselect the Include Disallowed Buckets in Tests. Note: the reason you do not want to make age < 0 an Allowed in Actions is this provides design time validation warnings if you try to create an action that uses an invalid value, such as the following: modify(driver, age: -1)). For more information, see Section 4.11, "Using Bucketsets as Constraints for Options Values in Rules".

  2. You want to consider excluded buckets in rule tests and in Decision Tables. In this case, you should select Include Disallowed Buckets in Tests. This is useful when the input data for the Oracle Business Rules Engine may not be clean and may contain invalid data (for example an invalid negative age). A Decision Table that provides actions for all bucketsets could include cases for excluded buckets and provide an appropriate action, such as asserting an error fact. To handle this you could either select the Allowed in Actions field for every bucket in the bucketset, or, leave the Allowed in Actions field configured as is and select the Include Disallowed Buckets in Tests field. Using the Include Disallowed Buckets in Tests field is not only convenient, you do not need to reconfigure every bucket, it also preserves the configuration of Allowed in Actions so that you can easily reuse this bucketset to handle the first case (when you deselect Include Disallowed Buckets in Tests).

3.6.8 What You Need to Know About Bucket Values

When you enter a bucket value in a bucketset, the value you supply must be valid for the type specified for the bucketset. If the value you enter is not valid for the bucketset type, Rules Designer makes the value you supply a string by adding quotation marks. Adding quotation marks is the only way to make a legal literal when the user provided data is not appropriate for the specified type. For example, if you add an int type LOV bucketset, and then supply a value 2.2 to a bucket, Rules Designer shows a warning such as the following:

RUL-05833: Invalid characters "2.2" in bucket value

To fix this problem either enter a valid value for the bucket value, for example in this case the value 2, or change the type of the bucketset.

For an additional example, when you enter a value for a bucket, for example if you enter a bucket value with bucketset with data type short and add a bucket with the value 999999, Rules Designer assigns this the value "999999". The maximum value for a short is 32767. In this case you see a warning related to the bucket value, similar to the previous example, because a String is not a valid bucket value for a bucketset with data type short. The solution to this is to enter appropriate values for all buckets (in this example, enter a value less than or equal to 32767).

3.7 Associating a Bucketset with Business Terms

After you define a global bucketset you can associate parts of the data model with the global bucketset (if their types are compatible). In this way, condition cells in the Conditions area can automatically be assigned a bucketset when you define a Decision Table. Also, when a bucketset is associated with a business term, Oracle Business Rules uses the buckets that you define as constraints for the values for expressions for the business terms in rules.

You can associate the following four kinds of business term with a bucketset:

  • Fact Property

  • Function Result

  • Function Argument

  • Global Value

3.7.1 How to Associate a Bucketset with a Fact Property

To prepare for creating Decision Tables, you can associate a global bucketset with fact properties in the data model.

To associate a bucketset with a fact property:

  1. From Rules Designer, select the Facts navigation tab.

  2. Select the fact type to edit and click the Edit icon. This displays the appropriate Edit Fact dialog for the fact type you select.

  3. In the Properties table, under Bucketset, select the cell for the appropriate fact property and from the list select the bucketset you want to associate with the property. For example, see Figure 3-25.

    Figure 3-25 Defining a Bucketset for a Property

    Description of Figure 3-25 follows

  4. On the Edit Fact page, click OK.

3.7.2 How to Associate a Bucketset with Functions or Function Arguments

To prepare for creating Decision Tables you can associate a global bucketset with functions in the data model.

To associate a bucketset with a function return value:

  1. From Rules Designer, select the Functions tab.

  2. Select the function to edit. This shows the function arguments and the function body for the specified function.

  3. In the Functions table, under Bucketset, select the cell and from the list select the bucketset you want to use. For example, see Figure 3-26.

    Figure 3-26 Defining a Bucketset for a Function Return Value

    Description of Figure 3-26 follows

To associate a bucketset with a function argument:

  1. From Rules Designer, select the Functions navigation tab.

  2. Select the function to edit. This shows the function arguments and the function body for the specified function.

  3. In the Functions table, in the Arguments area select the appropriate argument.

  4. For the specified argument, under Bucketset, select the cell and from the list select the bucketset you want to use.

3.7.3 How to Associate a Bucketset with a Global Value

To prepare for creating Decision Tables, you can associate a global bucketset with global values in the data model.

To associate a bucketset with a global value:

  1. From Rules Designer, select the Globals navigation tab.

  2. Select the global value to edit.

  3. In the Globals table, under Bucketset, select the cell for the appropriate global value, and from the list, select the bucketset that you want to associate with the global value. For example, see Figure 3-27.

Figure 3-27 Defining a Bucketset for a Global Value

Associating Global with Bucketset

PKzZZPK[EZFOEBPS/intro.htm Overview of Oracle Business Rules

1 Overview of Oracle Business Rules

This chapter describes the concepts of business rules and provides an overview of the Oracle Business Rules runtime and design-time elements such as facts, bucketsets, rulesets, Decision Table, and Oracle SOA Composer. It also describes the Oracle Business Rules engine architecture.

This chapter includes the following sections:

For more information, see:

1.1 What are Business Rules?

Oracle Business Rules enable dynamic decisions at runtime allowing you to automate policies, computations, and reasoning while separating rule logic from underlying application code. This allows more agile rule maintenance and empowers business analysts with the ability to modify rule logic without programmer assistance and without interrupting business processes.

Business rules are statements that describe business policies or describe key business decisions. For example, business rules include:

  • Business policies such as spending policies and approval matrices.

  • Constraints such as valid configurations or regulatory requirements.

  • Computations such as discounts or premiums.

  • Reasoning capabilities such as offers based on customer value.

For example, a car rental company might use the following business rule:

Description of intro_driver.gif follows

An airline might use a business rule such as the following:

Description of intro_fyer.gif follows

A financial institution could use a business rule such as:

Description of intro_loan.gif follows

These examples represent individual business rules. In practice, you can use Oracle Business Rules to combine many business rules or to use more complex tests.

For the car rental example, you can name the rule the Driver Age Rule. Traditionally, business rules such as the Driver Age Rule are buried in application code and might appear in a Java application as follows:

public boolean checkDriverAgeRule (Driver driver) { 
   boolean declineRent = false;  
   int age = driver.getAge();
   if(  age < 21 ) { 
      declineRent = true; 
   }
   return declineRent; 
}

This code is not easy for nontechnical users to read and can be difficult to understand and modify. For example, suppose that the rental company changes its policy so that all drivers under 18 are declined using the Driver Age Rule. In many production environments the developer must modify the application, recompile, and then redeploy the application. Using Oracle Business Rules, this process can be simplified because a business rules application is built to support easily changing business rules.

Oracle Business Rules allows a business analyst to change policies that are expressed as business rules, with little or no assistance from a programmer. Applications using Oracle Business Rules support continuous change that allows the applications to adapt to new government regulations, improvements in internal company processes, or changes in relationships between customers and suppliers.

A rule follows an if-then structure and consists of the following parts:

Alternatively, you can express rules in a spreadsheet-like format called a Decision Table (see Section 1.1.3, "What Are Decision Tables?").

You write rules and Decision Tables in terms of fact types and properties. Fact types are often imported from the Java classes, XML schema, Oracle ADF Business Components view objects, or may be created in Rules Designer. Fact properties have a name, value, data type, and an optional bucketset. A bucketset splits the value space of the data type into buckets that can be used in Decision Tables, choice lists, and for design time validation (see Section 1.1.4, "What Are Facts and Bucketsets?").

You group rules and Decision Tables in an Oracle Business Rules object called a ruleset (see Section 1.1.5, "What Are Rulesets?").

You group one or more rulesets and their facts and bucketsets in an Oracle Business Rules object called a dictionary (see Section 1.1.8, "What Are Dictionaries?").

For more information, see Section 1.2, "Oracle Business Rules Runtime and Design Time Elements".

1.1.1 What Are Rule Conditions?

The rule IF part is composed of conditional expressions, rule conditions, that refer to facts. For example:

IF Rental_application.driver age < 21

The conditional expression compares a business term (Rental_application.driver age) to the number 21 using a less than comparison.

The rule condition activates the rule whenever a combination of facts makes the conditional expression true. In some respects, the rule condition is like a query over the available facts in the Rules Engine, and for every row returned from the query the rule is activated.

For more information, see:

1.1.2 What Are Rule Actions?

The rule THEN part contains the actions that are executed when the rule is fired. A rule is fired after it is activated and selected among the other rule activations using conflict resolution mechanisms such as priority. A rule might perform several kinds of actions. An action can add facts, modify facts, or remove facts. An action can execute a Java method or perform a function which may modify the status of facts or create facts.

Rules fire sequentially, not in parallel. Note that rule actions often change the set of rule activations and thus change the next rule to fire.

For more information, see:

1.1.3 What Are Decision Tables?

A Decision Table is an alternative business rule format that is more compact and intuitive when many rules are needed to analyze many combinations of property values. You can use a Decision Table to create a set of rules that covers all combinations or where no two combinations conflict.

For more information, see Chapter 5, "Working with Decision Tables".

1.1.4 What Are Facts and Bucketsets?

In Oracle Business Rules, facts are the objects that rules reason on. Each fact is an instance of a fact type. You must import or create one or more fact types before you can create rules.

In Oracle Business Rules a fact is an asserted instance of a class. The Oracle Business Rules runtime or a developer writing in the RL Language uses the RL Language assert function to add an instance of a fact to the Oracle Business Rules Engine.

In Rules Designer you can define a variety of fact types based on, XML Schema, Java classes, Oracle RL definitions, and ADF Business Components view objects. In the Oracle Business Rules runtime such fact type instances are called facts.

You can create bucketsets to define a list of values or a range of values of a specified type. After you create a bucketset you can associate the bucketset with a fact property of matching type. Oracle Business Rules uses the bucketsets that you define to specify constraints on the values associated with fact properties in rules or in Decision Tables. You can also use bucketsets to specify constraints for variable initial values and function return values or function argument values.

For more information, see:

1.1.5 What Are Rulesets?

A ruleset is an Oracle Business Rules container for rules and Decision Tables. A ruleset provides a namespace, similar to a Java package, for rules and Decision Tables. In addition you can use rulesets to partially order rule firing.

For more information, see:

1.1.6 What Are Decision Functions?

A decision function provides a contract for invoking rules from Java or SOA (from a SOA composite application or from a BPEL process). The contract includes input fact types, rulesets to run, and output fact types. For more information, see Chapter 6, "Working with Decision Functions".

1.1.7 What Are Decision Points?

Oracle Business Rules SDK (Rules SDK) provides APIs that let you write applications that access, create, modify, and execute rules in Oracle Business Rules dictionaries (and all the contents of a dictionary). The Rules SDK provides the Decision Point API to access and run rules or Decision Tables from a Java application. For more information, see Chapter 7, "Working with Rules SDK Decision Point API".

1.1.8 What Are Dictionaries?

A dictionary is an Oracle Business Rules container for facts, functions, globals, bucketsets, links, decision functions, and rulesets. A dictionary is an XML file that stores the application's rulesets and the data model. Dictionaries can link to other dictionaries. Oracle JDeveloper creates an Oracle Business Rules dictionary in a .rules file. You can create as many dictionaries as you need. A dictionary may contain any number of rulesets. For more information, see Section 2.2, "Working with a Dictionary and Dictionary Links".

1.2 Oracle Business Rules Runtime and Design Time Elements

Oracle Business Rules provides support for using business rules as a Decision component or as a library in a Java application. A Decision component is a mechanism for publishing rules and rulesets as a reusable service that can be invoked from multiple business processes. To create and use rules in the Oracle SOA Suite, or to create rules and integrate these rules into your applications, Oracle Business Rules provides the following runtime and design time elements:

1.2.1 Decision Component (Business Rules) in a SOA Composite Application

Oracle SOA Suite provides support for Decision components that support Oracle Business Rules. A Decision component is a mechanism for publishing rules and rulesets as a reusable service that can be invoked from multiple business processes.

A Decision Component is a SCA component that can be used within a composite and wired to a BPEL component. Apart from that, Decision components are used for dynamic routing capability of Mediator and Advanced Routing Rules in Human Workflow.

Oracle Business Rules Rules Engine (Rules Engine) is available in a SOA composite application using the SOA Business Rule service engine that efficiently applies rules to facts and defines and processes rules.

Rules Engine has the following features:

  • High performance: Rules Engine implements specialized matching algorithms for facts that are defined in the system.

  • Thread-safe execution suitable for a parallel processing architecture: Rules Engine provides one thread that can assert facts while another is evaluating the network.

For more information, see Section 1.3, "Oracle Business Rules Engine Architecture".

1.2.2 Using Rules Engine with Oracle Business Rules in a Java EE Application

The Rules Engine is available as a library for use in a Java EE application (non-SOA). Rules Engine efficiently applies rules to facts and defines and processes rules. Rules Engine defines a Java-like production rule language called Oracle Business Rules RL Language (RL Language), provides a language processing engine (inference engine), and provides tools to support debugging.

Using Rules Designer you can specify business rules separately from application code which allows you to change business policies quickly with graphical tools. The Rules Engine evaluates the business rules and returns decisions or facts that are then used in the business process.

Rules Engine has the following features:

  • High performance: Rules Engine implements specialized matching algorithms for facts that are defined in the system.

  • Thread-safe execution suitable for a parallel processing architecture: Rules Engine provides one thread that can assert facts while another is evaluating the network.

A rule-enabled Java application can load and run rules programs. The rule-enabled application passes facts and rules to the Rules Engine (facts are asserted in the form of Java objects or XML documents). The Rules Engine runs in the rule-enabled Java application and uses the Rete algorithm to efficiently fire rules that match the facts.

For more information, see Section 1.3, "Oracle Business Rules Engine Architecture" and Section 1.2.4, "Oracle Business Rules SDK".

1.2.3 Oracle Business Rules RL Language

Oracle Business Rules supports a high-level Java-like language called Oracle Business Rules RL Language (RL Language). RL Language defines the valid syntax for Oracle Business Rules programs. RL Language includes an intuitive Java-like syntax for defining rules that supports the power of Java semantics, providing an easy-to-use syntax for application developers. RL Language consists of a collection of text statements that can be generated dynamically or stored in a file.

Using RL Language application programs can assert Java objects as facts, and rules can reference object properties and invoke methods. Likewise, application programs can use XML documents or portions of XML documents as facts.

Programmers can use RL Language as a full-featured rules programming language both directly and as part of the Oracle Business Rules SDK (Rules SDK).

Business analysts can use Rules Designer to work with rules. In this case, the business analyst does not need to directly view or write RL Language programs. For more information, see Section 1.2.5, "Rules Designer".

For detailed information about RL Language, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules.

1.2.4 Oracle Business Rules SDK

Oracle Business Rules SDK (Rules SDK) is a Java library that provides business rule management features that a developer can use to write a rule-enabled program that accesses a dictionary, or to write customized rules programs that add rules or modify existing rules. Rules Designer uses Rules SDK to create, modify, and access rules and the data model using well-defined interfaces. Customer applications can use Rules SDK to access, display, create, and modify collections of rules and the data model.

You can use the Rules SDK APIs in a rule-enabled application to access rules or to create and modify rules. The rules and the associated data model could be initially created in a custom application or using Rules Designer.

This guide describes the Oracle Business Rules SDK Decision Point API. Using a Decision Point you can access a dictionary and run the rules in the dictionary. For complete Oracle Business Rules SDK API information, see Oracle Fusion Middleware Java API Reference for Oracle Business Rules.

For more information, see Chapter 7, "Working with Rules SDK Decision Point API".

1.2.5 Rules Designer

The Oracle Business Rules Designer (Rules Designer) extension to Oracle JDeveloper is an editor that enables you to create and edit rules as Figure 1-1 shows.

Figure 1-1 Oracle JDeveloper with Rules Designer

This diagram is described in surrounding text.

Rules Designer provides a point-and-click interface for creating rules and editing existing rules. Using Rules Designer you can work directly with business rules and a data model. You do not need to understand the RL Language to work with Rules Designer. Rules Designer provides an easy way for you to create, view, and modify business rules.

Rules Designer supports several types of users, including the application developer and the business analyst. The application developer uses Rules Designer to define a data model and an initial set of rules. The business analyst uses Rules Designer either to work with the initial set of rules or to modify and customize the initial set of rules according to business needs. Using Rules Designer a business analyst can create and customize rules with little or no assistance from a programmer.

1.2.6 Oracle SOA Composer Application

When a dictionary is deployed in a SOA composite application, Oracle Business Rules lets you view the dictionary or edit and save changes to the dictionary. You can use the SOA Composer application (SOA Composer) to work with a deployed dictionary that is part of a SOA composite application, as Figure 1-2 shows.

Figure 1-2 Using Oracle SOA Composer to View or Edit a Dictionary at Runtime

This diagram is described in surrounding text.

For more information, see Chapter 12, "Using Oracle SOA Composer with Oracle Business Rules".

1.3 Oracle Business Rules Engine Architecture

A rule-based system using the Rete algorithm is the foundation of Oracle Business Rules. A rule-based system consists of the following:

  • The rule-base: Contains the appropriate business policies or other knowledge encoded into IF/THEN rules and Decision Tables.

  • Working memory: Contains the information that has been added to the system. With Oracle Business Rules you add a set of facts to the system using assert calls.

  • Inference Engine: The Rules Engine, which processes the rules, performs pattern-matching to determine which rules match the facts, for a given run through the set of facts.

In Oracle Business Rules the rule-based system is a data-driven forward chaining system. The facts determine which rules can fire so when a rule fires that matches a set of facts, the rule may add facts and these facts are again run against the rules. This process repeats until a conclusion is reached or the cycle is stopped or reset. Thus, in a forward-chaining rule-based system, facts cause rules to fire and firing rules can create more facts, which in turn can fire more rules. This process is called an inference cycle.

1.3.1 Declarative Rules

With Oracle Business Rules you can use declarative rules, where you create rules that make declarations based on facts rather than coding. For an example of declarative rules,

IF a Customer is a Premium customer, offer them 10% discount
IF a Customer is a Gold customer, offer them 5% discount

In declarative rules:

  • Statements are declared without any control flow

  • Control flow is determined by the Rules Engine

  • Rules are easier to maintain than procedural code

  • Rules relate well to business user work methods

When a rule adds facts and these facts run against the rules, this process is called an inference cycle. An inference cycle uses the initial facts to cause rules to fire and firing rules can create more facts, which in turn can fire more rules. For example, using the initial facts, Rules Engine runs and adds an additional fact, and an additional rule tests for conditions on this fact creating an inference cycle:

IF a Customer is a Premium customer, offer them 10% discount
IF a Customer is a Gold customer, offer them 5% discount
IF a Customer spends > 1000, make them Premium customer

The inference cycle that Oracle Business Rules provides enables powerful and modular declarative assertions.

1.3.2 The RETE Algorithm

The Rete algorithm was first developed by artificial intelligence researchers in the late 1970s and is at the core of Rules Engines from several vendors. Oracle Business Rules uses the Rete algorithm to optimize the pattern matching process for rules and facts. The Rete algorithm stores partially matched results in a single network of nodes in working memory.

By using the Rete algorithm, the Rules Engine avoids unnecessary rechecking when facts are deleted, added, or modified. To process facts and rules, the Rete algorithm creates and uses an input node for each fact definition and an output node for each rule.

Fact references flow from input to output nodes. In between input and output nodes are test nodes and join nodes. A test occurs when a rule condition has a Boolean expression. A join occurs when a rule condition ANDs two facts. A rule is activated when its output node contains fact references. Fact references are cached throughout the network to speed up recomputing activated rules. When a fact is added, removed, or changed, the Rete network updates the caches and the rule activations; this requires only an incremental amount of work.

The Rete algorithm provides the following benefits:

  • Independence from rule order: Rules can be added and removed without affecting other rules.

  • Optimization across multiple rules: Rules with common conditions share nodes in the Rete network.

  • High performance inference cycles: Each rule firing typically changes just a few facts and the cost of updating the Rete network is proportional to the number of changed facts, not to the total number of facts or rules.

1.3.3 What Is Working Memory?

Oracle Business Rules uses working memory to contain facts (facts do not exist outside of working memory). A RuleSession contains the Oracle Business Rules working memory.

1.3.4 Rule Firing and Rule Sessions

A Rule Session consists of rules, facts and an agenda. An assert or retract adds or removes fact instances from working memory.

When facts in working memory are changed:

  • Conditions for rules are evaluated

  • Matching rules are added to the agenda (Activated)

  • Rules which no longer match are removed from agenda

  • Rules Engine runs and executes actions (fires), for activated rules

Figure 1-3 shows these parts of Oracle Business Rules runtime.

Figure 1-3 Rules in Rule Session with Working Memory and Facts

This diagram is described in surrounding text.

A rule action may assert, modify, or retract facts and cause activations to be added or removed from the agenda. There is a possible loop if a rule's action causes it to fire again. Rules are fired sequentially, but in no pre-defined order. The rule session includes a ruleset stack. Activated rules are fired as follows:

  • Rules within top-of-the-stack ruleset are fired

  • Within a ruleset, firing is ordered by user-defined priority

  • Within the same priority, the most recently activated rule is fired first

Only rules within rulesets on the stack are fired, but all rules in a rule session are matched and, if matched, activated.

PKPK[EZFOEBPS/whatsnew_mlr_asrug.htm5 What's New in This Guide for Release 11.1.1.7

What's New in This Guide for Release 11.1.1.7

The following table lists the sections that have been added or changed.

For a list of known issues (release notes), see the "Known Issues for Oracle SOA Products and Oracle AIA Foundation Pack" at http://www.oracle.com/technetwork/middleware/docs/soa-aiafp-knownissuesindex-364630.html.

SectionsChanges Made

What's New in This Guide for Release 11.1.1.7.0

Chapter added to list the new or updated content for this release.

Multiple chapters

Added content for the following:

Combining generic rules UI and customized task approvals UI in IF/THEN rules

Add filtering support to choice lists

Add/Delete Global Variables in Rules ADF component

Support for customized action region for decision table

Ability to import dictionary from MDS into project


PK: 5 PK[EZFOEBPS/index.htm Index

Index

A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  R  S  T  U  V  W  X 

A

actions
advanced, 4.7.3
area, 5.1.1.2
cell, 5.1.1.2
decision table, 5.1.1.2
definition, 4.3.6
do nothing value, 5.1.2
fact type, 10.1.2
active option, 4.5.3
ADF Business Components Fact
action fact type, 10.1.2
creating, 10.3
definition, 10.1
importing, 3.5.1
key_values, 3.5.4, 10.1.1
types, 3.5
ADF Business Components Fact ViewRowImpl, 3.5
advanced actions, 4.7.3
advanced mode, 4.5.2
advanced settings, 4.5
aggregates
average, 4.7.4
collection, 4.7.4
count, 4.7.4
maximum, 4.7.4
minimum, 4.7.4
sum, 4.7.4
aliases, A.1.3
allow gaps option, 5.3.1.3, 5.3.5
auto override conflict resolution
setting option, 5.3.7, 5.3.8
average aggregate, 4.7.4

B

batch invocation, 10.2.1.4
BigDecimal type, 3.2.4
BigInteger type, 3.2.4
BPEL
decision functions, 6.3.2
Human Tasks, 11.2
java.lang.IllegalAccessError, D.5
service component, 11.2
bucketsets
adding Enum type, 3.6.3
adding list of ranges (Range), 3.6.2
adding list of values (LOV), 3.6.1
allowed in actions field, 3.6.7
associating with facts, 3.7
creating, 3.6
definition, 1.1.4, 3.1
duplicate bucket value, 3.6.6
global, 3.6
Include Disallowed Buckets in Tests field, 3.6.7
list of values (LOV) adding, 3.6.1
local, 3.6
built-in dictionary
Java wrappers, 3.2.4
business rules
activity, 6.3.2
decision function, 6.3.2
definition, 1.1
deployment and runtime, 9.6
dictionary, 1.1.8
in a Java EE application, 9.1
RL Language, 1.2.3

C

calendar type
with CurrentDate fact, 4.9
check rule flow option, 6.2.1
classpath
Java facts, 3.3.1
Rule Reporter, F.2.1
collection aggregate, 4.7.4
combined dictionary, 2.2.1, 12.5.6
com.sun.xml.bind.v2.runtime.reflect.opt.Const errors, D.5
Condition Browser, 12.7.2, 12.8.2
condition expressions
cell, 5.1.1.1
definition, 5.1.1.1
conflict analysis, 5.3.1.4, 12.8.9
decision table, 5.3.6
conflict policy option, 5.3.1.4, 12.8.9
conflict resolution, 5.3.1.4, 12.8.9
constant option for globals, 2.3.3
count aggregate, 4.7.4
CurrentDate fact, 4.9

D

data model
definition, 2.1
sharing, 2.2.7
data types
bucketset, 1.1
fact properties, 1.1
Date Browser, 12.7.3
dates
reasoning with CurrentDate fact, 4.9
decision functions, 6.1, 6.3
adding, 6.2
adding to a dictionary, 6.2.1
as decision service, 11.2.2
BPEL, 6.3.2
Business Rule activity, 6.3.2
calling with Java decision point interface, 10.2.2
check rule flow option, 6.2.1
definition, 1.1.6
rule firing limit option, 6.3.1
stateless option, 6.2.1
understanding, 6.1
Web service, 6.2.1, 6.2.1
decision point API
batch invocation, 10.2.1.4
definition, 1.1.7
production dictionary, 7.5
rules SDK, 7.1.1
runtime properties, 10.2.1.2
transaction, 10.2.1.1
with MDS repository, 7.5
decision service
decision function, 11.2.2
decision table
action cell, 5.1.1.2
do nothing value, 5.1.2
actions, advanced, 4.7.3
active option, 4.5.3
adding a rule, 5.2.4
adding actions, 5.2.3
adding condition expressions, 5.2.2
advanced mode, 4.5.2
advanced settings, 4.5
aggregates, 4.7.4
allow gaps option, 5.3.1.3, 5.3.5
auto override conflict resolution, 5.3.7, 5.3.8
cell values, 5.1.2
condition expression, 5.1.1.1
condition expression cell, 5.1.1.1
conflict analysis, 5.3.1.4, 5.3.6, 12.8.9
conflict policy option, 5.3.1.4, 12.8.9
conflict resolution, 5.3.1.4, 12.8.9
creating, 5.2
decision tree, 5.1.1.3
definition, 1.1.3
do not care values, 5.1.2
effective dates, 4.5.6
expression builder, 4.10
find gaps, 5.3.1.3, 5.3.5
gap analysis, 5.3.1.3, 5.3.5
logical option, 4.5.4
move operation, 5.3.1.2
priority, 4.5.5
rules, 5.1.1.3
show conflicts, 5.3.1.4, 12.8.9
sibling cell, 5.3.1.1
understanding, 5.1
validation, 4.4.3
decision tree, 5.1.1.3
DecisionPoint class, 7.1.1
DecisionPointBuilder class, 7.1.1
DecisionPointInstance class, 7.1.1
.decs file, 11.2.1.1
deployment
EAR file, 9.6.4
MAR file, 9.6.3
dictionary
combined, 2.2.1, 12.5.6
data model sharing, 2.2.7
decision function, 6.1, 6.2.1, 6.3
definition, 1.1.8, 1.1.8, 2.1, 2.2
globals, 2.3
link, 12.5.6
naming conventions, 2.2.7, A.1.2
package, 2.2.7
reading
UTF-8 character encoding, 7.3.2
validation, 4.4, 4.4.1, 4.4.4
viewing and editing settings, 2.2.4
dictionary links
updating, 2.2.6
do nothing value, 5.1.2
Double type, 3.2.4
duplicate bucket values, 3.6.6

E

EAR file, 9.6.4
effective dates, 4.2.2, 4.5.6
expression
constant, 2.3.3
Expression Builder, 12.7.1, 12.8.2
expression builder
about, 4.10

F

fact type
ADF Business Components, 3.5
Java, 3.3
RL, 3.4
XML, 3.2.1
facts
and working memory, 1.3.3
associating with bucketsets, 3.7
definition, 1.1.4, 3.1
FileInputStream
UTF-8, 7.3.2
filtering rules, 4.2.3
final option for globals, 2.3.3
Float type, 3.2.4
forward-chaining system, 1.3
frequently asked questions, C
functions
decision, 6.3
oracle business rules, 2.5
testing, 8

G

gap analysis, 5.3.1.3, 5.3.5
global bucketset, 3.6
globals
constant option, 2.3.3
defined, 2.3
final option, 2.3.3

H

Human Tasks, 11.2

I

importing XML schema, 3.2.3
Include Disallowed Buckets in Tests option, 3.6.7
inference cycle, 1.3, 1.3
Integer type, 3.2.4

J

Java EE application
with business rules, 9.1
Java Fact
adding, 3.3.1
getter method visibility, D.1
setter method visibility, D.1
types, 3.3
using a Property Change Listener with, C.5
java.lang.IllegalAccessError, D.5
java.lang.NoClassDefFoundError, D.3
JAXB
generated classes, 3.2.1
issue 490 troubleshooting, D.5
limitations with XML facts, 3.2.4
with XML facts, 3.2
JSR-94
definition, E
extensions, E.3.4
rule execution set, E.2
with RL Language text, E.2.1
with URL, E.2.2

K

key_values, 3.5.4, 10.1.1

L

links
dictionary, 12.5.6
to a dictionary in the same application, 2.2.5
list tests, 4.8
local bucketset, 3.6
logical option, 4.5.4, 4.5.4
Long type, 3.2.4

M

MAR file, 9.6.3
matched fact naming, 4.7.2
maximum aggregate, 4.7.4
metadata
.decs file, 11.2.1.1
EAR file, 9.6.4
MAR file, 9.6.3
service component, 11.1, 11.2.1.1
minimum aggregate, 4.7.4
move operation, 5.3.1.2

N

named priority, 4.5.5
naming conventions
alias, A.1.3
dictionary, 2.2.7, A.1.2
matched fact, 4.7.2
RL Language keywords, D.4
Rule Designer, A.1.1
rulesets, A.1.1
XML schema target package name, A.1.4
nested tests, 4.6
numeric priority, 4.5.5

O

Oracle Business Rules Function, 2.5
testing, 8
Oracle Business Rules function
creating, 2.5.2
Oracle Business Rules RL Language. See RL Language
Oracle Business Rules Rules Engine. See Rules Engine
Oracle Business Rules SDK2. See SDK
Oracle Business Rules service component. See service component

P

pattern binding variable, 4.7.2
pattern matching, 4.7.1
priority
default, 4.5.5
definition, 4.5.5
high, 4.5.5
higher, 4.5.5
highest, 4.5.5
integer value, 4.5.5
low, 4.5.5
lower, 4.5.5
lowest, 4.5.5
medium, 4.5.5
named, 4.5.5
numeric, 4.5.5
order, C.11
Property Change Listener, C.5
prototyping
rules, 3.4

R

range tests, 4.3.4
reload XML facts from updated schemas, 3.2.3
Rete algorithm, 1.3.2
Right Operand Browser, 12.7.4
RL Fact
adding, 3.4.1
types, 3.4
RL Language
definition, 1.2.3, 1.2.3
self-join, C.4
rule language. See RL Language
Rule Reporter
classpath, command line, F.2.1
command line, F.2.1
RuleDictionary
UTF-8 character encoding, 7.3.2
rules
actions, 1.1.2, 4.3.6
active option, 4.5.3
adding actions, 4.3.6, 4.3.6
advanced mode, 4.5.2
actions, 4.7.3
aggregates, 4.7.4
matched fact naming, 4.7.2
pattern matching, 4.7.1
setting, 4.7.5
simple tree mode, 4.8.1.1
tree mode, 4.8.1
advanced settings, 4.5, 4.5
aggregate, 4.7.1
conflicts, C.11
creating, 4.3.1
data driven, 1.3
definition, 1.1, 4.1
effective dates, 4.5.6
engine, 1.2.1
expression builder, 4.10
filtering, 4.2.3
firing, 1.3
for each case where, 4.7.1
forward-chaining, 1.3
generating reports with SDK, F.1
list tests, 4.8
logical option, 4.5.4
nested tests, 4.6
pattern binding variable, 4.7.2
pattern block, 4.7.1
priority, 4.5.5, C.11
prototyping, 3.4
range tests, 4.3.4
reporter, F.1
rule actions, 1.1
rule conditions, 1.1, 1.1.1
SDK, 1.2.4
service component, 11.1
set tests, 4.3.5
testing, 8
tests, 4.3.2
there is a case where, 4.7.1
there is no case where, 4.7.1
tree mode, 4.8.1
validation, 4.4.2
Rules Designer
introduction, 1.2.5
rule actions, 1.1.2
rule conditions, 1.1.1
rules, 1.1
service component metadata, 11.2
WSDL, 11.2
Rules Engine
architecture, 1.3
definition, 1.2.1
rules paging, 12.6.13
rules SDK
decision point API, 7.1.1
definition, 1.2.4
rulesets
creating, 4.2.1
definition, 1.1.5, 4.1
effective dates, 4.2.2
filtering, 4.2.3
naming, A.1.1

S

SDK
definition, 1.2.4, 1.2.4
generating reports, F.1
rule reporter, F.1
self-join in Oracle RL, C.4
service component
BPEL, 11.2
definition, 1.2.1, 11
Human Tasks, 11.2
metadata, 11.1, 11.2.1.1
rules, 11.1
SOA composite application integration, 11.2
standalone component, 11.2
Web service, 11.1, 11.1
set tests, 4.3.5
Short type, 3.2.4
simple tree mode, 4.8.1.1
SOA Composer
adding rule actions, 12.6.8
adding rule conditions, 12.6.5
adding rules, 12.6.2
Bookmarkable Link, 12.4.1
Browser windows
Condition Browser, 12.7.2, 12.8.2
Date Browser, 12.7.3
Expression Builder, 12.7.1, 12.8.2
Right Operand browser, 12.7.4
browser windows, 12.7
commit menu, 12.10
conflict resolution, 12.8.9
decision tables, 12.8
adding actions, 12.8.3
adding condition rows, 12.8.2
adding decision tables, 12.8.1
adding rules, 12.8.4
compacting table, 12.8.7
deleting decision tables, 12.8.12
gap analysis, 12.8.8
splitting and compacting, 12.8.7
splitting table, 12.8.7
switching rows to columns, 12.8.10
deleting rule actions, 12.6.9
deleting rule conditions, 12.6.6
deleting rules, 12.6.3
dictionary path, 12.4.2
edit menu, 12.5
editing bucketsets, 12.5.3, 12.5.4
editing a range bucketset, 12.5.4
editing an LOV bucketset, 12.5.4
editing decision functions, 12.5.7
editing rules, 12.6
linked dictionaries, 12.5.6
modifying rule actions, 12.6.10
modifying rule conditions, 12.6.7
My Edits option, 12.4.1
obtaining composite and dictionary information, 12.13
open menu, 12.4
rules advanced settings, 12.6.4
rules paging, 12.6.13
synchronizing rules dictionary, 12.11
tree mode rules, 12.6.12
updating the validation panel, 12.12.2
validating rules dictionary, 12.12
validation panel, 12.12.1
validation panel, 12.12.1
updating the validation panel, 12.12.2
viewing bucketsets, 12.4.4
viewing globals, 12.4.3
viewing rulesets, 12.4.7
SOADesigner role
SOA Composer
authentication and SOADesigner role, 12.2.1
stateless option
decision functions, 6.2.1
sum aggregate, 4.7.4

T

testing
rules, 8
with a test function, 8
tests
in rules, 4.3.2
list, 4.8
range, 4.3.4
set, 4.3.5
transactions, 10.2.1.1
tree mode
creating tree mode rules, 4.8.2
simple, 4.8.1.1
with decision tables, 4.8.1
with rules, 4.8.1
troubleshooting, D
getter method visibility, D.1
java.lang.IllegalAccessError, D.5
java.lang.NoClassDefFoundError, D.3
setter method visibility, D.1

U

Unicode characters, 7.3.2
updated XML schema with XML facts, 3.2.3
UTF-8 characters, 7.3.2

V

validation
data model, 4.4.1
decision table, 4.4.3
dictionaries, 4.4, 4.4.1, 4.4.4
rules, 4.4.2
variable, 4.7.2
visibility
getter methods, D.1
setter methods, D.1

W

Web service
decision function, and, 6.2.1, 6.2.1
service component, 11.1, 11.1
WSDL, 11.1, 11.2
WebDAV repository support, C.15
working memory, 1.3.3
WSDL
Rules Designer, 11.2
service component metadata, 11.1

X

XML Fact
adding, 3.2.1
java.lang.NoClassDefFoundError, D.3
JAXB-generated classes, 3.2.1
reload XML facts from updated schemas, 3.2.3
support XPath assertion, 3.2.2
XPath, 3.2.2
XPath
RL program, E.2.1
support assertion, 3.2.2
XML Fact, 3.2.2
PK$PK[EZFOEBPS/decision.htm Working with Decision Tables

5 Working with Decision Tables

This chapter describes how to use Decision Tables to create and use business rules in an easy to understand format that provides an alternative to the IF/THEN rule format. It also covers the various components of a Decision Table such, as conditions, conflicts, actions, and discusses the various operations that you can perform on a Decision Table.

The chapter includes the following sections:

5.1 Introduction to Working with Decision Tables

Businesses invest in software to automate their business processes. Historically, this automation focused on the collection, presentation, and manipulation of data to facilitate human decision-making about that data. Increasingly, however, software designers and developers are called upon to automate the decision making process by putting detailed rules about business processes into software architectures. In addition, many enterprises are experiencing increasing pressure to make software systems more responsive to business changes. In some cases, the role of writing and testing business rules is no longer assigned to software engineers, but is passed to trained business users. Alternatively, some organizations attempt to separate changes in the business behavior of software from the traditional software development cycles, and tie changes to business driven imperatives like product or sales cycles.

A Decision Table provides a mechanism for describing data processing tasks, especially when that description is done by business analysts rather than computer programmers.

The Decision Table format is intuitive for business analysts who are familiar with spreadsheets. The formal structure that a Decision Table provides makes it easier to author, understand, and change multiple similar rules and lets software check for rule completeness and consistency.

Oracle Business Rules Decision Tables provide the following features:

  • Powerful Visualization: Compact and structured presentation. This visualization matches the way real world business policies are expressed: with many tables, declarative, and organized into simple steps.

  • Error Prevention: Avoids incompleteness and inconsistency. Because a Decision Table is well structured, automated tools can check for conflicts, redundancy, and incompleteness to speed development of valid, consistent business rules.

  • Modular Knowledge Organization: Group rules into a single table. A spreadsheet metaphor puts groups of rules that work together onto a single viewable pane. For example, if there are six rules that check an applicant's eligibility, it is more convenient to see all the rules than to view the rules as individual but related rules.

  • Optimization of Rules and Performance Benefits: Oracle Business Rules Decision Tables provide automated features that can reduce the number of required rules, as compared to the IF/THEN rules (this is called rule coalescing).

  • Rule Validation and Verification: Provides capabilities for ensuring the logical consistency of rules before deployment. Automated tools for checking conflicts, incompleteness, or gaps, help speed development of valid, consistent business rules.

Ease of verification and visualization are the major reasons for using Decision Tables.

For information, see Chapter 4, "Working with Rulesets and Rules".

5.1.1 What is a Decision Table?

A Decision Table displays multiple related rules in a single spreadsheet-style view. In Rules Designer a Decision Table presents a collection of related business rules with condition rows, rules, and actions presented in a tabular form that is easy to understand. Business users can compare cells and their values at a glance and can use Decision Table rule analysis features by clicking icons and selecting values in Rules Designer to help identify and correct conflicting or missing cases.

To help understand Decision Table concepts, consider a set of IF/THEN rules that determine if a driver is eligible for a license, and an equivalent Decision Table. Note if a driver has taken a driver training class then the driver has training certification.

The IF/THEN rules follow:

if driver.age < 20 and driver.has training then driver.eligible = true
if driver.age < 20 and driver.has training = false then driver.eligible = false
if driver.age >= 20 then driver.eligible = true (do not care about training for this case) 

Figure 5-1 shows a Decision Table representation of these rules that includes areas for Decision Table Conditions and Actions.

Figure 5-1 Sample Decision Table with Conditions and Actions

Description of Figure 5-1 follows

5.1.1.1 What You Need to Know About Decision Table Conditions

The Conditions area in a Decision Table includes one or more condition rows. Each condition row has a condition expression and, for each rule, a condition cell. A condition expression is an expression that you build in Rules Designer. The condition expression is often a fact property or a function result, but it can be any expression that has a type that can be associated with a bucketset. Test expressions are often used, such as Driver.age<16. These expressions are associated with the built-in boolean bucketset, with values true and false. The value or the range for a given condition cell takes its value or its range from one or more buckets in the associated LOV or Ranges bucketset. For more information on bucketsets, see Section 3.6, "Working with Bucketsets".

For example, Figure 5-1 shows the condition expression for a Driver fact with the Driver.age property. The corresponding row in the Decision Table shows condition cells including buckets for the ranges <20, and >=20. The values in the cells come from the global bucketset named driver_ages.

Figure 5-1 also shows a condition row for the Driver fact with the Driver.has_training property. This condition row shows condition cells with the values, true, false, and -. The hyphen (-) means "do not care" (that is Driver.has_training could be true or false in this case). The values for these condition cells come from the default bucketset associated with boolean types (this consists of default buckets for the values true and false).

Decision Tables show rules in bucket order, and to change the order of rules you need to change the order of buckets in the bucketsets. Thus, the order of the buckets in the bucketset associated with a condition row determines the order of the condition cells, and thus the order of the rules. You can control rule ordering in a Decision Table by changing the relative position of the buckets in an LOV bucketset associated with a condition row; however, you cannot reorder range buckets. For information on ordering buckets in a bucketset, see Section 3.6.1, "How to Define a List of Values Global Bucketset".

5.1.1.2 What You Need to Know About Decision Table Actions

Actions are associated with rules in a Decision Table. At runtime, when facts match for condition cells, the Rules Engine prepares to run the actions associated with the rule.

Table 5-1 shows the types of actions you can choose in the Actions area. Thus, in an action you can call a function, assert a new fact, retract a fact, or modify a fact. In the Actions area the cells corresponding to an individual action for a rule are called action cells. Note, in advanced mode there are additional options for actions. For more information on advanced mode, see Section 4.5.2, "How to Select the Advanced Mode Option".

Table 5-1 Decision Table Actions for Action Cells

ActionDescription

assert new

Assert a new fact

call

Call a function

retract

Retract a fact

modify

Modify a data value associated with a matched fact


When you add multiple actions the actions that you add in the Actions area are ordered; actions appearing in the higher rows run before actions in the following rows.

The Decision Table actions such as modify can refer to facts matched in the condition cells. For example, given a Decision Table with condition rows on the Driver fact that includes condition rows for Driver.age and Driver.has_training, actions can modify the property Driver.eligible and you can specify a value for Driver.eligible for each action cell.

Certain types of actions in the Actions area include a Parameterized checkbox. This checkbox specifies that a property from the action can have its value set in the action cell associated with a rule in the Decision Table. When the parameterized checkbox is selected the value you supply for the expression value in the action, in the Actions area, becomes the default value for the property if a value is not supplied in the action cell. For example, see Figure 5-2 where the value false is assigned as the default value for the action property eligible.

Figure 5-2 Action Editor Showing Parameterized Action with Default Value

Description of Figure 5-2 follows

5.1.1.3 What You Need to Know About Decision Table Rules

A ruleset contains a Decision Table; this provides a way to group the Decision Table along with IF/THEN rules. When rules and Decision Tables are grouped in a ruleset, the IF/THEN rules and the Decision Table rules all execute as a set of interrelated rules.

A rule in a Decision Table is not named. Although Rules Designer shows rules in a Decision Table with labels, for example, R1, R2, and R3, these rule labels are not names for individual rules but are labels derived from the current ordering of the rules in the Decision Table. Thus, a rule with the label R1 could be moved to position 3 and then Rules Designer relabels this rule R3.

Rules in a Decision Table are organized as a table that contains a tree of condition cells. The condition cells in the first row span the cells of later condition rows. A parent cell in row i spans its children in row i+1.

Figure 5-3 shows rules in a Decision Table where each rule consists of one cell from each row in the Conditions area, and an associated action cell in the same column in the Actions area. Figure 5-3 shows the rule with the label R3 defined by the first cell from condition 1 (the Driver.age < 20 bucket), the second cell from condition 2 (the Driver.eye_test equals fail bucket), and the third cell from condition 3 (the Driver.has_training equals true bucket). Likewise for each of the other rules, R1 to R12, there is a unique path through the Decision Table.

Figure 5-3 Rules in a Decision Table

Description of Figure 5-3 follows

As shown in Figure 5-3, it is significant for a cell to be a parent of another cell and a parent cell spans lower cells. In the Conditions area, when condition cells have the same parent condition cell the cells are called siblings. Certain operations only apply for condition cells that are siblings. For example, Figure 5-4 shows two sibling cells that are selected; with these cells selected the Merge Selected Cells operation is valid. For these cells, the corresponding bucket with the value fail for Driver.eye_test is also a sibling (as shown in the R3 and R4 columns in Figure 5-4). For more information, see Section 5.3.3, "How to Merge or Split Conditions in a Decision Table".

Figure 5-4 Sibling Condition Cells in a Decision Table

Description of Figure 5-4 follows

Rules Designer lets you easily reorder rows by selecting the row and clicking a Move icon. By reordering rows in the Conditions area you can perform operations on condition cells at the desired granularity. Thus, the move operations can assist you when you want to split, merge, or assign certain values that might only be appropriate at a particular level in the tree, depending on the location of a condition cell or depending on the location of the parent, children, or siblings of a condition cell.

5.1.2 Understanding Decision Table Values

By default, when you create a condition row, Rules Designer creates a single condition cell and assigns the "?" value to the cell. A condition cell with the value "?" indicates that the value of the cell is undefined in the bucketset. For example, Figure 5-5 shows a "?" value for Driver.age.

Figure 5-5 Sample Decision Table Showing Undefined in Condition Cell

Description of Figure 5-5 follows

In the Decision Table Actions area you can specify that an action cell "do nothing". In this case, deselect the action cell. When the action cell checkbox is unselected this means do not perform this action when the pattern matches for the specified condition values in the Decision Table. Thus, for each action cell you can specify whether the rule associated with the action cell should activate the action, or does not perform the action.

In a Decision Table, when a condition cell represents a bucket that has been removed from the bucketset, Rules Designer provides a validation warning such as the following:

RUL-05831: Decision table bucket reference not found

To fix this type of validation warning you can do one of the following:

  • Define a value by double-clicking the condition cell and selecting one or more buckets from the list.

  • Add the missing bucket to the bucketset or associate the condition with another bucketset that contains the missing bucket.

5.1.3 What You Need to Know About Decision Table Loops

A Decision Table loop occurs when the value for a condition row is changed by an action. Loops can occur across the rules in a single Decision Table or spread over several Decision Tables, or spread over rules and Decision Tables in the same ruleset. Try not to create Decision Table actions that modify fact properties that are used in Decision Table conditions. This could cause an infinite loop.


Note:

You can prevent infinite loops by using the rule firing limit on the containing decision function.


5.2 Creating Decision Tables

You add a Decision Table by performing several steps. These steps include:

  • Create a Decision Table

  • Add conditions to the Decision Table

  • Add actions to the Decision Table

  • Use Decision Table operations to validate, correct, and modify the Decision Table

5.2.1 How to Create a Decision Table

To work with a Decision Table you start by creating a Decision Table in a ruleset.

To create a decision table:

  1. From Rules Designer select an existing ruleset from the rulesets tab or create a ruleset by clicking Create Ruleset....

  2. Click the Add icon and from the list select Create Decision Table, as shown in Figure 5-6. This creates a Decision Table.

    Figure 5-6 Adding a Decision Table

    Description of Figure 5-6 follows


Note:

When you add a Decision Table the rules validation log displays validation warnings. The Decision Table is not complete and does not validate without warnings until you add conditions and actions to the Decision Table.


5.2.2 How to Add Condition Rows to a Decision Table

A Decision Table includes a Conditions area where you specify Decision Table condition rows. The condition rows determine the facts that the Oracle Rules Engine matches at runtime. To create a Decision Table you need to add one or more condition rows to the Decision Table.

To add condition rows to a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to add conditions.

  2. In the Decision Table area, from the list next to the Add icon select Condition.

  3. In the Conditions area, double-click <edit-condition> to display the navigator to select or enter an expression as shown in Figure 5-7.

    Figure 5-7 Adding a Condition to a Decision Table

    Description of Figure 5-7 follows

  4. Enter an expression by clicking in the navigator to select a variable or click the Expression Builder icon to display the Expression Builder window. The Expression Builder lets you build expressions.

  5. Each condition row requires a bucketset from which to draw the values for each cell. When the value you select has an associated global bucketset, then by default the bucketset is associated with the condition row.

  6. Repeat Step 2 through Step 5, as required to add additional condition rows in the Decision Table.

To use a local bucketset or specify the bucketset for a decision table condition:

  1. Each condition row requires a bucketset from which to draw the values for each cell. When the value you select has an associated global bucketset, then by default the bucketset is associated with the condition row.

  2. If there is no global bucketset associated with the value, then after you add a condition row to a Decision Table you need to specify either a Local List of Values or a Local List of Ranges bucketset to associate with the condition row, or specify an existing global bucketset. To add a bucketset for the condition, in the Conditions area select the condition and then select from the Bucketset list to associate a bucketset, as shown in Figure 5-8. The bucketset list includes available global bucketsets of the appropriate type.

    Figure 5-8 Specifying a Bucketset For a Condition Row in a Decision Table

    Description of Figure 5-8 follows

  3. If you do not specify a global bucketset, then you can create and use a local bucketset by selecting either Local List of Values or Local List of Ranges to create and use the specified type of bucketset.

  4. Repeat Step 2 through Step 3, as required to define additional condition rows in the Decision Table.

For more information on creating bucketsets, see Section 3.6, "Working with Bucketsets".

5.2.3 How to Add Actions to a Decision Table

A Decision Table includes an Actions area where you specify Decision Table actions. The actions determine actions for rules in a Decision Table.

To create a valid Decision Table you need to do the following:

  1. Add actions to a Decision Table.

  2. For each action cell, where specific values apply, set the values for the action cells.

  3. For each action cell, when the action does not apply to the rule, deselect the action cell. By default when you add an action to a Decision Table, actions for all the rules are unselected.

To add actions to a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to add actions.

  2. From the list next to the Add icon select Action and select an available action from the list. Table 5-1 lists the available actions. For example, select Modify. Rules Designer displays the Action Editor dialog as shown in Figure 5-9.

    Figure 5-9 Adding an Action to a Decision Table

    Description of Figure 5-9 follows

  3. In the Action Editor dialog select the action target in the Target area. This specifies the data model object the action applies to.

  4. For the specified target, as needed to make the action do what is required, modify the fields in the Arguments table. In the Action Editor dialog the Arguments table includes the fields shown in Table 5-2.

    Table 5-2 Action Editor Dialog Arguments Fields

    FieldDescription

    Property

    Displays the property names for the specified target.

    Type

    Displays the type for the property.

    Value

    Select the default value for the action from the list of available actions. The specified value applies to either the entire action, as the default value, or when a particular action cell is selected, the value specified applies for that particular action cell.

    Parameterized

    This specifies a parameterized value. A parameterized value displays in a Decision Table action cell. When you select parameterized value for a property, this generally means that each rule supplies a different parameter value.

    Constant

    Select to specify a constant value.


  5. In the Action Editor dialog, to select action cells for all the rules, select the Always Selected checkbox.

  6. Repeat Step 2 through Step 5, as required to define additional actions for the Decision Table.

To set values for action cells in a decision table:

  1. From Rules Designer, select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to specify action cell values.

  2. In the Actions area, check that the appropriate action cells are selected. If the Always Selected checkbox is specified in the Action Editor dialog, then all action cells should be selected. If Always Selected is not selected, then select the appropriate action cells using the action cell checkbox.

  3. In the Actions area, enter the appropriate value for parameterized properties for each selected action cell. To do this select the action cell property cell, and either enter a value, select a value from the list, or click the Expression Builder icon to use the Expression Builder dialog.

    For more information on referring to a bucketset from a Decision Table, see Section 3.6.2, "How to Define a List of Ranges Global Bucketset."

To deselect an action cell in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want deselect an action cell.

  2. In the Actions area, select the action cell and deselect the checkbox in the action cell. You are not allowed to deselect action cell values when Always Selected is selected for the action.

When you add actions, you may need to change the order of the actions. In Rules Designer you can use the Move Down icon or Move Up icon to change the order of actions.

5.2.4 How to Add a Rule to a Decision Table

You can add a rule to a Decision Table. Rules Designer adds a column for the rule to the left of the existing rules and each condition cell is initialized to "?", which actually means a validation error prompting you to populate the cell with relevant values.

To add a rule to a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to add the rule.

  2. From the list next to the Add icon, select Rule.

  3. Enter values for the condition cells. Notice that the new rule is added as the first rule of the Decision Table on the left and the other rules have moved as required to keep the bucket values in their defined order.

  4. Enter values for the action cells.

Ordering Rules by Bucket

The Order Rules By Bucket checkbox under the Advanced Settings of a Decision Table is selected by default. In this case, the Decision Table layout changes automatically on adding new rules.

When you add a new rule to a Decision Table, the new rule is added as the first rule of the Decision Table and the other rules move as required to keep the bucket values in their defined order. This is because Order Rules By Bucket is enabled, which means rule ordering in a Decision Table is set according to the relative position of buckets associated with a condition expression. If Order Rules By Bucket is not enabled when you add a rule, the new rule is added as the last rule of the Decision Table. In either case, the cells in the new rule column have "?" symbols, indicating the cells do not have values yet.


Note:

When Order Rules By Bucket is selected, the rules are ordered and duplicate rules (rules with exactly the same buckets) are combined. So, you cannot add two rules without any buckets to a Decision Table, because in that case, the rules are duplicates and would immediately be combined. When Order Rules By Bucket is deselected, then duplicate rules are allowed.


In addition, the Move Left and Move Right buttons pertaining to a rule column is also enabled and you can reposition rules. The Span options also get enabled and you can also cut, copy, or paste rules.

5.2.5 How to Define Tests in a Decision Table

You can define tests in a Decision Table. The tests must evaluate to true for any rule in the decision table to fire. For more information about defining tests and working with rule conditions, see Section 4.3, "Working with Rules".

To add tests to a Decision Table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to add the rule.

  2. Click the Show Advanced Settings icon (double downward pointing arrows) next to the Decision Table name. If Advanced Mode is selected, deselect the checkbox.

  3. Just below the Decision Table name, click the <insert test> downward pointing arrow.

  4. Select any of the following options according to your requirement:

    • simple test

    • variable

    • nested test

    • not nested test

  5. Click the left and the right <operand> to enter the operand values, and the operator list to select an operator.

    The added test is displayed in Figure 5-10.

    Figure 5-10 Adding Test to a Decision Table

    Description of Figure 5-10 follows

5.3 Performing Operations on Decision Tables

After you create a Decision Table there are operations that you may want to perform on the Decision Table, including the following:

  • Compact or split cells in a Decision Table

  • Merge a condition or split a condition in a Decision Table

  • Finding and resolving conflicts between rules in a Decision Table

  • Find and fix gaps in a Decision Table

5.3.1 Introduction to Decision Table Operations

After you create a Decision Table you may want to modify the contents of the Decision Table to produce a Decision Table that includes a complete set of rules for all cases, or to produce a Decision Table that provides the least number of rules for the cases.

5.3.1.1 Understanding Decision Table Split and Compact Operations

The split and compact operations allow you to manipulate the contents of the condition cells in a Decision Table.

The split table operation creates a rule for every combination of buckets across the conditions. For example, in a Decision Table with 3 boolean conditions, 2 x 2 x 2 = 8 rules are created. In a Decision Table with 32 boolean conditions, 2**32 ~ 2 billion rules are created. Thus, you only use split table when the number of rules created is small enough that filling in the action cells is feasible.

When you want to apply match conditions for the "do not care" values in a Decision Table and create a match case for each cell, you use the split table operation.

Split can be applied to an entire Decision Table or to a single condition row. Additionally, split may be performed on an individual condition cell.

Depending on what is selected in the Decision Table, the split operation can create condition cells. Thus, using the split operation you can create rules in a Decision Table. Table 5-3 summarizes the split operation for a selected condition cell, condition row, or for a complete Decision Table.

Table 5-3 Summary of Split Operation

OperatorDescription

Condition Cell

Creates one sibling condition cell for each bucket value represented by the cell.

If the condition cell value is "do not care", then the cell is split into one sibling cell for each bucket in the bucketset that is not represented by a sibling condition cell, and "do not care" is no longer represented.

Condition Row

For each condition cell in the proceeding condition expression, create a sibling group which contains a cell for each value in the bucketset. The effect of this operation is the same as adding a "do not care" to each sibling group and calling split on each condition cell in each sibling group.

Decision Table


Same as calling split on each condition row in the Decision Table.


Depending on what is selected in the Decision Table, the compact table or merge cells operations remove condition cells. The compact table operation can be applied to an entire Decision Table. Additionally, the merge operation may be performed on sibling cells or on an entire condition row. Thus, using compact table or merge you can remove rules from a Decision Table. Table 5-4 summarizes the compact table and merge operations.

Table 5-4 Summary of Merge Operation

OperatorDescription

Condition Cell

Merging two or more condition cells adds all buckets in the cells to a single cell, and removes all but one of the cells. If one of the cells represents "do not care", then the merged cell represents "do not care".

This operation may merge action cells and this can create warnings for duplicate action cells, such as, RUL-05847: Duplicate decision table action parameter.

Condition Row

Combine all values in each sibling group into a single "do not care" cell for each condition cell in the proceeding condition expression. The effect of this is the same as calling merge on all cells in each sibling group.

This operation may merge action cells and this can create warnings for duplicate action cells, such as, RUL-05847: Duplicate decision table action parameter.

Decision Table


Compacts the Decision Table by merging conditions of rules with identical actions.


Split and merge are inverse operations when conflicting action cells are not associated with the operation. In this case, without conflicting action cells, a merge operation combines all the values from the siblings into one sibling, and discards the other sibling condition cells, and as a result of merging the condition cells, when a Decision Table contains action cells, the action cells are also merged. Thus, the merge operation combines multiple condition cells into a single condition cell and adds all buckets to the single cell.

When there are conflicting values for the action cells, a merge operation merges the action cells in a form that requires additional manual steps. Thus, if two action cells have conflicting parameters, after the merge the action cell contains multiple conflicting parameter values. These conflicting values are appended to the action cell and must be manually resolved by selecting and deleting the unwanted duplicate parameters. For example, see Figure 5-11 that shows conflicting values in an action cell.

An action cell that contains multiple values for a property is invalid. When you select the action cell Rules Designer shows a popup window with checkboxes to allow you to select a single value for the action cell. As shown in the validation log in Figure 5-11, Rules Designer shows a validation warning until you select a single value.

Figure 5-11 Conflicting Properties to be Resolved for a Merged Action Cell

Description of Figure 5-11 follows

5.3.1.2 Understanding Decision Table Move Operations

You can move the conditions or actions in a Decision Table. The Move icons let you reorder condition rows in the Conditions area and actions in the Actions area. Moving conditions up or down may reorder visual display of the rules, but these operations does not change the logic in any way. For example, if (x.a == 1 and x.b == 1) is logically the same as if (x.b == 1 and x.a == 1).

When you work with Decision Tables some operations only apply for condition cells that are siblings. Using the Move icon you can reorder rows so that Decision Table operations apply to the tree at the desired granularity. For example, when you want to change the action of a condition cell for a single rule, then you need to move that condition cell to the last row in the Decision Table Conditions area. For example, consider the Decision Table shown in Figure 5-12.

Figure 5-12 Rules in a Decision Table

Description of Figure 5-12 follows

To view this table with granularity for the Driver.age, move the Driver.age condition from the first row to the third row, as shown in Figure 5-13.

Figure 5-13 Decision Table After Move Down with Age Condition Last

Description of Figure 5-13 follows

Now to make the Driver.age conditions "do not care" for the first two rules, where the driver passes the eyesight test and has had driver training is true, you can easily apply changes to these particular conditions when the Driver.age condition is in the last row. Thus, in this table, it is easier to view and modify age related rules when Driver.age is in the last row, with the finest granularity.In general, the move operations can assist you when you want to split, merge, or assign certain values that might only be appropriate at a particular level in the tree, depending on the location of a condition cell, or depending on the location of the parent, children, or siblings of a condition cell.

For actions in the Actions area, clicking Move Up or Move Down lets you reorder the actions. Actions are ordered so that when multiple actions apply, the first action runs before subsequent actions. Thus, using the Move Up or Move Down operation on an action may be appropriate, depending on your application.

5.3.1.3 Understanding Decision Table Gap Checking

A gap is a "missing" rule in a Decision Table. A Decision Table has a gap if there is a combination of buckets, one from each condition, that is not covered by an existing rule. Rules Designer provides Gap Checking to check for gaps. When you click the Gap Analysis icon, Rules Designer finds gaps and presents a dialog to fix any gaps that are found.

You can choose to make existence of gaps a validation warning. When you deselect Allow Gaps in the Advanced Settings area, the Decision Table reports a validation warning when a gap is found. For more information, see Section 4.5, "Using Advanced Settings with Rules and Decision Tables".

For example, using the Driver example if you create a gap by deleting the rule that covers the case for Driver.age < 20 and Driver.has_training false, and then you click Gap Analysis, Rules Designer shows the Gap Analysis dialog as shown in Figure 5-14. Clicking OK with the checkboxes selected adds either all rules or the selected rules to the Decision Table (this example only shows a single rule to add).

Figure 5-14 Checking Gaps

Description of Figure 5-14 follows

Gap checking generates different new rules for the following cases:

  • Sibling rules: multiple missing sibling rules are added as a single new rule. For example, consider a rule with two conditions, Driver.age and Driver.hair. When there are two missing rules for different hair colors and the rules are siblings, that is, they have a common parent, then gap checking shows a single rule as shown in Figure 5-15.

  • Non-sibling rules: multiple missing non-sibling rules are added as individual new rules. For example, when there are two different rules missing that do not have the same parent, then gap checking provides two rules, as shown in Figure 5-16.

Figure 5-15 Gap Checking with Missing Sibling Rules

Description of Figure 5-15 follows

Figure 5-16 Gap Checking with Missing Non-Sibling Rules

Description of Figure 5-16 follows

In both of these cases shown in Figure 5-15 and Figure 5-16 there are two missing buckets, but for sibling rules the multiple buckets are combined in a single new rule. Thus, in general gap checking suggests fewer more general rules in preference to many more specific rules.

For sibling rules you can add multiple rules then edit each cell to pick the buckets you want. Alternatively, you can use Find Gaps to add a rule and then split the cell with multiple values, and delete the rules you do not want to keep.

5.3.1.4 Understanding Decision Table Conflict Analysis

The rules in a Decision Table can conflict. Two rules conflict when they overlap and they have different actions. Two rules overlap when at least one of their condition cells has a bucket in common. Overlap is common when a Decision Table contains "do not care" condition cells. Overlap without conflict is common and harmless.

Rules Designer finds conflicts and you can see the conflicts in the Conflict Resolution row in the Decision Table when you click Show Conflicts. How you handle and resolve conflicts depends on the specified conflict policy. You can choose a conflict policy or use the default manual conflict policy. When you set a conflict policy using the Conflict Policy option in the Advanced Settings area, Rules Designer sets the conflict policy for the Decision Table. The Conflict Policy specifies the Decision Table conflict policy and is one of the following:

  • manual: Conflicts are resolved by manually specifying a conflict resolution for each conflicting rule.

  • auto override: Conflicts are resolved automatically using an override conflict resolution when this is possible, using the Oracle Business Rules automatic conflict resolution policies.

  • ignore: Conflicts are ignored.

For more information, see Section 4.5, "Using Advanced Settings with Rules and Decision Tables". For example, Figure 5-17 shows a Decision Table with conflicting rules that you resolve with the default manual conflict policy.

Figure 5-17 Decision Table Showing Conflicting Rules in the Conflicts Area

Description of Figure 5-17 follows

By clicking on the cells in the Decision Table Conflict Resolution area Rules Designer lets you resolve conflicts between rules as follows:

  • Override (Override and OverriddenBy): You override one rule with the other. Override specifies that one rule fires. Override is a combination of prioritization and mutual exclusion. Prioritization is transitive and not symmetric. Mutual exclusion is both transitive and symmetric. If A overrides C and B overrides C, then A or B runs before C but only one of A, B, or C runs.

  • Run Before (RunBefore and RunAfter): You prioritize the rules. Run before lets the two rules fire in a prescribed order. Prioritization is transitive but not symmetric. That is, if A runs before B runs before C, then A runs before C but B does not run before A. This uses a Decision Table runBefore list specifying that the rule that runs before has a higher priority than rules in the list.

  • Ignore (NoConflict): You OK the conflict. Ignore lets the two rules fire in arbitrary order. For example, consider the following conflicting rules in a decision table:

    rule1: everybody gets a 10% raise (as specified with a do not care value in a decision table condition cell)
    rule2: employee with Top Performer set to true gets a 5% raise
    

    In these rules, if rule2 overrides rule1, then a top performer gets a 5% raise, and everyone else gets a 10% raise. However, in this case, you would like to have both rules fire. Because it does not matter which rule fires first, and there is no conflict, then a top performer gets a 15.5% raise either way. In this case, use the NoConflict list to remove the conflict. Note that no conflict is what you get with IF/THEN rules with equal priorities, only you are not warned of a conflict and you have to think carefully if you want one rule to override the other.

Figure 5-18 shows the Rules Designer Conflict Resolution dialog shown when you select a conflicting rule in the Conflict Resolution area. This dialog lets you resolve conflicts between rules by selecting overrides, prioritization with RunBefore or RunAfter options, and a NoConflict option.

Figure 5-18 Using the Decision Table Conflict Resolution Dialog

Description of Figure 5-18 follows

You can use the Decision Table Advanced Settings Conflict Policy auto override option to specify that, where possible, conflicts are automatically resolved. The automatic override conflict resolution policy specifies that a special case overrides a more general case. For more information, see Section 4.5, "Using Advanced Settings with Rules and Decision Tables".

Thus, when there are conflicts in a Decision Table, you can do one or more of the following to resolve the conflicts:

  • Use auto override conflict resolution by selecting the Conflict Policy and then auto override option in the Decision Table.

  • Ignore conflicts by selecting the Conflict Policy and then ignore option in the Decision Table.

  • Use manual conflict resolution by selecting the Conflict Policy and then manual option in the Decision Table and set Conflict Resolution for each conflicting rule in the dialog by selecting cells in the Conflict Resolution area with the Show Conflicts checkbox selected.

  • Change the Decision Table to remove an overlap.

  • Combine actions to remove conflicts.

5.3.2 How to Compact or Split a Decision Table

Use the Compact Table and Split Table icons to compact or split cells in a Decision Table. For more information, see Section 5.3.1.1, "Understanding Decision Table Split and Compact Operations."

To compact a decision table:

  1. In Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table to compact.

  2. Click the Compact Table icon.

To split cells in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table to split.

  2. Click the Split Table icon.

5.3.3 How to Merge or Split Conditions in a Decision Table

Use the merge condition and split condition operations to merge or split a condition in a Decision Table. For more information, see Section 5.3.1.1, "Understanding Decision Table Split and Compact Operations."

To merge a condition in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to merge a condition.

  2. In the Conditions area, select the condition you want to merge.

  3. Right-click, and from the list select Merge Condition.

To split a condition in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to split a condition.

  2. In the Conditions area, select the condition you want to split.

  3. Right-click and from the list select Split Condition.

5.3.4 How to Merge, Split, and Specify Do Not Care for Condition Cells

Use the condition cell operations to split a condition cell, to merge sibling condition cells, or to specify a "do not care" value for a condition cell in a Decision Table. For more information, see Section 5.3.1.1, "Understanding Decision Table Split and Compact Operations."

To merge sibling cells in a condition in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to merge condition cells.

  2. Select the sibling condition cells to merge.

  3. Right-click, and from the list select Merge selected cells.

To split a cell in a condition in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to split a condition cell.

  2. Select the cell to split.

  3. Right-click, and from the list select Split selected cell.

To specify a "Do Not Care" value for a cell in a condition in a decision table:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to set the "do not care" value.

  2. Select the appropriate condition cell.

  3. Right-click, and from the list select Do Not Care.

To select all buckets to specify a "Do Not Care" value for a cell in a condition:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to set the "do not care" value.

  2. Select the appropriate condition cell.

  3. Double-click, and from the list select all the available checkboxes for all possible values.

5.3.5 How to Perform Decision Table Gap Checking

A gap is a "missing" rule in a Decision Table. A Decision Table has a gap if there is a combination of buckets, one from each condition, that is not covered by an existing rule. Rules Designer provides Gap Checking to check for gaps. When you use this operation Rules Designer presents a window to fix gaps. For more information, see Section 5.3.1.3, "Understanding Decision Table Gap Checking".

You can choose to make existence of gaps a validation warning. When you deselect Allow Gaps in the Advanced Settings area, the Decision Table reports a validation warning when a gap is found. For more information, see Section 4.5, "Using Advanced Settings with Rules and Decision Tables".

To perform decision table gap checking:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to perform.

  2. Click the Gap Analysis icon.

5.3.6 How to Perform Decision Table Manual Conflict Resolution

The rules in a Decision Table can conflict. Two rules conflict when they overlap and they have different actions. Two rules overlap when at least one of their condition cells has a bucket in common. For more information, see Section 5.3.1.4, "Understanding Decision Table Conflict Analysis".

To perform manual decision table conflict resolution:

  1. From Rules Designer select a ruleset from the Rulesets navigation tab and select the Decision Table where you want to check conflicts.

  2. Set the conflict policy to manual (this is the default conflict policy). For more information, see Section 5.3.1.4, "Understanding Decision Table Conflict Analysis".

  3. In the Conditions area, in the conflicts area, when conflicts exist for each rule with a conflict double-click the appropriate condition cell to display the Conflict Resolution dialog.

  4. In the Conflict Resolution dialog, for each conflicting rule, in the Resolution field select a resolution from the list.

5.3.7 How to Set the Decision Table Auto Override Conflict Resolution Policy

When you select the Advanced Settings option in a Decision Table, you can select that Decision Table conflicts are automatically resolved using the auto override conflict policy (this applies only when it is possible to resolve the conflict using the Oracle Business Rules automatic conflict resolution policies). The automatic override conflict resolution uses a policy where when there is a rule conflict a special case overrides a more general case. For more information, see Section 5.3.1.4, "Understanding Decision Table Conflict Analysis".

To select the auto override policy:

  1. Select the rule or Decision Table where you want to use ignore conflict policy.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name.

  3. From the Conflict Policy option select auto override.

5.3.8 How to Set the Decision Table Ignore Conflicts Policy

When you select the Advanced Settings option in a Decision Table, you can select that the Decision Table conflicts are ignored using the ignore conflict policy. The ignore policy tells Oracle Business Rules to ignore conflicts in the Decision Table. For more information, see Section 5.3.1.4, "Understanding Decision Table Conflict Analysis".

To select the ignore conflict policy:

  1. Select the rule or Decision Table where you want to use the ignore conflicts policy.

  2. Click the Show Advanced Settings icon next to the rule or Decision Table name.

  3. From the Conflict Policy option select ignore.

5.4 Creating and Running an Oracle Business Rules Decision Table Application

The Order Approval application demonstrates the integration of a SOA composite application with Oracle Business Rules and the use of a Decision Table.

In this application a process is modeled that uses the decision component to:

  • Process rules from XML inputs including: a credit score and the annual spending of a customer, and the total cost of the incoming order.

  • Provide output that determines if an order is approved, rejected, or requires manual processing.

To complete this procedure, you need to:

  • Obtain the Source Files for the Order Approval Application

  • Create an Application for Order Approval

  • Create a Business Rule Service Component for Order Approval

  • View Data Model Elements for Order Approval

  • Add Bucketsets to the Data Model for Order Approval

  • Associate Bucketsets with Order and CreditScore Properties

  • Add a Decision Table for Order Approval

    • Split the Cells in the Decision Table and Add Actions

    • Compact the Decision Table

    • Replace Several Specific Rules with One General Rule

    • Add a General Rule

  • Check Dictionary Business Rule Validation Log for Order Approval

  • Deploy the Order Approval Application

  • Test the Order Approval Application

5.4.1 How to Obtain the Source Files for the Order Approval Application

The source code for Oracle Business Rules-specific samples and SOA samples are available online in the Oracle SOA Suite samples page.

To work with the Order Approval application, you first need to obtain the order.xsd schema file either from the sample project that you obtain online or you can create the schema file and create all the application, project, and other files in Oracle JDeveloper. You can save the schema file provided in Example 5-1 locally to make it available to Oracle JDeveloper.

Example 5-1 shows the order.xsd schema file.

Example 5-1 Order.xsd Schema

<?xml version="1.0" ?>
<schema attributeFormDefault="qualified" elementFormDefault="qualified"
        targetNamespace="http://example.com/ns/customerorder"
        xmlns:tns="http://example.com/ns/customerorder"
        xmlns="http://www.w3.org/2001/XMLSchema">
  <element name="CustomerOrder">
    <complexType>
      <sequence>
        <element name="name" type="string" />
        <element name="creditScore" type="int" />
        <element name="annualSpending" type="double" />
        <element name="value" type="string" />
        <element name="order" type="double" />
      </sequence>
    </complexType>
  </element>
  <element name="OrderApproval">
    <complexType>
      <sequence>
        <element name="status" type="tns:Status"/>
      </sequence>
    </complexType>
  </element>
  <simpleType name="Status">
    <restriction base="string">
        <enumeration value="manual"/>
        <enumeration value="approved"/>
        <enumeration value="rejected"/>
    </restriction>
  </simpleType>
 </schema>

5.4.2 How to Create an Application for Order Approval

To work with Oracle Business Rules, you first create an application in Oracle JDeveloper.

To create an application for order approval:

  1. In the Application Navigator, click New Application.

  2. In the Name your application dialog, enter the name and location for the new application.

    1. In the Application Name field, enter an application name. For example, enter OrderApprovalApp.

    2. In the Directory field, specify a directory name or accept the default.

    3. In the Application Package Prefix field, enter an application package prefix, for example com.example.order.

      The prefix, followed by a period, applies to objects created in the initial project of an application.

    4. For a SOA composite with Oracle Business Rules, in the Application Template area select SOA Application for the application template. For example, see Figure 5-19.

    5. Click Next.

      Figure 5-19 Adding the Order Approval Application

      Description of Figure 5-19 follows

  3. In the Name your project page enter the name and location for the project.

    1. In the Project Name field, enter a name. For example, enter OrderApproval.

    2. Enter or browse for a directory name, or accept the default.

    3. For an Oracle Business Rules project, in the Project Technologies area ensure that SOA, ADF Business Components, Java, and XML are in the Selected area on the Project Technologies tab, as shown in Figure 5-20. If an item is missing, select it in the Available pane and add it to the Selected pane using the Add button.

      Figure 5-20 Adding a Project to an Application

      Description of Figure 5-20 follows

  4. Click Finish.

5.4.3 How to Create a Business Rule Service Component for Order Approval

After creating a project in Oracle JDeveloper you need to create a Business Rule Service component within the project. When you add a business rule you can create input and output variables to provide input to the service component and to obtain results from the service component.

To use business rules with Oracle JDeveloper, you do the following:

  • Add a business rules service component

  • Create input and output variables for the service component

  • Create an Oracle Business Rules dictionary in the project

To create a business rule service component:

  1. In the Application Navigator, in the OrderApproval project expand SOA Content and double-click composite.xml to launch the SOA composite editor (this may already be open after you create the project).

  2. From the Component Palette, drag-and-drop a Business Rule from the Service Components area of the SOA menu to the Components lane of the composite.xml editor.

    Oracle JDeveloper displays a Create Business Rules page, as shown in Figure 5-21.

    Figure 5-21 Adding a Business Rule Dictionary with the Create Business Rules Dialog

    Description of Figure 5-21 follows

  3. To add an input, from the list next to the Add icon select Input to enter input for the business rule.

  4. In the Type Chooser dialog, click the Import Schema File... icon. This displays the Import Schema File dialog, as shown in Figure 5-22.

    Figure 5-22 Import Schema File with Type Chooser

    Description of Figure 5-22 follows

  5. In the Import Schema dialog click Browse Resources to choose the XML schema elements for the input variable of the process. This displays the SOA Resource Lookup dialog.

  6. In the SOA Resource Lookup dialog, navigate to find the order.xsd schema file and click OK.

  7. In the Import Schema File dialog, make sure Copy to Project is selected, as shown in Figure 5-23.

    Figure 5-23 Importing the Order.xsd Schema File

    Description of Figure 5-23 follows

  8. In the Import Schema File dialog, click OK.

  9. If the Localize Files dialog displays, click OK to copy the schema to the composite process directory.

  10. In the Type Chooser, navigate to the Project Schemas Files folder to select the input variable.

    For this example, select CustomerOrder as the input variable.

  11. On the Type Chooser window, click OK. This displays the Create Business Rules dialog, as shown in Figure 5-24.

    Figure 5-24 Create Business Rules Dialog with CustomerOrder Input

    Description of Figure 5-24 follows

  12. In a similar manner, add the output fact type OrderApproval from the imported order.xsd.

  13. In the Create Business Rules dialog, select Expose as Composite Service, as shown in Figure 5-25.

    Figure 5-25 Create Business Rules Dialog with Input and OrderApproval Output

    Description of Figure 5-25 follows

  14. Click OK. This creates the Business Rule component and Oracle JDeveloper shows the Business Rule in the canvas workspace, as shown in Figure 5-26.

    Figure 5-26 Business Rules Component in OrderApproval Composite

    Description of Figure 5-26 follows

The business rule service component enables you to integrate your SOA composite application with a business rule. This creates a business rule dictionary and enables you to execute business rules and make business decisions based on the rules.

5.4.4 How to View Data Model Elements for Order Approval

Before adding rules you need to create the Oracle Business Rules data model. The data model contains the business data definitions (types) and definitions for facts that you use to create rules. For example, for this sample the data model includes the XML schema elements from order.xsd that you specify when you define inputs and outputs for the business rule activity.

At times when you work with Rules Designer to create a rule or a Decision Table, you may need to create or modify elements in the data model.

To view data model elements for Oracle business rules:

  1. Select the composite tab with the value composite.xml, and in the Components lane select the business rule (this surrounds the component, OracleRules1 with a dashed selection box).

  2. Double-click the selection box to launch Rules Designer.

  3. In Rules Designer select the Facts navigation tab.

  4. Select XML Facts tab in the Facts navigation tab as shown in Figure 5-27.

    Figure 5-27 Opening a Business Rules Dictionary with Rules Designer

    Description of Figure 5-27 follows

5.4.5 How to Add Bucketsets to the Data Model for Order Approval

To use a Decision Table you need to define bucketsets that specify how to draw values for each cell for the conditions that constitute the Decision Table. For this example the bucketsets are defined with a list of ranges that you define in Rules Designer.

To add OrderAmount bucketset to the data model:

  1. In Rules Designer, select the Bucketsets navigation tab.

  2. From the dropdown next to the Create BucketSet... icon, select List of Ranges.

  3. In the Name field, enter OrderAmount (In Rules Designer be sure to press Enter to accept the name).

  4. Double-click the OrderAmount bucketset icon to display the Edit Bucketset dialog.

  5. Click Add Bucket to add a bucket.

  6. Click Add Bucket again to add another bucket.

  7. In the Range Bucket Values area, in the top Endpoint field enter 1000 for the endpoint value.

  8. In the Range Bucket Values area, for the middle bucket in the Endpoint field enter 500 for the endpoint value.

  9. In the Included Endpoint field for each bucket ensure the checkbox is selected, as shown in Figure 5-28.

    Figure 5-28 Adding the OrderAmount Bucketset

    Description of Figure 5-28 follows

  10. Modify the Alias field for each value to High, Medium, and Low, as shown in Figure 5-29.

    Figure 5-29 Adding the OrderAmount Bucketset with Low Medium and High Aliases

    Description of Figure 5-29 follows

  11. Click OK.

To add CreditScore bucketset to data model:

  1. In Rules Designer select the Bucketsets navigation tab.

  2. From the dropdown next to the Create BucketSet... icon, select List of Ranges.

  3. In the Name field, enter CreditScore.

  4. Double-click the CreditScore bucketset icon to display the Edit Bucketset dialog.

  5. Click Add Bucket to add a bucket.

  6. Click Add Bucket again to add another bucket.

  7. In the top bucket, in the Endpoint field enter 750.

  8. For the middle bucket, in the Endpoint field enter 400.

  9. In the Included Endpoint field for each bucket, ensure the checkbox is selected as shown in Figure 5-30.

    Figure 5-30 Adding the CreditScore Bucketset

    Description of Figure 5-30 follows

  10. Modify the Alias field for each endpoint value to solid for 750, avg for 400, and risky for -Infinity as shown in Figure 5-31.

  11. Click OK.

Figure 5-31 Adding the CreditScore Bucketset with Risky Avg and Solid Aliases

Description of Figure 5-31 follows

5.4.6 How to Associate Bucketsets with Order and CreditScore Properties

To prepare for creating Decision Tables you can associate a bucketset with fact properties in the data model. In this way condition cells in a Decision Table Conditions area can use the bucketset when you create a Decision Table.

Note that the OrderApproval.status property is associated with the Status bucketset when the OrderApproval fact type is imported from the XML schema. In the schema, Status is a restricted String type and is therefore represented as an enum bucketset. Rules Designer creates the status bucketset. For more information, see Section 3.2.4, "What You Need to Know About XML Facts".

To associate bucketsets with Order and CreditScore properties:

  1. In Rules Designer select the Facts navigation tab.

  2. Select the XML Facts tab in the Facts navigation tab as shown in Figure 5-32.

    Figure 5-32 Opening a Business Rules Dictionary with Rules Designer

    Description of Figure 5-32 follows

  3. Select the type you want to modify. For example in the XML Facts table double-click the icon next to the CustomerOrder entry. This displays the Edit XML Fact dialog.

  4. In the Edit XML Fact dialog, in the Properties table in the Bucketset column select the cell for the appropriate property and from the list select the bucketset you want to use. For example, for the property order select the OrderAmount bucketset, as shown in Figure 5-33.

    Figure 5-33 Associating the OrderAmount Bucketset with CustomerOrder.order

    Description of Figure 5-33 follows

  5. In a similar manner, for the property creditScore select the CreditScore bucketset.

  6. Click OK.

5.4.7 How to Add a Decision Table for Order Approval

You create a Decision Table to process input facts and to produce output facts, or to produce intermediate conclusions that Oracle Business Rules can further process using additional rules or in another Decision Table.

While you work with rules you can use the rule validation features in Rules Designer to assist you. Rules Designer performs dictionary validation when you make any change to the dictionary. To show the validation log window, click the Validate icon or select View>Log and select the Business Rule Validation tab. If you view the rules validation log you should see warning messages. You remove these warning messages as you create the Decision Table. For more information on rule validation see Section 4.4.2, "Understanding Rule Validation".

To use a Decision Table for rules in this sample application you work with facts representing a customer spending level and a customer credit risk for a particular customer and a particular order. Then, you use a Decision Table to create rules based on customer spending, the order amount, and the credit risk of the customer.

To add a decision table for order approval:

  1. In Rules Designer, select Ruleset_1 under the Rulesets navigation tab.

  2. Click the Add icon and from the list and select Create Decision Table.

  3. In the Decision Table, click the Add icon and from the list select Condition.

  4. In the Decision Table, double-click <edit condition>. Then, in the navigator expand CustomerOrder and select creditScore. This enters the expression CustomerOrder.creditScore in the Conditions column.

  5. Again, in the Decision Table, click the Add icon and from the list select Condition.

  6. In tlhe Decision Table, in the Conditions area double-click the <edit condition>. Then, in the navigator expand CustomerOrder and select order. This enters the expression CustomerOrder.order.

  7. Again, in the Decision Table, click the Add icon and from the list select Condition.

  8. In the Decision Table, double-click <edit condition>.

  9. In the navigator expand CustomerOrder and select annualSpending. In the text entry area, add >2000 as shown in Figure 5-34.

    Figure 5-34 Adding the Annual Spending Entry to a Decision Table

    Description of Figure 5-34 follows

  10. Type Enter to accept the value, as shown in Figure 5-35. If you view the rules validation log you should see the warning messages as shown in Figure 5-35. You remove these warning messages as you modify the Decision Table in later steps.

    Figure 5-35 Adding Conditions to the CustomerOrder Decision Table

    Description of Figure 5-35 follows

To create an action in a decision table:

  1. In the Decision Table click the Add icon and from the list select Action > Assert New.

  2. In the Actions area, double-click assert new(. This displays the Action Editor dialog.

  3. In the Action Editor dialog, in the Facts area select OrderApproval.

  4. In the Action Editor dialog, in the Properties table for the property status select the Parameterized checkbox and the Constant checkbox. This specifies that each rule independently sets the status.

  5. In the Action Editor dialog, select the Always Selected checkbox as shown in Figure 5-36.

    Figure 5-36 Adding an Action to a Decision Table with the Action Editor Dialog

    Description of Figure 5-36 follows

  6. In the Action Editor dialog, click OK.

Next you need to add rules to the Decision Table and specify an action for each rule.

5.4.7.1 Split the Cells in the Decision Table and Add Actions

You can use the Decision Table split operation to create rules for the bucketsets associated with the condition rows in the Decision Table. This creates one rule for every combination of condition buckets. There are three order amount buckets, three credit score buckets, and two boolean buckets for the annual spending amount for a total of eighteen rules (3 x 3 x 2 = 18).

To split cells in a decision table:

  1. Select the Decision Table.

  2. In the Decision Table, click the Split Table icon and from the list select Split Table. The split table operation eliminates the "do not care" cells from the table. The table now shows eighteen rules that cover all ranges as shown in Figure 5-37.

These steps produce validation warnings for action cells with missing expressions. You fix these in later steps.

Figure 5-37 Splitting a Decision Table Using Split Table Operation

Description of Figure 5-37 follows

To add actions for each rule in the decision table:

In the Decision Table you specify a value for the status property associated with OrderApproval for each action cell in the Actions area. The possible choices are: Status.MANUAL, Status.REJECTED, or Status.ACCEPTED. In this step you fill in a value for status for each of the 18 rules. The values you enter correspond to the conditions that form each rule in the Decision Table.

  1. In the Actions area, double-click the action cell for the rule you want to work with, as shown in Figure 5-38.

    Figure 5-38 Adding Action Cell Values to a Decision Table

    Description of Figure 5-38 follows

  2. In the list, select and enter a value for the action cell. For example, enter Status.MANUAL.

  3. For each action cell, enter the appropriate value as determined by the logic of your application. For this sample application use the values for the Decision Table actions as shown in Table 5-5.

  4. Select Save All from the File main menu to save your work.

Table 5-5 Values for Decision Table Actions

RuleC1 creditScoreC2 orderC3 annualSpending > 2000A1 OrderApproval status

R1

risky

Low

true

Status.MANUAL

R2

risky

Low

false

Status.MANUAL

R3

risky

Medium

true

Status.MANUAL

R4

risky

Medium

false

Status.REJECTED

R5

risky

High

true

Status.MANUAL

R6

risky

High

false

Status.REJECTED

R7

avg

Low

true

Status.APPROVED

R8

avg

Low

false

Status.MANUAL

R9

avg

Medium

true

Status.APPROVED

R10

avg

Medium

false

Status.MANUAL

R11

avg

High

true

Status.MANUAL

R12

avg

High

false

Status.MANUAL

R13

solid

Low

true

Status.APPROVED

R14

solid

Low

false

Status.APPROVED

R15

solid

Medium

true

Status.APPROVED

R16

solid

Medium

false

Status.APPROVED

R17

solid

High

true

Status.APPROVED

R18

solid

High

false

Status.MANUAL


5.4.7.2 Compact the Decision Table

In this step you compact the rules to merge from eighteen rules to nine rules. This automatically eliminates the rules that are not needed and preserves the no gap, no conflict properties for the Decision Table.

To compact the decision table:

  1. Select the Decision Table.

  2. Click the Resize All Columns to Same Width icon.

  3. Click the Compact Table icon and from the list select Compact Table. The compact table operation eliminates rules from the Decision Table. The Decision Table now shows nine rules, as shown in Figure 5-39.

Figure 5-39 Compacting a Decision Table Using Compact Table

Description of Figure 5-39 follows

5.4.7.3 Replace Several Specific Rules with One General Rule

Notice that five of the nine remaining rules result in a manual order approval status. You can reduce the number of rules by deleting these five rules. Note it is often best practice to not do this (that is not replace several specific rules with one general rule). You need to compare the benefits of having fewer rules with the added complexity of managing the conflicts introduced when you reduce the number of rules.

To replace several specific rules with one general rule:

  1. Select the Decision Table.

  2. In the Decision Table, select a rule with OrderApproval status action set to Status.MANUAL. To select a rule, click the column heading. For example, click rule R2 as shown in Figure 5-40.

  3. Click Delete to remove a rule in the Decision Table. Be careful to click the delete icon in the Decision Table area to delete a rule in the decision table (there is also a delete icon shown in the Ruleset area that deletes the complete Decision Table).

    Figure 5-40 Deleting Rules from a Decision Table

    Description of Figure 5-40 follows

  4. Repeat these steps to delete all the rules with action set to Status.MANUAL. This should leave the Decision Table with four rules as shown in Figure 5-41.

    Figure 5-41 Decision Table After Manual Actions Removed

    Description of Figure 5-41 follows

5.4.7.4 Add a General Rule

Now you can add a single rule to handle the manual case. After adding this rule you set the conflict policy with the option Conflict Policy auto override for conflict resolution.

To add a general rule:

  1. In the Decision Table, click the Add icon and from the list select Rule.

  2. In the Conditions area, for the three conditions leave the "-" do not care value for each cell in the rule.

  3. In the Actions area, enter Status.MANUAL, as shown in Figure 5-42. Notice that the Business Rule Validation log includes the warning RUL-05851 for unresolved conflicts.

    Figure 5-42 Decision Table with Conflicting Rules

    Description of Figure 5-42 follows

  4. Show the conflicting rules by clicking the Toggle Display of Conflict Resolution icon, as shown in Figure 5-43.

    Figure 5-43 Adding a Rule to Handle Status Manual

    Description of Figure 5-43 follows

To enable the auto override conflict resolution policy:

  1. In the Decision Table click Show Advanced Settings (the icon next to the Decision Table name).

  2. In the Conflict Policy list, select auto override. After adding the manual case rule and selecting auto override, notice that the conflicts are resolved and special cases override the general case, as shown in Figure 5-44.

    Figure 5-44 Adding a Rule to Handle Status Manual with Auto Override Conflict Policy

    Description of Figure 5-44 follows

5.4.8 How to Check the Business Rule Validation Log for Order Approval

Before you can deploy the application you need to make sure the dictionary validates without warnings. If there are any validation warnings you need fix any associated problems.

To validate the dictionary:

  1. In the Business Rule Validation Log, check for validation warnings.

  2. If there are validation warnings, perform appropriate actions to correct the problems.

5.4.9 How to Deploy the Order Approval Application

Business rules created in a SOA application are deployed as part of the SOA composite when you create a deployment profile in Oracle JDeveloper. You deploy a SOA composite application to Oracle WebLogic Server.

To deploy and run the order approval application:

  1. If you have not started your application server instance, then start the Oracle WebLogic Server.

  2. In the Application Navigator, right-click the OrderApproval project and select Deploy > OrderApproval > to > WLS Server Name.

    Then the SOA Deployment Configuration dialog displays.

  3. Click OK.

  4. In the Authorization Request dialog, enter your authorization.

  5. Click OK.

5.4.10 How to Test the Order Approval Application

After deploying the application you can test the Decision Table in the SOA composite application with the Oracle Enterprise Manager Fusion Middleware Control Console.

To test the application:

  1. Open the composite application in Oracle Enterprise Manager Fusion Middleware Control Console, as shown in Figure 5-45.

    Figure 5-45 Testing the Order Approval Application

    Description of Figure 5-45 follows

  2. Click Test.

  3. In the Input Arguments area, select XML View. Replace the XML with the contents of example Example 5-2.

    Example 5-2 Sample Input for Testing Order Approval Application

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body xmlns:ns1="http://xmlns.oracle.com/OracleRules1/OracleRules1_DecisionService_1">
            <ns1:callFunctionStateless name="OracleRules1_DecisionService_1">
                       <ns1:parameterList xmlns:ns3="http://example.com/ns/customerorder">
                               <ns3:CustomerOrder>
                                       <ns3:name>Gary</ns3:name>
                                           <ns3:creditScore>600</ns3:creditScore>
                                           <ns3:annualSpending>2001.0</ns3:annualSpending>
                                           <ns3:value>High</ns3:value>
                                           <ns3:order>100.0</ns3:order>
                        </ns3:CustomerOrder>
                       </ns1:parameterList>
               </ns1:callFunctionStateless>
           </soap:Body>
    </soap:Envelope> 
    
  4. Replace the values in the input shown in Example 5-2 as desired for your test.

  5. Click Test Web Service.

  6. In the Response tab, view the results. For example, for this input:

    /OracleRules1_DecisionService_1" xmlns:ns2="http://xmlns.oracle.com/bpel">
          <resultList>
              <OrderApproval:OrderApproval      xmlns:OrderApproval="http://example.com/ns/customerorder"
    xmlns="http://example.com/ns/customerorder">
                  <status>approved</status>
              </OrderApproval:OrderApproval>
           </resultList>
      </callFunctionStatefulDecision>
    
PKA#PK[EZFOEBPS/non_soa.htm Creating a Rule-enabled Non-SOA Java EE Application

9 Creating a Rule-enabled Non-SOA Java EE Application

This chapter describes how to use Oracle JDeveloper to create a rule-enabled non-SOA Java EE application with Oracle Business Rules. It also shows a sample application, a Java Servlet, which runs as a Java Enterprise Edition (EE) application using Oracle Business Rules (this describes using of Oracle Business Rules without a SOA composite).

The chapter includes the following sections:

The source code for Oracle Business Rules-specific samples and SOA samples are available online in the Oracle SOA Suite samples page.

9.1 Introduction to the Grades Sample Application

The Grades application provides a sample use of Oracle Business Rules in a Java Servlet. The servlet uses Rules SDK Decision Point API. This sample demonstrates the following:

  • Creating rules in an Oracle Business Rules dictionary using an XSD schema that defines the input and the output data, and the facts for the data model. In this case you provide the XSD schema in the file grades.xsd.

  • Creating a servlet that uses Oracle Business Rules to determine a grade for each test score that is input.

  • Creating a test page to supply input test scores and to submit the data to the grades servlet.

  • Deploying the application, running it, submitting test values, and seeing the output.

9.2 Creating an Application and a Project for Grades Sample Application

To create the application and the project for the grades sample application, do the following:

  • Create a Fusion Web Application (ADF)

  • Create a project in the application

  • Add the schema to define the inputs, outputs, and the objects for the data model

  • Create an Oracle Business Rules dictionary in the project

9.2.1 How to Create a Fusion Web Application for the Grades Sample Application

To work with Oracle Business Rules and create a Java EE application, you first need to create the application in Oracle JDeveloper.

To create a fusion web application (ADF) for grades:

  1. Create an application. You can do this in the Application Navigator by selecting New Application..., or from the Application menu list by selecting New Application....

  2. In the Name your application dialog enter the application options, as shown in Figure 9-1:

    1. In the Application Template area, select Fusion Web Application.

    2. In the Application Name field, enter an application name. For example, enter GradeApp.

    3. In the Directory field, specify a directory name or accept the default.

    4. In the Application Package Prefix field, enter an application package prefix. For example, com.example.grades.

      The prefix, followed by a period applies to objects created in the initial project of an application.

    Figure 9-1 Adding GradeApp Application

    Description of Figure 9-1 follows

  3. Click Finish. After creating the application Oracle JDeveloper displays the file summary, as shown in Figure 9-2.

Figure 9-2 New Grades Application Named GradeApp

Description of Figure 9-2 follows

9.2.2 How to Develop Accessible ADF Faces Pages

Oracle software implements the standards of the Web Content Accessibility Guidelines (WCAG) 1.0 Level AA using an interpretation of the standards at http://www.oracle.com/accessibility/standards.html

ADF Faces user interface components have built-in accessibility support for visually and physically impaired users. User agents such as a web browser rendering to nonvisual media such as a screen reader can read component text descriptions to provide useful information to impaired users. Access key support provides an alternative method to access components and links using only the keyboard. ADF Faces accessibility audit rules provide direction to create accessible images, tables, frames, forms, error messages and popup windows using accessible HTML markup.

For information on how to develop accessible ADF Faces pages, see, "Developing Accessible ADF Faces Pages" in Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

9.2.3 How to Create the Grades Project

In the Grades sample application you do not use the Model or ViewController projects. You create a project in the application for the grades sample project.

To create a grades project:

  1. In the GradeApp application, in the Application Navigator, from the Application Menu select New Project....

  2. In the New Gallery, in the Items area select Generic Project.

  3. Click OK.

  4. In the Name your project page enter the values as shown in Figure 9-3:

    1. In the Project Name field, enter a name. For example, enter Grades.

    2. Enter or browse for a directory name, or accept the default.

    3. Select the Project Technologies tab.

    4. In the Available area double-click ADF Business Components to move this item to the Selected area. This also adds Java to the Selected area as shown in Figure 9-3.

      Figure 9-3 Adding Generic Project to the Grades Application

      Description of Figure 9-3 follows

  5. Click Finish. This adds the Grades project.

9.2.4 How to Add the XML Schema and Generate JAXB Classes in the Grades Project

To create the Grades sample application you need to use the grades.xsd file, shown in Example 9-1. You can create and store the schema file locally and then use Oracle JDeveloper to copy the file to your project.

Example 9-1 grades.xsd Schema

<?xml version= '1.0' encoding= 'UTF-8' ?>
<xs:schema targetNamespace="http://example.com/grades"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"     
        xmlns:tns="http://example.com/grades"
        attributeFormDefault="qualified" elementFormDefault="qualified" 
        xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:extensionBindingPrefixes="xjc" 
        jaxb:version="2.0">        
        
    <xs:element name="TestScore">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="testName" type="xs:string"/>
                <xs:element name="testScore" type="xs:double"/>
                <xs:element name="testCurve" type="xs:double"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="TestGrade">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="grade" type="tns:Grade"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="Grade">
        <xs:restriction base="xs:string">
            <xs:enumeration value="A"/>
            <xs:enumeration value="B"/>
            <xs:enumeration value="C"/>
            <xs:enumeration value="D"/>
            <xs:enumeration value="F"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

To add the XML schema to the grades project:

  1. Save the schema file shown in Example 9-1 to a local file named grades.xsd.

  2. In the Application Navigator select the Grades project.

  3. Right-click and in the context menu select New....

  4. In the New Gallery select the All Technologies tab.

  5. In the Categories area, expand General and select XML.

  6. In the Items area, select XML Schema.

  7. Click OK.

  8. In the Create XML Schema dialog, in the File Name field enter grades.xsd.

  9. In the Create XML Schema dialog, in the Directory field add the xsd directory to the Grades project path name, as shown in Figure 9-4.

    Figure 9-4 Adding Schema to Grades Project in xsd Directory

    Description of Figure 9-4 follows

  10. Click OK.

  11. In the grades.xsd file, select the Source tab.

  12. Copy the schema shown in Example 9-1 to the grades.xsd in the Grades project, as shown in Figure 9-5.

    Figure 9-5 Shows the Grades.xsd Schema File in the Grades Project

    Description of Figure 9-5 follows

To generate JAXB 2.0 content model from grades schema:

  1. In the Application Navigator, in the Grades project expand Resources and select grades.xsd.

  2. Right-click and in the context menu select Generate JAXB 2.0 Content Model.

  3. In the JAXB 2.0 Content Model from XML Schema dialog, click OK.

9.2.5 How to Create an Oracle Business Rules Dictionary in the Grades Project

After creating a project in Oracle JDeveloper create business rules within the Grades project.

To use business rules with Oracle JDeveloper, you do the following:

  • Add a business rule to the project and import grades.xsd schema

  • Create input and output variables

  • Create an Oracle Business Rules dictionary in the project

To create a business rules dictionary in the business tier:

  1. In the Application Navigator, select the Grades project.

  2. Right-click and in the context menu select New....

  3. Select the All Technologies tab.

  4. In the New Gallery, in the Categories area, expand Business Tier and select Business Rules.

  5. In the New Gallery, in the Items area, select Business Rules.

  6. Click OK. Oracle JDeveloper displays the Create Business Rules dialog, as shown in Figure 9-6.

    Figure 9-6 Adding a Business Rule to Grades with the Create Business Rules Dialog

    Description of Figure 9-6 follows

  7. In the Name field, enter a name to name the dictionary. For example, enter GradingRules.

  8. To add an input, from the list next to the Add icon select Input....

  9. In the Type Chooser, expand the Project Schemas Files folder and expand grades.xsd.

  10. Select the input TestScore, as shown in Figure 9-7.

    Figure 9-7 Shows the Type Chooser Dialog with TestScore Element

    Description of Figure 9-7 follows

  11. On the Type Chooser window, click OK. This displays the Create Business Rules dialog.

  12. In the Create Business Rules dialog, in a similar manner to the input add the output by selecting Output... to add the output element TestGrade from the grades.xsd schema.

    The resulting Create Business Rules dialog is shown in Figure 9-8.

    Figure 9-8 Create Business Rules Dialog with Grades Input and Output

    Description of Figure 9-8 follows

  13. Click OK. Oracle JDeveloper creates the GradingRules dictionary as shown in Figure 9-9.

  14. In the File menu, select Save All to save your work.

Figure 9-9 Shows the New Grading Rules Dictionary

Description of Figure 9-9 follows

Note that the business rule validation log area for the new dictionary shows several validation warnings. You remove these validation warning messages as you modify the dictionary in later steps.

9.3 Creating Data Model Elements and Rules for the Grades Sample Application

To create the data model and the business rules for the Grades sample application, do the following:

  • Create Bucketsets for grades

  • Create rules by adding a Decision Table for grades

  • Split the Decision Table and add actions for rules

  • Rename the default decision function

9.3.1 How to Create Bucketsets for Grades Sample Application

In this example you associate a bucketset with a fact type. This supports using a Decision Table where you need bucketsets that specify how to draw values for each cell in the Decision Table (for the conditions in the Decision Table).

To create the bucketset for the grades sample application:

  1. In Rules Designer, select the Bucketsets navigation tab.

  2. From the list next to the Create BucketSet... icon, select List of Ranges.

  3. For the bucketset, double-click in the Name field to select the default name.

  4. Enter Grade Scale, and press Enter to accept the bucketset name.

  5. In the Bucketsets table, double-click the bucket icon for the Grade Scale bucketset to display the Edit Bucketset dialog as shown in Figure 9-10.

    Figure 9-10 Grade Scale Bucketset

    Description of Figure 9-10 follows

  6. In the Edit Bucketset dialog, click Add Bucket to add a bucket.

  7. Click Add Bucket three times to add three more buckets.

  8. In the Endpoint field, enter 90 for the top endpoint and press Enter to accept the new value.

  9. For the next bucket, in the Endpoint field enter 80 and press Enter to accept the new value.

  10. Similarly, for the next two buckets enter values in the Endpoint field, values 70 and 60.

  11. In the Included Endpoint field for each bucket select each checkbox.

  12. Modify the Alias field for each value to enter the values A, B, C, D, and F, for each corresponding range, as shown in Figure 9-11 (press Enter after you add each alias).

    Figure 9-11 Grade Scale Bucketset with Grade Values Added

    Description of Figure 9-11 follows

To associate a bucketset with a fact property:

To prepare for creating Decision Tables you can associate a global bucketset with fact properties in the data model. In this way condition cells in a Decision Table Conditions area can use the bucketset when you create a Decision Table.

  1. In Rules Designer, select the Facts navigation tab.

  2. In the Facts navigation tab select the XML Facts tab.

  3. Double-click the XML fact icon for the TestScore fact. This displays the Edit XML Fact dialog.

  4. In the Edit XML Fact dialog select the testScore property.

  5. In the Bucketset field, from the list select Grade Scale.

  6. Click OK.

9.3.2 How to Add a Decision Table for Grades Sample Application

You create rules in a Decision Table to process input facts and to produce output facts, or to produce intermediate conclusions that Oracle Business Rules can further process using additional rules or in another Decision Table.

To use a Decision Table for rules in this application you work with facts representing a test score. Then, you use a Decision Table to create rules based on the test score to produce a grade.

To add a decision table for Grades application:

  1. In Rules Designer, select Ruleset_1 under the Rulesets navigation tab.

  2. In Ruleset_1, click the Add icon and from the list select Create Decision Table. This creates DecisionTable_1. You can ignore the warning messages shown in the Business Rule Validation log area. You remove these warning messages in later steps.

  3. In the Decision Table, DecisionTable_1, click the Add icon and from the list select Condition.

  4. In the Decision Table, double-click <edit condition>. Then, in the variables navigator expand TestScore and select testScore. This enters the expression TestScore.testScore for condition C1.

If you view the rules validation log, you should see warning messages. You remove these warning messages as you modify the Decision Table in later steps.

To add an action to a decision table:

You add an action to the Decision Table to assert a new Grade fact.

  1. In the Decision Table, click the Add icon and from the list select Action and select Assert New.

  2. In the Actions area, double-click assert new (.

    This displays the Action Editor dialog.

  3. In the Action Editor dialog, in the Facts area select TestGrade.

  4. In the Action Editor dialog, in the Properties table for the property grade, select the Parameterized checkbox and the Constant checkbox.

    This specifies that each rule independently sets the grade.

  5. In the Action Editor dialog select the Always Selected checkbox.

  6. In the Action Editor dialog click OK.

  7. Select Save All from the File main menu to save your work.

Next you add rules to the Decision Table and specify an action for each rule.

9.3.3 How to Add Actions in the Decision Table for Grades Sample Application

You can use the Decision Table split operation to create rules for the bucketset associated with the conditions row in the Decision Table. This creates one rule for every bucket.

To split the decision table:

  1. Select the Decision Table.

  2. Click the Split Table icon and from the list select Split Table.

    The split operation eliminates the "do not care" cells from the table. The table now shows five rules that cover all ranges, as shown in Figure 9-12.

These steps produce validation warnings for action cells with missing expressions. You fix these problems in later steps when you define actions for each rule.

Figure 9-12 Splitting a Decision Table Using Split Table Operation for Grades

Description of Figure 9-12 follows

To add actions for each rule in the decision table:

In the Decision Table you specify a value for the result, a grade property, associated with TestGrade for each action cell in the Actions area. The possible choices for each grade property are the valid grades. In this step you fill in a value for each of the rules. The values you enter correspond to the conditions that form each rule in the Decision Table.

  1. In the Actions area, double-click the action cell for rule R1 as shown in Figure 9-13.

    Figure 9-13 Adding Action Cell Values to Grades Decision Table

    Description of Figure 9-13 follows

  2. In the list select the corresponding value for the action cell. For example, select Grade.F.

  3. For each of the remaining action cells select the appropriate value for the buckets for TestScore: D, C, B, and A.

9.3.4 How to Rename the Decision Function for Grades Sample Application

The name you specify when you use a decision function with a Rules SDK Decision Point must match the name of a decision function in the dictionary. To make the name match, you can rename the decision function to any name you like. Thus, for this example you rename the default decision function to use the name GradesDecisionFunction.

To rename the decision function:

  1. In the Application Navigator, in the Grades project, expand the Resources folder and double-click the dictionary GradingRules.rules.

  2. Select the Decision Functions navigation tab.

  3. In the Name field in the Decision Functions table edit the decision function name to enter the value GradesDecisionFunction, and then press Enter, as shown in Figure 9-14.

Figure 9-14 Renaming Decision Function in Rules Designer

Description of Figure 9-14 follows

9.4 Adding a Servlet with Rules SDK Calls for Grades Sample Application

The Grades sample application includes a servlet that uses the Rules Engine.

To add this servlet with Oracle Business Rules you need to understand the important Rules SDK methods. Thus, to use the Oracle Business Rules dictionary you created with Rules Designer, you do the following:

  • Create initialization steps that you perform one time in the servlet init routine.

  • Create a servlet service routine using the Rules SDK Decision Point API.

  • Perform steps to add the servlet code in the project.

For more information on Rules SDK Decision Point API, see Chapter 7, "Working with Rules SDK Decision Point API".



9.4.1 How to Add a Servlet to the Grades Project

You add a servlet to the grades project using the Create HTTP Servlet wizard.

To add a servlet to the Grades project with Oracle JDeveloper:

  1. In the Application Navigator, select the Grades project.

  2. Right-click the Grades project and in the context menu select New....

  3. In the New Gallery, select the All Technologies tab.

  4. In the New Gallery, in the Categories area expand Web Tier and select Servlets.

  5. In the New Gallery, in the Items area select HTTP Servlet.

  6. Click OK.

    Oracle JDeveloper displays the Create HTTP Servlet Welcome page, as shown in Figure 9-15.

    Figure 9-15 Create HTTP Servlet Wizard - Welcome

    Description of Figure 9-15 follows

  7. Click Next.

    This displays the Web Application page, as shown in Figure 9-16.

    Figure 9-16 Create HTTP Servlet Wizard - Web Application

    Description of Figure 9-16 follows

  8. Select Servlet 2.5\JSP 2.1 (Java EE 1.5) and click Next.

    This displays the Create HTTP Servlet - Step 1 of 3: Servlet Information page.

  9. Enter values in Create HTTP Servlet - Step 1 of 3: Servlet Information page, as follows, and as shown in Figure 9-17.

    • Class: GradesServlet

    • Package: com.example.grades

    • Generate Content Type: HTML

    • Generate Header Comments: unchecked

    • Implement Methods: service() checked and all other checkboxes unchecked

    Figure 9-17 Create HTTP Servlet Wizard - Step 1 of 3: Servlet Information

    Description of Figure 9-17 follows

  10. Click Next.

    This displays the Create HTTP Servlet: Step 2 of 3: Mapping Information dialog as shown in Figure 9-18.

    Figure 9-18 Create HTTP Servlet Wizard - Step 2 of 3: Mapping Information

    Description of Figure 9-18 follows

  11. Configure this dialog as follows:

    • Name: GradesServlet

    • URL Pattern: /gradesservlet

  12. Click Finish.

    JDeveloper adds a Web Content folder to the project and creates a GradesServlet.java file and opens the file in the editor as shown in Figure 9-19.

    Figure 9-19 Generated GradesServlet.java

    Description of Figure 9-19 follows

  13. Replace the generated servlet with the source shown in Example 9-2.

    Example 9-2 Business Rules Using Servlet for Grades Application

    package com.example.grades;
     
    import java.io.IOException;
    import java.io.PrintWriter;
     
    import java.util.ArrayList;
    import java.util.List;
     
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import oracle.rules.rl.exceptions.RLException;
    import oracle.rules.sdk2.decisionpoint.DecisionPoint;
    import oracle.rules.sdk2.decisionpoint.DecisionPointBuilder;
    import oracle.rules.sdk2.decisionpoint.DecisionPointInstance;
    import oracle.rules.sdk2.exception.SDKException;
    import oracle.rules.sdk2.repository.DictionaryFQN;
     
    public class GradesServlet extends HttpServlet {
     
        private static final String CONTENT_TYPE = "text/html";
        private static final String DICT_PKG = "com.example.grades";
        private static final String DICT_NAME = "GradingRules";
        private static final DictionaryFQN DICT_FQN =
            new DictionaryFQN(DICT_PKG, DICT_NAME);
        private static final String DF_NAME = "GradesDecisionFunction";
     
        private DecisionPoint m_decisionPoint = null; // init in init()
     
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
            
            try {
                
                // specifying the Decision Function and Dictionary FQN
                // load the rules from the MDS repository.
                m_decisionPoint = new DecisionPointBuilder()
                                    .with(DF_NAME)
                                    .with(DICT_FQN)
                                    .build();
            } catch (SDKException e) {
                System.err.println("Failed to build Decision Point: " +
                                   e.getMessage());
                throw new ServletException(e);
            }
        }
     
        public void service(HttpServletRequest request,
                            HttpServletResponse response) throws ServletException,
                                                                 IOException {        
            // retrieve parameters
            String name = request.getParameter("name");
            String strScore = request.getParameter("testScore");
     
            // open output document
            StringBuilder doc = new StringBuilder();        
            addHeader(doc);
     
            // create TestScore object to assert
            final TestScore testScore = new TestScore();
            testScore.setName(name);
            
            try {
                testScore.setTestScore(Integer.parseInt(strScore));
            } catch (NumberFormatException e){ /* use default val */ }                
     
            // get DecisionPointInstance for invocation
            DecisionPointInstance point = m_decisionPoint.getInstance();
            
            // set input parameters
            point.setInputs(new ArrayList() {{ add(testScore); }});
     
            // invoke decision point and get result value
            TestGrade testGrade = null;        
            try {
                
                // invoke the decision point with our inputs
                List<Object> result = point.invoke();
                if (result.size() != 1){
                    error(doc, testScore.getName(), "bad result", null);                
                }
                // decision function returns a single TestGrade object
                testGrade = (TestGrade)result.get(0);
            } catch (RLException e) {
                error(doc, testScore.getName(), "RLException occurred: ", e);
            } catch (SDKException e) {
                error(doc, testScore.getName(), "SDKException occurred", e);
            } 
            
            if (testGrade != null){
                // create output table in document
                openTable(doc);
                addRow(doc, testScore.getName(), strScore, testGrade.getGrade());
                closeTable(doc);
            }
     
            addFooter(doc);
     
            // write document
            response.setContentType(CONTENT_TYPE);
            PrintWriter out = response.getWriter();
            out.println(doc);
            out.close();
        }
     
     
        public static void addHeader(StringBuilder doc) {
            doc.append("<html>");
            doc.append("<head><title>GradesServlet</title></head>");
            doc.append("<body>");
            doc.append("<h1>Test Results</h1>");
        }
     
        public static void addFooter(StringBuilder doc) {
            doc.append("</body></html>");
        }
     
        public static void openTable(StringBuilder doc) {
            doc.append("<table border=\"1\"");
            doc.append("<tr>");
            doc.append("<th>Name</th>");
            doc.append("<th>Score</th>");
            doc.append("<th>Grade</th>");
            doc.append("</tr>");
        }
     
        public static void closeTable(StringBuilder doc) {
            doc.append("</table>");
        }
        
        public static void addRow(StringBuilder doc, String name, String score, Grade grade){
            doc.append("<tr>");
            doc.append("<td>"+ name +"</td>");
            doc.append("<td>"+ score +"</td>");
            doc.append("<td>"+ grade.value() +"</td>");
            doc.append("</tr>");
        }
     
        public static void error(StringBuilder doc, String name, String msg, Throwable t){
            doc.append("<tr>");
            doc.append("<td>"+ name +"</td>");
            doc.append("<td colspan=2>"+ msg + " " + t +"</td>");
            doc.append("</tr>");
        }
    }
    

Example 9-2 includes a Oracle Business Rules Decision Point, that uses an MDS repository to access the dictionary. For more information, see Section 7.5, "What You Need to Know About Using Decision Point in a Production Environment".

When you add the Servlet shown in Example 9-2, note the following:

  • In the init() method the servlet uses the Rules SDK Decision Point API for Oracle Business Rules. For more information on using the Decision Point API, see Chapter 7, "Working with Rules SDK Decision Point API".

  • The DecisionPointBuilder() requires arguments including a decision function name and, in a production environment a dictionary FQN to access a dictionary in an MDS repository, as shown:

                m_decisionPoint = new DecisionPointBuilder()
                                    .with(DF_NAME)
                                    .with(DICT_FQN)
    

    For more information on using the Decision Point API, see Chapter 7, "Working with Rules SDK Decision Point API".

9.5 Adding an HTML Test Page for Grades Sample Application

The Grades sample application includes an HTML test page that you use to invoke the servlet you created in Section 9.4, "Adding a Servlet with Rules SDK Calls for Grades Sample Application".

9.5.1 How to Add an HTML Test Page to the Grades Project

To add an HTML page to the servlet you use the Create HTML File wizard.

To add an HTML test page:

  1. In the Application Navigator, in the Grades project select the Web Content folder.

  2. Right-click the Web Content folder project and in the context menu select New....

  3. In the New Gallery, select the All Technologies tab.

  4. In the New Gallery, in the Categories area expand Web Tier and select HTML.

  5. In the New Gallery, in the Items area select HTML Page.

  6. In the New Gallery click OK.

    Oracle JDeveloper displays the Create HTML File dialog.

  7. Configure this dialog as follows and as shown in Figure 9-20:

    • File Name: index.html

    • Directory: C:\JDeveloper\mywork\GradeApp\Grades\public_html

    Figure 9-20 Create HTML File Dialog

    Description of Figure 9-20 follows

  8. Click OK.

    JDeveloper adds index.html to the Web Content folder and opens the editor.

  9. In the editor for index.html, select the Source tab.

  10. Copy and paste the HTML code from Example 9-3 to replace the contents of the index.html file.

    Note that in the form element action attribute uses the URL Pattern you specified in Figure 9-18.

    Example 9-3 HTML Test Page

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></meta>
        <title>Test Grade Example Servlet</title>
      </head>
      <body>
        <form name="names_and_scores" 
              method="post" 
              action="/grades/gradesservlet" >
              <p>Name: <input type="text" name="name" /></p>
              <p>Test Score: <input type="text" name="testScore"/></p>
           <input type="submit" value="Submit">
        </form>
      </body>
    </html>
    
  11. Select Save All from the File main menu to save your work.

9.6 Preparing the Grades Sample Application for Deployment

Business rules are deployed as part of the application for which you create a deployment profile in Oracle JDeveloper. You deploy the application to Oracle WebLogic Server.

9.6.1 How to Create the WAR File for the Grades Sample Application

You deploy the GradeApp sample application using JDeveloper with Oracle WebLogic Server.

To create the WAR file for the grades sample application:

  1. In the Application Navigator, select the Grades project.

  2. Right-click the Grades project and in the context menu select Project Properties.... This displays the Project Properties dialog for the project.

  3. In the Project Properties navigator, select the Deployment item as shown in Figure 9-21.

    Figure 9-21 Project Properties - Deployment

    Description of Figure 9-21 follows

  4. In the Project Properties dialog, click New....

    This displays the Create Deployment Profile dialog.

  5. In the Create Deployment Profile dialog, in the Archive Type list, select WAR File.

  6. In the Create Deployment Profile dialog, in the Name field enter grades, as shown in Figure 9-22. Note the Name value uses the package value that you specified in the form element action attribute in Example 9-3.

    Figure 9-22 Create Deployment Profile Dialog for WAR File

    Description of Figure 9-22 follows

  7. Click OK.

    This displays the Edit WAR Deployment Profile Properties dialog.

  8. In the Edit War Deployment Profile Properties dialog, select General and configure the General page as follows, as shown in Figure 9-23:

    1. Set the WAR File: C:\JDeveloper\mywork\GradeApp\Grades\deploy\grades.war

    2. In the Web Application Context Root area, select Specify Java EE Web Context Root:

    3. In the Specify Java EE Web Context Root: text entry area, enter grades.

    4. In the Deployment Client Maximum Heap Size (in Megabytes): list select Auto

    Figure 9-23 Edit WAR Deployment Properties - General

    Description of Figure 9-23 follows

  9. In the Edit WAR Deployment Profile Properties dialog, click OK.

    JDeveloper creates a deployment profile named grades (WAR File) as shown in Figure 9-24.

    Figure 9-24 Project Properties - Deployment Profile Created

    Description of Figure 9-24 follows

  10. In the Project Properties dialog, click OK.

9.6.2 How to Add the Rules Library to the Grades Sample Application

To add the rules library to the weblogic-application file:

  1. In the GradeApp application, in the Application Navigator expand Application Resources.

  2. Expand Descriptors and expand META-INF and double-click to open weblogic-application.xml.

  3. Add the oracle.rules library reference to the weblogic-application.xml file. Add the following lines, as shown in Figure 9-25.

    <library-ref>
        <library-name>oracle.rules</library-name>
    </library-ref>
    

    Figure 9-25 Adding Oracle Rules Library Reference to WebLogic Descriptor

    Description of Figure 9-25 follows

  4. Save the weblogic-application.xml file.

9.6.3 How to Add the MDS Deployment File to the Grades Sample Application

To add the MDS deployment file:

  1. In the Application Navigator, select the GradeApp application.

  2. Right-click the GradeApp application and in the context menu select Application Properties....

    This displays the Application Properties dialog.

  3. In the Application Properties navigator select the Deployment item, as shown in Figure 9-26.

    Figure 9-26 Application Properties - Deployment

    Description of Figure 9-26 follows

  4. In the Application Properties dialog, click New....

    This displays the Create Deployment Profile dialog.

  5. Configure this dialog as follows, as shown in Figure 9-27:

    • Archive Type: MAR File

    • Name: metadata1

    Figure 9-27 Create Deployment Profile Dialog for MAR File

    Description of Figure 9-27 follows

  6. Click OK.

    This displays the Edit MAR Deployment Properties dialog as shown in Figure 9-28.

    Figure 9-28 Edit MAR Deployment Profile Properties - MAR Options

    Description of Figure 9-28 follows

  7. Expand the Metadata File Groups item and select the User Metadata item.

  8. Click Add....

    This displays the Add Contributor dialog.

  9. In the Add Contributor dialog, click the Browse button and navigate to the directory for the project that contains the GradingRules.rules dictionary file.

    In this example, navigate to C:\JDeveloper\mywork\GradeApp\Grades and click Select.

  10. In the Add Contributor dialog, click OK to close the dialog. This displays the Edit MAR Deployment Properties dialog as shown in Figure 9-29

    Figure 9-29 Edit MAR Deployment Profile Properties - User Metadata

    Description of Figure 9-29 follows

  11. In the Edit MAR Deployment Profile Properties dialog, expand the Metadata File Groups and expand the User Metadata item and select Directories.

    This displays the Directories page as shown in Figure 9-30.

    Figure 9-30 Edit MAR Deployment Profile Properties - Directories

    Description of Figure 9-30 follows

  12. Select the oracle directory checkbox. This selects the GradingRules.rules dictionary to be included in the MAR.

  13. Click OK.

    JDeveloper creates an application deployment profile named metadata1 (MAR File) as shown in Figure 9-31.

    Figure 9-31 Application Properties - Deployment - MAR

    Description of Figure 9-31 follows

  14. In the Application Properties dialog, click OK.

9.6.4 How to Add the EAR File to the Grades Sample Application

Add an EAR file to the Grades sample application.

To add the ear file to the grades sample application:

  1. In the Application Navigator, select the GradeApp application.

  2. Right-click and in the context menu select Application Properties....

  3. In the Application Properties dialog, select Deployment and click New.... This displays the Create Deployment Profile dialog.

  4. Configure this dialog as follows, as shown in Figure 9-32.

    • Archive Type: EAR

    • Name: grades

    Figure 9-32 Create Deployment Profile Dialog for EAR File

    Description of Figure 9-32 follows

  5. Click OK. This displays the Edit EAR Deployment Profile Properties dialog.

  6. In the Edit Ear Deployment Profile Properties dialog, in the navigator select Application Assembly as shown in Figure 9-33.

    Figure 9-33 Edit EAR Deployment Profile Properties - Application Assembly

    Description of Figure 9-33 follows

  7. Configure this dialog as follows:

    • Select the metadata1 checkbox.

    • Expand the Grades.jpr item and select the grades checkbox.

  8. In the Edit EAR Deployment Profile Properties dialog, click OK.

    JDeveloper creates an application deployment profile named grades(EAR File) as shown in Figure 9-34.

    Figure 9-34 Application Properties - Deployment - EAR

    Description of Figure 9-34 follows

  9. Click OK to close the Application Properties dialog.

  10. Select Save All from the File main menu to save your work.

9.7 Deploying and Running the Grades Sample Application

You can now deploy and run the grades sample application on Oracle WebLogic Server.

9.7.1 How to Deploy to Grades Sample Application

To deploy the grades sample application:

  1. In the Application Navigator, select the GradeApp application.

  2. Right-click the GradeApp application and in the context menu select Deploy > grades > to > and select either an existing connection or New Connection... to create a connection for the deployment. This starts the deployment to the specified Oracle WebLogic Server.

  3. As the deployment proceeds, Oracle JDeveloper shows the Deployment Configuration dialog.

  4. In the Deployment Configuration dialog enter the following values, as shown in Figure 9-32:

    • In the Repository Name field, from the list, select: mds-soa

    • In the Partition Name field, enter grades

    Figure 9-35 Deployment Configuration Dialog for MDS with Repository and Partition

    Description of Figure 9-35 follows

  5. In the Deployment Configuration dialog, click Deploy.

9.7.2 How to Run the Grades Sample Application

After you deploy the grades sample application, you can run the application.

To run the grades sample application:

  1. Point a web browser at,

    http://yourServerName:port/grades/

    This displays the test servlet as shown in Figure 9-36.

    Figure 9-36 Grades Sample Application Servlet

    Description of Figure 9-36 follows

  2. Enter a name and test score and click Submit. This returns results as shown in Figure 9-37.

The first time you run the servlet there may be a delay before any results are returned. The first time the servlet is invoked, during servlet initialization the runtime loads the dictionary and creates a rule session pool. Subsequent invocations do not perform these steps and should run much faster.

Figure 9-37 Grades Sample Application Servlet with Results



PKU$PK[EZFOEBPS/decision_point.htm Working with Rules SDK Decision Point API

7 Working with Rules SDK Decision Point API

This chapter describes how to use Oracle Business Rules SDK (Rules SDK) to write applications that access, create, modify, and execute rules in Oracle Business Rules dictionaries (and work with the contents of a dictionary). It also provides a brief description of Rules SDK and shows how to work with the Rules SDK Decision Point API.

The chapter includes the following sections:

For more information, see Oracle Fusion Middleware Java API Reference for Oracle Business Rules.

7.1 Introduction to Rules SDK and the Car Rental Sample Application

The Rules SDK consists of four areas:

  • Engine: provides for rules execution

  • Storage: provides access to rule dictionaries and repositories

  • Editing: provides a programatic way to create and modify dictionary components

  • Decision Point: provides an interface to access a dictionary and execute a decision function

Other than for explanation purposes, there is not an explicit distinction between these areas in Rules SDK. For example, to edit rules you also need to use the storage area of Rules SDK to access a dictionary. These parts of the Rules SDK are divided to help describe the different modes of usage, rather than to describe distinct Rules SDK APIs.

7.1.1 Introduction to Decision Point API

The Decision Point API provides a concise way to execute rules. Most users create Oracle Business Rules artifacts, including data model elements, rules, Decision Tables, and rulesets using the Rules Designer extension to Oracle JDeveloper. Thus, most users do not need to work directly with the engine, storage, or editing parts of Rules SDK.

To work with the Rules SDK Decision Point package you need to understand three important classes:

  • DecisionPoint: is a helper class that follows the factory design pattern to create instances of DecisionPointInstance. In most applications there should be one DecisionPoint object that is shared by all application threads. A caller uses the getInstance() method of DecisionPoint to get an instance of DecisionPointInstance which can be used to call the defined Decision Point.

  • DecisionPointBuilder: follows the Builder design pattern to construct a Decision Point.

  • DecisionPointInstance: users call invoke() in this class to assert facts and execute a decision function.

The DecisionPoint classes support a fluent interface model so that methods can be chained together. For more information, see

http://www.martinfowler.com/bliki/FluentInterface.html

A Decision Point manages several aspects of rule execution, including:

  • Use of oracle.rules.rl.RuleSession objects

  • Reloading of a dictionary when the dictionary is updated

To create a Decision Point in a Java application you need the following:

  • Either the name of a dictionary to be loaded from an MDS repository or a pre-loaded oracle.rules.sdk2.dictionary.RuleDictionary instance.

  • The name of a decision function stored in the specified dictionary.

7.1.2 How to Obtain the Car Rental Sample Application

This chapter shows a car rental application that demonstrates the use of Rules SDK and the Decision Point API. You can obtain the sample application in a ZIP file, CarRentalApplication.zip. This ZIP contains a complete JDeveloper application and project.

The source code for Oracle Business Rules-specific samples and SOA samples are available online in the Oracle SOA Suite samples page.

To work with the sample unzip CarRentalApplication.zip into an appropriate directory. The car rental application project contains a rules dictionary and several Java examples using Rules SDK.

7.1.3 How to Open the Car Rental Sample Application and Project

The Car Rental sample application shows you how to work with the Rules SDK Decision Point API.

To open the car rental sample application:

  1. Start Oracle JDeveloper.

  2. Open the car rental application in the directory where you unzipped the sample. For example, from the File menu select Open... and in the Open dialog navigate to the CarRentalApplication folder.

  3. In the Open dialog select CarRentalApplication.jws and click Open.

  4. In the Application Navigator, expand the CarRentalApplication, expand Application Sources and Resources. This displays the Oracle Business Rules dictionary named CarRental.rules and several Java source files.

7.2 Creating a Dictionary for Use with a Decision Point

The car rental sample uses the Rules SDK Decision Point API with either a pre-loaded Oracle Business Rules dictionary or a repository stored in MDS. When you are working in a development environment you can use the Decision Point API with the pre-loaded dictionary signature. In a production environment you would typically use a Decision Point with the MDS repository signature.

The CarRental dictionary is pre-defined and is available in the car rental sample application.

To work with the Decision Point API you need to create a dictionary that contains a decision function (the car rental sample application comes with a predefined dictionary and decision function).

You perform the following steps to create a dictionary and a decision function:

7.2.1 How to Create Data Model Elements for Use with a Decision Point

You need the following to add to a decision function when you create an application with a Decision Point.

To view the data model in the supplied car rental sample application:

  1. In Rules Designer, click the Facts navigation tab.

  2. Select the Java Facts tab, as shown in Figure 7-1.

    The Java Facts tab shows four fact types imported, in addition to the fact types provided as built-in to the dictionary.

    The Driver Java Fact is imported from the Driver Java class in the project.

    The Denial Java Fact is imported from Denial Java class in the project.

    The LicenseType and VehicleType facts are imported from the nested enum classes defined in the Driver class.

    Figure 7-1 Defined Java Facts for the Car Rental Sample Application

    Description of Figure 7-1 follows

When you use a Decision Point with Rules SDK, you call a decision function in a specified dictionary. The decision function that you call can contain one or more rulesets that are executed as part of the Decision Point.

To view the ruleset in the supplied car rental sample application:

  1. In Rules Designer, expand the CarRentalApplication.

  2. In the CarRentalApplication, expand Resources.

  3. Double-click the CarRental.rules.

7.2.2 How to View a Decision Function to Call from the Decision Point

When you work with the Decision Point API you use decision functions to expose an Oracle Business Rules dictionary. For more information on decision functions, see Chapter 6, "Working with Decision Functions".

To view the decision function in the car rental sample application:

  1. In Rules Designer, click the Decision Functions navigation tab. This displays the available decision functions in the CarRental dictionary, as shown in Figure 7-2.

    Figure 7-2 Car Rental Sample Decision Function

    Description of Figure 7-2 follows

  2. Select the row with CarRentalDecisionFunction and double-click the decision function icon. This opens the Edit Decision Function dialog as shown in Figure 7-3.

    The decision function Inputs table includes a single argument for a Driver fact type.

    The decision function Outputs table includes a single argument for a Denial fact type.

    The decision function Rulesets and Decision Functions area shows Denial Rules:if-then in the Selected box.

    Figure 7-3 Car Rental Decision Function for the Car Rental Sample Application

    Description of Figure 7-3 follows

7.2.3 How to Create Rules or Decision Tables for the Decision Function

The car rental sample includes two rulesets, one with IF/THEN rules and another containing a Decision Table. You can use either IF/THEN rules or Decision Tables or both in your application if you are using a Decision Point.

To view the rules in the car rental sample application:

  1. In Rules Designer click the Denial Rules:if-then ruleset, as shown in Figure 7-4.

    Figure 7-4 Ruleset with IF/THEN Rules for the Car Rental Sample Application

    Description of Figure 7-4 follows

The Denial Rules:if-then ruleset includes two rules:

  • under age: this rule defines the minimum age of the driver. The rule compares the Driver instance age property to the global Minimum driver age. If the driver is under this age, then a new Denial fact is asserted. A call to the decision function collects this Denial fact, as defined in its output. The rule also calls a user-defined function, audit, to provide some auditing output about why the Denial is created.

  • too many accidents: this rule defines an upper threshold for the number of accidents a driver can have before a rental for the driver is denied. The rule also calls a user-defined function, audit, to provide some auditing output about why the Denial is created.

To view the Decision Table in the car rental application:

  1. In Rules Designer, click the Denial Rules:decision table ruleset, as shown in Figure 7-5.

Figure 7-5 Ruleset with Decision Table for the Car Rental Sample Application

Description of Figure 7-5 follows

7.2.4 What You Need to Know About Using Car Rental Sample with a Decision Table

The car rental sample application includes the Denial Rules: decision table ruleset. To switch to use a Decision Table in the supplied decision function sample, move the Denial Rules:if-then from the Selected area in the decision function and add the Denial Rules: decision table ruleset, which uses a Decision Table to define similar rules, as shown in Figure 7-6.

Figure 7-6 Decision Function for Car Rental Sample with Decision Table Ruleset

Description of Figure 7-6 follows

7.3 Creating a Java Application Using Rules SDK Decision Point

When use Rules SDK in a development environment you of the option of using Decision Point API with a pre-loaded dictionary. In a production environment you typically use the Decision Point API with the MDS repository signature and the dictionary is stored in MDS. For more information on using a Decision Point with, see Section 7.5, "What You Need to Know About Using Decision Point in a Production Environment".

The source code for Oracle Business Rules-specific samples and SOA samples are available online in the Oracle SOA Suite samples page.

The CarRentalProject project includes the com.example.rules.demo package that includes the car rental sample file, CarRentalWithDecisionPointUsingPreloadedDictionary.java. The project also includes several .java source files that support different variations for using Decision Point. Table 7-1 provides a summary of the different versions of the car rental sample.

For more information on working with the Rules SDK Decision Point API, see Oracle Fusion Middleware Java API Reference for Oracle Business Rules.

Table 7-1 Java Files in the Decision Point Sample CarRentalProject

Base Java FilenameDescription

CarRental

This is the base class for all of the examples. It contains constant values for using the CarRental dictionary and a method createDrivers which creates instances of the Driver class.

CarRentalWithDecisionPoint

Contains a static attribute of type DecisionPoint and a method checkDriver() that invokes a Decision Point with a specified instance of the Driver class. This class includes these methods for the sample application so that both the MDS repository and pre-loaded dictionary examples can share the same checkDriver() implementation.

CarRentalWithDecisionPointUsingMdsRepository

Contains an example of creating a Decision Point that uses MDS to access and load the rule dictionary. In a production environment, most applications use the Decision Point API with MDS.

CarRentalWithDecisionPointUsingPreloadedDictionary

Contains an example of creating a Decision Point from an instance of the RuleDictionary class. This example also contains code for manually loading the dictionary to create a RuleDictionary instance.

CarRentalWithRuleSession

Contains an advanced usage of the Engine API that is documented further in the comments.

CarRentalWithRuleSessionPool

Contains an advanced usage of the Engine API that is documented further in the comments.

Denial

Contains the class that defines the Denial fact type used to create the rules and Decision Table.

Driver

Contains the class that defines the Driver fact type used to create the rules and Decision Table.

DriverCheckerRunnable

Contains the class which can be used as a thread for simulating concurrent users invoking the Decision Point.


7.3.1 How to Add a Decision Point Using Decision Point Builder

To use a Decision Point you create a DecisionPoint instance using DecisionPointBuilder, as shown in Example 7-1.

Example 7-1 Using the Decision Point Builder

    static {
        try {
            // specifying the Decision Function and a pre-loaded
            // RuleDictionary instance 
            m_decisionPoint =  new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(loadRuleDictionary())
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " + e.getMessage());
            e.printStackTrace();
        }
    }

Example 7-1 shows the DecisionPointBuilder supports a fluent interface pattern, so all methods can easily be chained together when you create a Decision Point. The three most common methods for configuring the Decision Point with DecisionPointBuilder are overloaded to have the name with(). Each with() method takes a single argument of type RuleDictionary, DictionaryFQN, or String. The DecisionPointBuilder also supports similar set and get methods: getDecisionFunction(), setDecisionFunction(), getDictionary(), setDictionary(), getDictionaryFQN(), setDictionaryFQN().

This chain shown in Example 7-1 includes the following steps:

  1. The first step is to create a DecisionPointBuilder instance with code such as the following:

    new DecisionPointBuilder()
    
  2. The with() method using a String argument defines the name of the decision function that the Decision Point executes. Calling this method is mandatory.

    .with(DF_NAME)
    

    The DF_NAME specifies the name of the decision function you define for your application. For example for the sample car rental application DF_NAME is defined in CarRental.java as CarRentalDecisionFunction.

  3. Call only one of the other two with() methods. In this case the sample code uses a pre-loaded Rule Dictionary instance, containing the specified decision function. The loadDictionary() method loads an instance of RuleDictionary from a file. Example 7-2 shows the loadDictionary() method. For more information, see Section 7.3.2, "How to Use a Decision Point with a Pre-loaded Dictionary".

    .with(loadRuleDictionary())
    
  4. Call the build() method to construct and return a DecisionPoint instance.

The DecisionPoint instance is shared among all instances of the application, which is why it is a static attribute and created in a static block. Another way of initializing the DecisionPoint would be to initialize the m_decisionPoint attribute with a static method that created and returned a DecisionPoint instance.

7.3.2 How to Use a Decision Point with a Pre-loaded Dictionary

Example 7-2 shows the loadRuleDictionary() method that loads an instance of RuleDictionary from a file.

When reading or writing a dictionary directly from a file as shown in Example 7-2, ensure to set the encoding to UTF-8. If this is not done, Unicode characters used in the dictionary are corrupted. The UTF-8 option must be set explicitly in the FileInputStream or OutputStreamWriter constructor. Do not use Java classes such as FileReader and FileWriter, as these classes always use the platform default encoding which is usually an ASCII variant rather than a Unicode variant.

Example 7-2 Load Rule Dictionary Method

private static RuleDictionary loadRuleDictionary(){ 
        RuleDictionary dict = null; 
        BufferedReader reader = null; 
        try { 
            reader = new BufferedReader( 
                        new InputStreamReader( 
                            new FileInputStream( 
                                new File(DICT_LOCATION)), "UTF-8")); 
            dict = RuleDictionary.readDictionary(reader, 
                                                 new 
DecisionPointDictionaryFinder(null)); 
 
            List<SDKWarning> warnings = new ArrayList<SDKWarning>(); 
 
            dict.update(warnings); 
            if (warnings.size() > 0) { 
                System.err.println("Validation warnings: " + warnings); 
            } 
        } catch (SDKException e){ 
            System.err.println(e); 
        } catch (FileNotFoundException e){ 
            System.err.println(e); 
        } catch (IOException e){ 
            System.err.println(e); 
        } finally { 
            if (reader != null) { try { reader.close(); } catch (IOException 
ioe) {ioe.printStackTrace();}} 
        } 
        return dict; 
    } 

7.3.3 How to Use Executor Service to Run Threads with Decision Point

The car rental sample allows you to use Oracle Business Rules and simulate multiple concurrent users. Example 7-3 shows use of the Java ExecutorService interface to execute multiple threads that invoke the Decision Point. The ExecutorService is not part of the Rules SDK Decision Point API.

Example 7-3 Checking Drivers with Threads that Invoke Decision Point

        ExecutorService exec = Executors.newCachedThreadPool();
        List<Driver> drivers = createDrivers();
 
        for (int i = 0; i < NUM_CONCURRENT; i++) {
            Driver driver = drivers.get(i % drivers.size());
            exec.execute(new DriverCheckerRunnable(driver));
        }

Example 7-3 includes the following code for the sample application:

  • Create the Executor Service:

    ExecutorService exec = Executors.newCachedThreadPool();
    
  • Call method createDrivers(), defined in CarRental.java, to create a list of Driver instances.

    List<Driver> drivers = createDrivers();
    
  • A loop through a list of Driver instances to fill the driver list with drivers.

  • A loop to start multiple threads from DriverCheckerRunnable instances. These instances open a Decision Point and run the rules on each driver. For information on this code, see Section 7.3.4, "How to Create and Use Decision Point Instances".

Example 7-4 shows the code that waits for the threads to complete.

Example 7-4 Code to Await Thread Termination

        try {
            exec.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exec.shutdown();
    }
v>

7.3.4 How to Create and Use Decision Point Instances

The DriverCheckerRunnable instances call the checkDriver() method. Example 7-5 shows the checkDriver() method that is defined in CarRentalWithDecisionPoint. The checkDriver() method handles invoking Decision Point with a Driver instance.

Example 7-5 Code to Create a Decision Point Instance with getInstance()

public class CarRentalWithDecisionPoint extends CarRental {
 
    protected static DecisionPoint m_decisionPoint;
    
    public static void checkDriver(final Driver driver) {
        try {
            DecisionPointInstance instance = m_decisionPoint.getInstance();
            instance.setInputs(new ArrayList<Object>() {
                    {
                        add(driver);
                    }
                });
            List<Object> outputs = instance.invoke();
 
            if (outputs.isEmpty())
                System.err.println("Oops, no results");
 
            java.util.List<Denial> denials =
                (java.util.List<Denial>)outputs.get(0);
            if (denials.isEmpty()) {
                System.out.println("Rental is allowed for " +
                                   driver.getName());
            } else {
                for (Denial denial : denials) {
                    System.out.println("Rental is denied for " +
                                       denial.getDriver().getName() +
                                       " because " + denial.getReason());
                }
            }
        } catch (RLException e) {
            e.printStackTrace();
        } catch (SDKException e) {
            e.printStackTrace();
        }
    }
    
}

Example 7-5 shows the following:

  • Getting a DecisionPointInstance from the static DecisionPoint defined with the DecisionPointBuilder, with the following code.

     DecisionPointInstance instance = m_decisionPoint.getInstance();
    
  • Add inputs according to the signature of the decision function associated with the Decision Point. This defines one argument of type List as the input. This List contains the Driver instances:

                instance.setInputs(new ArrayList<Object>() {
                        {
                            add(driver);
                        }
                    });
    
  • Invoke the Decision Point and store the return value. The return type follows the same pattern as the decision function which is being called in the Decision Point.

     List<Object> outputs = instance.invoke();
    

    In this case the invoke() returns a List of length one, containing a List of Denial instances.

  • If the return is a List of any other size than one, then this is an error:

    if (outputs.isEmpty())
      System.err.println("Oops, no results");
    
  • The first entry that is returned from the Decision Point is caste it to a List of type List<Denial>:

                java.util.List<Denial> denials =
                    (java.util.List<Denial>)outputs.get(0);
    
  • If the denials list is empty, then no Denial instances were asserted by the rules. This indicates that it is OK to rent a car to the driver. Otherwise, print the reasons why the driver rental was rejected:

                if (denials.isEmpty()) {
                    System.out.println("Rental is allowed for " +
                                       driver.getName());
                } else {
                    for (Denial denial : denials) {
                        System.out.println("Rental is denied for " +
                                           denial.getDriver().getName() +
                                           " because " + denial.getReason());
                    }
                }
    

7.4 Running the Car Rental Sample

In the car rental sample installed on your system, for the code shown in Example 7-2, modify the value of DICT_LOCATION to match the location of the dictionary on your system.

To run the car rental sample on your system:

  1. In the Application Navigator, select the dictionary and from the Edit menu select Copy Path.

  2. In the CarRental.java file, paste the path value into the DICT_LOCATION value.

  3. In the CarRentalProject select the CarRentalWithDecisionPointUsingPreloadedDictionary.java file.

  4. Right-click and in the list select Run.

Example 7-6 shows sample output.

Example 7-6 Output from Car Rental Sample

Rental is allowed for Carol
Rental is allowed for Alice
Rental is allowed for Alice
Rental is allowed for Carol
Rental is denied for Bob because under age, age was 15, minimum age is 21
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Rental is denied for Bob because under age, age was 15, minimum age is 21
Rental is allowed for Alice
Rental is allowed for Eve

7.5 What You Need to Know About Using Decision Point in a Production Environment

In a production environment you can use an MDS repository to store Oracle Business Rules dictionaries. When you use an MDS repository to store the dictionary, the steps shown in Section 7.3.1, "How to Add a Decision Point Using Decision Point Builder" and Section 7.3.2, "How to Use a Decision Point with a Pre-loaded Dictionary" change to access the dictionary. The CarRentalWithDecisionPointUsingMdsRepository shows sample code for using Decision Point with MDS.

To see a complete example with deployment steps showing the use of a Decision Point to access a dictionary in MDS, see Section 9.4, "Adding a Servlet with Rules SDK Calls for Grades Sample Application".

Example 7-7 shows the use of DictionaryFQN with DecisionPointBuilder to access a dictionary in an MDS repository. The complete example is shown in the sample code in CarRentalWithDecisionPointUsingMdsRepository.

Example 7-7 Using Decision Point Builder with MDS Repository

    static {
        try {
            // specifying the Decision Function and Dictionary FQN
            // loads the rules from the MDS repository.
            m_decisionPoint = new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(DICT_FQN)
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " +
                               e.getMessage());

Similar to the steps in Example 7-1, Example 7-7 shows the following:

  1. The first step is to create a DecisionPointBuilder instance with.

    new DecisionPointBuilder()
    
  2. The with() method using a String argument defines the name of the decision function that the Decision Point executes. Calling this method is mandatory.

    .with(DF_NAME)
    

    The DF_NAME specifies the name of the decision function you define for your application. For example for the car rental application this is defined in CarRental.java a CarRentalDecisionFunction.

  3. Call only one of the other two with() methods. In this case the sample code calls a DictionaryFQN to access an MDS repository. Example 7-8 shows the routing that uses the dictionary package and the dictionary name to create the DictionaryFQN.

    .with(DICT_FQN)
    
  4. Call the build() method to construct and return a DecisionPoint instance.

Example 7-8 Using the DictionaryFQN Method with MDS Repository

    protected static final String DICT_PKG = "com.example.rules.demo";
    protected static final String DICT_NAME = "CarRental";
    
    protected static final DictionaryFQN DICT_FQN =
        new DictionaryFQN(DICT_PKG, DICT_NAME);
    protected static final String DF_NAME = "CarRentalDecisionFunction";

7.6 What You Need to Know About Decision Point and Decision Tracing

The Rules SDK API contains methods to assist with processing a decision trace. These methods process a decision trace to replace the RL names used in the trace with the aliases used in the associated dictionary. This makes the decision trace naming consistent with the naming used in the Oracle Business Rules dictionary.

The basic API for processing a decision trace requires a RuleDictionary object and a DecisionTrace object:

RuleDictionary dict = ...;
DecisionTrace trace = ...;
dict.processDecisionTrace(trace);

This code shows the processing call that converts the naming in the decision trace to use the same names, with aliases, as in the dictionary.

The Rules SDK Decision Point API contains methods that allow you configure decision tracing and retrieve the resulting trace when you invoke a decision point. The trace you retrieve from the Decision Point is internally processed using the processDecisionTrace() method, thus you do not need to call this method to process the decision trace when you are working with a decision trace from a Decision Point.

Table 7-2 shows the Decision Point API methods for setting decision trace options. For more information on these methods, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules.

Table 7-2 Decision Point Decision Tracing Methods

MethodDescription

decisionTrace

Get the decision trace produced from the call to invoke.

Returns DecisionTrace

getDecisionTraceLevel

Get the decision trace level to be used by the RuleSession. This value defaults to DECISION_TRACE_OFF, which means no trace information is gathered. Possible values are: DECISION_TRACE_OFF

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

Return Type: String

getDecisionTraceLimit

Get the decision trace limit, or maximum number of trace elements which are retrieved for the trace.

Return Type: int

setDecisionTraceLevel

Set the decision trace level to be used by the RuleSession. This parameter value is a String. Possible values are: DECISION_TRACE_OFF

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

setDecisionTraceLimit

Set the decision trace limit, or maximum number of trace elements which are retrieved for the trace.


Example 7-9 shows a sample usage of decision tracing with DecisionPoint API.

Example 7-9 Using Decision Trace from Decision Point API

DecisionPoint dp = new DecisionPointBuilder()
  .with(new DictionaryFQN("com.foo", "Bar"))
  .with("MyDecisionFunction")
  .setDecisionTraceLevel(DecisionPointBuilder.DECISION_TRACE_DEVELOPMENT)
  .setDecisionTraceLimit(24000)
  .build();
 
...
 
DecisionPointInstance dpi = dp.getInstance();
 
dpi.invoke();
 
DecisionTrace trace = dpi.decisionTrace(); // with aliases replaced

For more information on decision tracing, see "Tracing Rule Execution in Fusion Middleware Control Console" in Oracle Fusion Middleware Administrator's Guide for Oracle SOA Suite and Oracle Business Process Management Suite.

PKWPK[EZFOEBPS/img/faq2.gifZPGIF89a&}//I44T;;alXq]ye[Z[EElIIxVVxgfgqmovvv"(%(49:1\;nCDUTJHUYRlcfrjz<\0i?`POXXOiBqggiij{tth}yyN};,<*J/oqpI}V!&97)9!4%)1JREZ~wcc{{WDBBZRfhkkcss{Κ-,.;7mu~f0G,u vr|D6 = ;CK*JU/b:ZIth_@lO|bcxe~gzWg:Ҟ@ɼHܷqqAw 8Yv|o}U{}͈΄֗׃۵ȔĜșɭꭌΌޙƖحΥַʶٽεެޙ¸ںȹ뜋煉йÎ؅ωإ!,& DA#@(1D JXD1^1#G ?Hɐ%Q2%K0_tI͘5qrsϞ@ JtѢH*MtӦPJ-իXjʵׯ`ÊKՌ)I\l8!p۾1?*VP·߿ LÈ+^̸ǐ#KL˘3k̹Ϡm RXw/_%c˞M۸sͻwo7;ZY8MDNسkνËOӫ_Ͼ}Wğ/>߯?H&_u*&B*Hh'A!DЭjy&(*+袌0hc8Ҩ;>@)dHL&NF OV)T^e\b_v)%teC!Bh@?(IcYE{ꧠjh衋&裎F褐R*iNCni~*jjjjj*kjkުkZfUgfB )TB ٦D~jֵfv+k+nac׻vhPP0oρH-Ql'0Yg6G WLgw "k80!{x܁=2{TJ^t-0P?-T7muUc}[g͵`-dwmve}>6CnvCo7L}smw߀Cv .w|xɌl9hnyr9ޛk޹c~yꡃN:믣5Xˀ2،0j 왜K,dV gf^?g=Zރ}>P~O~/􃏹(9v %@.0tmNPu< @%M|;x4ÃD/ PhPF }Pzw@ yA3A؀0B !3LA5pTC H2h<8Qh3`g+"_8 leI'ġWv@.H[,W#HJZ,l[&7Nr %(G)RL%*WV򕦌K89q O<6GL`XHTpB]!7"VifYIVfmMR 8Irrσ iR 7{byY>¥(/Ρzpx*hNUp5zh@C%-l2DҠiΎz iY?fe (ғ^( C" T5: lQu88^! Xt P̊Te(OL["4|Zв7Bo}kbm&z_8ƭx;'L [ΰ7{ G%.JVA6p @z'[RWۅ':@THE{iZNH]MKeO$?V^F@@e&3hN6pLgj%@0 ")9ҁ몣+<щ8&P*;әniNUuQg*X|cWɣuu]Ml_Nf;;C*Y . G T 4 &Sc>.L N<`(hi T#niwn~up۴ wċMa[5LwA9G$?Sr|/o9g.43@ЃN}Z=8]}΃VHȸYT@Vx+Rщ*<"o.[j56Q}{]Sӝ{Oyч'z֯~=g^wz#z6aCvQucPKi QݞBP 4̻ L};YNcwu~yL~q~y~ ؀8XxYuW3S3{p3.WGuobk P@i' +HQ͔vyQT}9 A@ J LNMP8RXTxV \؅^xGuT-&GVwW-`Q!v8sxXzTH:Hw؇8ȈwH{(ȇIxx~(o؊xȊX؋ȋqx@w3x39w@+dͧZ'!q艝؊؉gx~ ؉(明hhُY9o 쨐 v9Yؐyzb@p(*j@bPukxm(^"* ;89y;B9DYFyHJkb/P0i2>,b#y"Gs`s_ras%ksjiskinٖ+yt9{uyw9vxɗzٗ闅9ɗ*lo 9))G`$@ Vu&(hrk2ma;lDRmN9)iٛٚYyșʹ隁mm 9Yعٝ 9)YypLS!9h`(Giٟiџ,yj,ʠZz Z* :&Z *, +-0:2Z67;J= zDZFzHJLڤNPR:TJC -WYz3f,>6dZfzhjlڦnpr:tZvzxz|ڧ~:|J\_ڨ:Zz`*:Zzة:Zzfʪ꩸ګ:JȚʺڬΚڪZzؚjӪjʫz蚮꺮Z:vo/@jn{Jmjdj;] ʰc ˦k !۲Z,2ۮѺf* 8ڱ>۳ >F{HJL۴NPR;T[V{XLG{?;%Z;d[f{hjR{#;]aC+&[3wgʷiJw~Ko+rKB;kZdJf v+˧;]۹˸_x{\ۺp *jEe )˺jۻ˦kes K[[C˻қ;˹ܛǺ廾{szۭcZ{ߛi*޻\[k< ܷ\ | l$#|,̾)L4L1Lp{0<<9L?6<ܨ LNPRV`vxL ,ʤ<4]6}8:<>@B=D]Fej)ė=]P--؂}܄0ӕNme>] NX'n%.)#3*+n2:N<@B>~DߝLۋlR{ S.UZ>[^\>^>/^]nbd~lmnp>j^onrt~| ~ LS^3T^a>^<>5n镮ޙ~n㗮鞾~ꢞ꡾ꦮ~~5PN^޿K)Hn&>^>.ӞNؾ.^~ hNʓn->o Lޗ Wcfj4 "#O~脽R*!_cĎ6:_7<9/;?AFE>LOJJW^]^ >O5?)_(1?-o:p/rP?nNwoc|xz?T?Յ$?g[c>k4o8/w//O/?N_j/  _e_>M-,/@oݿ__oP2T?}4t0„ +VdQF=~RH%MDCS &<B,?nO ~D>\E>U>UTUrdf:tUjv$A X3ΤGnƭRqbCxy^X`PjUN&͍8b])Ɵl73^ʅ=Z4–/աKWkcbn8x#e~%s˭} s B{9|ś?wtթ_vݹx.'6XFdze{{# +'-?$p@ м1sVc, -Ԫ+4t !ZDR984PA%PCE4QEeA!;$8M23:FlSO?5TQG Gg3B 5_BXo6Ʉ:\굞`{%Xc}Xd-cYi6j6[l[m[q1ǑtՃZ]MZ;{=][aQ\}ݗ~7`x` rIUUJ]uXLN>M8c7c?9dG&dOF9eIF T}]6)cW9gwgƙvXV^-kJgΤi:jj:kk;l!D&IydR)._;n离TyQwv0LIEG7>y䗿]y飧^魯t&ZVRi6MG?}g}߇?~秿~?*7n"T@6Ё`%"p G4VƃaE8Bt$Da UBoZ8CІ1 uC)/PdC"ш7D&d!ۚ8E*V*IbŒUf09LbӘDf2Lf6әτf49MjVӚД(Rr' /Nrq+g:8Nu3D;DvӞG<O#֓D#OԎ4hBu<*ԡ*C%Axs(B1> hHEQt*mIUJԥ`/y—eNuS~ /m:T(rDjRT6թO46ժ$16խN#_kX:VS(zU~ĨG\Cծwk^UtMBmk`ݪQlGb-ƲlXS0ղlf׍lpUi(D + 9p}}$al0+{ f;\ₕG)AAP3ڔʰqGv nû@+r .-nzջh7#Ur \bCCdA]ѰH7]ol[ݒ!n S-ٻa׽iJEPpD sXԺn7!H0,9¹-%avG!ώ%&0 ^!@q|̘61% `Av3oX?Ar#Hx"i]b1! 57p5i"|@8Eqh)z5LfOȖ5[7s׿CGZ ^~Ae#BzՅmC>^mJ<x,I?pnvKSL~ر-O,H"|@ h|]wp;v_ !lh"HI9dyOQ}|u.nX8d.sA$7ǹ]>!* 38owŚ?tB%7WpDCz]w9{úvI:&.G gE!kb|sO;,=7G?vc;Ykv}Jv綹Nߖ;~7A`{^gA=KOkx[O>D&0}W{k=8Cqx7$~#F4ID΅o~+' &a޻?°S#+@`? ls dB@*HrT5?NܬL+,& R܇R C\!D E|Cdr\\p4>Pv1qkF 4O$a4BTTEb\-E`R>],n+3=*bfTglCi1kEJįx+BL\NvKЈΨ$ܴ(<BW0F0305Bs4D.{tOрOwbr+X6O/$OAP0%BS4dP[5YOƴ/P B4 ݦmEl۶FP usB"  QԧOKO$ 6i,m0%G(%)c{99.FeM0%1=d::SWG6D/E48RA-BdI4EM&tGaGTXHB%C?EDEm*WA `WNtS;N$O} &X0OOr TTDM}NW$X]*XӨN`rVЛ_}a$U=Pb-VAR1&WXu^QH?VBfJWiZW.TR1JamUlm$cM4&dUHWSN0_*a4+WgZWFWdbBVQ[mXsD">M&,X+&r`$tcpVg&nF5_Х6ޅڻenEZUo#倫dA'`.)&4X#o6v[]U&p~owq&GoZ'/D?`Z.H(0`20-q-p=n(quGp+WojW"f # x1,!*=.q/tCr51qFqpp4!5L $0h( t"e`/Ts`S-nT/Y'_V?e u74k믞>`Rt2 ~u̒vƞ_`!JJe*)@c$0`sWqv>w~WVR!'&x@jӭw5G'H*xϿ_xjxvzɗUQQVX нĿ7r'ƦGDy6f| ~ݴgd/P wPQSPݷ~]{4~\y)n „ 2 Æ'Rh"ƌ7*ܴ#}B$A X qK.gҬi&Μ:w'РB-JR&I3)ԨۑCHԉn+ذQdZd ,$k-ܸrҭkn[4~t*oB.l0bn_4҂ږ.[2̚7sl2㘉G.m4jUvrβgӮmmS?l7‡KqIcn9GRoJ:ډ'̥/o&ny(v$Sp~R' Òqgwini \~Ŕ(( IS*vSmʁʠA[iWy>Yuz-!YC 3ʯ tj,6m* 껯tZ`li 1):,z0Z akj({[il.(Lg{g)$&m61A{2ElPA.Gk }5oKaԧ!8UbAݵSS[Y6D{ 0d]T1y>s=7g9}x[e`NB.yLnyk9{盇9襋n:}v8z+^>}n-<N ?n3Z`_ݾcoG8Q>3$l8;?ṡ^K} $%(6qRm{͓=X2'2 Mjb$#r`H}4t!oBO>! _(J02epc? ~QǤlP)6a +,!1Cb 2fli?'EgբMh o XVG":<,wFB~(ZrN=C}Tq+a-s"F$c$kEƒeXH+%2szaM;X/򗻼e%qM]zҖ&@-qZK&:LTFd(Sօj2򈓴 m8VS>$?kO14Dxt2q6MIa kzӡ|I1uM=TS'էNթVUZ̅4 ,#fLG.`mT2P  gTBնU.o5E2!x,Nkl@g4Sy!e>@$@139Nkg%yA\j4:՞\_NzON>*sͷ@xb \Ȃ?MSZ&jڲv miԶ^uh* /DB fxaq]dYv! p?p™<3"ԁ Tei8+e-GU 8s1s<Ʀ5wu+[!H9 jX&==ҟ-O6"8 r) *ʁױez^enՏܪ@q}BS${{>2Yv]aksж9?.KmgC; 䴩]-5k|[>w7nq6w&L/TV xK^Wu/bmywE,r(V1-7Zw/}nr eY!;tjK=_a5ģEڤUڥeڦ߁Y9YNQR[-D [[-?4[A E FюwuĻۼ۽۾х` [oX1Dɝ\C` n oUD B]Vf! f`L-؉^"EBUj`ѕ]a㙡bWݡY`a!V!bd)!##Iijkٞc1_YO nHu"`Cpq!r⧕+bV,-I*Dx?yzX*]0B&B_&#C-X|XX@6BbMu7"b8#:#}_ y@ߘY_#|#cC4cB$@HYZj9A<CC"DF 5!1/)dH:H.bID*ՌԠћ᛾-BY~LMv=G`NNz' DNRFN|!]WzMf"XX%%Z6L=ZJe[ʥ^fHb]T`N_FQ`bvD_aPb.d*FcczPdNbc^&df Wz&fhhfi%gZjkRfllfHm~f^&prk^oNn0fqq"%*rNs:gE'L'u!tbqvT&qzhxNuByx'|vg{ zg|{gxg,'}'R'~!y^&&hpg>6( (Ⴒ' ^h"%>jbKz]IUh%ZDi΍rix闒͖iiF͙`fZciR >eiiN* *=i"jrj.*JJPjB p+)b5V'jr穢꟪ j'x*.ڭ22j%j1jv.C2^*2J+hjc1FBvM)kRb(f~s+dka&kGB,mHZlkh$vRƎxPŪf`l\&̖,ibF{l -ulgm*s0mBm]H"¦6fm9>mׂ^lњ-mmmyf-"­ jS~ڭږlm>1_mQ- Y=,- U>n2~fTn܂.m.^*Oݪ[}n*ކ(B^Ƭ.1. oqE*/C8n"oB~RorjnM~o2nT/ZL)nцʍH/o+'0.pO*>pEwgM|0 {0 pCo߶p0 * _p[/ M11ӄ //.71pD1OV_'s 永.o.q>11b/",D g!On!"3n"# n#[$m$%m%7&m&'m'(m(o)gm) qaԶ2 rrr 22  "s3*B:sSsJ3bZ32,28sq oX93Ziս֥Ȧs 3;+:˳ s=ӭ 3>;>sp A +tL4 ?AFL>ԃFsFwt=̂-Ђ-tII4JIJ4KL4MôMM4NNtNKH4Q{QQ5R/R7uR?5SCSG5UORkFF)p>B?di?VXoZw5[u[[5\[׵\5]ߵ^o4+u=xsoaW)B_--@a6HõjA[VC?Xvc[eXCg@g6ii6jvjj6k6?k6m϶mvmm5-efvpp7qq'7r/r77s?sCcv?`K`to{v?p6?v?x6yywy7zz7||z5?;ăzw||7wwk7{'8?GxO8SW8#tCFCۯEkBg7jBl88Ǹx3<Ì縎8xb66yye_w @a-W_9go9w_9?C4?~GFc'Va&`>sw~x~>~蟾>˾k~U???'8;r |NFNCg_Mdϰw w@zב[>@ 3!P1zڋ5"=`*K@X6)@C qd)A2C s R!<DT0glqOK"ɄhGHҬAl7-B~Ҿ)R@| 1-F1!3bp.R8 ý8dp9,.Nq9tTVQ%4>|QYHH4 u V2];\am:H{< `ڶ S`VqWU(%WucV_7Wye{1\!rwM .8_NI5{f)F7!xڊ97b;`sycQc~SnY]}Kfdivs kY݇Z&g.N{ABwj蜎L[.N[n;1jnZ_|3P[wOl 2=ig/cDV^k)嗩஽t͉F?Ry)Kġm.)J=Ir4g8 Ft*P17 * V98(jr# n:|> itZ%?A/4`|@ ~(CӧD>!Jŷ9Pu5Е .@jE#,cΨ4Ҫ6`)1Vba谨9;FTGdHDэ"F:"<#GJ|V2? D` 8B'V{<$)KY#/qM2@ -ȶrYLTɼ~t k*#MtMp%b9ͭ4r+I#njS2tf r3$5cO@2: фJsbގ P^)1tGCQ  4bPZK %iJSΔ5MqS=OT H6.MuSզ"4R/]i4tU}"Ze^VZH3kYguxgeY +\1B޵vk_*Wsn%:Y,uc!YNe1YngAZF6<5iQZծui㪰Ζgmq[V-͎'mq\Wu{Nbnu]2]W]%y+Jx!b 5oh;_Ϋ~_p7Hց,< Vp! R#b >;X,'La μ ؉/*ώ9[ۅ%B1 dn&ID&͍9\ *Se'b3f(3wkT^3@i2|4ͫ iC9sH[ۥOsP(PXdGjt˟ȎI k֌zְFȩQ3V?ZԲ_]Qߺ[9m˳jP[vvU [$k=Z.7c\z\G9h;&nL{]5׎ AY#pyqV%񼬙V']g\w6LpuCƮNZW+$/('jl~sS,w8ān{{3P!c:/w }R=_k{A}{별t/`'Ou=uٕw+{6Ӎx:}Ww/Voq-wVS91=tT-J jA&d/6gۯD
,Jz,$//m0P 9~tP/m ُ / P!0# pPiPL  *0M݂a< H 1 P !P`c {#18$ 7bPgԐVz.DqKqAjO84OIkrO1_1NqOIqmO]O qkN@ݡ/ZqaT"1׭ӱQA4sȱO/]Ѱra2!r!q!q1Ʊ #1!r#C2!E"oo! %a#g#e&7Qѥkor((('r+Ҿ6((r*(yʠ*+2 7G؏(߱ڒ-a-R.1Qe0-s. s-1'R/R1 312 23,L**/.J3P334[6wrxAXL!4r4W7K5S8636*9Txs(8U35O::Ys5s8Y13 a(!+`=%=%==۳p37u3^S=%?s=S?ѳ ӿS?s?3>>e=4"֋>%"tB-ԫB5BoC=T*CEt2tDMTBDU4wRtE]sJEeTwZtFmn0JHxJTH{G}4ItIII4JtJJJ4KtKKK4LtLɴLL4MմI7@^HD6@NtNTN7`OOO5PuP P P5QuQQQ!5R%uR)R-R15S5uS9S* $(@HTMTQ5UUuUYU]Ua5VeuViVmVq5WuuWyW}W5XuXXUX!  `Y7YY5ZuZZZ5[u[[[5\u\ɵ\\5]u]ٵ]5 ;PKV_PZPPK[EZFOEBPS/img/adfbc17.gif7tȋGIF89a }<)TFYVfWv\~)fdig9&veZumBLOgȧYaj衊6裋FꨤNjiR饛fiШJꩦꪪꫮ 묲J뭶뮺믾 찭Y՛)95kPeAҒ'Df{fu+k覫覰>kcf@Lm'mQ 7G,1Y&Pgw "L&*\quk%+=4#s" J0AP`*^EQQ[u\c`oaw]fvlpqWfv3y7w~[8{ރ߽Z;=yC99{.衃9Cꦧz鯟>{뺓.;^?D3`rI#|3Έ ǝ\@AHK[k_ I= ~W>a?{H5f\`m'ARc `18Am E;u+G#AghBykAҺ6 ,Dj=&THL&:JdKڢgD1|tj@:a4p]7DaĩApH:1\pbZ"a`a$0FMDGg˒HrIl+$K;򔨴 [LU|,cIYڲ.s]e\y g9C~EiUh Fu&xBCZPVf L,Wĉ`-,&8Jv̧>.D e"zb (9ܡ{8:d,{GreWA'YoSLgJӚe!#CԆP"!x6 NL(9H(*zʩΫ^+W5ɭr՜k;ARVsfҬg%&*ִզxͫ^:14qC_( h.x9 O8#>ъWa7xœx~$iFnEg6[m,I咼Ei[V m:akRNQTJZajQ&q^>+aENM ^|(9X#'0!~A7,\Q.ILpm@` '0-| ?DìUn/ZX( W0gL8αw@dEX؀,@X<^@Hwgp74?Cׄ+C3:kYClVKgLF;ѐ'MJ[Ҙ􋍌Eh^xAl`X,,p 0D;qD@:)::ғt;}Oo:ԧ.GTǺճ{]`>th?}.Ύ+s Y(g`է ~`X':l8ƳhC>Ay٦$|O__}cp"x <>#d GWQ 1@!Q!&O 5w3 x8؁ ǀ8)l*|X|4H3X8:<؃>@B8o3uNVXwwxG$ GxR!" !_HbH f؆lort8vXxxA|؇~kA3hքOhRjQqݡڱx(HHp؋狼ĸ8X،Ըzxژܸ{04Ppꨎ{Lj0+!2y硌xhøŨXh78 I ɐ 9)Yyi!9I&q%' )ɒ+)- /I348|kw >@rk8'63PR9TYVyXZTnk/`i/|wVb!1"Ƿt]UGuPuZ'vuusIt'v|u}v~iu˧{}ɘ阕 inٙ陡 Yyx~-Fb|gde}e+@"' 3',OéGiÙȹٜ9YyؙڹٝyjYy㙞橞蹞ٞɞyɟٟ X_T U'`9y:J͒ڡ!z(*!(.J"-jz*,z)/8>ڣ58:BZ%j*JGI43ʤO*QڤTU:Ij\ڥ^`b:dZfzhj*1mڦ ʥR5]eЧ{:Zzڨ:Zzک,Uxڪ:ZZzګ:Z^zڬ:*jyZںڭ:׺Zz蚮꺮Jʚ:Z گ󚯨 [{  ۰; [ ۱k" ;-0$2K3k39[:k>۳@[8[;F[-{,,M[H˴PS[D+DKYk)[{^{X+ae{Vjlkm;o+quptv˷x;}뱀:K۸;[{۹;[zۺ;[{[+;[{țʻۻ;[{؛;k;[{蛾۽*;[{ {*<e[ e ^ ,K$\&|(̸lY2<4\6|8:<>@B$^&~(%gN2~,^=0>: ׌m۽D=mBE~N^ J«ۗ pׯ[V^ԍRП Kfč7` ݼ{lNr^M ~kRo 熞逍}M=黭؍=m>螋难DA'=w.a޹ψ//~Npm閻[ɡ劝> NNǿҾ/=>^ ^5nuT/C>>h?_>ﶝ8 "/#^v,-.ޝl8:< /~.oտ2., ێ_{د//@0X!B .|aCNLSD!ZP@ 3DRJ-]SL5męSN=}zH;wnF=*`"|VČ%Cv4E*5Q$[e9śW^}X`C3 rKW: uj FUDrՎ[3Y&=5vG KXlڵmƝ[7ˡx\(!clV]&9 Ұ+$݃`z;GNߝ^zݿ *p˅+~x/7,|>D0Ad0&~ N{|[" ëG$DOD@klp(l,c S GwG 섾iE ڏ+ ǔt2J)ʗ q\4fd2J3D3W)- TD*j(;O?4PA%PCE4QEeQG4RI'RK/4SM+5eR?;QL5OE5UUW%1ɭ,5OVgV[oUFQC\6XaGWF@beYg4)0cJg6[msBdv[q-(sE7]ue]w߅7^y祷^{7_}E7T%y7*k%T FXc[jN8b%XSvZ_+֋;cdtx*bSx2|1nٟ2OjSY63פy\fʒmJlGgċ-$g:wP,[k/t¿Ow+:-NpSlŜE!T5"F:⍍_Nx'fU`8#3xm.#Awj>O;AMw- p̟@)±q]I1Љk[햴Omr-=i;&Ύe A z~Tc+= }tNF "u:ӍiC&Aq/H$,%,(A2qVdhE[`ĽS|%B 7A1s'?8wԝzU(wYM2YpФ"ӵ46Oz>9SW2.&4>sPx -OSiPT)Q ԝTOFwLQ0&HǦClyVHr-&S>ztTn6/WmDa&F¥V.{PQnԫĚFlXvv0zԃ\1%cVڮN e%Wn4J+fnxu]zޢo˻^V2׾ W~_׿0 +Fp_6F3pw4p5\1xq5LaJ'F)L_/.- cd+ucR3%Sؑ9]A pgVosTZgJjXPءd#b`!VEt|7Gүӛdb0C dhkE+$Ɇ"Ҝ;&-KzO6wk4N6U=VqwL@{ vllj;ՆT)Lp;A&NP&[{0Czl̳^q5lwpXFG0YÏ=xȣpYP"Gx{!y^>sd%yu^YQ;zБaR\Gy!t2ozuI3yѝ}uS~zC,bG{^b+y[nryB]0d/ ;nℑssMYZcD)Ur+!?;4= jQ/? GJz`s j^e%%/΅/g@#ڼObOclMnoZ?}wgE&:ۡ};1\yvG0|gمTӣ7#9s 1 @ -$@DAdپkl d3AmylYea!4B[ #TBZ)%tSI'4B+ (L$}(qȈ1(B.) Wp8N,,4AX6, SObUA(Op@C=A>h7O8D9SX8EC41 RL>񹭃D*B_Z*xKROOLDXDSXNE8EClĂ8EN\FxVD.j\C)l0l ]DAFb,^)l$p\D_ ǕGN|GLKaʐJ)0HSNE_ɔ8v ̊lBDW8XLPqȵ,4lLy,~8s+UE 5HГؔ%e&u'()*+R(<.͕-R/SH15ӹQ;5M="R5e8J0S9ә;Ӗ(+?@A%B5CE&! ÊTTq RsT8T{ zU)9eT-OS]6XU6Y5Z-T>:p"_'UuSN;O5kRւXVkVgeiuVjjkVklmpqrWs%Vtesutvwz{MuW{~5W}}؀&\>- j̽t5*K3~ ]Ide}E@uE@ 8Y+E٘}ٓ5֚ٔٙYYٞYٟ٠ُ"CAbYM٦-ک%ڪګڬMZZڣZ[UYZڮ۵۪-gڟ[m[ڰUaMeՙp-sMfuV}4όά +U}Vl \Ʌu\̕\\̽\&!@;[mYfEݦ5]%Yͭ\ٽ\ϝ]ۭ]Ѝ]]݅iݐ-]׽]ߝ]%i-ߵMެ!EuF=V^E7`ZP=Zu_}_A=]޸[mY-^5FVf--^-.^U] n & 6XNUafj_aq:__X_%a}a b&# .#^$'^&)vb}--&a-b'&c$'. Nc3^nc4>c5#^' 1f)(6c?v&/N_%d#V?*VdF⏕Ԣ0ua!FK_Q_S_T&VmeKNdeڜ`PcP~^_&pp,^WNdmY aSVf>i^ mM(joj|_qvY~@gZ^窙@i玚ng@~zgx瀾g}&h~6|hV{fh~`sn;6; /vVhN~$q6ii.{idnhV醶gv&@dynio~hi~in&D7VPg&~[~~g-.Vg|-~vk|fjV^_klkl. nl~l뭮i^$-NkV{i`$.l6>mnn^mN~Dmfmmvl@h> ~ jNlmžNmuj6nw6jf^kmؾkl4jm1km@ko~o.lop&.pFVcpNi(pyvp&pkFg pp wg'nnqp6ooGp&iFr/(? mg$WVq\h.~k Osz1osxvs6so~:5; *hm3UF5DAx׽m P/̦mF$a[>yez|{mKzc9j.BLx[-\'4' ;z;g<@ Q|{ٶ-aBh=̃ɋ㛟(dMS8u>HKꧪ?d< 2| #( R 3 rP#e=f&*Ўճ@TdB#*Q8ԡ(F3Қ(HCZv.HSԑl9W*әlEJӝ#$5g+{*ԡ0 *QSJ}*MzϘB)??jխbGu*W*Qb=>ɪGTֹSd+]MBҬz3U|,jŲ%,c#ؖ Ҕ_%d3KKǚ%(,hIYL0` -j')زj5#g/٢1-nڵ5+Rbn2W]ns{ҽtG X肷Ԯ0ZȚuD2-KN{uMS\w+`ᗽ>0 ˸^W S03 s0C,&>1SX fw,-P18>v"s!3qB&2d'81N)pM2gd)ge,mc>sݠlT|,爕9sf{ _. G'ơLKцt}1%):LBt) @Ԥ)> Wczص~ W՝yk=ԝįU SD;qK}mK{YOlG#V}! G0 ]脵u#lS6'|Mlz|\J".XeuϡwG6O=^# .y&Htyթ)\>@}{{%ɡ q&*mSV CBE87s.swwt`о7<׺.Mw"! }lh (+ D4Zu+pWpOȩ .{ל C{x{s uDG^Iz 늇9C1U *Aȟ:yĩB?ZJ&у9 9d6L_ZqS9xKRQ`G̹D!cFag! ʄZ] "L!&"t)"$>J!G%^"&f&n"'v'~"((v!ƠE"*ƛ)Y* M),"͢+"". J.F.,#1#2&2.#363>)Xi턦 5 U6z6ͩ!\"}D7T99M:R7W##UNJѣJ٣cǴ"Bଡ଼Q!H$ccqL<$ FCF5BD^EfDj$FnGv$HrH~H$IIdI$AT$JJL$M¤MM$NΤKO$P~dOOdQ ?> ##:閺p$e"+Ԏbh‹~@\F(b(iދi*2j"*6 =]H"yJNjnH*j*ꩪꫲꪪ[nijj*(ZeBt4"%bVh ˜)z"i^+"Zk+U̱)+vn+k+'듮kڨ.n&l(VpԽBbG~r䃎쭢Fi Ȇvl ֬- ¬ά,Fgoq,fmpʥ&m؆,ي-Җ-ڞ2-ֲ-Ғۮrp+rjvlmFxoܪq".ӞL*-ڬp *m&J~̮Ȯn/roڮ*"olޫoK֒n⩰.JKo/o^:V/Bm^-.o&0pjʢ,V/f/XLc,Fb" B I ,pҒ`p0p1 ðq+3qF9.ڰ ,K q [ 'q n qcq +1qk00^q(  oqr1Y*#$Ȥ0~b ǰ `q%g_2Zr**r*2*ϲ2--ײ,,&1+-/{,ְ!'_22S3(2(64o)7qq'3+2.+G847Cn20[4_+?PRbgp:q' ;K /t3wB711#ϰFqC"{4; tCo4vIqp&Dq2cNtt/rPO4?r;WpI)4PpMt # #[4N uS 1UtI k5Vo 5K4Tk4tE5E]I#4T#5^_ 6\5[4Kt[54_uc'RC6c[Sv__[Ov]ovfw6`^tW _Lgo6`j^h_6a;886pp7qoq#p/wq3p7wr;wttW7t?u't7so7u_vwwvtkr{ysyz[{y7{Kwq{7yq7xsw~{7|7vw{|+w|78rA06ncY1$U瘄7؇؅CԈXԉB^W؆ã6dX{֍X֎Wߏ8$O+x!#9J|Ҕx_~U9syK#c{8yyty9995לKG2'ay@ q9K9G/:246?:3zY븥_zW7oozcjz{xN֭Uz֒gzzƂ:;:!֮֬δV˵/oA o{je{ֈ;38nkV/ Uk{f{{a;K;c黺 <`{U/gy3<3O7?<~hSk0V/ZgRJ>ci>V飖~j~~f_žk}Kd ?/ >[t\M0qn]`?g\_ Y?M`R??l3 BW? @@ <‚:48pć bŋ!FF 72TeK/aƔ9fM7qԹgO?:e|G&e!ƒ jH:5_8a0-Kb"YeGVXݞhȴvx.]ՙXAXvG琞>M6lm=ZЧֽwo߿fLyid )Whs6뺮٨Eʭ/vi՛W}{޸SR[9&:آ4J;p 9sx07]{PB%s0,K S(QT"V4ebyBW$UDn'xF2hKщ6&|cȾt6 1498F@*r-Ute+7T CeQJ3"Mٯ5(xd{Y%&P2Ҋ,C%`y8n Qs義)+Бd6nCDL8;ֈH{= 4Q0ٔaiHs0;Z|Fa_yP{cӘC=azR4ItJT{<ʍnc07 JG&?b3s:8(J Bt4dPfT8N;x냜ΎTk$< ̠$2A6(]$~N+iHWyU{U_]Yj8ᥖ[#aBtm99JCe_9ɗNҳݪQJΖ-&Ls(ƤB JBCPu=,hIJ's{VZoؒgbE9JFU#A;!hOS]b~;ԯwc\Pp$Dۓw+i7LHP!ˇsپԙ2k@1&( !)B#ΰN6n)"ٕ5!zhonؚ f5P}c*p( `@o9j.`!̾ɕf=7a.!px(^Ll9WwH+3o4XQffÒ\6|j./h%b ,&\@E-G_8vHUINzTћ]Ŝ_Uon#EneS|E,)){|Z{Vyz0UvC\>^mrbr@+PhXG.ۘxzv(z}?dx\|<9RǷk/1 `:<щyt';6}u|mFU[m"T u(Dw?(„I~,:Hћ#~.# PlZj mLBP:Z%p%jJjPLKY4HЮ:n01T"!X]a1eQɒ!uqA% Q%hk*k2k:PoP.ݐzQf>o !EQDQ%q!rǚ0뭊븒k>qtD (hxx g ő""12)RQk)POKk:o,BR r Aro A貑T"3r(q#i:R0Jh@LHL lذKh,hX//+')+(29! ɛto)e0l˴˼,+utL\,n;RO4$0n𯄪T.7I(|v!.b.  or&2*""mTҒ+-{ӂ.{b45!0>*7|jbsN*ipܖp":ib33OB.+Ȃ4ӘZbJmD o됫f:M#!M;528r2=驩 Ъะ>?'h'bSs(!\.jJ fR$Sp*))-(6:T8is(4Q, 4q!m2fV ,B# iN4ӈ(#!arM !ݴ!JCG+GU")sK Q@ԉ8ƁH9$˽KK;ƠTq-QzNI OF\͢mTRVFOr8-vg[^![QTiN -mie{#fflkVu4*LԸ g5!r$!O'  𞼶pIg7&l?qPM2QUQ@oVW/x bb5Ne318uOuuW"v9NES*UYURkQJQ+,r,wB'C3RW%zr8.zSlm2˚˞Uw23ߗL߮ɌZc<ӿ"Q k,ySqg1ExSoWYzG{3U2^sxSNʵ&nLzt999oXXJ.2[3673dy__wpOSe0 Qf][axY0WRdsPLv eS8n NKO},hQEEW261%XFScqOTlmQI|WtHƤ+og54%yLaJq$w:brq]DY?؈W)#N{"bY+")J un%u%/'7"dD/YS2mY+깟?(z2T{{7sϲ嗋?Q\z:+yy9*Ax0 0UQw%01#!:u959;^&py٨ZzJfoS^i8>HFUmog'\q`6 #9+ ` :9:)zMSc+x-PTBqX; {r:Lܚ!I ``@ E "S::s֌V3TEEZBn<e+XViT?Iz+BC{ຳ ۟۔96Pi6IQmYx/$1?rir37uI[Br|[_]׼c(\L1r?EiGܾ!rƣB P` <@~<= :<)^{r1<Ç:KvUs0|kapęǗ`Raړ'̡#SCC} 8 Pݠ]ɟ#,‚|Omq{{KUz+&]_|}Wsuy<YǏ <`Ȁ 8`V9`PBəϡȆȌ ɔ@Y!Y,jy{/l0G:XٺWǓ1AAՅ`a,  mՀus4qҪ;۱)C ƀ} ڽNzA9LHP6;i۲d;Y۩)ܵ~%^e]{}sm mH>(teegPYuKvK!mߙߝw#^Wabs!蕕M-ސoBٗBY8Ӏؽ-&A &.,!jA}+,@ιjo9* u;(/#?Jaa|a92v~./6WV'Q˲8|[CL3zbcq=_Y.%KȒ "Ѭmh{=ܻ+u//_‡˛?8qqk2-p!1٢J7QZvlȟwmpV\1vwɣ=H#Ms*b.^_!W958cz1N,1E(E,D ?,} <m9 hqрAn7LUζeOI٤ړ_%`~Sf!qU!܆9Y SQO5\ݕq袎)gc9^ij:z Q5 cvuz!VravLɳ> LCi$Q^yQkp*Kn枋n閒Ϩ(@ @/ 孷۪sp滔vvkrqsa7$+"3@#'["emwb/"5'LJ'r˝2LQ%50UVzJ$$+ϱP"I&8 rjQYmքNՠIlj]s7;JV>33Oavc˕sqa' 71Xt$RM/[VMDmKB5`#'owT}h@ÀK!yaG?>M\F yf?] `~"/Ϻ{'=woL!pCq$G!իmV5{.ߏ[z>O)ݘ42! eB iI.5+1lʧ>i?DP( Op+P.SK V K"݈ aD|x6%V&~-Ac ֱּ&&p!F`uqTZ,RCpgY`WXt b ~:0 rSID1,7D=y(@,bq#.ω! 02`,eFfȍS#] KJ䒦%>\2gб/(01>/<\+؅.y CdJrl*yJr[MptpE.nSfT5ۘ7ns<7U8G(z zPi dpx@/JP3|)Vq-)9t?@^Ȕ,H PaI:{r4 i@ P*;(=;Y6](X R A HL'԰IGzNusiQֈ'V6gSvᏼC )B B4S U#%%a^hr+R^T EƒUxdj$-vYOb\fR[[(Ol\^DD@hcCR'̰lKOsձ$ka4r¸BB=-kO|Ԡ%-xXL8jTD)>Q2 ^ppzVXB( BlxY0C_h*6Xh( j]wwK't!A׆ gŘwwJ2kmbŞD'\!Rsűpϕǒe0Vaq6BP1!o{.WeIWd-$n+\.9Xvz":֡K4 IJ|d$viW˯iį]1Jki\g*TBX*zyv4 l~l%R.]WpyFʦ=Hn{GRe~O-Mt޹z^?6!|"! /…žIU&qǵhȞ<&Xwҕ+5nrw mCQR7/r3/9̗ әԦ8)Ot?&]Y/)TUծ]^׻{h+wj*?.vu<o9U.nkvqOW Oԫ>_Sg10ߝnq/53qls==??_Mt]Dː wM~ɟhl[/}7}W}h}Mx'~d^va6ZIbfdDV>u1s6uWHˀ (ȋ(0W6Kn?DL8vF$hK2mF&9/IZrkTXk7%GW{{(؋CSɨn~GPr* l*׈+ )V?eyu8W(#F׏84^?Cnrnny v0XP 5iXȸ#yFxPPM;oo0c 䐭QQ9Xɑ]qA)# Qu%'iLw'87*H]) 0 0  (P"1aD5i}r(0 )̑)2esϧ]gon!By`)YɖcP.P PCđed@cC։_yp % )Q7S5uS9S=E(z{Q>P ^Y 95)(yWzW y**/I2ϩʣ 6P p|ai Z=YYyÚhHk[gw DŠX peRhtǧdYlmJO8 -1Y8))/+i/2P˨ UH?uSJ 2N2PRjZ [^w6j&Z;wO O.*6nۿ sMk{j+ \X $fY,˃ۧ6#& i^[-< K5l v{h" zA @ElGIKMO Q,SLUlWĴ ?x拿: Úgl J mpi _\vk XQQspQ ]O}x,NN.n^> o   oOlVS(R,&_$-321O8:;?/>O6_9oIKJL_PQUOW?YGoZ?N[^aR/h]lf_d?m{y{}/Oom3/OoJ/O_&/o/Oŏɯ͏/Ooٯݏ,㇗o/+ \@zzz($XA .dC%NXE5ncSGdI'UdeKd,`ȑ0_ٓL4m&d!ƒ jP)I~'JYnu|>%[YiծemA*rJWkWuj:kXOKkpauV,QH1,mjr\j6=3(CИΐrfնq4o}{oo|?qVҧ>zշ}YF y`2!KF(ST9>EPU[ xILf0ڢ$#IO< xCNpd*GYRH1$R%/CH6ZR$;q^&SGYRdf5 KhFxZΨyMpb/lEyNth&8Kqf/\"yOe:SdS8(@"T %A:퓍8E:-zQt=(C ч:ԣDwQRDhH;RDβS*:SUC%jQԡ`TKOTF59-SzUF5?UUXzV^Mk[pk] 0U{+WV` {XĎelcˑ>VlC[Yfvk{RX+x ZPӚ,`mk]ZVmmm{[Vmo}[W%nq{\&Wens[ d`H*P Nfu5]W%oy{^Weo{^Wo}{_Wo_8"p`'X fp`GXp-|a gXp=aX#&qM bX+F 0qm|cX;q}c YCqi|dYH6rd( SF2|e'GY<w`Lf4P^󗥌6ù6;PKͮ;Z!H:2#bBP.[ s?̳ C<Ѕ|Glg4""Wf+ ԜdOC#L`:9ŷW\`lms"l+ ny=#gR x{/vNQbL1Q r;΄>3t6I3O\1+jDѩWj`ФΪ-uβ xЌ˼޴|Gf=x@a߯e O@z,H9h򵐕 4Ҳ.`; hhg ; ?."V^!`L0`F*@9QA0Px^[C sBuP@DVR{:H2A(c4GΕ@/Ym1_@G?,.pA`&Byy|d$ (ԁ2@ʌ4`W*?R . mWZ+֯f/A2fJlƪPs 9M;9mQ cKmlp;hDP[vHl:Y9psK<ݕqYf.PEI,?\i 蒛@P0"dGJ Ahӝ{[P?(6eTx;P:ԹlA]# :_b$NvBqbi%M$X5ʽW.\Z/{%>t  HOdz!}N5J׻7_{ Mӽf;#3JGgO+WAD⋠habh[_ qχ{j׿+ϾO2 Ͽ~d@暆* + ؀8X}Mp "8$X&x(*,؂.g,P5x#:<؃>@B8DXFxHt!NTXVxXZ\؅^}KH0!_Xfxhjl؆<!StXvxxz!|8Xx;Q6e98Xn1!Z8Xx`I~AH@8#@#k|P8OxX(M8;PEҸ؍8Xx蘎긎؎I؉((p90.*6O~p>*HQȍJP $ gTd`MWs(0hZP54Y6y8:<ٓ>I%y)+i!`t1r()`4s"'ōzPV|PꄋM8@@}\D&HZPI` ' %`~z3)PЁ)u:~?ٙ陉%3.)p^ԠX@E {ZiԶA@"~ 2`ZԸ$E\{iII:+`YVN(MP 9ȝM:Zzj9BLNQP-b)I*JN(G#* XPBp{KOeA0  %@%C9)XTP¥+Zv` 0sٞ ":ꛤxLz npr:9ɥYQ: ;ZJ(@jE1E)ڦȢµO~TDpƣ %2:ՉF`芒:8>q|h((Nf:ɋv~tZzؚ*BFNPǚxi3"X*1'$'dPzKDX؜pDDjT t U8J=%]ZǙ,XG:T06{8:"˘Xj(G)"(0M)$J4 64`) T`JNoHʯ{eNNPB8֙"* g  9 QpٶB4@;۹{ Eˉ`BX6U{ZI(`Nx_[bd{µ,QP@P@`:4+u\^{QZ<0GP " ฐԪzT0g4 4P;\(0[p$:3@3'2ZKPvI;ж{҉T|6|*#K| T?ʾPP{h&<v9+{\^5jOLbOyT;Y٣**$,4KUepHѫPKG+z `>ĤPQMlI);Z0+Ro Ʈʰ˹ɜɡ<Lm ~@@2vNxDV̊l2|k:y7,|0= p&VŨOʫ,<90ΆhA)ƨH5J Mc ٌxڶ \3KBѠ}A'IΟ8l{ΠéΪŭ\4]6(*},]Ѣp;DNzzK-kӥ&ռՏ|hؘvkx,k;`gep:P}v}xikzp=ͺD*蘊،؎؎Ypٖ ZPSмAz{Lک A`*UH xL]ۺۼ۾=]}ȝʽ܊ڱm٘Brܱ9PK݇Q}ن @p@PZpH=]}߼ٻ >]cx "(.Ʊ;*,.0JK -:<>@.@B9HJLNa)phw\^`b>d^f~hjlnpr>t^v~xz|~ib{[H芾1F^~阞_i1>1Xa`.01>^~Ȟʾ>^~خAm:i^~0)A˹-1? .?_O / *"?$_&6R.s0X 8:<߈ u rpN PR?T_VXZ\^`b?d_fhjlK*O02+g /l~N_ ?0aX*^`r0 q`dsO_ݫ*aH ?Y!?/ @o ߮i0YA6r:srs?_\)_r ?{K5IQj (018q08@Piya *:JZjzJ*@+;K[k{K!fYl|  za<( `3 '777ѭ8q_(0r/o8m  )Y&-B0N\7p:F ,gxO%JjE~+JJJu6yC^b,(#cRe@ \fg4'un2K| XRdB(\ "|YfAZ "n $mKH)B5G7c,P3jAdH]P W.-(  z20l28e@>lPA >= 3.#k/'" @6*윉 hp9@c0' lS$%؅d\!,jYV[{ (\ 8hܱ Lt`e'H`|eU* M"D$ nIU2y;6ʍIԍ_0xP\D$!/&,&g)qD>q?OYFPx.`b% w  tUZt:P] >i}` " !`XD` %`A:p KE,"S|5qA65qф1퀪XW5VKԤ!VZQ+UP&8’ `dS dJqJ)0&90COqIOxMsd( t@^ h8AoJa" ,& pM '9V(5f2]HFk `$jg!0` ! B0'{fjXL%O-bRiU<#2Z"b(6Q- VD@~JLm' #@#8x$4B;tέ"HH>?$ *$ZF >UQflWbmR K^h5v2 GXFMx`/\0j,,^!p`4r:e@sѮ s2VjSZD2eQy H3ժQC@|<,dM~r)v,2@l\wxbhi#Y /' e*'*:uloSղ 骯1RKOGV&̻MP02V= ܵk_5l1'8 >5Ŏ\Td)Du?>]77{=X>ƂR EvȑSP`aQvaFq[.+%a#7@fNg&~͇Tu=SA){3M爟Лƒ4dϩcTCK\MۖL2@Tԓ֊,C5z 1:CB*ćL;@XEF1hS{hεA=l~ƑX JA P3\͝v;*4w*\~^gy4t!.7v*zzTd"̻Eg ;@׾2B[WsGRA|m *,d+'1ر(m7b$mEA&~Ele{p6CC5Wz wVszfyyp5Ghl@=D!(?l{6|Wb5]}caPp7hkv=7>E#cG#8mPP*Rd[}GwH6c  chgilm>V&*H| {s{cc6nvI?6nXcZU2'#~UfeOH&XowH1 cx芩8؉lpF|}SsH4XmxHAdChc;&~8<֌j/,X2`@~f[H討ȎH ȏxd(?Ȍh84\T7UHhxY3 IXpчW%/i )&  e50ɓ=I A)CIEi }KɔMO NSI2S4y'f: ѕ9Y! AcIeigih + _it k{ɗ} >֖gSPm2  R`}+V}0AANvIIy )IH8#` RD0h?Q!Pb@[7Y虥IiljfyۅA#0v|X& yÙ )y ,DRkVDǖy[\ɟ *Jj ʠ  *JjZ[49G iƤ]B4VguDٙ]B5j79;ʣ=? ɐ4 AR3q(b?9PCAzy :Y[ʥ]_ a*cJejgikʦmo q*sJujwp13YB5"@DPy=-`nʨꨏ *Jjʩ꩟ *Jj |>D5 !#p ҚzqC૿ *JjNJɪʬ *Jj׊٪ʭL]>q 0oCJjd*ꧯKk +*v殗 q+k5 ۯ媱>E!K%k' IӮ-.ۜ(5#z.2˳=?0*{ 5EkG@ǠT ⅳN ;WY  H G [ LNP?Pi9N#dKukYӵ/a˷{A T붖D]iY˸q}c0TbSTS kXK0%KHkkIf @^Vb9+kZ˺⺯k{@ h=.l˻K+߻K+UqDJ+qW!;k| +K~떤w'˾yQ5+Hۼd20Z˾/VCK)kvE뼏 z%p#GkS!CL*’I:3zvDrbט* łac\el9y ?ÂXPBV rVwڲŅ Ƈlȉȋlgȏڱ.1 M!s"֢R#$H5'bd|ȭ ˯,ːL˵LIi<LHɀM 8Ü`XĝLl9l }4 ,3bةl`l眱͖G $#IL.JuG19YL’g"]`/Лǘ)RJH TM%SP[;1ӉP&XIЯqNJ;1-7mTaԬhMm;=D'`x `& \-K[]ջfmb_}N  KQRTM!]^h~%ր{|Նb׏LQMٕ=v}xz}ՍeGdץ]ڟM؈؆ ٯmmٳ]٘m-! ֫]ؽڨ-ڦ=օMܭ԰ܤ(۴MRƸ=!z۪qؾ۬m܊-=۶]ҝl}oj=֡؜]Խ߹Z]=dMͯ M-ꭱ^u д^]#^ >K\Xr"N/&(WXe];?2 ^&&2@ >ONBn f&  } P.,ύ2` @@ {Œ岒y{}.Nn臎艮N=\A o7O8SJPKNf{A*Nn뷎빮돢Nٶ P \0K0X+3y}eN2U.N> 엝&apJ!ri)ĕEbnbgNo ް !=v_P>JGü/-S'?i o')+ [{[`52v_p4!*Ma>VF_S,OQ/S1A&Ygr"դ @a gl]M"SowyQ1Y Y0-76&@+{}? M  0-@?bOo.z;mRS-I⩻ɯ>[ٯOϯѯA Տ/&/?^ }_AAƶϊؐɤ H&NJ#gGk@TȱǏ Cɋ* F\4˗0ed͛8ssVMR( ы3 ɴӧP[)Cv Å tUhӪ]˖YXjmx) w_ҳm Lԍ MD3>PAl"6̹Ϡ*^l/3фG%Lfиs޽SCZ=WVg[RNۨmeKN]K_3`wqfޑ/`B" L5/vu]hvFp7  \lT@ y^U~v4 \8M 2e<8"dE@)$S]Ubc(0@@&y4W92@HQ frl9pNWd\r!I R+vAT#yQ؞#0e6`hF 飘Rfj)-m稤~6\@|PxPVg|hbtT"fF*m Kf`g$gKpA+F Z,iR*oTf-H)L.BJ/ ^0pOb@ZɃ[&V\ovlO}LZ(Oø0˲HL;b<,5%*7m8?]\WS5`YE|-lIPf͵mm7~oR}߀wD{ݳ߁'8"V5ȆG ЋWn9ĪBw.◇.NS8$ 0痁>T:=;: :_N5 <'XL 'E5#=KX Gr&4*Z^S3~40< %pFoL}2׿ ZcL5w  @*)@yqgWyalZ8E s', C0g io >* VpDl[@B~ '@ (0)X86Ʊ/@X@B  Mh̨$/q| & 9I؈3Fa00b>o,B\ 9Cp~s2,jF3z&4Gš0դ)*CpG`)SR'ԵQ4+ Z֮5w` c(0̔aZ$8,5\3CVˎw bI^os ,I ik\~MoSՕu,^1rKf8˔Om|n20ڽ9@8 Q9HGT "(Rӥjҩ 7,u1ObB7){U r {;a̋;+yCo2!>rk'ߕ.q*G.6|Ђ4[L?T@el+8W>O=?nS lGp ؀8Xx؁ "8$X&;pw` 0284X6x8:<؃>@B8DXFxHJL؄NFEqǂ-}'\؅^`b8dXfxkgWx IrlXoq8zuqnxT}k4(dh83@40ൈaHP4?8,@#)5`4@[ +0,Ȋxc( 87p(06Xh^mOah\C87Ћ,-0cø]P#LQH !()0)希鸎8pQYy2Jɑ6%SAVS7#" gc5Вh.1Ӹ, ٓ1y‘H) 554J&M)CYwhVi2)X 6>9 ByI {! KP7t/$}9*θ^ fL*E1Ci TZVzXZ\ڥ^`ڤbAi'"bB!p-lݤoqzq2Y:`xzק p<J *  jP'ڪ* #<%[ Rjf :P @$u V5V`y* >  I%֊[XpF2 )*L[5;ɪz `*L&W NoPPC`ŭP {O^Z4KUpS䫧%>+OJ+*O[i5XqQų?2:kO M 𴸕(Y'W5Pdr tKN Z۷yBk 3gk xn5+Iڙ4="K:  ജ{ZB ;p+K+2ۻ {ȵʊ$hΛŋ(h[0`۽k{J`;[rrEʾF8wkpؿW|g܂|`d|\8vlb\ }"<Vxɗ*`,<.z06X\v8_:<|d>84VF<^HJ,bL6T\V܀X`Z b|ZdfL_hKƑ plWrt]v|[/~,R|{L]\tȡ  Ʌ%LlJǁ;PK'q==PK[EZF&OEBPS/img/rules_test_function_out2.gif#GGIF89aX}lvnyl+l5v*n!q!'n'"r$:q:Y]YGtGUmUnnnuut ""*,%(461==1:1\5b=n*(ѣF"]ӧPJJիXjʕ*F>CX=vу(ɕ;`#HП@ LÈ+^̸ǐ#KL˘3k̹gπh4Ө")\"ɻϟ۸ͻ Nȓ+_μУKNqOmzFbHqáw˟OϿ(h&x |F0`>(aNha^ana ~x!QEAD,0C 08CF#>ޅ'idHƦK&NFPR)eX^\f^ _)dflo r9uD{p = tP &lO 4pâ9QNjV饚v駛ꩨjjꩡFD*kjkުkk*lkll.k+DQ'{ UKà( 0P|k#8:jC:v+kR)-9\Lp!(x `Px2S ABmq k2"L2#r032L3{2" 98sHͳB'OG RtS;=Bu`-vdmvhvlvp-X!Ԓ *w)R(p"J(S%xA 6!8|v碓飗:ꦧe5];CXo;+/<;O_>u O?߾ۓV7Q ⁨`J Mωl׽l(>)g_è=bыX4cƱ=?hop-7mH?L<.r("b {D=THJZ̤&7Nvfa?Pnq{;EF@#!K/:֨G=A[ɓ 0Ibi0J[Q\Fqp4!  ~a{c \d F/`\;Od,>Os (@ς Ԡ=BP:tm(D'7\&H6c8oʀHЋsSB]jJS^)HMj&y29PeT2UYudO*VJծ^5^ݪVE7z|\LQ|L H n (B1t89 c0FNX ܴ+ iOA,V\1*ezH5+3MGͥ j])W#> IE#Vq v`Rl< ո5.r c*ebV6s; xK^~OQÁbq=\?y; V*| hbIT f.wSX\.l ؝0M7⛀xĔ1eICLRR"aH7cs@LdGd&+P~d*;HQB{U vhp;رtChF qئ3@K8'^h$эnk:h0‘v0]JXƠΉGMRԨNWVհv5NZTZֶ5t-]y־b:ؾ6qa/ٽ>vl?o0ŗU^(2`&& ";}#}F3|&H E-r9MhE:0 ~'`0 O`8{ GN(OG(SܟD&`'@D6 X:!uC.!4MֳuZ_QN{eֽNa@)ˎvKX.q?v~</~O; G(Jmy/; ܢ!$H _BKHfoµ=ڣ]}{ցov>e/~וwE>/CϾַ}s_??~ߧOۿZ@ykuy7 y?< 0t+PZʐg Q'uA{&2|qG05`|S災gv*8%X|!u&)1(2{,؃>@B8DXFxHJG}'GX8Zx[h^`Xa\X_(hH^ PsH  ?7r+b"M P 0% w FHEPSXhSXvFxɗH1X Ȋ(Lx؋8F` 8C Pn  %P!-FN  &R!8 ︎(ꈎX("!2YhI i!9"p P8oX8P h?ȍ,}$B",/) Ғ1 Ȓ7-ɓ6I!@93I2y9F1ɔG9P8UUyRVٕ\[Z9^)e jٖlȂ @ px zy З0 ֈav^ydY\(h阕 qI`f9遧IyS9鎖Y9yɛ 雲9{ө@iAr(Yy虞깞ٞOـ%PE*r"$)~}쇘P}7~~هwzWl"Z z$#&j 234z6j?0j=r$ X)1p 'blQ>cdVTZVzXZ\ڥ^`b:dZfzh^lڦnpr:tZvzxzrq**W) _'pnE69J#zک:-Kj1ʪ:zj:jJ˺:JjΊЪZzߚậ0Z @!pGqگ;[{ ۰;[?h6Z۱ ";$[&{(˰j)02;4[6{8+[->@B;D[*}mT֫:S Z|ө=[ʨl\-`* VUX S`.b}xd{WPb ,p 2׎رӠp R @ @ ٢=2QQO--Kڴ]%kz0` =۶ϒ Ҕ   @ݰ   A<][CtzLޯ^`k  !-^ $n#^(',.+0n/4.3^87<;@?D^C^_E|{LNN^}{UZVvM hbfќp>k:MqjNNӭ|~g|ū9]PNS閾X.Ʀ~.颎>.-ԧ{[޺>^~븞뺾>^~ȞʾΎ ^YK־Q:޴>>鎯ھힷޯM N.ɛ͜RLϜ>\Յ< y~vnӁΰ߱  }#\7&N*V]\^[IFVo\NI_YmY]^Q1ogmR<ίC5}x~s΂䛎v^_E/EՁ>RZ̚Jn:o>QoH_92_<ϑ08Z=?dcˏ_ў^5)|0R~?Uk W@&d@ .TpC1JpƆ=H#G''<"˔#UeK6IyeΗA%ZQI.eSDuBÄ'(: iV$$ˁa?Mײj/mیt%m߯dks޸h,඀su/ao+G\6E&]^VukW}cϦ]mIWoU eU+WwgsO^AF>4uŏ'_y+n?{ϧ_z_': ү; pAtNB 3pC +  JAK4DS|IC=cqF#qG{:q04H$!GLI(r%]l)rdRD,sL2J0+"L6tS3sM:C&R;S55PD\E9LQH#%FRL4I3S67TRKRTMUuUQUUXcUUGeV iW^{]P0}vXXd=Nul/Uh7i-k6l9[r--QUwݤХ]x=v֦}U^|u|-wZ[w`k aUxކ#&f%Wfǽxc\3և[CcE69QOVԔWvӖ_јgКoΜw͞Z̠6zʢV:I5^i(jހ֚GK {.vjFQlmnfnoo/i pҳV|$r,|4mKOtMW]<m|ucyڗgvW=zKϯ~s{'?'?q/<}g߇?o篻~??molX@TS@* 4)(4 ^gԠ8A}2]VB )4 Y2pc1hXÈ C A/#1^IT"Du=Bݻ*dE/&, h2 it٘,7qbg\HG@~)u`!ȣ$aUIK 4&92G3 (1XJSn*YBW iYK-.aK_2hZd098c ^y]2OLgJ l40k^s`Ԧ|}8e6?,:N+MxjH'I~g3:erb@P':4hAIsZtV99F ThR([ٽEdf:J=Գ(htYjYkW׾65l9Xmkq+6npaۉW«Wm3>Ln[]'vK]nSBC\ri}zBo}{_Wo_X&p |`'X fp`GX|/xWK]Ña# !6ԈIX-"b[gG2$d)6}sd$C&~I^d&?SG? x)A.r,e0GYP24=lhgZӜxx_n]^Iu>oֻ޼sK6i>M߷_OG:,^]'_Y9߃7M_~?ܹO:z>?__GO[?c@,ct?tx L@ k{P=@0y<@ ?@É'GG B>)EDyCEH5ør<| zY@L93y'6 X$zN1rLhOEG)((-ю  HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz4jXJֲ fMZ*3I \J׺ h^W(毀 `V'uS׽:6}\Ȃ ÿ6r1*Ԉg5zd-ހ!d xC0wĶAt+ D pKvò.qa8w\Sͮv/rGA-AE[P ~9EP;GW 0dnBܡ[8r`"w}0.1Kŭ@8 BNt އ׽-IE{ol/ixTA$ d>H# OXY 4V7.sy1 /w^0s [PP p bP6{8|ZGG|QWX|lPnu20uJnG epu|De nM`uMu`n@PZMB}a}a!=s@@H T@B pGHZ@d1M@9 4Nq]$_T9TK%DOAaE% v^٧nCVvxƴD xqjp ؐ ـ   Ȍ ͸ 8`h rG Pp @ >ss H|G`nKn m7P ?ta@hn I)ЅV7mHkƱjtpXwS=8tF  $C9M~v@E$;/C:$C4ԉ40=3 >CpC>F$#Cwȃ! 7dgx  p _ Gy p90 t9 5[W |ɗ@ }9З }Y ֗l@fPePYm =G tBwP P|YN ך) Iч|鐵ɚZ( Xe #IX9(i CHzМcTM|Ft4i=qiH9aDٜ@ٝ'cwG0Q%SIB iBV {L p@ 1p  p ^)Y* X-8{)3a5 P PyE|BOGGO7ngV lh¤G}!i-Fd#^Dy)~gicߗߙvmĞ%QmPOQ9y}% cht w_Pky  0_W&** * {/'1: @ z{p pit0 i Ch I( MtպFP@|ں:qi9;ĒK,i3}Qhb?CJ=KFJw9و4K+cP ~٬ fx@yx@{`j y 0 zVK[ LZ Q`L; )P3(@p ̪V٤AXby|yZ0l~|qؚZWw@nfX)Wy&AFMd@qGiM臃X9/tNTHȔ4@;{9ߴԉ3*#%mci!pj8k۩ۀ8Vvh  С5[K盾`+ ]7Ge{6qV[ic] pp { $܀jpq7mག [lV쫾b (p 5x yP%mKZ\/b(J!, G#k+kq AywxPŁvx{ bo~@*YuȌ=,f 6u0@`\\ʯvκŪ]Ub mg\pTL,Jm kʼk`<a !Z$,-0D]F}HJLNPRV}XZ p^`b=d]f}hjlhc7+t]v}xu-S~׀؂U׆}؈]֌؎ؐm 6-ؘٜٚ-_٠ڢ=E]؝}ڨ}Ջ-٬ڮڮM5mQ۶}۸ۺۼ۶פ== ȝʽұڰղMӴ؝ڽܝM6b P]m}64642} = =~ ࢝.^!_^᯽2^&~MD .}b48a @"$F~Hn*nE0P2~7^I~徽g[A`NCӖsf~hjlnpr>t^v~xN#~m6r ~舞m]ba`>/]~阞难霎KN V:Ꝿf㐾>aN.m鮞뺾KM>㥞ʾrN~߶Ҹ؞ھ:>>~ꦎ(ܞʮ>׮~=_8m ۲ ?__s_ $_(,,/M:2?4_68:<>@B?D_FHJLNPR?TozX$")'bfhjlnpr?t_tz|~?_o?_Oa[b+(+c/aeo??įY\%^?O؟o_ǏWo_#(]' ""տ@@ DPB >|D-^ĘQF=~RH3%MDRJ-]SL/  SΜ j4QEuTJZTV]~%Xe͞EV-WݾW\ %ěW^}X`…k䙘OBN]Sɔ+_ yfb9ZuMFZu»~][6EõmƝEyrTbJ]/Å\n,6Y-V^X͓\uh;f=`^ cEf6bJtZ;#Lup ̒?.HWL5 \jf|c_~i}` "%Za`2aFz'8j3j㍷*ۭHNe[^wlQM^Lb,-6ϺoW~gRn4D%\BTjǟ r'\k//k6{eOmKmFt9>۴kշ|fVh>8aqD 'O1/tsSs'=lUtr{]nkW]^w{} xgNuCzʨEm;`ؽu!LܐyN7o%;}EPqMka(EáC 9GL\C?6qA9", ZA6fD$vQEJ 8ƎDь!K%,эZ0ю7'Nmd29Od9NzBg;9ЁE= Ёs1D(h" 4(EЋԡj(g&RY(IѓU)ZFSL)Mқԩ)49j1yjTn4KI*T+ԅ"Un\*UԌ][^-VjU 1b#W:4EEV̝5HT+]Vw\1}y,R)"na&Z adfk 60UF,N;Y)N¬RV6zeU&'UFvV-p7[)t[\v.p tcΆV0gv"S:+^mҥ.ܶ_vmO) VXeDI"z^>wmFv.ejf]-*^$xe0 0N[4Lctd lsX(S+ &2`XhqE/ nY.z[L6m9-ޯc8d%2sxLCsBLWN+ o%xkC"^]WN4,-+z4|E6Y[kj8zqCkN]VuY}`5%6$vmnw[e=nrFwսnvwmm.ͦv]L;ߩUMk|ۛ nKu.߲o;Sj8T_<"='u_ r\fŜ{d%/gM͋|'y4Cg55HŝNA^uM?GAӬwUwӌe'١v W:oEH{74}-ق_1mhiTmtiy{ _/D?Jٜ$,/߇>z{e};sl_ၙx8,}Mzj|{A+_ ?9v&aU|+oL`m@=> 㾭0=|Q@-3s23!|V[@iszBsC9 <돹?Ҽ ׃ 213>ٱ18̙B{A}@0,') -vа K.# $@k 2$#كB;87B9¡BBB5 3@ DC DCA 7 3+?KӐx< >C>L@WѰ"CBS44E <=ԀD;ė -$<@IEEEE% Fa@&*cdld;E(M,8= ;=(,8%=:(+]8<:'+ 58!<":#'$+%7&;'E:(')u+*7+;,:-e ,ӫRjKSS#t32hӤZSgS{SSp :.S<==->}?0/4Cƒ`Tsl*4TJ݂+uaAcTk"ΙK C),/S'H1ٜ~BTaSTԑ-[!]-(U+Ȩa=U]dյef8*VzVqk%Wڊ*`% "p,4DR's5te9u8vG.x{K̠1 WZ'' pb2WCXSXcXw-EȈV֜}סX()BlZPkي{مYUZ չXׯZ(&PEZIEXWTmYmXmذ[Hگ'0[]$(tzDZZ[Z\ ]&"H&@\5ϒHKj,\>\~{VD[XoX 0]%H"X]b]4h|Tk'"8=T%饶m"E25u6e&.]+%25=6} xfG&FETd`|`Tt ^ FL F  ,af$Kaش|!.K#^ Fb!.b%&K(M&~b*+L-L+bb/F0J2L06c45~J7nL5c nc9^:fJ<&L:c>N?&JAL?& dC6DJFKDvd\dHIIKKIdMNIPKESFeTfVvWub߲B\]^_`a&b6c6effvghijkll^dopqFYZ[&ufvvweeyz{zfx~g6?BgR6Fhp|fv臆e焦芶h7h5^&VipZMi\陦ioiilFޠ-SFfij]،MhVin~j&kj XޝYZ븖vkbkkakk_>kyMkY^nhk{~h~豖l\le^ۓui+h*hvm]l͞g̶mmѶ۬[6lVmƞVlfpޖvnՠ4ֆnnn|Fno{~ove3W1nnk^oNo>p}.pNp^l^#3xMmp1kovp_onpiq l>qmNnս!Jĭޚpogo"wW#m ol ϢlZM3Sqp$'q&r%gs7k~Fs܆;|>e'n&/5s`56AG89"IڒB*stCpNfDwkO q:G) z-ttPfRWs[fQ/k\gvtc}sLZuhfv~]hk_lBiTuR#Mf/gsiWwFv`' u2wwuwwwwc|'xfw~ǜՆzGx'xVx7y'7yKxax<ޏ۵kyE;mW<ғ__Z_aKƘyƚ߰7׵ߘ*o045_&/Wkz P+y0O)sЁx`;_/3@@X;'.G3ȏ(|,}6z||}""yU7vOS,@@ ?㧱p 3$G;JZ,h „ 2l!Ć hbEP#Ȑ"G,i$ʔ*WLR$,cG2wD`@tF 3hXQFĨRRJuAH:yr+ذ$j,ڴj-=kG/IoN a#.8`^}$j` 'PPE  ؒ.m!V9%n/٠gӮ]-܋r;[ޕZ,x8W'g~()=!B1D l/_5u׳w{h_;wƍ\erAހ~=7Rs`_u9pAPx`7!^xWU&"jPm](ڸ)%(q uINpaQGp7ZyH*V'%QPɘX9R7-$;qx#gB8١x]I9*R' } lcU&gy`) إvY$Zzr(zLFzZڹ*-ʨi)VN+)Z@@A:Dbފ+ibī- F;nBv{n]ВԮenՈz nZZ%0 ;0K<1[|1C{1!<2%|2)2-21<35|39w<08\ fЃ0V[4%<lq۴kDc=*][?ROMU-kx4q+E-|w~u-x,a}m.Zi_8XmS܌N.l?^K[~zi_88y2;k5;k8N&ƫv DUx*t`WA !IH9/V+ Axk&aj0.24қfR)U1S⃧-1AK_b O'4D1KS@,bV4ŕL)0 *P%+%&T):f̡~+_܉N8HEȊmx(`QBj$@)$`WhMꖡVI*rbQiHq\{!*ũY N b5SUz 4c-YӺ֚.4|$־5-Es>6e#~6m\O׻m˺6-qw>7ӭjڇƶ-h{7 sϻ53?37#.qE|s'+!˻ۻ3Nǻ 9-rbңljϮhr_ -v+A;Kb7:o7vI;/;)<?G^цg5/Ń^َ<#oꡜȘC=HHoc'w{:?2~N~t|V{7|6S 7v}gxitw?͏WWzYW5]S Z}Xc)Tt<`E`MYZBM?I`  ` ԍ`is ͩ ^&]UTѩ]\"ҧ$TaΡ!!&a^ *ܽ!Vա$a),IF b&Y")&&"έ~*f"%")b,\/"00#11#2&2.#363>#4F/]E 5^#6f6n#7v7~7E[9#::#;;#<<#=Σ=#>ޣ>#?=R5^\AA$B&B.$C6C>$DFDN$EVE^$FDFl+bMGc?H$II$JJ$>zIt@vDF֤M$NN$O>T 8P%QQƋK&%K.R6%S>SF%?&LR@$VfVn%Wv%C&X%YeQ$TTZ%[eZLW֥]%^eB:JzP%``f~a%bb&&cZD_ 6^^N&eVeV$>%avg~f7b&ci&jHE&M^&lƦlZf &d%hn&o&ppcڦ_l&r.gVv &oFtN_u'v^p֦qn&r2'xxN$wgR'z'Qjvf{'|gqjfUd'~g~fyz'5'Ifk~~6*'_gN(%{("hnT:&&]>hee(bhr(jhEe}}Vh(vЋ()iRe@Zk(&Nh6鎮F)[ʥfZ*Y)))R)J}橞2.)**&)i%hL*V^*fn*v~*****ƪ*֪;PKX)::PK[EZFOEBPS/img/rtdt_sc_gap_ana.gifZ8GIF87avcccBBB΄111BRkﵵνJ)R9{k{έƽέR1cJ{{cJ9kZJ{cƔZ1!cΜk{kƄRs{ZΔ޽cssJ1sތBޜZ)ƔBk)css9|ޥ{ތZ絔ƭޔZZs{1ZΌckkJRZ!!!ޭkkZ1c1ZRRRJJJJ{ZZZZΔk{9BkRB{9s9s1kcZZcssss{Zc{RRksssޭ΄kcccksJƵֵZk{19RR{9BZ{{JZZZskc!19sskkkkcsRc֭ssc{9Bk{)1c{k{{ƌ{s9c{)19BRck{Rc19c{kk{{JZks{ƌ{s{cksZk{9,v H*\ȰÇ#JHŋ3jȱǏ CIIR\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3kYjϠCMӨS^ͺף;˞M[ssͻ NuͼsqHNسkν¾˟O}( Zqd&A *N8*MR- Ij8$B`(NZx# fXyP>$X\v /axL(K)Ud[zi JbTZiiY։磐f",Yffz塜i*&%:驨B6!YUdJ믇l*I蟄dn"䬊`Vka}hHW!* ~+E.n֛8,lk 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmVgNXo5n Orb0u3vn4F N00l`C/cid9l,/K-MT}ؠWka{M :.L|z9Rf/sJ&ˤR)~3Ձyl.`}Kyキ"9-%@D (hHx(Ⱦ |b" Wdwt0H9p @wք HYĀ0"7<0,|WX̌ 9dž: aCΐ!XC&/R<=x5'b`Y:Hs"A Ƙ{8"1J-icq"}GS"!W $$&s"ntI6yC, D([It$+WO`dp˙2cIFOB,Rwyrۣ3eQ”TAy (c9ALJ)Њst[Bʼn88&U,Jv! t;MP9\w%r %(NwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp@׺x+K׾ _d@-,MػtX㲘ͬf7k$, hGKZXaMmiO{ظk$ʆĊe97`e nQₖ*iqܣ W&qtKZͮvr5BmO)0\KH%Hcܙx%I~[ߕ얷}~த)i*;h.`2@"3AK(wGL}B~|Չ^H /NI{$KB o)\d Pn-B&t ޝ(Y9]: vgrv&|)nztL j-7՜8e-Z:Ak#؁ 6ʯarX@VAs ɩ :˹unx (^`U7]TUr'_g^(ɲz ݶ9yt"oZ:Β_I:50︭A/5 xS c<$-7@.Ayk{7'#(C} J71'ǮvqZvA^]OڱޢdPC.ͱ3̉Sre i^&jq]\ [‡ }xP)y.!:ЀjJP % 0kQk=r^6 ːr聲r #8f(s3Gs  )wszw {Wt{'w]Eh] OJK||}2lGz}0uuu]>-1~d21?2FF*@pH{g$2_w5+ x {*cґƀq F  ҐhP[m0 0 3,y40 @t :؋=H_rh{w|B t|G{Θt˨ ` k`|ȧkЄ'ΰѨ|H Nw{'%@'؍)NhTV876ATJ :d>O  WD6pȣ<EcAy}pG#O) iM%SFfDC)F;duthl4(Ĉ4aBd 'xk ͐9 ̀hpwWЕ]^ ЕcP70 0 < @];(Ȅ҅O8t8t`'{)aӥtYtHW{pDU ~tDbmMwTO~ƴ>dGHEpJ:ItDf> NEwGRDEI2(@*. r97)pFC7P ƀp 2Y   `Hwe cy  0f* qsf 8 0 A'TGmi:JDžs}l}DrJ2=DIIlC1Y^z6pcc;y|0NPwP*@  (iɊPzj cf`s< PP`Js p~y;JćAzJIڣØtNx{: 슙iO(]R[ {zdjcw>cJ}GmjJI~s~ԝ$KK WS3L Gw}Qh3UДN:\j cId9GkZ` /y'@ {P { Ӛ jЕIF> pPxekta0JQZ:i|oghnn!{:ųL Ht~ Դ9~#t#A4E}LI~YKdMش2!uv/#+icSFb+}` /kYhj0V)p :W扩н+@c潂 )QPK @ KX+؋^ `/ 阤ٸM: j lۤie{lFʗ ܷItܸKPQx٨5y:{dAkOO 6| {EdBO$I#:I*3n4Y*a*iG}㿞*YkjJ hoW|,{ǀ,cȟ * &0Ȧw Zfc gIbR8u* U|R|o;axhZ1Zh9p/cik|kP^^~ 0S ^~ $^&~(h ,.⁶0>4^4.6>@B^F2~JLANV~XZ\^~b>d^fj]lpR>Tv~xqq)z~}!n舾Ns|u>阞^|}~l_^.>n갾>>u>븞걮N~^vn꾮>þܞҾ޾Nw>{7~) _$?_Gnf _&n*,.0/(/s(<@=?D?_L"SR?/VX46HTbGI?hOefnOh$tYx?5Au>_<_l!6_X& ?Dq+'P_ a? ߋwo1-/&A?aؿSS?_yY/x@@ DPB >QD-^ĘQ=~9 DRJ,hSL5mL@FN=}yPC9hҢG>ej4*RD )P]ADXe͞EVZmݾ2uśW^}X`… FXbjIdʗoR%̓/:W@j=jtV]KZ+DKVn޽}ޛ.cōG\r^ȒC[Gv3GƽJî*)Kaw ^>Oǟ_0@$h:ɰ̳ʴ{03 5sв,6<:=л**Q*ƋC/Fg 1GwqHӰ3(`װ9 NNHE|-\D6ԥ}C[ Xэo#u8npqvL 6  D%@d\2AAŘ}1n3 H:3k̞CQJ 1q|gv~}~&hgӲgf&fvvh.g?+E]fh萆g~fƗuS6ngvfe̝\Bfiꡦf&iڭof꩖eniꨶjjj餎٥޺sj``nkx뮎k똨kvZ_~&n>if &jh^ Ȯh]mlR뮦kj&цFmiZݽZlS~l׶jӶЎj^mm~j@TSq2mjmNmn~nѾnҎ.-9mԭnŦfo^o6L<WrC1-jvoNN iޮhohL,FlrS^ʊ:cnv,?-/N=V_D Fr%ok.wn/o0oF2YDL kns.tr sлjD`^]L7#tNg,pfsP?tTGOWuy"unuUgYZu~u"l;\op`t\fO2[aCfwghijvhu Kaa v wJ*w ;[wwjzwݺq]a xۦ}؂ϺϨ|w0/-0`Ne&s=dxoxshh%c=kȁXę?0y.zV*R CcXl4YX(Xp/zjsp7CÅ7[&(耿\t<1$JS|@P`h p|k_%{FKLɷ7][\۩>D{8mD}}븑GtI2فԀ ~[q;$}:~v77h ,!Ĉ'R bÌ Hp  0@P$ʔ*Wl钢_Ҭi&ΜcJl'РB  Z(Ҥ @RLRcƄ2jExРOb-*ˋg~x!Ȓh+޺z򽻖/.*-ӨߴlY^!kf%3vBg)>[AntUD֜aӞKpRNc`C#$.xE<>P8aYZd|4omGu'>([]ndz{`~ԀG D{eւ砈%>"y!,5x#9#=#A # y$I*$M:$QJ9%UZy%Yj%]z%a (cP!kZ'mev&Iݞg|ʘJ9hUv֦ vBW!()ZrRUԡFAy*mtzh+x۫/,6+!*uQO߂KѵqT[:TҺ++/n[0N"\|V\Ńȡf<԰û*qOwRtmRt//J^r.TM]sMB =-Θa/hݚ~25Q'eT4a-?]ua6N>K[if̰Ɇpׁg6lUw0 r8⩑Uw9C-9\M=W8wwsyߛ.ۗo{~t;>mft[㎹=giyo|S6[՝E-씡ǞϴfrKoT?>S=-/E3֋Xfs5(Dqў33Nfk&Au@[_0B}y#!s880? RCp<XckGAok\ 6/X&™pxD|a n!6AwcFr,Cx8fr"ѦumG8ɑy80lhHrI4JGDke y'Df+8 Ǿ!'h{JMO. ['6:;4)j2lLgfVވ6\{)#&d^HIJKj{5fzih 7jKik  +˟';E/RiiUC:)JSҕFELc*әҴ6)Nsӝ>F=*Rԥ2N}*TUHV*VURu^*XU XӪֵ]m+\*׫uvX** x+`Z_aXS|e_+*,e-ͮzl"V=]MVճDٶUWmյ-drժn{ۥ}syЏLCevZ)ɝvË໬oxQ;F[2$ yW[ߊܷE~)_H)5| x"VO`<&#R%ؚ.u CdĽhIŜUCXLYB na\ś1x[cB^,  Ǹ52~ eJپM`9S./eWW֥SV]-\fGV>m=Uj.) VomNF/:ҏ3}No:ԟ.S}V:֯s}Sq~ f?;Ӯn;.ӽv;0e v S ?+X;E.<3sBC/ѓSիcIc2:W7>/>ϯ)soӿ! ݆M_F2 fn!% ~Y9 `r ` ` Q !]Ѡ.%>!F!Q n! @!1!J!^ReaơJ !!!Թ_!f".͙! !$>bJR!^"&^"2"'vHb$"(N"]%>`&*b&z+.#,,%Ҝ.)=0#11#2&2.#36t1a-Ң4F=Z"/f6u7~#88#99#:7R4#;9^c#=֣=#>>#??#@@$AA$B&B.$C6C>$DFDN$EVE^$C@@;PK0~5_8Z8PK[EZF"OEBPS/img/rules_priority_named.gif0jGIF89a] (((00)KS[be+i,m0s1t4s_~pqAJ NPTZ\#a(c)}~e%f)i-h$m0i%n.r4v:|BAUVՄMׇTֈTًWٌYڐ_ڑaۖiܚmʽIߠxb{يڊ܌ی܎ݐْܑޔߖ杳蚽ӣӥú½սᦁ⩄㭊謅崓绝귗鼟龣ľۇȻ̿ĴĭĪʯ˺˴Ϲзһֽ!,] H*\ȰÇ#JHŋ3jȱǏ CIٽ'G|[I˗0cʜI͛8sh=,w JѣH*]'J޾1JիXjioQKٳhz [A>pʝKݻx˷߿ LÈ+^̸ǐ##.[|i̹ϠCMӨS^ͺװc˞M۸s e?^<Ǎ#_y̡;N}uثg;{~ɫ?>=㷟?!Ayc[` .`>(aNha^ana ~(b$hb(b,b0(c4hcTq>CD9E.$J6)eT&i%W>\NeUb)^=ءlp)tixwrOdejf`*h.裎F(9 p䦜v駠*ꨤjꩨꒀҏ?j뭸뮼+ҺJh6FKj]7vJk@*Ŧdϼo^V,<<#|p /+q?,clqoq krh+s0,s;O<3<9,@;-$0e[ . u &XPKV-t`3qboh+\plvp-wtmwx߭w|w߀=N.37ۊ=7s/& Ăy܂#r!n#bG"^<$4m9N׎lӵ<NjQԧ55VAK1R~yLCИv3º=4D4/Nӆ-8A BmrQ+_FjQ ;K1c=yo6ԋUfh8Ze*T m(hѢdhF# ["bu$E7! GOz,+^=u.L4:Wht{Irרr ^PEy͛RⅯy;hWU.g P&f87 h!j^UH&[W?L`(:V׺2 [|AڂE(.#* - cV5=CsȕyOtP~fr@QC{.km|<1{P(Lf'l>z~QaNEg9sTs\.yN~c |-jQ8 i C ɧ抺B=ɧG=jU?EuMָεw^׺Dl˚Ä< 0ev0l\;FDžBPhv8rXvHU wNֲ P-DY 5@ {%qA0r phdٲײgf٬ENR]8G@'ZП23XЈ\C flEs0=_ kc?dLz}0.` J]ZZ5Y}ꮷzղ;_w)m8G4 lhK[dfADXo20Ùr"!a o8Dgy`9   <>x/)6?VxsL~t:`/PW__gޟ>/OG WHZ'?LK/Oև7}&GRGb`uXP uiuXhWvubvhvw"8$lr_`ll 2WBŴm>wa{{`pW68} dM-M ̷MMM4ӷ``@p~T|p7C '| }ȧqa~:PPp 25~RwW~҇~~~7艢8g(}V O 0 d\puV@/ȋH/8Xphhh(PXx8ڨؘȍ(刍hUܐـsC lDX~:V f=؏yalHqDH "W{Mz0} Ix%Xمz`xwh j(~npWq'dvpçӇqW~W }G~F}'XyoV+WwHHW[I[yPI8(Q S qmhxvшyً8zw6_藅ɋI9i阐ɘ9)Usр?1PQguLm$i`pIs>zX{|!9}z; `|М | Xypx >XqȒ7dOaOp: }Iٟ W sZ`*ug 7z&  T@tUwuX ~3(P9>j:@=ڣ.uBʣB?I L*Q?ڤ`BzZj[ڥYZ]*_JZeg*U %VI*i mi{ai n! `zjpuxw p0w { Ji98PO ١} ʔ Uج' { Zgxs)_U_㊭J vߪh1WЯ;[{ pvjҦyjV {[㚨Zn+ y ˟Z1[_Z3 yz'J  z y)ګ\ \^۵_{X Zfh۵]l+r a;su+j.'3ZUڮc{d[wkbgkd˸ pkyU73Y{[&ܠU:[Kۺ뺜9+˻s W;bk2h _[{wxxy x[Vة ˸ - LةKٛe[W K˸xK:^Ko\ۻ_u+rk+rb l#<\ l" Yp_UE\zJL KMLQsWFWZlX^[\Lb|q1l{CkXKL P 0!Ókp@=B]4k"-!% ҳ, &`WMaS]fծ)=$)O`-wmx x]a׀v|=~im~-؄=؅]dd ٓؖm*ٜٞ٠ڢ=ڤ]ڦ}ڨڪI Kԭה ْ]eظmٺ-ۅؓ֯iնى ]-ٌشm9Yı]}؝ڽa}i']}'==B>^~` >^~ >"^$~&(*,.0>2^4~68:ޫ<>>^D~FHJLNP>R^T@ְ\^`b>d^f~hjlnpr>t^v~xz|8y ҝ)}>^~芾.YQ~阞难ꢎiꪾA^~븞#n>^~Ȟʾ>^~؞ھѮ N q> r#?_r?_n "O#*,.%(J0<>@1_#SV: oFPR?TCO 3]IO.qP !SUln/W#Yq ;dh!Qo_qo)s_uS}:oQPrQD-^ĘQF=~RH%MJ-݃ sĩRZtB< X'φCuETRM>UN7]ƔYJ՜S~VXe͞EUXZkZCśW^}]%V[ovXbƍ?rCƜYfΝ=#|rܹMFZ꒡4kڵmƝ51 ˾[pō?v).=9]t'띕3z<͟|=[斝O%0~G^~SՏ=ޤc *@zDPAK;\pB+<1DPN䎩1DE ;ActBcFaG2H!-*ѷЩ"E7d3yK+oH/HLqg-l6t2M9]lL; R̷ *t61PBl2QdQP*31J +'CKtTST$#TW_/UUXo8Y)W_6T?`E6ٱdLe6Z-1i6یuV[oRP\sc2]ue]ua{ΕO-^}-8ß~>&{d߇ŗV'_/~18{Y YGF;F`e_9fGиcA'[-9_ݹ3.kƌbffkFxGj~A 2&$1:&FFnvwsmmԢ[lBo& r2l5s<`B<"{Rh,"si W&'\co:nϖU?AoGw|z5<%nVGruK*?r+iF? Ȫƍ] &,>BB܅= AY0tC9xA }Z?Rn[]w+ #ȑw- ċw<|%CXf7lay؂'3ao#: ю{D>"nG9{} QčX)QCc (LҏutH}2u)DvUjғDPK7K,Ҭ,qi1څ8ҸF/3"7G81+mǛOBA FӔ&14H:'nÉk&D&h7ɲ\./1l(F6i@z lwg"RӼ>nE&)_Jy@<8ɉΔӓ0QF,7GU%_FЄ/%AØ0{Dy͆JGfQF H79VUI)(T+&K:VG|( A:v՟dţ㾺ubҔ; DRES_d*TzKj-b~hSZ\-&=אrs QԮ>mX Ae`VܩN_{%u-G[x[Ჰ{k;YAH͢APZ*qCD%R 7{~lX{ߖWt7` #p*ߕW*dG*ۄ_R,|Yo p >Ž hG#8,ycl=#P#CKQ.Ges0KTv)ƋnoVQ1EgfXueOts24B]Z =tEaJWҗ4+wӐt;9+)* g-ZԯߩeTK̈́} k^_nֿXO֝?H-e[^ܭ}Vz5gvmnwR7l17M 2fzwo~Z㾰 t͓Lm̻x#oC?91>`xM}p4&- wj.q\Sq7{綹in #@Ur]09Sn^s3yƝ< ʍu#=JYs>vt/TQSW/Z7r^:Rt"?5ylNd"+Du"p'H>wW7w}P߹={2.'y>ߴ9ߤLXIUK}Ss]~nWֿ~#_Or_}{/F|Z^4. XĖ=f'Aco˽ý=C= <{i?+Bs%wr,Z-ܡ Ծ @=AKXc@>e!>c Z9+X922 3A?"$!Լ\|9d3< A+mxjIX$]YXtN͸FX;ml؆uȇNtF$I9'-ɗؖSԘ-Yٜsjj|Hڦٔ5ZڲtT['ŵZ%OԴZAڙ [vZE[ڍIU[lۓYZӬ@[(ͽܛZ=ͅ-\[[ݽ=]ȕOeY\-]s\%]Սڔ5u\}ې וIQ=؅BRݍ^X Zkݤ=l<ڴE[5܃uB~D=X585RSG$\\3_A _\ݑ GPfd[_;2|t$٣:v`$F# N ]uL ~aV .Z $N v$V(>F&b'b)bt* Gb0 0f,U".]#/62˜rc3S4Y5& /v_+a>?.dBdD>dAd:T*+cY{dCBn G>L6@e99Xe_d`U>1LFd&yYDXRSa.&UfKeNdZeWdde]c;N+f>Vcdk&kNaffvecߘ6dN^FNNdE&ugoE%esfez5^|N_~6N;[.gX>[3\|Dh6+{Egg莎h/6iF&V>XEfghߐiiInhVjzFn楾a>jN& blݟvRꏝ鲆䏮ٚ<^Vv6]ϯD RkaƋc$l붮Q%%^5]NP8`le3(xPfO.Yɶkގ֖tv^ܶl&hUFml]Dvnnf @mNna^bL'mmf_uLp2췸$h6pgp~Vf~p3$ p $' _W2_qqg] _+C"#WW"7r$grgUr$V~vn*'w6R)3-/OM(r(ydFftN@[e4?b9WL,oenejeQ?7GAV1_Rseuvd@w~ZVs@'c/'J]C'sSdk./kmeueHsK7uT#fIfQrlsXfJ?ZTHO6Re8E&fZbS1?L7eQ"Ovfuvejilv8no/+vUrOqvsWDwr_wvyNy{gN{}Qv#Mtx7w#pgxvo+SL7gL??LyGy4g\y7|y?yS% 'WΛxg"z/ #(xzz+#{?{h{gzO{Gz/{z{{y'yG|g{"Ň|gyɧˏ+sȧ "}}'O}}o}_}ԏ}ڗק}ܿ}~!?O~xwg+ _~'?}O_|ogwz,h „ 2l!Ĉ'Rh"Dg6n1d"G,i$ʔ*Wl%̘2gG4w'РB-jԤM9Cm)ԨRR 5iGCr+ذbǶĊS+ٴjײmK#Ѕk.޼zRK).lߺ3nqĀ!Sl2擒3ss͠G.mӪWnɮgӮm;ew{!lٿ/~:ʗc9肝Kn:Y?c՛8o8 Zxqzahr"%>FΨ"-"18#5x#9#=#A 9$Ey$I*$rxQJ9%UZy%Yj%]z%a9&ey&i&m#<uy'y'}' zPz(*(:({Zz)j)z):*z***:+z=C#+ ;,{,*,:,J;-Z{-j-z-ȹk#{颻;{⻯<| # 3C</,.Ss!<%|r)-<1/235|393=3A =4E}4I+4M;4QK=5U3Vk5]{5a=6e}6X6m6q=7`]7y7}X;PK'500PK[EZFOEBPS/img/rddt5.gifWeGIF87aƵ{RRZBRcBR{ZcsZcks{sތޭJsssscccRRRRs)))kkc{s191{91Z))R{1{ބsZ9ƥBRB199BΜs9ޭB!޵s޽Z99)!!91έ)޽!Υ΄9޵ZƭJ9{BJR91sk9s1csssksƔΌ{εR{1c)ތZc!RcքRs9Bޭc!ZJk)罜Z!ޥ{ޜkZccRZkckkZZ{{scRBBB9ƔsBΜ{cZcs9BJ1ZZZZZskkkccZZ{RRZB9sss)R1Z)ΥkskZ1)RZ!!JZ)scckc{s9ss{Bk9Zk{1J)ZB9R9c)cs9!cs!ZBRRƔΜ!R9ֽRB9Zs9֭Zֽ1RksR9{R9Z{{kB19JJss{{BJ)1RJ{JsccZR)1)ZΔ),+H*\ȰÇ#JHŋ3jȱǏ CIң0 ˗0cʜI͛8s@ϟ@ JѣH<)ӧPJJիXjJU`ÊKٳh-6ʶ۷p~MKݻxJ ߿ \;ՏGy*^Xܽ#KL2X^,pl|HyDӨ>̺װcWĐvnDӡHJ㮖MVܳS޳io֎zx/pys3}O9]kCOU'mV@{tFnDS杁$h r hDŽr#$BA;|WC9d:"I?yA>:cR)ш(f\6d*28zE8c5$IPN*G.dS&oډ'S ]j$7h$Hgfhڨv)ꩪ}Zj:_+)zPJ1Gil؁+N f˪Fkmվ+覫n^Dls1cii`n؂뭶* JnGT[pAk>oJ#%Zr l l agsƳ>lH'HӌPG Q_+sS+4S9-dPNˆ\PmtύS~<6|-w݀~}7( Rn^4Wngw砇.褗n騧ꬷ.nSo'7G/Wo }w/ۏo觯җ/>hq XUh d8O .'H1*-72Sʱ(L!2A[tP+J;x(pCie0jQrb UD  _Y!D>J?*0Ea^iEb)< '`ƀMAnExNϘ5*1 ?L% 'j`V,f@C-6YTAQ!p%>X \R0VF4 @|@7r Rf:eπ)Da* A@t `e8-TESBL (&ψ2'I0'm'`eh*%7CTݦ`_! '¡+o@ Y,(MJB_N⨂6Qes*f /@O:-*p!Ї-PybSQ">'0,2)T vR AP @">w!ѩ@&F5I-0H MHc` ,:6wͫ)TA\ؤ_<̰N) v5/`@LSpҩ$*KlcW\qU*gXJa`_=IX ,r-P0dTisuJKINjkN !L%`Ǻ(79qJ IC SizR`-c2^,2Iu KÍ>AdcTls*_%?VK$FQwUkәL,o\&;~8.'awYS 7 BnYX蔢uJJ)p 3WB)BPR"p*˸!cCU1tb HA @!6,䕓;1r!5S`$5HA(|ONg;9i 90Se 5·u=wӟͫa`!4 fI R.yh+\ZS,3LW;/wT~3Q2D7ovBO$KE,l ,*wǥtPWO_|nv\:X@Z={sϵBVU!lB@|Yx @_$>0pDÎVn~ :Azӟg_7?rSWArTPT`W`T Hw[Q rYQ \t sbE\06~vo'@xgzYz747#Xay)Wfww7 8wdq1EYH[R8T(%[ VT1U `P '@a1KVtX^CZ`hl6@9Ԁ&Oa,`ЈOt{@5FI]pY% ҃o2hX!ȉ3m1LDcxvg8p8ĸ،c8xؘnc؍o8X>( 蘎긎؎8Xx؏9Yy ihؐ99Y3xّp _8$Y&y(*,ْ.0294Y6y8:*!^$PB9DYFyHJLٔNPR9TYVyXZ[?^Aɕb9dYfyhjlٖetn9tYvyxzf q(%|9YyD~ ?JR)$ٙ8.@Np=y$&9Yyٛ9Yyșʹٜ)N>YPB?װ0hYoP\Nt *X y(T\II>p? !2>ڌ9ED ع !RA!" ReL,ڢ.02:4Z6z8:<ڢʘ~J g=ZVr1\ڥ^`b:dZfzgJWlڦn+?j`3` jp BNZBCoz0PaJ:L ~)p{ʞ* }P *AcڪkjG4gWHl! k0 ~ 7`P  ê:6 zPGjM2j0ib@ԚWګsڟL+PL ǰS%Qњ1jp {ؚںHMD b۱8ʮ =pyG걉- 46K ­F!pfN ZO8{Ak.\! `L 9"Jq+<۳ZK+J0O[+v}?/+ `43a4[.K2;.0)e [Fo sKE["DyY0ux~K K;Mk̋4uR)D;2-*-2*0+e{S$g`ĺ;Ekr;󱘭3[.ުML_)kɋEIqRDk#3.{*"[0rj+`D<*aMzZ97R<)0@;\L4 R 48 l*`ŗ+3˽9Z¸re<`b `L4`0Q! !z~< (E\.{j+e\jS\T:X\L"C203 g*s0/<[ЬyȧĂý,Lȩ"\13K6qwwڷIj`l+\<~"-bƦ i2L +gr\ˌiܯ$*}<VkL̢,ь0L|+͎<;ߋ N@q+R/3,-Rӆ b1< Qњ<Ѹ]˵,2)2-2[0jOk;)6@* *//hOg; LL3AОpF=HMغN_ (@mؔ>+3 Af{- %p J}=^Խ:<(>1zW}J*Jⓚh2>4^6j:U, êA\=HJJcZ@>q1sL~X:W Z$&'ÿcZr>V % `|ˀϼt~舞kV$yҬn|Ox7zN^n#Z<霶~븞뺾  Jz X!J#.HC! QN& &̥ʯ"z|C1/-.U{A..^`@z?\$JT@Z[qYsLLI*>dL\3M`8ϠTrjI-Z(S)p9.Lz%43-k=nJPQ1uOYEiE`lBk>~\4E?J0f@j6a9NA[z//B?uDOml>i\_B#wAORUa432Ɵ?O/Pc=iJ(WauoM*/Nz_>cPP@O؟AA@ h @`€4 @PD "D X"7ZŎ5z(2%IMRSL5męSN=}TPTR,@xT^ŚUS)K3Ajfɑ_m\rR^}Xt]Z R%hg  !y(׮ O us؇e!q%qYMR,_Zn޽}\aL8m@;540C­5 P{]x͟Gċ?3 f0S5Ǚ !pBdZT0B%tB'İ /??1S8*2 . (:X/D)d($"42I$TI&tIJ+"c ŤLhfF9Ϝ-7J|2C=-s>;OA;PC-4-OT.8h2Ha&x?F2ժS;DG%TSOElTŝtfʔ>MS$PD5Xa%vTEMdU)X)8)7qh\[V/-6\q%wDU}Gx*h^vWmq[}Qr8`:V1.ӭUά2nu|wJc?`uY iMgvSnʍA9g`d'0lw6;`fiEQe=$€?iU7̰R( `m߆;n离nƛ滨s Ʃ .qgq<U- ׇ|%Ǵ}ZB}z@z ķRI!EM6D  hR B0"Ӝyg2AcLPXτ'oAEbk:1# !CbZr>d;9@(DhB*FLJ'fĥM@*PFA\ Z,.eK@ڄ[$&1X'$`ag4CVA\ܠ?6P8ѩP}DBa#i%bTҒ%wJ TQ('D20 ) D`91)PT)NAť\X_01dE2dQ1\lt;i ]# ٕqҜ3$"MF$bp$"fBOtғ?'"М@h@h)mOh ACcB 2K|El R2E-JE !P̜Pf-\/IA8[/0T/P@GGrө)aqDﬧ zaCi d[` AfD@ꓹ89@#Wr~ $D}D'0%O${$D$bȐ8-b*S|+91p NUGmӶ#Q t#YH/|y2nt%{U=hj=zOh, P-pa @#%?/}y>4B0P& z&>_ю)+-@ bi:) D3) ]c]ZNa+Avg?̓/!6l[jj.ƞ$!B0Q%u|ʤ z+2T.l`@ RGI  ECRА"0@,2XZ"زA%dZ\9_E:&ƉXE0\cגm,`?Pk6x Qc76QhMur fY lL7&52F:7ə)0hB $~BVt AC/P`QI8L"OˆG&dA)raL-v%GHLH '(+`2n;':zp_і1i^Tx1D*ZtVpXafBWD y^W 4GC['ϹsL0>M\wM&_yogumЋj\b%w!T>Ϟ/_ 04p `50@f*s:X8h ."خx+ԁ ЯJA/Z&^ zV[tEnN" ?;@$?DT ,@8;5;  p@@0:4ȅZ7 <<+h8@.07s3Z8ջH h #.h-؂,9 9`(14h] ~+x+6پθ'Ѐkc2@Ȧ:/#;2+(2K??XL KDsDJDTA@D@; p (3X(Ax+E؀ѸhAAA ګF ZH&lV20H0a=x=f,BF990c(P[3,uB [@V7:Wb+1CFRV-Y;>NÆع N1/ čLĎDu O "APQ+z `T P0x ʯ ,]Ɇ/h@$HHW@Mp O &r%W%(mLPG [) .h4.~+WElJQSH T0TX+?O'c;!<$  pMdMP F I@HI|M֔͑*w ůb/ IƜIZ$[t܉]TAJΣFCQ  C@QX<"*ˊ+c0-h϶"$'jI V̾KWǐ)L8ǘ(JP)(!8E䶺7ڰ\L̚Ȁ "!ʀ TeQL;P2p Zt\)ۣ]^4`\J `"J ûR%؀9q  1.ЀKS0;3}̜jJPp&h7( @l=: %ĀHTIuKeQ@'ڀKBS<[+U贉0jɄCȄS}Z\T0_O"R(Z& H#Pg> KHD(@=9P) ;'˘`ԙHuevuwxyW WϟԁԽHE|էWKOWG@Ì-JKmMEPL: ꔚ:≵ɛUٕeٖH{Y9P^=_> !&c5ڞ Ȁ6͉*>7a8dcd@dd>a-yX 4N|;Id΍PčX?.'-e d?b>U1= Pdx+6]l mfbf ^T>۞ jƀ6\L,lׄdCoz V(g0ThVyV?Z9|}ӫVluru2dcy^EVfv闆阖ich݉Յ8Pdj>}y_SR5FVfv꧆ꨖꩦ긬맦hh+%<)Tiw~ޱ^l.k5(  QX)2Ͷ.c"TǶF8ʀsn$昢&ڶlnTN>X첐ٮkfVj6?UX&mg]R ~o6ooFqNoۮW2w>klnp 'p owpN Gqpv Vqpq_j q_q>/rnUo&r po"7 n-oBiv$V.q(gr,sF9#?lV):7?:?p-DWtsԾ&pp@ss8GEmCunCFjD(UU VOWUVWXOuv]Rw6tVdeWfggwfDvh_-u_mevƉ`4x:nTGZkguwwuu!nuv pH<({y'G|_ܘw:؃o銷ii$׉o90lh><4[hUx(>h6pHS8ቤ]ynި*L w`Ghw^o2zAO^'f0y1665Lr :DlBh)#y^㸧|Եݫ ?4}}ݗa޿67:T dOHgN~>f*ҹ~A „ 2l8PÈ'R$h"ƌ3B E,i2VR0`)#XJ9n@#TDS,RJʫP6ԬR%u+֫?׮Sۂ/$I1 .0⹃3vM1+̬Y`NboNGw g^qtҳL^>fL4m̼rkA$)P v{C$)7 ^ ub (q5oޅ~EׄfvbDn*&Iud|4\ɸ#={qmWpiah$مbE * ]e5q\Q,e(cp>yg|I[xrO)NRh_ِF>#"JajbKjRe'2 GzJ⥊&((:i$JID7PPO:-vj^H}UszFi(qPVw+f~8,d$omb-&z)f <6. 0Ă)멋mk̚-E<ض%Ű)/k c:饛~ =9n|ƀP e#d!wF8L><<0c {H!;9 <>A/?ߖ7"=1"dO!p>:/t; @)y+5W.!?5 b?^y.[w5Q,h .8iNs8BO+a缨Y/|"H}[XhC~4 Cp+HUfƲ)I|*nMBSR2u[fYr$J@*Ԥ'-J*ϋ5wՀh*N{ΒjC*VGWTR"ukXTVS*Zӊ*nOYͪ/ҵtcTֽ&r]+Xo;XTՑ`#+ٰG],f}kle bvgS+оUT5y񨶶ue-8ۚx+ܫ6p9 K*WS}nPXٓu; &Tenv6EwjG w.yNfzy7~x/|@_޷m~5_= t803 mO0| {$_#)c,Ӹq>" ĭ$N~2,N/AH4 5BdFR)H~3W[XزzthC"9sE#9ʹ˔e H/vҔ+l]{M>ArpCPhD]ϡ|fB݊\49޴y:iu6A G.$xgɎNx]kz|*ry/倇o:V 2YgQ1 1\$[XK}kSQ*♯AlP 0HO3iω]z W䎹 B``9Z) ]oe; LC=t*5+sC0=%oڛ)OcےGjOO*_HYO$/zi?|e~#_KO^_a(VfS?k~ÜdE( ?\r50wο>_V k -q- `nV l_ rNu\jMq` Rl qĠ Π r f ` ~J  2VAȻd DBȭ%!K,!LmJ  *fLB ePNfa JLf"AΝ9 b~Wf @ʽ)ZYǘ|˟HHp&~L ~@r !*%*D+ !A^a%:VᆠDʱ ()R  TW+b3BcIi.a/|ya&ˑ܊##rDIB)V83^#|բ-6Nc"H9 7":H2*J9JJ J5@Уk#=cD#i$W76/ʷłHb3@4DK$AdiicGV7N)4:$i CKKVAdi5N`TNN^/Vi!cP䴼#CT5j$Gnx%Ee%NB%]?RGzc޹uҠ fa`&_ڡe`bXvdV`fOF4xf\f&`g&&KZn_f&b@l:Fm&_b&i7ަa&pIn&hp_r^rHqqfspN'iXgDנ[uFJ(fh8Җ Pt8zx(~xvċ*)D0u(@b[ :\ Љa{^t)~|hbF>C<蒾ZIB9)(tЊ ~ 6揞Ă@2()>jiҩB(C%ڋ'ݎeOJgb).j*6j*iNjjE*gʬd)aJܪjVa)*ƩܩH#LbKV*0X+G'*x+reTfvg(d'իG&l"d lfk*l@Jl0{+^mjl&thȎ0(+6 ɮl_bIJ̢,̬ΊN&kbqB -*Njf*-q6-2Pі{&Blv<ז-܀-ʩٶ-a#GbmԮ-ۺ-ޚ b*l^me.a"l>, 6BJn R.Z.bjrz.e؊n.z.⪮eԺ..nz.vn.u/ o")os2o Z+ʮJ:/Arjoryor׊/poעo/poպ/o/o/omRkϊN-,wl^Sb/fo+ԊV]0g̪pd0ɰ`0 0p0 q")q2j:qAqIqjRYa1iqqy11쑱1qqq11ɱq1q2} r|!r)12y9}A2IrxQ}Yrarviyqyuyrs2wrrvaԲ-2..2//20031132'2/3373?34G4O35W5_/WL{v7sM793:s8sJs:3>kD3&64AA4B'B/4C7C?4D3@Md4 Dz>4HZLI;@1`@natFptMxH״M 80@J4tFL[MߴR/58OTO"jQktLw4So5Ww|,tMh@Ud\@[huW5]uht ZW59AzML׵b/vNDv5UD`D@$6c6hcGduJ`Kgv׸6g{vh6mDI_[r]vkcklw6R@r/wY6tǝL7uW7u{5n6ooup [τq'5KL3c\@ZG7|(!B̷Pݶn@o6cvxO|`l7k8@x|}"DVtCTX"}Qj7oov; Lz7gxD\_l }цwW +^gCG});iLA`};ϛ='?:;s;<75[9\Z`I0dc|ُ>sw>o? MM[*창.4C+Qǒ QEA UQ SQMUUQ5A9d=@QOW_ VacMVYA]XO2R[)q]Ygf WqY\4u2ZcsFAlsWOsA6`5-IZetϤ4zOS1,>ߝ>.c=~3Q&w6F Fo:ޮ޴^;.>oF\'G]n%?pOyYn]x]ѪZ5{]#=Uo]҇C'?u/tsOy,rvҳψd0}#2/ۑae/YMcG5Yts;9oqJLZ7ϮO|b !M;mk)s?Cc{&x_AUڃz>bdiLl R#0׹~yXkLDVih=KZ?iA4pm؃CviZ}5y1{~f[-jhIm͛eT8N206 B5ζxlgߺ̕ksПV0HA b@0֎lw;xpF/9˩1ԝwjv:Zc+q{x).h{mx98_)o?mҧ,&af0 ts. rONzOMuܓZiW}1mz>6v ;a/AIRC'( ^P@;_(YoIF2l̞3r5WK2,gW~'}]eghLL,o֯Ov .(h+O~OK/kN cP onS@V`<'/PEENTj\KNZ'0J 5(Yߒ+_PO+X e?pBzI # ͊PU0\ȰR( a$г  p֐gZd)-1^<Y K0qIŨ""kLa1eiP'Eqy}\jQ ~1%ϫiq MC0NqqA)[(qq'ƱBIӱC/r cQo1/ !  M!-" "A#A2$I#0TL!P$Ur%$1#%i&3%Uqﶭm'}Rup2viP(e冒#2*7Q#j*+e)=Qr&,UՐ'ϲ-rTҲ"O-.$.ϑ+/30D/ϰ@/R0s1* 0-2-3!02S2A2 SsTL+*4QS0GРq+S5r5k-e/a6R6r2k31q7mR7768R8}39R94c:s%8;CR:q);!5O<ճ!973>=:Q>S2?s3 s!@%^TeUVcU!Vo(<WTmBWQX"&!#b"< '%DFaR@SXU$n5Uk5/uV[UU\u\yVb2XC1]U]uWUYߔ54Xc#W[YUYuYU#Z\`7UW;B#е_%Z#`6_v vab#c_"U^5R'Q5W!_'e;ci6d aqQ_V\w]Ifudv_k#bZ9UuiEv_}ZZ`er89LW5Y3bXaX1Vvh5V5gNc=!V$XlvkvY?flvo i\du#t.ngvnd6ovrk5frrmubA"[\erCW\=7L7&6pMsvd9gh)wwtvggvsqi7t6iqtyuuqsns $yj"Uy`ixvjly|)Q{]W7Bb7bxAh5662ycMxmv^?| %Ivox)YRM˧,-=^[7 SAQ8kC18:^nkSexi'Xp؜y}q^}􇉸X\C*LM>8)w`xG`H-8xٸ8x*8x9y*cB4H`' %y)-19 9=ߐd.mwj*Vّ!ey=yiqE9Iٔ+2 y{Y49 y/Kkz@ F sqٖyy}/%ʕݣ$ ObN=[YA@49kY w[$kV3@%:R":%*=MG9(ٛݰ: IZYzKZ_59e4|/Z!:§)!+B1x*A:DzcezU:)٫ qz Ũzw Y}-Zy:*{GZ[M:[:[Y: {6I; &zrZZY*®)Q:M[ ;{GZ[9A/`/N-NXvq \C!: t;?;۸3-{|i] "̯ҧ6$g;gbݻ:(ۺǵAY%Y;NٶnI.{dND|]]*顾~ꩾꡞ=rwU^+~b~ɾ>~پ>~>~? !*@ $ Mܰ*@* I=A?EIMQ?UY]a?eimq?uyY_!_)? ;PKDpWWPK[EZFOEBPS/img/rules_test_xsd.gifGIF87aS+Rƭޜ1k֥ƽc{ν甔R1BkRRBB9JkB1ZR{!sƥR)kkJ{k{ZZs!c!Rcckc1BckRJJ1BR޵)Zcks9kssk{kskck{νέ9{9c)Zk)ތZc9B絜ޜkޔk{Jޥk!ޥsZk!sZބ{έ1ƽBνRk{{ZcR){11111ƭRZR)!)EEE!J)֭k9ckB9sRccR{c{ΔcRZJֵJJ11JZ{9ΔkJBJZsJk!!B91)1R))RsBckB1k!B{ބ9cksJ{Jc9k{!kJΜ֥9JΥRƜBRJRRZ)ε9Z9ssR9Z{cB9s19JRJ)91J)){!sZcZc{΄Zc{΄EEEEEEEEEEEEEEEE,S+H*\ȰÇ#JHŋ3jȱǏ CIɓ(G XɲK ȜI͛8sɳϟ@ JѣH $LʴӧPJJիXN=(bW ,KٳhӪ]˶۷pݣ!`߿ LÈ+.ǐ1p˘3kjîcSqͨ/ Bװc˞M۸s͛L N8ՂvMN󈧍K:`سkνnO&ӫ'0e>/}AȺ ܀EWށ>'P yx'Vx[ft6hF:އ!bN"Τ )ğAz 2Z"8<@)DiH&Y|@@l1@>a\v]C* 4ЀhlpƉ AIr IgtIdFiЋE 討yF*F8rP %PA~,;3Xs7è"1BlF/[+@Ҹ%[?-vG}jzuJ } 2 c o ;8Σ!V”!,ڋ@9@J6Ӊ̂`Ȁ&Ip  2jЄ;]W8Punv8\S)A2$$>k7!hK\^5RbИyQUtbGE(b i,( #kw<|x9$񁏐cHHDa5o|@[(ǬAҎ[U, %p(32A<047L0|1)cК` U'4.ˡ80N $Hv3"! B<}N =O}s?PTh? shDJQlzfR7&w?:4)I+iEm$e)eJSK+EIcӵ|)JǧoJ~Bc!Ӧ pbYЖeA*9^e`0̵k:nuk[:׺?k]Wuv[W5~_D` 8'{,> LgΕ.wABPЃ޳ E?-:ThCW{ЅVܧA1N (@=ZMrR9iLUJݯ|{)PyFv)#)]tuiJ>q(*۬:fT_-Ճpakc iū` Ka*„E־6 k-XR|WRYOC|g%]Dw+ZȦ}u[QȸyA`%EFiOwC=O_4&ݮG4WuJ/uG10t|a 63r,*.oY`%,VxӭAGb.5ZTju=\b.B:T@p70<[Ec$6dަS 2Ȗ /}-ꢻr;&yV7SS- RyTn >0.%^cgqU-Z‰9:aV6-gkMsZ/+ wg[)2axYpsw9ti&?1]CI1>ГJ+gq?qS[14Q}܇C'secB7|88mxZ# ^Ё*kW&HNǁ}Q~'($&7i 0&z<#~m6lJL؄X|uR@xX&SuVb1X'-=xY8N [6Ir8tx|Pg!_f|؇q<|Gq7@؆u+x/(҉H`7/Qx؊x{42Xx؋x0XxȘʸ،8XxؘڸH@i8)蘎긎؎8Xx3RިH樏y ِIhKّ "9y)*,ْ.09V8{:<ٓ>@B9%&Disp2ٔNPR9HL-D`_ٕ^)F ayLIfyhjhɁA%cn( _zc dw) ʁɖy ny2816y\ ciC!(@$pp\E `=fb1 ) v 0!`0 `/ 9YyYǙјCAc ٕ}iB֡~~`'P'(}87af5Ɛ( Q#  Т94Z6Z!!:%z)jB@ H:yEz$qQ 0PQ P" 3rz0(u\`_J$ 0! 2a tb°p( =2 +*0@7کmԨ*J?BJVeeV֢VAJ2H:IڃKe#F:5S o2 ` 2a I0/#*#i$)&Jz*p{:` 6Ь*00#+ Z#$:[RlzA!dKA*:#$ؤQQ:0۫(PjAm =p"jت#0}#-@Fy-V*j``! P b0K2¦K;+[*TL4=.{MДL )Bĺ#BYAgaE!5aҳ;B9Q@C*`4ѴaA}  0[;^bk @N[ N`༯a,bv|,&z+@봲a*0*P q0kGCcu"4Ld62!3<4|5l4\;9>37Al6r ;F9.74N ITj*@q8@A@&+?& uʾc ] _P2^J@+~R;e+k:+ qkK#-0ɝ,&"(+\V3<34A?l: A<\l|lCIK,˙˯=Y<rP`clC%i\OmiǮ~ܾ Іl1p[ QR `42#0+]3 0 .MM#( ЭS+Ҟۏߜ2=@C,B,H=F= <\جchB@DlQq`,aLgygL}0ҳ!\Т0:x '0-Т _A<# Қ ײѸ! P` /ڪѰ8y?hO=̽NLH MMT5=Qjsc-_, -Wnמ<`}p@ g={=Ⱦ ="V xV=ʘ,S-@j  " @,+3SJIB[<̻ݷAbu@SN=w e9&l>J\VxPzѰ ]#PK*́\ 0 ☞"^∮Q(D,`@"Lw,ϸ ^问>P~A!c z60zNYzٗOfJmq@  O Ͻ)p>׎瑵! S[У>n~H:o@O˳} ؗ,b<[޸ajʨ+v,idn?:ty| ZSrP馜0',X 9QӍ*ˎ>IʹU~9P8;@?!ڐ_Ə,o_a?_K)Q0ioQ$!@@ DPB >|D,V =~RH%MDRJ-]SL5męe0ZLThϋ>{@TRM>UTU^ŚUV]QXe͞EVZm1,QFśW^}X`… FL8Ʒ?Ydʕw\QWΝ=ZhY[FZj֭]?[u5'Ɲ[n޽}kōGrlk;tխ_Ǟ]vݽ^x͟GbYݿ_|ǟ_~0@$@D0Ac.瀊'&B / o6CV FK! V_0F Fo1GwGن$J:D2I%cXx.@  XL3$OhM7߄3N9N!2r:XPC'0 մ8 xA*@P*@; 0 u@5U0\'5VYgV[kj.#`@WrYTg1h.X@!RI Z˅`3R*6/ 5L3c7W7^y祷rdo#M!(Xk *u &0vPYT"@D VKˌ +qȭ\lf9gwg:h&hF:ifz]W1;"{h_(Xj~.l&#>r :A (Ⱥ*8 "y6:D&pdދ'+C/USsg8Kv)yGKLy(" n(,pϫ8Td MࠂUbQ R` &a9Nvԣ*tӤ' ZV`A= D\QRTCh>-GQ5R XភѾlWjVSNوjTOҗ,`Ha&ơ*PR{SZ5 nޱg9wΎgt7t B@XC(\Z  Z>^JY\1dƋgRv"LmQk8y5XִuK}g' 8a(][`O:"kngת':6@Y쾵R׿$= 8A tN~3u:c2>6vvJݙxz*No~D"Xtfx/[mktϛo}w6Y}$ tD[u?k}%m|Ln=Tܵ>y\u-'9֣Z:E7m&0 :>hZ wGyߵ.zրח.xC}_zfv˙)}V;Gn[%|/`jnxW^c/^>/g4܃Jo|7w#_ŸvU0z*iPCl` 6݁ܞgu ?OT>a#B>9z9K=@6,310Pk?7[˿{5ģĿĽ+@ )7A 9۷346P0(Ps:$=AA+>A @(">XAPO5l4XUkC 5#BC? SܳC$'>ǻB™?$Da./C 6+3482B M8>EFlD2D.81(1ض6 Z,N|O],4EeAE=0:5/0a2xLh\r,iQL`,3d@ bFmdF ‚l?F`xGoD8@ƞXgzTwr++ȉzTHǵDxGa5NbPHvdH)*H'E$×䨌T@G<IDɥ2|v")('xԼARH<: V: -`cƩrJJ+A@ޓK/K. HH2”L('+˼K(Kʒc5{>0F˴L D؁x1B/JK0Ӫ:7,ʼḼ\s<ͿTNESM`MݸGH,O䯰b pE22hEXIJLxάνίܼ;P JM OGM ! MO92%5EUeu5TZAыP4P:>͜]MŌ9:O q+}L[1:O&]mN<  CCK\S1 'O(M19+ 1ȲND]O0HDS ͍S)}81AJs4.M|4HZe\N5}^' "(MU)Ǿ Hԋ0-]U]VdNO= |t2h iPkVbmW4;VqM ט2_SW`yw\Wz:WC]ezVoMX4؍؎؏ِ}X(8lB؋FWQi$ӓ%8ǘYأUچ0͎ٓ}ȇHȂ%R2ڥڰݎ}X8QM=ɢI*IXҭ=[ۼ=ZDۿ[7![0ہ5,`L[شX Ѥ\,XXY11 D 5-X0ݿ` ŝԞY59P\}ǽüž\\UMЁՁPH&gLh݌-ȢI L`̞Iߺ8\x+!4%^ X@ MX^ڑgQXH!K -8ЂPx]J _AȄ_A%Q]E56"$6$f&M=dVfp``1ĕ r^5Pava> ©LJ.IcJPk9B Žp\S4ணb\DD^V(]؁@,J< 2~3-yk  9n%=㺈_@6 d@v;DL-T!gHd}bD"EL.TΡvvXIdQ2Q>b)UYĐe88@(! uĂ  (_aM=f6 i6X]ax]fvgƋifCfD.Yn.bgrL5%R8>SB+X͑@@ F}& ܑ`?uBg[_ G9._9~fIXHhi1 jf@~&nִ͎HKL-jSz Fh'ő`rȚ`Xɋj[ިiԄ͵IRg  X@ȁ(˱, “țƃ  !kbD8(lînllɦEה_`.FjN;őX!FXr%Eߌ 1( Vm91nQ7|-7 0>F}fǁ{n" F$(i-`.in c&Kp mUlupR( GyH±EX@ȚH$ u\݄U43( 0ݦU^UFr P7F=b 1X%׹RI:~K8,du7`IB@s 6Gls2ڍ<=7>?wj A` DF;O}9zuUUuGH18>2rqp6pΘr@"/f`Nf^fNskvmtv:Yq'/r7w tv/Cρx#WPׯ\'Tz!/%bnA-؂,`!(Kfр>`! ^yg㞘v5'fJpopy$ WvJdMQN.2MP/WKOmRG }wM., pQ$'  πHPv_^pf?ll uYlʯ| <E `A@ !3 $pXАH`f,H0Cʤl%̘2g\`&Μ:w'РBu)ƌ@blXP4.]f(A&U@B 2mhɟZaæ ׇkSIHBK8# -~,M 81Ȓ45c|ТGl4ԪWn5زL  3~:G%r8#p"#IP#J`I[c&zf>.__4{J8@9YbnEI' `5WJK :tyrdj9ԛd!YjYqQ\"Wi1(5x#9m8نO9(R $^QJdhS \eyn_L$& geay"Iߋ9BRLAfUY$#&m#*(:xӏXoh: k@z&zA)zy*jny:a1EOHj(*,i:V)Zdzj-^i6V;خ'+ ;f+(/9 z;0>Y0 +pL~&.ߔ찚$h /%lm& Lj25lňA,[ C{rh"{2QKڿ*7kd̬ͼ5aS·d4.65ySՍ]--Ԏ=O]5+ns;6di;~;;; ?jD+ Öq"vH 9"w=˞r>~Oo;볏#в?n~Mг+D(M,'{45{ J5"V?F,zCB"*"ƀ,C`Y@45 Y4ej85ǔTDiE0\pP8fCB;Z]$}j"ᇳaEr{[{y(gKۗ`VClKY.ɷɵsT<.vה +`1 Xk5<+*לuo{U|U:l#TB1SхOVE|wuKKe]jF, AArsAE]4 <."ֳ9e Ӝ":굮l L|ћcmQZ'1EmhXna3 @-j޸YpkuK_=hgk|5vH˖2H~*y1 խB22Q'y&_yЃFt%_ү2L8zQ?0$bܙW , UJ"RC.c3k3KizquhyxjTA9@W&r ;z,΢Z"j"$[L#+ {e2A=xcF37scڀԣ(jA<3>EƧY`?{V'S?X/M!GsþJ??~~/jl2@`pA&TaC!F8bE1f|! @H>T傈U0`NA LPPE J&B5(U*RUZJ5Ԯ\fԩƃ%2@L&C|qw{a޾{`Ç`bǏQBTlPMYgN8 [#n 2aa eL1 2 LP0h:MHS" !: 5 Tk( "fK( )S<ŇH|6n3xMG .ℸLLj\#4!դ:(RRbj'JJ*'I+#椲K-3@JJpϭr@p? A CETIjP33ES `8=!P>Ծ@99or7]R6d@=!aE&"mDf(7>ypA]AeS3:R!HńUd)EGxBUTX_I g4JQF1Ibds~oΟtdKM\gHsvIjSJ5c!ƏqF j`PaNT"!4O9jbOA,tSƀOT/ȴ(QQIpnphLԁb."2u!6Scl@ >5T"&5-E$RQsZ^bPfW/bXX´@ Ƨ70%5_hO_+4c-4)J 3GV\HKMo3]]U@@ JrGu#RveJ6f V7+ $@)t8 w@~ Wqɶp{Yk؅6s+W8xN_IwL4 W#X|Xw߀ WrOwWf`_|6`tyVNx\wō+Q:p?Lд׏#7r!dWY1wmt6q9Kr8"* РKo^NU<`N9x1TR"lcYJ BrfSTuٽuk Pe{7rU8yr5Acz-B@8٘@t6sBTDtu{;ݹjR=bUaY]8,Gwi},6gEab?TR 6H+A~?ا_lEz4lt eh}&RQifhV/hh/s^p:_zFIz4,Pga+,aiU,t5Դ b7 zA:t9ET'}g~UuHU l.NviR$;s@{ ֭!ZE皰#[LKRGҵ tz'Yg[?k۟'B Ba倻5[?;biPե1vaCֺ+PK۷=-3"W:gHu z!] `@}#%)Ơ 6٘}ȽY't)"H:M;;f:i~Ry1R/ܔ4 + R q& @v1CPf7%O_UZǛh|aGQ_ üiPVjR<JW}ϟ 6(=QW %X{ǞQ_ $;U+.{W\;5t QՌ)sUB T>\` ƍ;2ȑ$K<2ʕ,[| 3&ˏ'<,@Ν<{J$u hK3&`*TS:FQf5,ج bzXhK UWLߊuj70xݤ?p߽qi ^|I~`}}}]%~97|iEW~u]s uy"qX.zSTbI<3p {A}?9 "#pP{Fm2`z@Apc`H$JKL>I1ӁmE1`ak?47>ocTn`t g9x=B4 K"fD Q). $:Epώ!(;Q]Q:SҍS%pHx{$ G@g yH%#,ɷԕ(!I,ޑRL(?"ud[h6e-Tjy\p%$!*3!OD9 0c̄ _Q&I@G:uSæ><~3r{td_680}:gN5p!`LgYb&f'¨nd PX/&8Q2 yUY[459Nݔ zN@*1H]2\ֽ.vl\\ på)dv{ᵉzOޭnMfiKZWGo?^xCL3g̓P'"y>3|q8ni8M7N3R/ ZDBP@J o\4gg;szZkyv:K( h-r#d7Q[4)^8ܮzQJR#:Ov*zK*yI.erםq,exo*i|_K_j ŅtϚH!,M/},gxq>ݕ7cC^ 'C$Ç6yHTөԅ! HI(Bq0zu&(US.u7t{{8~~k#pwm#U;#`$BbV&izJRysȁ恢"'%8ZEVLÂRF)b@A$B5j7Fo$^Y ^E^LV0C:D aHIXc§X|MTqAaІg.E&G4HD"pmN |H:r%tNKcei~,Xa!tOU_%hO3!o(oLȊ芀:%s2)2/{Ċgg`SSA5T!TV؄iHј+a4P6ƌ傋FVqs5uuWR{WXheb.XY4f\`P%%%Y٨`<)Al}o2\3-[^[R\\ !\bO\[ՑEb c~F_r3FYӨ mn߷RfnCm瓎;  "N^Ga_e_& `2 \F=G598i@)o;Jyhny&}ۨ(&afUbf\Pbh)b\hcpmur(qL'}ir'Fd W?6?Qsq y9DfdKdId["NeVUveZ\ef !fAѝQj8?VɊtyD,qt'}%%uQZuq9xQ^Q`wG"Ɖs8gQgKdh'\~h6_1XP `eAb"Y鞪8sgQwWE[EyxJRuHB#7C>HJw8}T' C?jb0jp9|z7zWMQz1GizMoAW{gp ڔm%[Zf/U%3D4Δtm4&dm:d}3;C3~dD/A(_lʈ]Zu -1euEnltHg}4%xn4.sƴ$1V(y/ʬ H*:h>8 ­n J$8"1Ux'@:P(m4{j<} K: =7+'##;K.D&6 VI,+-(ʳ65.+gF1˅P<6 ;F3>ۊ0+ AN,8 DV۲` 17300(n\XqӴl1P p6AVploK5q+Ca4xз p%0{s!yn3Rjk4K;1з%pG}nZxvr+9ky_7vQȷ [0紻˻0{VA Ptz/5ӋFkk-ýދ;\`ۨ둻ZH+J E$1KPh{JK|S . l\ (L."<\%(f+--|ì2#Cܐ=̍: l [tMl$9TAO'gbWYe<.a,Ɠh*Xn,.j.t0;\Xz؅|wܻ a*V`Qp,WljvlaƖ(+S@5GOPDɾəhdܵȈ*P@˴QY<ʼ,0̪\˷|˹n˻, Ȝ{L͠ć߼D<ƬLzk΅9\$H{ ΂<,m"+rDM-@Ժ"Jg DM+O=չ!Ym"/m\D&]bMl6pC;P AK4@C[pE,0CsF0kD h%q捕!}`k]ƹk%g촑~`Wh$#{;)~wTK(թ;: hBڹZ]>3'YsS<얹"1([2DDչk X"Jklo&Qx-B-[raԳOvSe?֮=ݱx?sϝ7^rϡ~<@$V0iOQe@M|Tg/\wDhtl[hV?xQ^^A"m8Vu0T$8TNC;#0)aEh8F1(9xť4X| k2JQ?"DHF8|Ś Sޅ1G3JX5=c!3uoK~pDC)#yN2lg8N"@%ITfRPdeI<9>I:N+GJS-l##mO!rb(1%PI :\:1d/cLl6LK[57, MEsӤf I8tӍ[1?̚6ف.uB䉧l *gH@ف1JA/υڱ(ib~[U@uQ5zT i7] (tC,5K3STi1U YR/nKQ5*ljj%@+hvzRCn ]9YVP*5*{^_!kH6}M<4jaL˺Gl,8f9_h;ڃ r\ a&s=kEj3 EB V#j;nVKPVV%crsYZGrj 43ya](? {ޣWhૡ *z0ٻ4`Δ2j -5B` X4x갇 n^) xT-v@c8U't0XȄq%LΉj#}#}(V-N|)98Ah=o+ 1W0>s' D L3p${ysBpf. 3 fA6-}mrIqpW=o}V03%P2’:Ի4Ggэͪi-_ ג4Fj@յJT@+ pVo ~~a =~h̭n:Ty=mQU37 :y}Zc76nɯr^i[z(x=q\#'yM~r\+gyS-`5 KhuMnL;s:g3wktXf^[+-߷G-oZ.u%R}6߽8pdr=:z}axϦ?)g=7"|!t%^@:-\s9Ż4DEĮFG;ܢJpO0D:?Ņ*.3! E<$\lEͨӰEP- 7t[# `ƦcDc7DBQF71J GGrs$HGpYkGw xy H$@ ~GDŽJ$ ,9JR" wJ{O"4ʠXKb$˲4˽JaEs3EHGu ESF @T'TM]JTZTTRPLUQ1 а .[F\UVLuU4ԔhY *PV``VgpUiՉ_$Vc݉ddV"Wz*H iQt=Wv%vקBWquUy=vrh֛VkV0`WgWvWwUXsXXWW؁ -YU2XBA괉 p0WwؑYXٚ}Wh׈Y%YY ~ff搀VdM5hrwUگFT896|Fzj}g_>ij᨝eZZ%gjfDeh h(V fV_^c[5I-_.ݾ.]}]` &ɵZl~湦QEܔ]kMm]վ~e;g fΆbf^>nN 0> mn_mS nê mj펑moo%onofoopWT= p p p p ppp;n~kUGW[pqO]q *>qqqk0 `!j+>?rr6rhqC5rY]U@,@˲p_*._8XF֬9e evr6osxsVXo剫X{Wms}EyurI/gGYs"O+#`Mrj膭5[Yxm[6u-YLNteieWuetWHEitUp?utXZuifw؄Fhjm ,GYgth?XOht^y6զ{očw~G\{qsw`/x?xOx_xoxxuWiў۾]wmw]v]&\Myx] xsDHߎyxy ߛy?y_zQzzz1Ozzzz{{/{?{O{_{o{{{{O7q 8||/|?|O|_|o||ȏ|ɟ|ʯ|˿||||p[}ҿ_}o}}؏}ٟ}گ}|}ޏ^/=}}~/~?~O~}.tP}~~~g~_սY@4OD_o|wk N)%8+/D0 p $p`!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&O6DP._Œ)S6o̩s'Ϟ> *t(ѢF"M5 lZ&PmZ@ L6ذŖ55-A(+w.ݺv{R%K~\*x0†#Ntԩ[eYUYvjV泝+ЭҦONz5|[2ڶoέ{iU;/jcA7z:֯c.w/~0K 0i~/NC_/t[wA;7k@'9Do 4'[pG:`CEP\0w#b@h$p t"HA :p2 F&H8TtxLd~"Hp1̢ SW7p;!B^;| D_f48QpP|A+PT E/y0Ĉ |I+ vx!9`P"hPOs)`p+ ,5 8ȅD2{ A%QEP=bQ}R,-',87ҒdDΉZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJ֌xhMZ׊ւp-*:)/xͫ^ ._a"\SBםOy_Kٻv v,e/ .[ZVFKҚvZ,C3zf0Cg!zĶAt+bv pKp^ n: ! Aq&MVГ U-AG<*ނXp/ *ona7!NA`Gľ-{70wLшt08!Ȱwx!MRv]Q/{;͵-*q 3@t =c@<1m 2Y(` т<u^eb`V1sЎ)h!d@A:g X)Hxȣ V.H%4k89'NilcŕhGd 7Nr*.0!D{F@i@R'gZȄ Y_:luZEc"\@:a{t647hGO&|uh$!4a?HGgGgz FD` J z/9ލ?ov|cd 9!n'hp^c9 rhp4;;F;J.m iFiJQDP8 (t9zvNI1natXL\*q~ݐv!Mt&^zk`޽s{;ͮv^L{t G6qp@$ !:Ax7npH 5 Ĕ.|8:eF-Ml _6sPGͳ xa:|̠ x-m6\Wv?qT㗐S)wzg=>#n ^fx`@z Q|ڱ$Pi tj1| 1 ` `P%8t`% t @㠂 fra{ a@|Bhf"}U}0M r |Pt&Gz:הK؄cߖ }Q8n?OtVcuRHXtq}}~8Bz ?C8~A n #ZHGcETMN?$DvC>ODD4AȰI]w}bp7FFD xq@ OSzpHp@` a" Qw0VgPs ķp|U؄Fw g0nq w@HmG Npx`9a3 V!4nV ch ِ۱]!(vH aLtD BIٓ9d?wG'$?2)ÓxiD*BWd1=CLmĊ ݗv v AF( 0 k0 ǘnhy'tp z9p ~y ԠYneitP 鍇Y tp`f9Ystf ; Qsp` xȏ uχ U탐KUT}NtwkhɆ-BEa'*bwؒ0yG) RWP9?`vOcv; YESy1tg fFPFĕyaɰ `nK &Pq : zyʀ  ˰\0##$ᘢ Fy=a? ΐl 9}Y3TJaX }m M +`N*фƩŠh*hʠ+9^]yI=~3 ELD{TGwg}P`Nj7Iş_pp gY dkj8xqZ J0P  s@s`f1j"@ 0=H m{? >CE)t$"S}yv K(z𛡴it抮%IkʠЯЦ#J03|(DJ Ji?D8J+G{LOJ1o!KRx  xnuxy ^ t \PU+V[*[`Vc{Ȫ z _ъwJJn}-; IN8 ٱtw;G4 {}nҴ?q mJ+EM9J̈́ $ow#E88MDL L9cB1+ c1 ~0p7pfQ*7BQڋ8S @PU:;u` 긎5zz0 [smjqs[h&ůۯm۟f+ia*"ˠk 7  +Ȫ?@K?>LЫ*B<@ vĆpfpL@X|X ^aezۥ8j8ml\F,ke`g K|:+ipyj_ hxuaj ?prY_pɘ|D fCɘ`u`wyz`{_PsȰj<|]d\-ۅ ry\q\iWpas ˏʲf?-e\ͬ ֜͗ 1Ƶl'5Υ%\̽l'^ڌ\lR||/,0,l1p =]>%"h;ћ "=$]&}(&M@`]R4]6}8-[>@B=D]F}HJLNPR=T]V}XZ\^ԥ19=d]9MY&`lnpt]v}x} |~z ؂=؄m`֊،X @є]ٖ}٘ ٞ٠ښ]ڦ}ڨ}٤ڬڮmڇ}Љش]cMPp`0ٯ]ٜ]}Ы}ʽܨЭbm}+ V =P =M} MM7 q"±^>-~ɑ!N ~(6 |"=S(I0N4mA॑<^>=>.$`GJNL~F&M>ⳝ.5.W]n#:T~IknOtNqx^zV>>3._._Y~݉^d;gR.^qm疾H~颮}7N慾Nbnᔞ伮n^}B.ny '.xw>{^ǎn׎팮ݶ~nNonm>>.nۑ۾ָ J昞2 * =5Ԟ.3پ^ .jnDFʞ,N;:}NXɒ\`?vLoO(ROTݿAWr_"vzh?lOS@U?_?_o10pO~?bto ȟʿ?_؟ڿ/o_SV?Q?_.A QD-^Ęq"=~Rȋ DRJ-]SL5męSN=} PIEI`x)H.^0ÐC?D@$ ,/ Ӑ6 [#AF{#kAc@'Q.zDȐVm_1ʉfJ+Lm8(kA.tpL3S$j %X`"r6NthN'*d6sA ; %O)NO4%I_,(.2TQkʱ#.DL43]((*:$"GAsWE3QA{ _UNc-OMSNOzjMQRUs4UXQ}TGZ>*9{_3~-X|6Xa̕؄baYln?ZoE9q1jXme2g~xk}ދsMtg{!Fby&{`訧F5*4C䓷n[hT۔uZN I|I|ȶw4t>VY+І}^)3i{~k6lI%CvtK)E;+^ys_ibjqٕ")/ʭֳx۱I7]ukd}yfř ?how|)}j7hzѯ#jbH~%a8}ª /EiW~w(مP3H"Osca^H6u#LQ%ZJ: h"@lBD'8Ix&VQ"PV\qgDDF8 9 :юwcG>яd ҐDd"HF6ґd$%9IJRR!d&5INvғe(E9JRҔDe*UJVr]dcC"`Lvӟ(3PԠAP3%.yOVԢM&C5Q&8=Re#D9Qԥ/=&?M:SFs5ũIoS~dTDa:TU=EGwTtM?j(,jVJѣFի|W*ұuSm[D#%L/LUYU՘]5k^V|k` 5]&jkfWծ/*Xڴ&`1WmCBWdMI$ibKˈb5d7{Y6mY;v;ukQRZ8ǥlsX.unTw[7uKvoVےT%/=U]y 5}x+VoNަU4U *C} t)-h{mf|^Js] aROpyG5m1a!xubRu[]F٨F돱 ,".r` c5Ik<'X7n\e78|fB30i<e"o_ް+L9̒'}h[YiUmj=۸ͪ^u_-k>:ձ>O-k]Z2H[73؜6)aM:ֶnzS,_V갡JԲ=f/{ž6m@kՁ՝pWܶmg'?\f|ϻx?F;wȭ9p)Ծs?3o5iZU~ЎCtz\H_߉'p{=Bۘݹ\?k}>4nB]t]ߘ݁\l{}la 8E0Bx7|%?yK~GB?5zr|`A}e?{}u{ a>=?|~77m!$x LЀT~}ws%~.tG`@4@#ARdt@$J AtPTdt41AAP̏4AC#D$T%d&t'(|Bx B۸,,#.",BW1D%/ D5\6t0$:N2CPC܀>\?DϘ+LA4 5DDEFt(D!|E[REP^$_ƑhEad^Dƌe gbcDFeƊhkdFm i|'jFkƈqFs$ o%p) qDǯGey{|udcD|!pw| xrG~`ȫԕZ}$\$HP ȁ|GLHXHኈ<09! }Ɂ̠HItɑdĜɨGYԠ?@R8B5CSUKMNTMOQL%SETUUPeW=USYZUDu[UH]_`\b^5dUeUbegeSdijTglRinoSlqRn%sEtRqUt5vxUWvWp}z|Vzl~؀V~XhׂE؄]U%҆u؇ш؊؋،؍ M EuFI5 E]F5KEEFNEFO]]EFuP-ZFEPmEEEQj`[rL[\ۇ[985EEٶu՘\[X[EEmYmeW XED\YTܛe\pGyPX`(! Տ% ZX -W\hzYօHԘ̅E]Z%ϝȭH|]^\]@uKQUdީuGaʐ8Pňc^x 08iH!9L|=߮M%Л$J \OLOa`b^U_DJUE~ fe^  a`nL 6EN\>aVϥܗ )b{ "t]`Qtbͅ^bfa;n_ 2 0Ni OycOc>b~_@d (cDLd)Mde#:D`6b cCTXYNZFC} 8fUNf\)@ýfefS(ڻf QdXevvgAwg!yg{%XMփhPhmF>~Vh]=膆舶SY}>ShURQF^RViN=閆if阶ԗ雮i^鞾iiF&j6ԡFףfj@U꧖jxuTꂮꬶӨ֭k96kf]}Vvxf뷆븖빶qr>\&6FFlPvdžȖlfɶ콶kd&mFV>v׆nDmnޖnÖm mLVlfnT]n8nKLnޖ6oѶnܕ߱>&mov.` _&Dl7?OaPpGpg po  pqg_vK& \g`qqqqOb RqanqD'^rhrrqPq,g,'*+o7GsV2/ssv;"7r1q,gO89W7nAsZ%pBwH_A'6oCn6DOΐFtq}HftJHwuLt@?VtZtu !u;XunWut>vZBudP,V+,S׏1+u^tgX2Gq^bΘb(Wswrn~on?ox4b6L?|w)usPx6x5=ty LˁpugÒG^N|7 y% @/zWtwڔKdOvwz?f8r«J?pOsHu1{tz{v{@wz|{{dwLJȗɧʷ|F:|nsntώCeDϗegBCҏD_fBՏCwD/}BwC_Do}7\߯}Dg_[_CGD}EGgO[smA~W~~p~4~@~c߿t_ϮMx.h „ 2<a &6h"ƌ7rĈG,iɏCD%̘ȬiSc-]hqgϛHPФJ*Ty)ӨR:%t*֬/ij:2gFV  I6Ȃb]YѵhzH(Ru5X5mlx0Æ^0qDKɀ;VBzmjQW+M+㟗V)P*ԡF=*Mԥ2N}*T*թRV*VjTj^*XzSf=+ZӪֵ>[*׹>t+^׽8_+Xu=,bXv}Q RlPNV,hC+ZjvgOղH-kcʶhab-pW Kq~}.O RBuu+rŮw𒷼y;E{yҷ}k;q x-i3Xng Sxe% sc5 @S.~1c,Ӹ61s81,F>2%3N~2,)+(-k\ 1d>ӌ5l~ 9M@=~3-AІ>4E3ю3+b+Ct533MkӜC Q9 tUծ~5cM-+yҴ2s]׾NI-lQ{.6Rϲ~6-iS{зFrmsޖ-e{.7}#~7-?r}߸v~ 8]vϻ8(73q?Ck_#&?y/Ӽ8s.N8-F)N:QT: 3^:3Q?;ڝsno{v^~v.x?^T߽/zS^3Ok~ 7r/7(7Sz'멎ӝg/tݯ}a/cֵ=j>NSg~蕯+z>~"??ӯ?/֯>   &. 6> FN J^ A`t~  7 Ơ ֠   a W@;PKp0#77PK[EZFOEBPS/img/rtdt_ruledel.gifsGIF87aF'R8}klkrsyߜ]419tٝX2455Ϧ<@q Z D+hcdxz/XV4jpSxgЖ|է,$XZps̴5Sw2)yhx0knu4eOJ!sq tPǪVUTII6rwX'pT·8зNx8|V2qS TVt*ԗ\Hs%1 tVv/T{X3WYadՌ02^d}yKpZ]6ǵrPֵyyz1D~LjO||;ik, Х  I$$)12'*\h={"#Amȱc&ygDC#64$>lt#>d~`ȳϟ@18p K!S(d .hyӣ]9z8ĵ6aهڰ?SٍX'Èscp ZgP/ ADR b~=m6&=ZBo9%{֣e6EDb> \M$}97Dسb1#,QNi|tC/ORwY@byhnC$jWtYW^ \q@ fWa,Qv$h≜(@w X B`LzX:^=.d%C Mf(@"Q~_"QN[bQ G5!u"gD΁huW>9)fI {u\tՠ\(F*ĬxH@G^I<*DjdM<N:PuRlF-Y}kf@t\Kq m>r{ӗ.+Q\ڀ*J̘&ymPDtN-xt q>3̱yG2D5",r#<\p>MB @r&R b+!.N6)e#EÖYij(a! F(vΑ thf_ W sY׃Psأ+{28 (4lO@ wg4q1c96jNSM؞;`yg^̮2@Mi"쓂!CR} ~.%[mDO٫Ȫ4*B>&Znȵ!?hrb9Hqv^!䨳ih9wVN;GxZԸǕ/ . %vYӺO}r0s]/FoNv* XNi2p(Bg|h  d'`Q] #e?,&j"1=B@7 B[!jo?6:d %#T0Uѱ7x$0`=42AKbru %cx2|:xН$! qx`{P$բXjX#Zw咘,X#˗<'9/}D(ґvߚ?Bяk_5&#-N1 @Wr湁 2ihzCF, *ǟvz:ɬp2 'p I(7l4$أg?40AN`AM|&PwHv?pVoPy@ تx(ZQ0)N)"df;@!x q׉&+JBY,t/ kCFsY`&3m}+HePK Q $ C>.ib;0ބU(d! iBoTt$f(m{#9k7%:ũz[th ++Z]ɸ ׾T*bqM@bF^D,\D ug!"]h!H톍HuG*w,6mٝew7a8@-ԾWHATU193^Ucg(m*]#Bg䃴$Y De X2>]<7Y|"HR.  ͞,D2k"vγ3ShMAe;xъ3'MJіδ7io`ӠG OԨNIaUհheMZZ֭wkEa\f;[+(P Ht&n{py0r],H MoUfPȻ8 H3ML1\Tx-d pwF 6`ml;\f _x [XYnr'ϹMp( yk p vz+:MmN@0.ȃ^'P"߷n|fڳta8߹.|{6gy6@!=+,iP3=g3ͫqG] hHwӠz2reTM;W <`'!Q1yFЏ{~q,L|7O¬adrl+^F_~>˿}yͥopWswrW|wws too1'~nX,r~2v(sPW&xmr%28' g/ 6 s' 1H@BXFlDxJLPk TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~x P8Xx؈8Xx؉8XxX؊8Xx؋ `XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎x8Xx؏98y˱ ِ9Yyّ !$YY&(,ْ.0294Y6y8:<*@=YFJLٔNPR9TYVyXZ\ٕ^`G9d)C B"YLRYNpa9tYN vP9|ٗ~9Yy|`閔YX I2 90U6MI4H`2'0M0锌| ٛJ9YyșyٜUhi O13Жѹpɐ2@ )*F@^KI0 O )[ٗBCSf=DDP(1=YRzڡ "ʡ Z&z(\.Ȉ $ /ݹ2@@IDH`ɞJ)@ij=P=pW j)Z%w5D xp<zP0":I50ofJ#l|ڧ~{ʥZɢ7:1 N4 6 6c˱=b@BJXoF02HPOxVwǃM`0$ |yI`C})bCPRZRyi:P~rP`PpPڭq**:ZzwگM3 & w"jʩ1BpJL Ma<*80(KY:%0 Iz*ʬ|OjzڭzIkڧC5fzXjK5`b;Zh+EB`.Mp+|\~\zL|2籭"ͭ%M $ʫD*$]6굮<@ ܐBCv@|ƨiˆӼLyQ@c}l+;scp΅lklڊϳ[S?jDDTy|}1ЊM-_u`m{0Z}Ml.mIP3M7}ɦ9ӾMCEG͐At&q cb\VmXͼ)nM0L$ 5>| {) B 5*ሩ)2H`w vܗ{ } 5'Еmuzx*# =~;{R ۱=1]vۻQn䨬}XýY܉z- Y `AT-͐&-d= QHÏmS$MDP2L`~ 6*J^yD~:Ђ0KЫ\l#;,)1.Ъџrsڊ~έnOCJ1- ҂RȫY\_")86L Zuw!y^7aY^+L.CLj9J~$Y*Mп^"o䎨~,.?99~Mi$@s^i;Ra ? O o'P \NY,z!d4_in:<ti)FPYL9>l(P۾J9 /+zi/i(9J9uYloMO Cɸ_Ӭߑݐ,VI`iuO3;9?̹#꟯Ϝ⟑ n@"8HXhxX)9IYiyp *:JZjz8 +;K[k{;t ,I~n/?OO+}_;0 ;k1b+r+1U;z2HKg1JQ[|2&Õ4k83g<{ 4ΡDa:թ<8eȴ9;ڼQ'X?<9?pbt[]{'!G˛?>=w=WxxW`(Mu{- } o "'@ ,@ ,@ Hbn`."wR6a` * @38hbF67lN>98Y~3|g 4qdbH9jyQY}aZ[.gwQ cF`W˕َ iB9Jə5g]У$tYiEP`P 1ZiZ%j 7&ild)Zix.x **jz+$𫬡麚gj޽2"l?/bUmYע-= @$0FB{j+ |믧rhz3 걾#3lk`DZmV_]wVd-|. l[ş6B3^Q@<˪ڽt f@Jܮj۵*ɌK8h}֢nqOmڨ=F< {6g Ѷ*ڪ~8nxrM?r.{j9X./iOɦReQiL8 0 KY9|.4~B:A1D̜) ,OC)l!{XM! YL&\ y$kOE/ьjtG? Ґ5HOҔt,mK_ Ә2 nӜt`ʉ0:;ʣ(XIZ9jhU ~Gڣ  :ڝEJ ۂYĩJ~k)aJcjega*ZXʥM}Oz.*VJ+uъtp0^n !Faѧr}tʢ8xJ*ըAQ@j"Y} nbҦ}":Zz qtuPtGA. 5ل`ʨz#RB@1'hHj"늮J*Q1?ˊ*&jъ`0PKxؚRڊ#ZA1xRCzlx}90Ss)1:`Rs(X5B'kpsi()ڳF[P抇K;,˧ʩ*MG"[1 60IP9@1 "%YA-8+16B 2Ekȱ% R-k#4@,uTK⮟8Jkz۹X T« ZKJ!$4ek$gkKQ`s{+?:v?$Y-zѯ!JV; !#(00*~sI,V0NR`]0W `ɺ <+ i˲ 체.AKE;-ѩLJVcd[M˷!m!&+CuŜQ?){RKk @?VZ{9 A =Ph,ls23"ɲҺ]QS@³,S :\(+`p=,^0:<`V ˼8E2;H͒8;k C*x$G^3@E#nżKb Ɲa9E:l㺷SF1o %Rڭ l`􉖉|0)l/@Lk͕" %K. C<36 < ϹQ4K&*\һļ:l0r+f2|0vr#- ѡݍ⸧]QI0 \]ӽ+:}K+,UhDm˜EPnSվM;=W=I >ܶa-cM2v֦1ī0 o\2 ٠H*xM\kTݴa*͈׼x5ٕ]@M1#PSd {q$pғ9$:Q]=Y@l;+EPU+]ܫl6[V8jݥle`46h \rm1 Ktp޹?mޞҼ$-^-0\~z|~%c~ఓK`^ ^{.уYb*}6IY;n*Kw!۸,H<9s`1ˮ.% PL` ?,EȜxX Hۺ^F橁Zo^s]*tzj~?iB,{㳢Q>_q|l:9 @ȁL6 @,s/-h+rެd35&6Q/^ b`?~ XU( }gHlQ,jHV%ubABa1UoKǬ!^п_O1X/ =tv_Mf[l$y;{+_us܅lb?oze.K!Gk i*?/SЅlp;PCٝWI~w1y/:UWZOSo`8_w ŬժȂʠΦ蘙z& y!LȰÇ#J_@uOCIɓ,zJ,AA -18pb.Rϟ@ JѣH*]ʴӧPJJիXjʵׯ`RRى@vbp$F5ݻx5IvF8b-#"QPîν#KLrfI$8 vNR]װc˞@Һ Qqi+_μsz+H ֋[Ii z!o˟O~-7,H $fcY@(!$g߆v5gUBZx&iA<lAψr oTs6Mݎ4Q=TO|wmI=!9 ܴ.9si#bquPB.@;)|B+񒷼+4yX GLz8  HV @΀+qhcb@p}a/އsȪ)p;uH`@ `1"p!E@jGj!x:t`[A*BrASЅІ IМ b"Ic⪈xKhJOJ2 ( %E\a¬A/QlȌ(@A Pjb42rScX 21aIPM`H!!-r[ [$P zmE&T@*JK* lBUM"LD) Ґ0Gft Y'tDn;Ɉ,74id"r*Jd!0 '8hBj wI#Tq!-+Ae]G#2)R-R0"(r9YB1)21 LZID|4G@EDMSV}PX A%dr+&'D3e2$RTSF$wXD,qY0#2ZDoJ _WkC"yTX;w6@pLJ@ *Dqc03Ib҉JsUDJ] G QZM}J p |%VZWF;9kחWFبt4]/($6\ԙ0hIʄh\&5 TMfr!`V^ЁOUF&0#]`s005@+DM" M,"llQ`q!ȊQLME>1V$#\M @&CZ  ̀+HDB@Жn $o- tz=9(+ܽU]KOXh.1x`G@rTִƸqCp׊2@ @Biĵ16"Y7 d, GBs$5]͓0N\% |ɺ@6_fO{~rux;Hh{!rE$ټ&_ dh FU`+ЁM=1œRh#A/oGӥztizmG ''Ö6PG`6@l\eW u'\Ƞk#2 s#?gnn!8lyg4XˆSWzIJSc xB/("Є #p  [% KJh!  Hw|d憭84*1k~I;8TN1"4Wpm-Y# r YxQ8 ] 8XH֐򆈐c&(/uA8 (,Yl@2"фzb# !U8!0! )Q/S)X X ta1' oD{*8dd!/!R e@ "( ).riR!Ž F*1s88:a8i ib HAU8Ry%$'f0Pq)[ىX(╌\AaCl9C$7z 8J 6i#b])%RQ\Ўt +u FPyRHh0bX+[y'OɑQ!e Xֈͩș'2ᖴ v铮9z)@beiOb؄фΈH#ayxM bXb 1+2IPؐIC ً ^&#c) } @J8@xyi*,ڢV Q!3Pq@ 1;oY\ BZnYYY Xw%tag Tڥ pzٞiu0qaaxj UZ zj|ʗdy΂wWq>z:9 2aڧY+ 3_ 3JJ :V* otZ+jphӊF3uz 5j/j PZrڦ`V$ ^94z"  YXb{7|%`q1kP&>[}yWo!;!;PЊeE۲rPI{B+9ԚuEي$ %;IQHKKQ2+RXk 13[G >+ p;l;EPkWw!Eۣ[wU{o"*u˱5\5`{=$[k[+8E]WI۴󗹪)G;C;; ?+D' @CہWqW kk󓵶V@D@D`@hq* XdA8en;٣þ?DkpFiFFп s0;3k*15 BCǍ0G|tꐳ%S4eS8ST'HВR%ّhLȻʬ<0\b2؊;I@YtYna2YOԙ8Bf̙1R ˹ʭ<ͭ#[ 3_EP_9z")q# 霌ܙِƪ+Ԝ c#<۬dQ S&UfRɝx1*!*ٝ˸ }0;L NkVkpk  f3a\ٙ !}#$+&m( 0qGKM ;qHյH՛czv'Clbrmu- tMs~׀m|-M؁ׅ؇ - $Īْ=~}؉ٗ ٛ ڝ}V٥Mڣ}לmجحڮ۰=ۢڵ-۷MۦڟcU`Jl\{ {sNv-@ݪ`0HM%=]=]}-m=Mm^~dZċ ؀4C-0n#~%~ւ - :"H/DN37ܱE{\ zV.P;W {JKi`fn^or\l`'q>|NJkZ爞uS~杲闳R)]咞?JI!5~*ꨞn֦γlčܵ~;)8 ^䟎^~.ƎnT~n kjw>b,}&JEcY v>qz;cܮ ^ʎJpG<7yB7wWAV؃[ þ.lf":%3</- P݁c-?s />H^@Jp0&(@ q-h3p4tSV6tCB/!_N@V]QLoz_TSU1қO\_2S68ef D9VTPdq soM 꼰S[OAL?TOo\Z/}$8c&rj9j\e(Vmsư~܅R=p%z}]yS@{4 TPQ( )9IYiy)0*:JZjz0*0*@*I{`;ܙ@3p} .>N^n~I@0= NY_``N)PAB DD BκqUˉETeɓJMa*LL`!$fϊ@C=ʄ4RK8}ǩbUzV@=N<. [^OK`Rn1mQьW >8šAz/=['_"Q!P#XќFh(xFdflb0")X)ʅ o okDrQ|.zjK{jx6XhFZ =# >YNo,'X4x@^zp_yNHa^xc@&d>ftfgΡVZ^H0A) B(h`h(yЁ, T^I9OaNY"mIv^ w߭ɦ0&yS\}E"5و+(@T #1xwS ,@N J,6XV6B8gJjhȡdcyb"bV@(2rP!Q/B8>TBATâBCHҁ*dK~^((U%/kS0XKIcEC(]f X`0 pm~ij7x_D(4)ҺVn( tKzP^"Щer. s̉ Ov$ d@ZB ci.*PD*79qmLKb BUKFt U ӽf[hRo!=Q\ 8R)37ep%!3WE5l I H5Ğ*/}S-26|AxN{ЬaͪRMΗ ?{f+B0&,':2?l#"4*aQGbh=-[g5m;UG>%cEp'_b'JN ƛߠO( SҀ]x +P$6u(ס. Jf͸|gcT4# 0oJITg(шJtE/ьjԡG?Zyz }Re?ɲ@I$tH49@C'zqSA<) 6;v+9ս~{aʡgv=s{uN<1iqG#vfY(!@>4IIrx$wTGmQhlX+u >Uܣfz"md|||=%^FD}~ 0>EA/Q;_uoUl er#5`9a'w~'H{5vAaw4H'N'd6VV@)'_B с%xIXxVfq}9@q _~\,8~~';3Xp'; G N' PR7u]*bV> zXru{>M؈4tQ0=yzrD_GIdGp-<HwQvUp+oh0dCYҊQ{42qa(~_cpj(3xhrx P v x8`zX`T1 ydr'(杻Ĉ+(w5D}Xeh1_8PaJpը 0Pȏ9 8V9=6]ɋZ\_`3/( KNQy蠍h?j* 7 h^v~9А:''X54hk/x:7J~Ui oYmVkP\Ɋ`AHVpEp$G[Dٖ)) #IC'#@ixUe&^8n ui\r‚=xdz p:/{w4y'$/~'H{ hi#{2t*H{I"~ɝ9gy5 3 e0ZiyI}fD wpgiW 3ٝ߉x*Oq*R mb J jn=‰dg@n-nJu j(jgJOڞJ (*m2 F:b1Lڥb m`dJ$]ʨꨏZQʨEbsb֣`m46@9`` g`0p *@^t wY:PnЧ,e`$  %^Ê骮 pO&)jgcgJ~Y ^1ԫ2Bbrʰ^k z  1Г `jiiƤV@-Y7+6` [Z e%\0G+!+SKƊ2jֲ\2+P8+bKF q+m۴U˷}Ю(.VY^ 38jHtz{:@2%Zk\7dl6+ ۪}^P˰pk˫$ۑ+;Y{xzl0^[rlpKJw{ZzKQC*FZyz6P_PLLQ n̚ N: 0/{[{{6 ( ? īk6{AKCE|8:Ul0R ^ˇ5w_ 5JaiܷcFܬਆ biAsl-ruwLy |ǂlDžLȴb}ȃ|ȊȵȎȈȒ+zLɝlɕ ɗɢɟɡ ʘLʓlʭʧʩ<ʲ\ʯʱ ˳˵ e"l pFd1ʹR͵t͎ ,Ll<\| ,Lm  -MѭLO\%j)}y4|Ҍ5*m7!W5L۽A-Ԉ0ͽ2_5=K}Em1-J}WRUN7l&m]*GIgu'!^Tsma,%tb:J Әׅ]vo=qm؍Ԉ=ւ@ؕ]Y [ז) n-H]{٧ݵx]ҝگmŪ]GU4 1 14( h"(mpӓM1ܐ۽ 0aȭi̭]1ݾ =X_]SQMѽ(` ^M֜mݛ)սiNE]֔m#x^%~] 1&nɅ]E {]7n乕$=\>-BWGn奕䬽}]>Yn;]e]`Nۭ}fQoqm.psX}yj*N܅ߍ֫jNҖ/NEZu>n5~]~SNڞ곮].M빾\.c[k~ZY`'1f]*n*ѮO=@@Eաl@0tqN ^؞花C0 D`2tǥ Z(eK` @15 ~*p _K'e = lXٜ.! Ā9-E2g  KT@1OX  bӠ;?AN3İDiG F39}q $L 1 $JLUێ=O) M?1 p p , b[ ă䈑=Mlnډ]0S5P$po Ez_[)o<ُ>pNIS@0àČ(lAة8qb2p1GOqMI3    11333ϋ31  ތ;< P B !EO[1Q˴ 0XA3p*h!ZTz@bʜI͛8syL5kشqnQ8q@gn'P./FmpUu" 萗i41H[WE{KZE`B壓*^̸ǐ#y +ݾti:$nF7f}UP"hͦIVVR,Iw};p*aC"l%KN}$p̌rVʴA+N} =5!]&ޞ4ŹFx5]=GJ2I$ޅffW[5Q3^:HQ!u.j B#. ~0.V%!(RX>VH ,IXXf3Qbwٌ 0C?hU]Ÿ ]Gt`QZ9 "梌6裇NCY"Rx^J'_z9Boc\+ͳ) gu]~}]hmx6M6њtynXrc 8/M8┳*ITQ8r˼䚗h/BAHDC zPp#O"ƛ J2U)פ;;`O#C W޼SPï䋟Kz=Me`yF'A . z`/ @.׺`0BP;` 'ӠxB @ hA`} TӐe1,c{** [$l1u 4X 2V X;2x C !ϋ\b"'CZz˒^x5Y$OǠQu)` j4ri, } gDž ,9H1;4'N'-Akp,VqL.8P4qwCcB lQ&Mp,(Oi&ur ""g>Ϋ" *'%z4Lٵ}>0,畖`[W[_7&RD/5%] Un➘ wӕ-0uxQc/ h@$ H2,b2jd=i]83nE+~M1< `wmcF#%2W9jfDfUxiE[Jb`!6 ppW!Я~eM`1L(材9saKaMA=:~^Ɵuk@Xp euAIK* 0Ɯn/rO"˦%ReE! ݻ`̻B9h.! lH2$v7Oi#30 %0Wʙ5FNr5(ͻ]$ p#Adn-g Ы\5c s2:iЇMoX*gwNZp(ˢ`)*R,M## ضF]u:jhB?Q/"@ 4<k23aji>0@/?2B!ַ Qx:Nؠ94\r)/#'{OE}QHHP0sd/W;}eThc,oш킄_! .ڧYnj{ud~4Qvl2=oMQh0iyW G`CVOVŤV}Ea0va2@ ndg?p py :jo-(=y4@4z4;TWJTJ&|g$i( xCIBu~}zJjLbuTfwJ$GvHJfWaXPD-8 ,XdyyePhyzwvTg$wP &7[U ^8ۤP:ky~&{M}Hi(NDNoZ5siAz`s{Kvߴ`sX]ڶd@,ab4猭V0SCOБ6P 7;Gp#YG`g g{zNN؏Ǹ ajbjЌSvP,u9@0J:PQ7HC;P7Q~'Q}#R@RV QԄCG'dY.hY̶ؕd=E/9Ζ9- 6Ƒi n\gIw] bdcK p/(p)Ho3Њ9p,EzO 3 zf;iBN!T{=  YHƆgGeBPy(AEPTuhqMUWI"TTUaeJSeUBY59Hv:e׹ENSȝJTT>vcaC&.HVRqڦ`]B 6Pi Ha !v{)iƉW|;)8rqZ@ zZ|vOhe"x3uکҨzVzl ڪ.jyikmgj:6 Z;˷JJeFHY8kkTMEXB:EM\} j&a .ǸKGGPNBp Ŕ%SVٯ+{d=ǎtNhWt0Z!جۯQ7M0~9`U䀍! :75r(KhV[4F*0kɳP!ʪL۳ct0MZY;lIC\[ഀ ;K3WD;s){Mu` ˶eʱj4ʷVO7;SCA!=E j}9 IJx| f bJ:; ںMzRˬ P}\jj{e[ [S:K {Q{Kћګ {.ỽ+K*[۾{Q)뻺{ (C;;# ɿr[Ukh̳ܣ9 ,”~B+*$ &\[e +\ï136âÀê@|!*ēx0\΋P,|JL(lQk6V;>b\苪_> ZN1ZrX}|)ܙHkm g6PaCW(%@E0@֝p0n㋎>C@5 @rLL>@@ ǀxa]dܳv:~hc(EO(ٓ=Zq[pL@=06_ 5o [~\Npߺ@0X|] ? #?+L냈I0^J`x`KxLBm-$p5`n(~ GpqN 0 .K RfnXe i^PAh_DC:`*յ`*'@5># 6_]7_&p 0 Nh n(Q-\o ֵin].0AHX3H(9IYiy9P0 (01!+Qq{Py12"IR3\{Bҳ:bZ$!;6I?Y}˘$;xΝz0NR YP}!}& @եR D"!ծ9ttac6U ,0W- ~MeC ٵ?hݍHb&8bA@G6n&u"i2@Y_5ЀB: J.dN> eRNIB/hی$ɋ]c:z$YeiHfn grIg)]3H]II7h> iNJE%yc&0b2@gYi'j k>gFzjY#|99(Rr@ʲyl> m>Ykm{+!^VA)*N (枋n;Pjʥ2eofS6گJp /0j^+0AWqo{F,ot&rz!r'%Ls6&8c2BMt_j+غ<ȶFtROMH[6=AW vb3OZ3vn wrMwvߍwcwxNfR6g˵ߎ?yk%c<7.y:Ɗgy'ov誯zN:^Ț~f{{x_~h{/K<}KO%3:o~~Wrw~^/ߏ?ٵ+vl_*0_:/AIQ|?ئ "$, G$p,LM [ʰ!/ oC0kSQ 5X* $$*QZ ( kT%"m7Vr0qd,ψ4qll8qt1;PK!ssPK[EZFOEBPS/img/faq1.gifGIF89aQ$$+%%&++:3330Y56J77kVhHr:EQ5KwHHHCGVDR\XXXNTmLmVUdqc]\k]iehkinslrwqmoyyy5;EQ f+R'Z&`1k\m{<\(y1j8y?`VV[[^lPw`_jwt|X~dd($,000)8UAG'\\NNYfrAffmkW-i6\CV~rHsc|J|h01/1)=OXHp{sSTJRpxkjkc}ssp|Ȑwq64   (53u _NeUmnXTUOkLwt4= 0DJ4L_/ok'YJpLlgwB}kZ}SmzƝ8Ѫ3ۈDښnŤBƦkHxN1\jẍ́˃هˋܓƗʖؘ⨶ѱ͋ɭіϹ뭕Ϙا֔Ӵ׷띐껲ȼËǹӹ!,Q H*\ȰÇ#JHŋ3jȱǏ CI7U[ɲ˗0cʜI͛8st9O_ϟ>*(ѣF"])ӧNB**իVbݪ+ׯ^Â+,ٳfӢ]-ۧRݻx˷߿ LoÈ+^̸ǐ#KLyO޺ݬ؟/8:4ӦS^ְ_vM;vٶs}n߼ NNj#_y̡;N}uAW];ꁗ я_O0{7^W___&(2x5(!FHZabxz"f"l'h+P*(c48e!"<)A&9L* N$T>iQ"Y%[j dzgޘa flm ^rIwf|)h:hڧ6Gf^hIi|>Jꩦꪪꫮ 묲J뭶뮺믾 K&6F Һf[&+k覫+/,"p μG,Wlgwq . $,;4l8<@M55 /cL7PGtAxO=sO='`ͮBmh6c$p-txw,|yNjX#NTBuԂ .dkn騟Syz_N{رt~.:>OJ$+/Μv0mXs .c3M|GϫK.+a_~l3 Yf@rmzlg\( lxp؈Fpeȅ-ja}|F av3/~?Axa|3 S0It {= \^D bBЀ;t4Q0p3/1E=aZc /Ff̑!P R>dq2m@.R-l i1VV̕1rHAҐT`.^.cS8N$\nj.0+w9G57A/6cvH'#.XҸFVEguTa$Ge<#8kZU5g\quNJ{ܩ+\C`R7m*XJ7)oU! 6(3JObW'~haΘ06-P.sx03`[ ; N~#8"p= [ /la2Wyue3bS+hZ֍# 29R3|Ura5w]f޲In5tk\qTRx̄&2Lj:0\!s1y|^p06jg\Sl рF-l TMNv'l4;'=mi;vMmmOV]o{涸uŐQ:us-e_wL/\۾v^`X˺4怋Ħ utN7oyףO2ӻ]Ū2=\&6|7hæNPOFygK7Ϫax8tM~2Ep[bcF4 h8#С ` mo;'ݾh;cy` BBpaEcĶŀd xIѰơn :n*&1vt ` GZd t cЏsP=Zp Oɜِ өED:.U0;[J8]*8_U8SXC^. yjpUYgv3.{j)/3c@Sw `^ J.} yh+ dy !* 즪Ȫꡨ& x1*nꪜ֫:%z (.G ` CcAxdtxڭjj9j 3 >S pڨڧzz /? Iv碰暮Zdb[.+V~[5# g@G7 @ ]˯Ҳ- 1n:=v5;1 .媱êɘJ ` M:HS{zƪlڵU b۪cVXyI/ԏ; /1n9pw.|k. <{1=ёK8Pzw;.5<$HdC22J;!»Zb۴zZ뵨ZK;kԀc+Oƺcp6k%벻@ ˸Bj@Dӹ1R/۸K+K. 0 .$ĎJQPk]˰++N|` .-@=F]HMJ}KLNM=PMR]X}Zm\ Pb=d]f}y []@ , =z o{|ׂ؄ ؆=؇]؈؊؉4 0H;qٜ٘ٚP ؐ%-# +jw %ڰ۲=۴]۶}۸ۺۼ۾=]}ȝʽܺM P=] ]ҥ,#j ګ-=a@M0P6- v="0(l&mō%M)^~ ׽[V$~&(*,.0>2^4 Y0- ުjvʯ} %R^ Р: Z[>\^40 f   V]_` `0 M.f;n/Fs[@ Ր([n>gN^~n霞靾>^n~ꪞꬎ ` :a!پ9 ffiqAg_^ HKnϑ^N:D R~>aP 0?0\N\+a ^p un pc #- O.)p.^/./0?2_)O7o(,>'@oDAE?/LQ @`4,A  Ϝ>O .P 8"%~S~ U>9 䔟N #啿%] P ܠ`CҠR ` 㰟/p@t0?s0 Yp \n ȏՀp"˟_ؿ/Oo_\ @yA! "xD(^ĘQF=~hgծDy2W)S* I5д5'gZm&5M;ḃ.9c1å潛=I6n^ 'VkvLJi: agkv# FwԦo jH|ZQM4Kf^jRL{:g0.X̙#ϔ$BI Bօ3'r͙?wtթ_vݹb= : 0_KB;_|g Y^KiW¸0\&[jl&DJ2H殪j+I ,ɺƬh#ⲠWRѤSԱj/tQM6}x&0AG-FN:>j&-}х,P[36\:[L*߮AAȲP4DUQF]4RG%tRK+ŔRM/4SN?4N#f{.R%r:0Z5` #5W]qugVA lG0l,Tž < Zz:樣))?J{RDrq,U4E- Ѷv: 0b 4ZşybE{gTp! T_ &FYď K8ɢX Cq76ɶSxROsN8EuԤFifijkн[ʩ% nIԙ^w;n'zT5I10 @CxMrC*~HK!V!w6ٯү!xv}\`Wfc-^Gb YDqYiRxDx D(A1 zSC uzh`8@ЀD`@6Ё`%8A-q"B6HblCxl̈́'O r@ "@1L#[bgg5v 8yheh*X]$F]3t!` ]+`A0qc*Z7j000F=̡tpg~+̱ohJ:d70͙3RG `lF#!],@][`i`  tE9Ə;! 'F&jT`pLuRxBJ׼EozջޭƢfZUp"/:9Nׄ*$F,(Xϸ W`Lh 53ap^"* zh' `v?$׶3Wu(!C@hB" L.`4`rBС>a 1{ռf6on3FLlW0-_<";U (a/ h$Z_ 0M>Y -| 0W#`m7jX ^a:56 h2JQOz4p 3#͂50XԾRW-9RoVwU0mp`pzwų@%*LvnC \8,e$A,s"VKc핷#jkК.$0P|徃0 L`dXGn6aaT.t`uÏpLt(umwuw}xvĘDT1pG+xlǼ|Jgy?$BP˵Zb7V,y1,60ьgxs+?_09t'?~ ~w?׿8ݼ o?[ɼԕ Wx>#?ˢ``(#w_\j@K?d{k?  A,8:"#4$D%T&d't()*B8@œ=С(* »k a93|h7\729:;:U"@DZXj@<\CR;C#w0jDtC7dLDMMFPQCOES$EMSdERPlDdXEWETZ[^_`Eaa4bDFbTc\dXPXxAÆghtmln/4IDXFZsEft,EwdU4\4xFu|}G~~H$HRQIdȆtȇȈȉȋH\[ w ȂLHD{ǔrY\ID|ɕTɖIɜtɝIɘJIJɣJ4ʤdʥtJlJ|ʛʞJʫJJʮI KJJKTKc9`~C-dDfdە5d(`.c-8)0Z\EcoPG9vJ&XjcjSa}-c.$^zR+vprBUѩfeQ\@' 03|\X+a;[?KgeL]Y;&U#fDz.Ig,c\bՈml|cL虖_5Y]duueYuꭦF~6qhh݊?fUkek:e|f;kYsa\ڇa窖j6~bވ)&S>NX~fm.M5].Ǯ룮iCkcc\FgĖ>^^~`k~Ai5aZT.Vk hD-mc= ¦n}fm,e؂5e e>o.ejmj1U-1@"ֈg%oyp삭l4.n~nm")=CFsHnNfqi΅чSlk [-~juzZ^" PRn.rVpFm@eo!/F" &oVϵ_q%7/'B?ӹb1$gnh.NXcS5nӄ،Vh:n;{su@>+P{ZhTT\]u^^_v_'`/a7dGe?fWvggghvhijmnovpV|'mJft%qiJ7Q”NTUO >oQV7`X'^[p\쳖xxέx'y7?GWOgywyu^A7ZƝv߆w~p>e 7z~o4;ZturSnrkoѶw{-VrNzDSƅ[{O]Gg7>X*߇{ۛy/W'7G||W{uw|h V~r7u'z|!SQMrbYV}շ~0/7Mslÿ"pp.x}Or`\$(A~ Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*-՗2gLXe̛:w<_>~B *(ѣE.e)ҧIET`=[s7]gSJ"mZfջL*=?ʜ5%_wkF*p4v<2m+P&+̭Q6W=;lPs%LB3L-XY9۵tMg,ש{3B'Xx):AzE }@;lOFa9\$_2ؚ2H?R/`.g6^M3bԙ&Lc#n~3"˹uqf14J"pTzP/C|ǧP9Т4-mgv\E}Ѓu:2@ ҍbh;e:Sli1]Wvȴ~$~'Μf)V/xRUgaԭ|,x?RNO˘T1'&+^J\xCkVdl|6JC-J_͌"!]Agbi]+DI5FqCX^0ͳ@T֝pVvuf24x&\i gA/3 HHxN[t%Q/Y J B> .rcjf(drU>=lo]X[$h5?v2\]3̏2ǣ ~3/"qnFxb:Qg_YMBuGX)0}* 2dWVj\m=Q{RV-!"f/Xhz430k{zq5'b\@`P؋`Ze'o6yM : Z{JB${^?C9ZaR}slDn)$ S1 %Z)0$ ՘a>TѕN3"'whVK Zqa%.lbP>nfEfxizXw>. ?A*iɲxAOs{2(֛C>(?jJ?zE){M ovZEnwWg.PGc/{sv',ѿd tc@Ŕxrm+[eG:/qcqy2n=]FPtϐPGJm hTyET[؝؁M^`M?lGD lJPYU௭G%޴X[qpM._L !FTAxMLĝMY f|WT]Y]55` M4Fjf-_|lv̉ț[ !‡(a猝 ڟ dFC ŖQVh)b:]ݑIm%{l`vxi A``'e^\r,!6VY|QQ$`a/n!^0fS&j"h#.VM*ӎBS!( &"rW} (/P :N1g r~(c^*A#"?!?,΢v#@BI_9(?׈:#EvP;#gp$ B3Yr4ZVS5X|\@v|ܙK~9"O:V$PL&}2ңB e(ZaE>S?^JDfiɝM*,R--e0ZA_QQ.O-VH3:M]ef}+N]"|#C9HTDeZN[ʇFb(Gwd<"IFdE%Č6 @l$5Y#H!efe߆ [#1%gV\36i4N%JV%j>fC`2Hr!f"=b5TWicJOyDeG']>%U)IVKN0_rFvʦL~qU9dnO'HQ'FfdiSg(&&x)I:giV!UVh@* ,JZ-BƉ?e_7H! fI~C@=:!7zBm}0}_Qb򦏞PpvF\ ^f.E`C-d"䈢hqf1Y9Y(FS$Jפ^jZR*j~Aĥ**ZJDFD* Ffӛ"Ig^H~xRi!jc^ ŀv4xz:엻FnDȸC*h(GjGk*lؚiq%r*Usye^_~Ve'Wzǖ6Q8Ⱥe:`_:t9pMFX.dn,v~,vuE ʞʦ,ˮ˶,̾ D+Ɔ,rB,-#agʢ>'MU^=LgNUk,̹}ЦΒ$,ϸ,ۢ-ۯ>d" >N)VVrek6tj1)u>Tlyfޔr"٭M]a'3+T0&Uat/Xm$Lz%liaȪnȶ-^XZHFGr,®ZZoڪoǪ/iҶfީ-nD>ó6z.,9/@&TbEƾoǞTJ|/{Sp~ǎ܆pƢݺ+m i/jfPfNIJB0Dk&BB!r'a0p.oS1Z/H0ΞVzTszNm/Dtw/C1pbkq g, /_qo!k W0, nTRaF 0`" r'j#=os1,/r2bpmQrrr.kp031_D+2,23&s-r323q5q6+=0]Rro^jvWLW+.E)KXRx#y̓F1 ,S/ tsG./#D,t1ooQBtB/[?l,ò5q4q?C6_sGqHot6rm$C,zhIRQDe E'3(q( Eό8 9.>g4rJOT-g03+1sCC1YC5HOr_T570Qu6c5]]27"B:%Q[r3J%R%?=n|vM=>*enZ/^uIoz5EWj5wujjSEuh+wgSTho[s,KY_ k:-&cE>=i6/ n<&xîŏRsZDT!?KF߲V1q7}qzwk\/4!u?6{x"5"x{2ѹ\ oڴh"a?gr^nBn(BONJ>xe-9d>7VDmpښvH)ru|8 mz=$t%f=0BB0y#1cg^Pcd?<L >nDUxwհnoFg 9#xӹ{K'& CWX3@0:+5Pt~VGkn󾜋H6 X)>m{n:4t$4>o2'8u8Gs|wƞ;{qgӸ87ZT7S3 C0 ;b {rL5"lǣîe`k[ĺ㬳hsv|4r+ȩ(7t2_;<@:4;{G Sc|wſ>ԃ ^|$W7n=O=sN)ϻgmMk>?胾5G&Ux?>c5M/i!E}bB }uw#LƬ,~o'7>?G>OW>_ZĠsvrF6džˏ2+kc T)|:П}L@D>E;?\D|z838P=;٣gu76>Ͽ~>^Cڷ~WNq:$׮Lw= |>@_zݻ(q/ZH1cE9aIPT!A/aG ?| ogN},HRfQ%UStiAOF:jUWfպkW_;lٱh[A kܕ3Qoޏ|n{>}湳Fٰ``W!p;Q4HDn4 [v ڵʺ+F%hxqǑ'WysҮt[;`+ax=׺ iP3gkOzoiySi~N.`G~b&4M .*P 9A -ZpL "OFD#[`Jn)HAz;OJ[2 ,(KB.1,3:ԢҮ/ݔiEגNIÇ6kcǫ~\H l >Hs?3ё`pJ*JJ,r8_* ,SQMjW-ָV%lJ2 1s 2'{2-]!utK,mkNUDeJLU-sjͨJiV ])oejQRgQE"0? 2";d$֟jEs8>ǟ%v3\HMQNyLVr%O fN|qֵYyF|1X >2HzzvtW#}xJ׭l=|񸦐ߌidUT0.UVo:\e鬾jk.Ox]o`b9;d'ci[ҿ$.73Ř'2|cnd۬]iEIv}JW\fحtO^bv豓^Lj_码ݑ }G dRH$w^˟?̫>j:(yag 5Ƀ8R& LN!!0SE-rrPwH|+pE-h q˝G=eԓ ar}S2R8LqdWDg!Y5~$Ĝg0<8F@1*c(SF5vl@6 J*RT#^+Rèㄴp-ZQic*naĪ8)5ġ8g{Np@lZ_9FT)5r|Md_(?Aqthx9qӀ[ʶFe.*m "Zd[G<#UA CxJ+ uFR]SVzkgp5#cQ.>q2Z\R-2OZ$1RxC{RtF~0%Fp p)9HUr?QݴUPhqPt؉J.Œ-M"Q]f ŕ';OGzD2aj,$]A0 ;lp ʈ@)Ф}Uff7; e^EtU P 2FU@GVyT[4*3TjN ڧ󤧈E{G*Ŋ&.Sg\C:V,% +#^abƭ`KXb)(o-YB=,RzlȨU)Nr,SLT;u%Kb;B<\UC$]}qRNue9N9ԡ@DZcE, )}iwRD?>M{V <'"s׊fexB%g-1dM2͊KM9&>5"H4{, ٫`{gE<|+r$F sEo7фxڌSQn*ރֱx2SW9Ng*lT$/tExc5ka[# 0^nm(<;] Xn{9эcr9xa [랜2쩑m›Zw5'=h*[ة>u$q 'V$_+RŅK5+$&yvYCeם Ҽ+"Yo -pn>~q.uhV𕡂D#gLa\j?'pŇn(H8f T(-Rݼf/!+"0v*pH(0ȯ֬f"tD6ܡA䪫Chܺ$0e2 @":Dbj@AAÎĉ/L~.M[xP"Kj pLeȝ" j g nɗlq. S }J1di -ESpDA7Uq!CGp Q;xH3iJΏ" jim k>BVgKNY1L>Mgb }Vp0f0Y\/A\,c/Dq8 1f ֱ@ wD [{1Jx 9a W" '$so2s-A^-YB@4B4JADO/:"tX",@p>FЁ~PtHI71)"7[tK lEKbqFR !t"T !d|PKo>466fhS ڪ%z1L^Q!5&^M@F ǪHt 0OT~Bl0<|0g1WMK+"W2{XKBLa>-5<3Uk1.!ht1 j,qNLS/4 ŬAVуЬAœI>Xu^$^u3C.9 sRG#ToTKY UH̄B*J1D=p>xU%U^+^}WR^adOKR@5Iq)S[FWUH3 J" 4!ɬH6=*61aPi\7%J ueE^W6^vkkvmնmmn6nvnVnnVm%ovppp p7qWo5Yst p#QrATTHvBb]5Г\=sdcK?$%BlUe[Rlw[e٥L'WTt`Gg#ZI3N+1"1y[gQS̕j \vq$G]1;rXD~6~W~}}7xw~~8!xL-a-WJ[5sSg1zE7HktPfjw u?]GeTm-\ol7xևu>%4ü8˝%]!-rr{{\7oif,[a(.=b_lUW~σAa@&%(` ` @duwSީ%IV2})֚[\#L$`-b/Mϣ 9ⷝЁAՁa#鋂8 pca vEYB5d98D?'$*3Ǿ(ab_S r׹i^^\e[>-s `c %B"{}3  @a _?.<E_8?ǿݿ-?=U <… :4XĉF8qqdǏ$C<)dʓ#7:yk"B*% 3/&uP2<t&iTVxA`[nYhg9nvb% \+14c-䣏Ii;)qGYC$JYUYKDM8ͷOETB uO.Ըg_ifE!B䁁 Ya:t`aW_ &'<d#9FbX1Bf5XdoQ驯N_{uo{ېΉ=nq"ln}koInx块o_I i^ḗ?Hu|I?!c<٧ LdQʘ!aICC2|! tT ^(Wò C4 ZC EHBHGcu1O C ^*Kv)䗮%m :-_vKH>?G~Jg~ IhBPGr7N r@(,cs [̍2kFj;[~LFO q$$%JÒ䤶J!܉-&ddʖ" : 0=twƓ!=U" JkgY\Q[=+n8ч LEL zkYZWV,n,m)K'1J9WN" Ae"dǠ?5c!D5QÄJ.=u'J*BP4]xKދ>o" )I7̓b&6c1jD7gڄJ<АK xЃs}U kwi#XUdgGјLZk>혗:#Z]''Gkn,{N_"{iau sm 1f 9RZWUrMqۮC\gkFa*Z(u4im]GzC~WDgN0 t <8dUYMKV7݇Pb̻)_֏x5˨>N7"$8&w" 9|<־efjZwH5utVW9^ҳ/ы88L4إ)Kuݮ0hB@*jQT/6G)l5 >5:O;}hu43=JzԿhfWԿæ{JXGv}:vk\x/jF"±kO8smu-SE{yYܧ@mk7bɮ?AnS'B-/2_˰g[m<]}|~o/|׫'|{={:ԷLT6IEi튘qU<׫ƅ7MҒЯ6T2oAz[4F*E}}b{mw}}{X|z{!x O}wB'W{p|\!u.k'fw>APa~q?ɶ7x&lWx&6'bgKArrGxFx?@yf1Uz3~#X}5x؆2k$xpHg|}|pƧw|W7fww|džw#"(~Q;wJcб$[YsvxvUB^q`7Nd(ey@&Wщ~zi:z%~FiM oȈ8|rh׌z{vog'}|(̇Ƹȍ(=23~#~.N(7WmބVDUyɤ\M)%z'sze\ yvv+$uU瑅xZ'}duxwttظc* w]Atw%v.ɸWvbq@(q HUuqKYRxPLghshh.'rC,6G}'mpI&8}BX($xIYxY(T)I'U]Whr`>_9u;p)YFq.I%,kiB—-61aaf7Jiq[im^5~QY#r1cY~g X ziDaE~grmWQPFTQX(R1T__Fa#n H  q{se9M9>gYğ q})y xsvʣ=B9PVl쩄I=)YD5|ǔ H?r6yaIL9z>1 e:fZzśSX9yy0(8RѢoV>&ZaZ@9JDG!J:jʩꩡ *JjWʪꪱ *ZFY&O٧IǤ!"yzYI&+z`crG3Ǩ<\@hʭحC鹣6zYq UZcFeR*ddhiYj-y)6XRѢH~5Ewz7G> 0۶W 9vW*. *Ig 3 PԕfEfڕ\YsVbFz}PQDxufhy? _6` t64U3 a fkaaS_JZI(腜 "LKX]Jiby1 2B g;UPIn`ʰ_fuմECw/*_6(w5iyg9ۅ.  Z!k0DRvA9: ˗&_:?[;}pZ(O\Aac[{|::Pu e jOԠAPa0[8+ce{^k>ڛ'K)gI!텻9Y*Z_JiCܐ$޺Xs 1H@  %X l`b` eT+@ L-oie%% +$+fؾ) ukۡf({WZďr=1+4ap =  kOƓ8w1)dD:{=+g껡2l4\yjG( thy3ZiK,!? Nu%4viWw?IZ,F".#2B#wgC4nnqpˬK̚ilj9~[,x_Ӛ[ժn \!"#ĸɗ53;Ƴk\G,B++C34YsEy窴Y' Qqڜ|VWCd ;&*b**.B'  t D 62+B3]™_4q3935'+} F2#%zOz@ фY,ܻ̄ Ĩ,$_A872%@2B7`XJР5z3]w6;::v<-%.Iݰmf‚ɮxzQII /  MN,l[0fx٦}{Ρ֑;֑Cؿ`A%X+CXXUp}N?y6nrq ,y[~&bd?;iO@ \NO 'BǀaǶ^} P*ރ^'Յ576dl=/`@`v` ` &~/_Q紎FJn}|ʢ?;žRޠ *_JlzJdd &eN^In⸖%JKlt1QDK UZK +3 {j\@ lO22Am49"Hѭ>1"Y箊lt+,S}RUOP&d Vm[im^s]uay%Wc8/=tuΰ45LۺˬC %t[Dݫ,^0Q2HBKRR [T;7'S= [c]WVauKg˲u>:0@uzz޼jy: Lp Je|nӏ nmؿyKǞ;oįa9z3~6ȭgZsK>3ih0-I-\ʦ4_G&!o#9oަ$U~KFB$hU !ŭ׳xt1$ڡY^e3l0s_huPD[ï2C' v`+}vJ4De&X+~E2Ez~ h{'u"] '&PZY Q4U#O,[":r <[&!/#"D!jdrRd$821!abEHʮ)Y1Rlt%A0˙Q#I-sI#3_g Iĺ=sF 鳠A1nJg?ѢFG9w'K4"57L7"O&1)RT8E5:}.|BK iQ4K @%*k%IPP]mKdL < Pr\z2ϫfueD֔5J4bx% N娦N_D,(;So%jsu}m:&gY2CW;גYukm(Xqa*'R3RAur]mհuO[ƱOݡǒ}۽6̰3i XUtvlVdړx]dmڈ)n۲CjӝW|Ҷx (W)U"f˭~u|#Uw3Pm`EغNzkXD5SN'>c^AOu2VhxBC^1e:6R[jQ zSO\sB?>t+}&oEo0_M[ۮw+R{mԎ}o=Gm +4#i+Jأ8F3Ӱ~-ˏI=vFEW{07{8[2#3,<"3bC{ k+6/=?LA=dk@ܽ4=I1 =4{x =?x[A* @ -L'#q ?2Ԏ>@p±K'QC;C<ÿCA+C@ī9<7AF<󳙊3C:uٸ28Bl @,ES@'S1SČރ@3@ Whͫ"ĜCER42 ?/ž8?IC~>#@C!O<2Y:b\GALEZs s|FdGGGnC*6iGK(D2IBa: G+FrSӋ+I~6&y2LL┻Ci̶F~ReT9JNV\,4VDt;7| 4DDɔIXI9C|HO>J*sO0$;4;R;Ϫ8CDND2 *,6͔3O 9NL@Ḓ4P;aO\OU#Px$KUP,݌Ut=] j( T5 >4֌ώNT>ܨ04ODOTlO|O5ڙOiR9e&qŭ4QDQ`O#GH65}M@HJ>*SI'RLP͵$3UQ8 lQE(&73;³TY#O[./%0 9ʱȉRb$MJqQV> }TYTԣGJ;1 4U,{CEuRсLj~QnW!+CBu8dsGfBwtW,L;P0pURFCWpYXUMև]F<#V{-S+B-?iPdPu)?hPeYkwIY R1`F0 XcVσ5Yl }դ]ZE+8$PSN\=>Uk4KW5ԃ=T=Մ [gر ׳]\hk)ZULLĩm oZڴh;BYoYe ZZ(PO[U]pY}W>%!-MmR`پY]im[Eچe]㝊 5¥]^A[~lMS4&[E-_p]}ZbׂNRS T ESy#}_|R\wbHM+L^AүRT>-QڭZ%2n:R5WHN#]P3=\9_a7Uۋ[%%ɽZ\MƸGaRPl3ઠVdMYJbč εߵ[ұuߪH5"0\N>NM/~`_v6D(e/rbq[Xc"zR%]LXOu۝bKQ=UF㡈S?cJ[ d]>=}P5ߍ@м]O],7F-+AN`Mb}KELEc'DE[ n*ccaeJ =Z-\a[]Bҹ޺PU_̫aHfG<6 e>RjSߚ[nR~{bcb+5cZg3 K L0&c[2eb0ZfAh1Rf[O&`@vZGz^ MD``h0 ahО5Ngf\NhM8Qi/gߎner@ YZ.V\&_z>_le`RfXiEi%hL0L^hb>k>lNmnƲ^-_I6էNtN_`Oni[xk-kgSٍȸ\7ڸ֟#kV5߱ U0l#ڦjӞ+^=&qiX^g%>>j^ܕ^HRaٙY@M=<ૉ}>nUff=כ^;-9EDϮ֯~簞oVZ߳_^cMmKȯJD Muo潖fV?v+l=dua X 4gFg,vX-wq#9絾p>&IH hVkQ!wibF#_Z#g9Wecq)cFqXrs2$_vgP;& ip mr4Fp'J?W!gg^ٕjq@ q=*xN@ϊAE.e=&f"utڒt\`Y<-!W]quY}q>If\dU/ V-gE=0rl]wAf%vrgSgTGO- ~P\FVov5yv>`&&p%v7LJ;Eu癅 yxn^f^iwDbY €Z(x7(.y=.tnw/fq_O^uɍ;uFK eGLHfj?;?_Yq6ԛ@yWouT뗢'G{] >| w _eiza7k|%mRnБrTr,re{lt|3f){7wr yg7u>|Я|( "\|iޏyl}gbW/N~ߟ#~`jwg(@իwo!Æ[@1?H1bu+1G%IR$˔.nf̚6o̩s'>yT!~"Mt)ӦNB*u*ժVL5֭T5fKN%ɶkCeZm&Dx^:2nČysf;b^64sL^sxT3ҦONzu#mhzD yލxsz7Wz3n-'WW'e1/%U|AC~=߯wPCɫU-]Jq vOHx B|mKbeRcVHd6u~SwӇ7h+-WSQ8ֵd> `CEs峐FH4] v;aM"5"k^VbCWg?UlavcMrە<2[beWEEacDe ^Iedє X暟m%V4t)T:^@Jh)R&((YQCOrğYi)S~.D&CZbTm.M:*j"cNI\^à_C5 iODpA2ܰ iPGidgi%b \q =RZZv0NQܳgn|; ?ʴ h%4JP9ľ|@$OG#.c| QsӽZBZtNzdnKêvB)5Fg2B+,o];=VW,-uV6li+'~g(~(.}91\q{m3߼Owь[x}):PF*Z )*i#;_͗~MCn]N`f箩vCYDT;kŪ?.?Y { z[9zg%h8rkKEA *^i4(?J\b7}SAԊ܃Ȃ@xxpV»*,`h;IO[ p{G2Q"xEIPrmY7# ܤ~+us;y,*i!FC\dw <)w35o2n,%ك<~f{X jfmRcZHAji^t@R #Ij@W7b3dCxqQk{V+c %E_%H*FJΩ·B*l(k#UJld)]ʐ2̦dGR}0h%J=,!(Mk v2ĝIh^F .)PԼxHYvF+VbXU_S6*Ww2ќѥܨ-)TBFkH!5(mZ$JR\)CV׿ hLx:ădE%c=XӨ3_bٌ3?=)UxX 0rBYiէXq*EM*J#&s=VxMaCINLʅ`Zz&ue%RFTNG?%pJ%irRIx6ڱW81QŐgKJ^U/-b7lNU^tm Ń+dwi8 ^yZ]ukD:7/nJ=eagrqBkf]ag1on݃V/][9!86HuP/[;i\+V8?ެl{60X4ׁ䀦Ѿ*s.:xx޴(l^E׏tu| !癗z&%oj.YEԌ9ktV=0W$YGhF?vlb(M\郃o6lav,nQwûI̴l;vhelgpgz:mt϶.i-nY \D,!kۆ$*gM?Z8CXcc/b(-vϱN~a_M ck{1h,;WdFIr"K|c8uP[s+A$ bv,smV2խ_&.*䆯.&sh0&Ƒc?E"4Gyrvu,V7 whqηߺ~c>E8ckaWrր̛ٱmMH͕MXqZW ChW%՞a9 ShB`m ^3%He-:[S !) emFϸi ["\ҥ^nBp^^zai^Ry Z`!,Da!ҥ! F_2DYqy@!=..(~W]!U "i5b+:PH1a!$ Z Ӂ!CT 0f]QLb3J-Oa!06 ๠bG :c:2 fa Z8 Y0 #7B )1!,>օAz#M5nZq6vEaF#de+"dI RC0 ;CM>?S*"I eLl@j#$ eD"DE> C.7xU #GꤤcCFHzPA$3Icb[dNC=B=0&)2cPY%4%iaS[!Bdڕ&_0n0du$e[&#"AX}!<P/ B/e1c|$hF"fibFOD?TdDeeB/lf|)&p>zagI%qax%\&-lE=P'nB/,JvvZTp+eRzR>_Skj"LN/ 7%|*/\'`Vgg#祭 `6Ne0'uCXg'` &C$rA~32&rfy.YکT!zCC L}#gbi(9"iNc;*E%%:=lCEH)tCvgz߀g0n*j"j*2JjR*Z^jbjjfr*zjꨚjꩪB**wN)0gh{Z.j~FZqhւޙ>b+bk,Oy&ٙK.iL>yȁu֩fe))j4R&WL-+C0NCk6D=a$kRR$7i7@mlԫR|':0Ġ>L+] ,\-BR(emͥ+$D^zWЩ0ҍR29AЂ?Zbmjrmzׂm؊ؒ6Cٲmۺmܺm0,UN-h R,V|lw^5.ΐ `C-Xکn,ItfPhBM>nnnn.^C4DkL8q0@4<q1qr r!!r";\34""Kr%S%Or&[&c&30qR8E|#¢S>/&BlTƤB6N}/0<13(C02+1733/31?4G3(W4[3_6ks7C7S38g7s889+sF2c;s9ó8ϳ3>>߳?s4rR|.Y rCG$hq{:ht2D҆aĽ j0!1h0gdIw#Jt2IK4tJJw#MK3LtNNtOtM4N5PtR4RߴRKQ7u0S4T+L_M RcTk5QGUuVtYY3uW?5WKu[uFUl)n*n('6R2(!"+Qrid :nàj0f0fk0`6vggejh_6Mvg0gvi6hvllvmmkjvnnilwpwjvfovorKp#wpm'puvv7vOwtuSwywy_Y{{n(jFPF{bDc(L5-ץB$HB?x*HGB[K…kxg{w{xx8o8ox88x8s8븇Ox#9gBFqG*z: -HHn%1 2weyyyy9oI1HK^dq`gVh ?-.CЗg[ߜ;CzKSz[zcY=`²*8l~M&g`g,Ӛ.X֥zzۺ9SX94A'` _D}qz0cS{[c{9:=yBf+!zF## w&{;׹7o+i=:zeF>`TW+4{[c|Ƌ:9}z/PR?b􉪺\@|-l|z͖icS<8:‡q8̼29x$x$3=~[=W~Sǽ_==eo66ͫÆ~?+n)M+A|˧#z{|#?w+[|P[Ft /Qɋpo̳GGǮdC&nй:as&sc?waB 6tbD)VxcF9vdȈ4yeJtfK.͜7qsgΠB 9Tg=P[Gůaǔ)~~Iբ&RcŖz(YRs;SL/έ;UEp` 6|We\TOzJ'5ޫ:M,˳3Ӗ-JJé<׼M K,LOƽuܑ.%2;{t4JM5M쪅[RE0sr$k 6|854#LѢ>-k'}кѠj*G{E1%,2 2&;4ϓ֔PEG;] SJɢ(CW3< - _0_'K%VS?%h0:UZ)Ib.py24n=\JpJH)\[1YtlQbS!ZRD .x6x68#VXZSH޸a9^xb;a x!Z"d)^c%dIDF9`8aIz`mdwg1f(zmOAs o<*ѵRQQ.Z'ן|QeZO !Zh)iQu׽)[|Nb.p^o|&(5;!q(ocO(D2ZLv* +S 9m*D~Q4HE-ӗ )nwQdUNԪ)Op|-^*! p2wyzCnX7) 2?3fRGtf7P>t\4h6=4)gF=(Pt$f Pu|%* ISrq(.uIJL)eOTG!(>qJ!O@G~BwgB5c-SUѝ5pHRj@gr@k1ͳStjhq*?K+! 9Aȓ*G6BK}2L::D9 ^aoRX͘UE:R(~ ۟V7hhu/f|+e!SaPΖ!qoubVL)MsUl[͸Šͫ& rwhYt3|zH-KO  (w Ul{a!@Rf잹NZsAik5bk [h$U3uaOiF}]YI aiTxz rd E:T$LID% ]B uނrMa׷AZ +~椂Bf=_o =i˶D{xo;hAێf[KXl;^=az7epw 2JK"p|%Q䗡I}֐!ܣkD 9CجtQH.Ru嚕Љ ;_Br殻L6u!g֟>rK] ޴PH#j*̏kHS#QNhYy)lu9ON`;'zC}rH!_T}.s<7kl|2Or%e wq6Tˡ{J3^+V+Qj>l+@&hV?z<__J}R վR~͗߀>3 B*˞"BKb뽤$"Cԃwɒv¶Mc Ao@Nx/ϏdɍP0{0 fso0 #h:Ȫcm;,tJب:+60dˆСmP@ Ѡ ja0q1;?Q1bg O/p!ZAiN K(p /6 :P0F_?NFЀ% GQCѠqYqqQ-Q!_1d@ DC Pd.e%ʫSQ9)""'R"+"/R"- o #,R"iH#'2%KҾ#K$) %gr%k%q#;rb&{&Z2'YoPֲi:/D^5Rn{R,ǒ,˲d#?0R,R..P-Ҁ.///ג/ s.(ָ2lԖ()1r"  +K!$A /55US\T #u-4 o,W5y55}36}s6kSr3(Q5s98y9e/S!,99;i6)kĂRF"0o"R5O,+2{1/Jnd 0 44A]#jvn0s7T@CC tA=%CA2B B3CTESCCCCB%rE CEGAGeFt4m/Ӣ4>! q#?3 "c F4FLteL7fLai(t9tLtMaдN4MTcfBtNӴNOhQO4bNTMP͔hlBH#?II -Pf3y*>"4pMHZNgVk!eS73q=+J"1{3xRU'ZuUsN.%jQl[#rn4E2Ѱ)s)Dm3nKU%R[_ݬKom^2S'*=I DY5.zb/ZX<3cWX'NxpXX3+36 il0gs6Nl1L?#Iõ5;A5jaUXTSuI*SDfϫc$(Zul@bV I\=T726qrKv$Ne6o%Ef\/MQl pcplWW[FVthriQjAasU`j6d?sp[uacaUbv`ulޖwGUK$vVvKLWZ\2uWz%_Uh1֖ICz72nw>?z!'xuty!BU!Z!7W؀8 ؁X#!؂'58+7؃9XCAG؄?XQUh!oG0d#r)i>W>wŧ>W JtIwtyok7{؉Xhk {4*iٰU*RU}"k2u؍Xeȏ1f12sԆ'q274}o*WU{gx#Yyqq*srNV!so!jsA[5~Hw_cYّyvw8 E$?|n+hS ʘy9Yy NCٚ4YٜٛٝYy㙞ٞYYڠ١p/ڙ15 d,:*J~x)psW\ڢakڦosZKx!/4zG:"~W bBG~aZBzO"P]>W}G,x;PBWFZ;(z5Cy77})xB-Ll0{(4y&OL;Q[[_{c۵eg۶ki[o{s۷[[ L{ۺ;[{ZP)[('B;ѻ(xwEz;7Nj'A[AM\!#)\%M;=?ܴEO\'SC|GUKQ1keu⤉$^뷞^Ǟ^מ۾a!^>8B;Mb8 _#'+/_37;?_CGKO_SW[_f?osw_{_/賷WEB5*___ß_ӟ_A =Hp*LpÆJHqŊ/jqǎIɓ(S\ɲd{0cʌơ2[vb]H*]ꏗaž{uTRfjUkWW*دe]mڷd㢕{.[suKn_zoU|xbŒ#C2ˎ17,rϜ)k,Өys5-x$xlQe N9연`̝C.=sӛ_]{ܿwˣ_=㋟>}~_~( 8``F VRJh! '$xkdS9 O'6/EcQ%#裍>$?)dCIdKɤP&)%T>9U:e\FeWn%d&_ifg&hfrmt眀کg' z㎌6JZbNKmܖiP ?*ꨡz04ꪮꭲښ+K챳"6:[--v kn뮺KkK,.ӌ0ˌD G,Wlgw ,$|qlBH5&,4l8<3:v)$-H'L7G"I$TWmXgPwC%lChl-S* sw x獷= 3l6߄n'0q ?j>0N$v#*Pa?d7ꬷK3޸ICj[9|jy׹<<8 .(,ڶ0ngIJNR ;g?W\ORiLΐ4x,#6A:;l i5Ⱊ&7INkr,7k(NtT'<&wӞ<<ѹl'@}F͂o[I'M~(o\#IF/юr GEz4t}JARkjy bsc*G%tl?'iA4%j$ -թJ$!ICFuWRIJ`'Tղj5Fg6+NV5 uhC=ZPE*$r@L:Smd(KfYq6&pLԱAauG9\a!3zEa :ί<+!mud;8Ϫ-=;\"TPܶR i-rCS$KT)[2O%/LqP9xF(f++I.@=֚ҭq;\uK4(> }3ֶk;m{6?nw\n9bQ;c-j,Wu*"Ǐ |K+;ċ[<Y@w A {p}gަK[R Kln[P@WSSa|yϻV@!@< GPŊ$G̤x[̉dF+o5܃Nw 5]E9rv:#@~ _sV\(hkڦ`W֯Lɻ5@"}點7ǘS\/ɏoTD"{_?F}5}njg{4'Clk, ؀(x ؁聸&x(*,؂.0284X6x8:<؃>@B8DXFxHx{uK P 'R'r'^X\q@__hX8ll r8tXvxxz|؇~8Xx؈88`~)ӃQ(ЅobȆ_xS(UHi芣Ȋ^H Xx؋ˆ`Ga7(1k((H(q88Xx蘎ꨇȌ&ȍXH؍Ȋ菴Yy p0# lmgk*,qc iH/!Y kȒ Y6y8:;َK%^-oJ)h)Oُɍ4ɓXZ\ٕ^ Ÿ@:m`joEV7m p%U'Gɒ*) h.u| u"]/_9Yilu9id4FF}x+ IU9^ljKG;zӖWGuGP9Y(wyIiXĹٞ똙?əiIΉnY#AiȗiSթ9 9ZzDL ɜ)F_ؠGI*z 'yv9_ڣ>@J7;PK燃[qgPK[EZF!OEBPS/img/rules_test_mult_out.gifG%GIF87aBBBﭭ9991{{{s޽s޵sB޵kƄ΄΄Ό֌ޭޥ֥֜)))ZZZkkkRRR111!!!999ccc{{{sssJJJkkJJsJRkkZckk!k)k)k)s1s1s1{9{!9{!9!B)B)J)J1J1R1R9R9Z9ZBZBcJcJcJkRkRsRsZsZ{Z{c{cckkkksss{{΄΄ք֌֌ތޔޔ甽眽9Jkck{{{BJsBRs{1k{{s9Js!9kΜs{sRZk!1k޵JRc19Zss{9Bkksƭ{kcc{ks{{k{BRR֜Bc1c)Bs{ތ޽JRs)9sRZk祄kskkƭƭƵƭss{,H*\ȰÇ#JHŋ3jȱǏ CIcR\ɲ˗0cʜI͛8sɳϟ@ JѣH*]Z$ӧPJJիXjuGŠKٱHҪ]pʍݻKݻ߿8Lp'+V 1(#K,˘LټϠ?WMti+SF}+Xb˞;۸s֢eNq]w˗УK.aνCdʨ_Ͼ={3fȟO|4ϟF( kh l 6 ƄpThfav(LJs($"(b,Ȣ0(whx;>!D ǑH&d|4O!TV9Xf\v`Wg]Yh֚H\p΅ל|؝Ib|&cYfZYg%JiڣVmbۥܦ[穧-uuiުGz'{gk}_꫁&F8&zК.82ި C km ҼtOK-<+Z]jm#]{D-vͮ[vIL-d%2P#HgݝVzɷ]~xF8cx-θh; X1Ur\69scJӡ.=ZGv pw;w F<:xȣż9zC% {lI>zπ2eE}\Ҿ9$~L_ t0CA'2ߢF3՛ir hM˓A ƇA8;E3 gZ-|a ek84Cu]j bJ4rLރ[r d$C`F3(,kG~Ӣ`(0&F !cdxʤll%G9q7u?91e~T cAVD$}+F6X$$9IeUj$4͐ăQ|8%*ݥUr% _F01 b /}#D-/b*t o)1?ŧ A8 bD* (Ls Q H5ɸlƍoT7rjyLYtl ٞ DC) Ng?5π j--4r( Q^)c +3OE-la["/@ԥ\@Z ` m:.W)* "3E<RM@ƹ}j5y(5zƪU*7Up`-IVRi 1VUq+]ϻhګ?B(,[6THblc6ri{*lee H*VVb0x,b aE/-Or̺V?qpe ?.r\05Art9Zڅn*)';Wfj`{^Dw}_򕿖l5vU =(Rbd]9ٕ ѲFb}XTfLI3 ӥlUɿfW1υs:^=}z,tt&{OIQJ|`U`W{BK'0. ҷ/S}ccɤE۷''MNF+9r]~~yg:GWmtgVrZg6׀`b(>aA&Pp!(wC%xy󳂃т.?~rS~rrY`ysW3csczznzGWcۂRw{T{{X6`(bA}T'}*|d8rl¦el~lxG;Iʼn{U(XWCY8.[h]{/]goRpa؂?8T6hȈ=__SFhmmhE{ōS荟PnQ/$Y&y(*,ْ.iho294Y6y8:<ٓ>@B9DYFyHJLٔNPR9J)KTyXZ\ٕ^`b9dVYhjlٖnprIg9vyxz|ٗ~Iu9Yy٘99ySY9除yei9>隘9ٛ9Yyșʹٜ9XiWi9Yv)|ٞ`ɞQ )yLif89YГJ*ZB7% zɟNi J :6١Ei$*Mɡ39o*D63Z4z@j491J@<8:2 ,ZVz.ʔ0ڣ:Oʥ`JI*bڥ1Rڣ_zjT*PjC R\WzzY[ZJzezj6qFʣtjt{z }Zg*ꤔꦦꥉʦZmZdIvj*hz::jJ(j^Hɡ?PZv:Jꭍڦ7ZJ:ڮ:z)zY* RYK; ]By ;  [۱E9$[&{(*,.._4[6[{:Κ<@{>D[9FJ;HNٴP;TR{Z\۵^`b˲W[`l۶npr;t[v{xz|۷~;[{+32y[{۹KF@+);[;= E@Cyɺ[{țʻʛ˓@Be˼ڻ۽;0ϻ;Kx{K盾;:鯇J[' ڷڶ J\p[| °ۿhZkA@?.79z 쪕̷L,>A,F"NPLJ8ɻA+L=:;ۓ3:*z=nkoʫi꫉*Mzz\~Z+C0D^ a\]8P8쯋J_CŠΜe8ik<8pi;ƏZL`̼>̽Z\,\`鿬Լ<۬4;:̨l<: K "&}(*,.02=4]6}8:<>},iύ АމѬѪP ғ%#LmM=[^`b=d]f}hmӂȇ8Mۏأc>m) $^]9&*>Ͻ.[0>4^8/:>7B>:)KiDK>9J>\ -L\.Vn6 ʾkhn,*̕i>y恚xHN~nk!wU ]JZǓL~F\<겾>]Ế^ɺ%qȞʾ>~.Z՞ھמ~2i^~s]?_ ~?" On?$_&n,.0?*68? >@*FHNNPG*VXToY^@d_fobo5lniOk#`wOzs/S 10S!- J|?~/ -p6 @/ <  )/8:ɏ*aÏPo A `1,/o'00`/_p@  B >QD-^ĘQF=~R$LD9`@*Q$RyA$hflp(SRA̹`b +r]! v%8ؤ $QІ¥5iPT x[7/M#RP6]2F>Ydʕ-_ƜbI'Ut٤̈ H<AfU[Nuj Vu(-q o"Ukb%H`wu5kF^zݿYDh: ^zStPk8- ALXA'G C1EWdE3B4*B@%D ' ʹO,m! =.Ăjү6CK%I2,_3L1$LbiFѪ|b 9G85RK)RBRh(CT!4KCD-K4RK/4S|Ib*HNgP!-DKР|"s{US@!X0"oY]ЂD h @: HM]Qj' X!\n]ܥXr]TS{7_}4͆+d6H0tX1)o-Zȁ "ՠa>R eJ6+6D2Vx`*GV~Ru50&Coι8:j~_3Ϯ;l$O;툨UmVlήnc;oTn;p'pzͺ gqqr/<%m?=t{-WDj: -RVYq{'OA)?Bԅ4N4.LٕS41h1˔Bh6k@p_DIA#d7)Pn\S$.V&դ0l ЄGDb>I.+ stSiWӣ>tJIc+“#wAȊȉ- PbcUDFЯ&4Ѐ 'ȩU5.J @e R%9TX WZʪ\]U" 6eg pI %uM-1qsh!,- ӡX.#aK%* ,U 6@3x9NrΗf9չZҌg*ٍ=mjWvmnww=nrFwսnvw=s.K"8bJ_ x1:X$>qWx5qwyE>rG'Qr/ye>s7y o9C# oroӞJ /#u7ϭWzՉ0]z ;ɞU7],ٝ^ϴG覽KdN(YgH)@ݽ!!|-'4{A/ÿ& nUk-ƞA&0>8AFօ VvP'Svs y>yߚ &T}}ICٍ/$]Vk~㏳ru |y~7ޥf?:ˤBCH2/7Կ?*.LY->1 Q:CómҀ*4 k@h҈H0̩N>I˾[ZS+++̎+>Č( ) 'h;pBBAB{k:ǂ<>,?$< ?,&TC|hCx$șëC;1Q- 4+8,sP$AaEE-/\Rd- ٭ FIńx-h -Y$? Te$f !@.t==RǚH1ğh!B$DSļiGȮ2!x. 8ᘮ nxH4 DںL4"rs)-Ңa> ǵ(b0>]ɢǣ$\vS\@ 0[I -tD\m;1@0 4{WL# ZKl »K)K%AJ!ɰti ?D KʚJIP1JȐC0qE Ab#L\1|[=#B{8 :;;KAFK4V :@P ]e%O:<A՜83ŘZ4 `PEP )L5}D#QR?d5dChR$#G DM3DO#L*-SrB`̎X0B18$P%%P[SغfQdFR$:8TeC5T4eHYL= @2 UK=SQUbKR1]ҀRֆ:O-V^]֑0`uVfO!QxQPmm;a-UZ]VnSvՈnEYzݿy5xWzU0hqpW XkV{oW&׎@؉mX_uW`؃X،Xvן#PzCٔUٕcksٜٗٚٛs{X"XY-Za8gSháUZ9IVMڥڍhZ~לڭڮMڋk %۳E۴U۵eۘ+U}WEZp-Z=Z5aۻWܼøUrَW! ȅKɨ܌\܊P%\XԽ*b|} ٝ]@d]OLvZZ \=jܿEU ɋ ' -̨^žþZ5UM]]TF剤ް^3 Ȋ_,*ρuڂmUxE_5݅-`͹؋Њ 2 o"2%vF W #*hG`Vaъ"ihQ8 PRyp6a`  ^_u<`+^' -  c!Bqލ7V("x) ^x 6CN@8Ơ@$(R"<^ ?>F&ZzP6 EInchԸd-JVd-[.^r5Kc8^ FiHETc;aI fng.FPbbfa.hfoFȢ kiv>.#_Mb-ce2e1g;ggx!.}0wmnf艖hFw=sFLfZ.;E}:>DYIݎh>vg$.shjqv.jvibv&2i~N|VON0q){%Z&% fkh%J. \BkvIci:&"n%~kBk6UŶpZ(8lHl`nsodKڧ֧&g*› aF&o.m@)0nD`U)!$.(ppInnInntygaojTAff. p+V%X}꺭p n ^<]=pNMVjwGGVppUqqqq k!7ܬ^q r5]r}"qp^r,'-(&e0O܍hsxȈh9u6`` r4OVQ@fEF G e8t'5/_1gjsL̲ m T RWdz^˖YussP]߂xQu+^!yv(^iώ ,2g`ߥ_\kbv aC1GMu&ah- st%^ a|ƋVs/c?2k b"w!x8 &b>|w{ox  b auO@mowW0qaϡf9eRm@@McEAԸ RLZAD&z0ee64W&l=MAV奟<SN עB zWz"dg`_*v{V=mN3`y,u&jG.kn//(s&ujVgqfX显.Hgg|vGjq))FH ~f:>j5Foh.o=~N'`|"jH0HLPB6` hQ@Ň>E !DHcC7 ACEȑC H0ȋ*7t(peÞ'q ̄H}MzRџ5P00# ȒU6 `,ƪEXaj.޼z/s<၄r@ %x @F V l̡a & -ր1Vieu 9uHlsPnHċ'8nX^6[)Pz5D7%~zu͜K 0bk zp8mQ]7 7z|QYo[Hxb)z!! yXW'&W .e T sآ-|{1+`4ڈP4@5 J5$D)RJ$;Y0`R,fY#HeE &hUc9 P&"2hiB&hG>Y ,0ҟm*ޥbEmx+j(',*,ᅰz! ,&{kk% Йmښ{.Hky. 󢨯#HQ;0̮[-;n%F [|1pk /1VL\2- tpr2η3A }/2|ML[U[}u1C+!!Lu/ :X'v_T}J3mTFtڶv7$w|@x͛z1H)p`PP< ԂUyy?W2 jW%h,n@(<Vpyv!ou t И`eԏ)Z@QBr9UN^S%@/?KF^]@Ëv6$J<"0 .,!`}Lzn[V+#aB `,=_)xd)m${!K7!~ eU٫#Ĉ$'2ax@\Y,颮"C,1a!=%q sC̀+[9Sю$IX@""-"Ŗ9#Ԁ @tj{ .IQ T'k' )e#O |۾F6@Hm;L1h K25%Nb*<2!w (gv|OR`ʴT3dKY!k+2MVӛwI<4x $_SL (yMdG5h f^ZJ|hD}Rsef6UO\D@>4, SiBڅP7:푐bݰ!5lĔ%$Q*&UR !OfHC O[Ӥtn\T4h }KV"j@ ,ÔÎ܏`Wl@Ѭ_ʛfF|jf%ΊZ[kV\22_L.㕂phN)M w5i}Px$yʪL^}! |.J BkƏ !Oh |U|_P']{aNwIAA C6 v Lzm%G"@J1zaE!{Fk e+T 𽠑v|K0O @Gݭ7P昨_>2|jWb9s =>m~,R.ˬ%U}mP  o`=3 H[P ҕ YUn됴#Nʮqz|β&$McF{eݝ OdG\twOY7n *okTV-"Ҷ Aww oD;}D2M㞐[gpZ=Py\1 Fdg; mBBkgsHiRq+ ? Ó$(/ 3x{~@6u6n _'c:d,7'@F~u)G,}6OgziPGCE݀eO-%t G MEW?ҁЍKҏtˡ2y]IN]&' hJ`YATRD%|>2 Pa -HߞVyiR/E%R:ªL5?$J(R*fn =V}-5*`sꑯOܙLaɊIml< E^_u(ɗx`ȓ̏MA8] a K FYL^ҘŠɕ T_ˈK ֋  u̥՘5_}0_ x QM rR_: !ڡ bb* ."#N"%Z߾U8^x"^"'")*a a) ( $"-֢bdm-b,/RO0$K11E2F(]X$ޅ32"+ی&b/+0F,dK9NE}b:Zb& v|#bp:8ٶa c8Q"ri=!>>f8b ^Q`$GZAFjH2d9$Zb4FL$Xc ݌AeR3GS2œ*nO53AɊY|< IM΍R2%Pӕ*TADP>}X^FITMz啔}%>DI19RSHH݉RuT-^"=V7d=zdkAo`AS-P edݫinu&{T_} VUA~ f¦B jFm>dnnloDVu|hJAA|&l5 Xi#ab*b"(&Dac؆͍exAgh^xuqO $QxZ'ѧyQkj$@ Wt"")bgvd?B(~ug}}gSţiQHZ})Yj Y1[ZZh@h(od ؛_૔Cnv )w⇒aXI]8یc^ :g[YJhMNBb- ̢blZlNb֢͆--άTf0--̬mV׾-6bmm5K4"c*B,u֣ےߒ~"h٢J<F9:OaШn YdƭnQiLV Fx;av-~mrQAnd= l.bK^&TE]zO$?][N@519$ORUP$P>eGh< `.%O/?Y_=(YW0R& mжmbnvK#~Qri q[iUhfYRݰ^ V PEf]&U_ua[ͧ[- qpUeso6ǰ~t atx'qSm g>0ZXn~BXډ՜t'~['jp wyҗ1/'p#ש/1 1+3o- h*`NQI)Ieh'($(zhj(Ujf.(YwywƱ喰,oҎĮ颽OPT>YDNQ؝۫g4E j ;=g y]ݶ2۾2.S$:PniIVkTh^Bjdg2ڽǫ\:@@F@ ƒITH*jX4TcbGAN  cގ2G'aHr[[DT\slkQ @+Hu :IXQxdCgƏk>2OnvqM^JDa'Gw<>'/~>?>G;W_S>o>w>ޫ燾k>>̛귾Իo׻[9@yv?'/?7?߾G>go?w?G??c8?';׿ ?@x8`A&TC 2D@ŊdcGA9HPHgO?:hQG&UiSOF:gofպ TZkY s借cϞMj]wջo_Z n91Ipcsd+ϙ9hzRȀA=tiӧ Ƽ$ |Z3k;ӕ쒲[dk(#ָ;ysϡGnYM ׍~=q:!^L̶=֩Uk/2I,J5+>#3"-;1[$|J+jî@Sp ,QLѯ+=C.F/e2,ǐ71?z+:4()jP-.Y(,L2 5Ӭ2wIЬ:D,='<.<{J.?>lG!.̎C/B3MN 1:ϴsMCRK-+R2QnjT*IUT]y5\LDim3Z,SC*TLk}rڢnu(B4ZWV}MWu u3\dT٘n`PEjVqe=W}M' rc~b)^eW92%a)Mfb-`~N^YmY\ UH㧡:7諱qٌZ+8h3C@#;嫹>m(G;(Z.\뿛Fժ>!\rP 1\sA]g dkYW[+|y=7W .H_ut_Kvˮl>z߹ /O_wV+ yɟ>{2Ɂ@ -A 21A nܠ4 Q)@i_Cΐ5 qXC4=rD!CaLXD%.:|E)N&bE-n/y!F1((ɘF5Qf<G9{n"G=Qjv|HAQ~# HE.?IINR4<$$)IMn2*dK@JQ4)QJUt+aKYΒ-qK]/]E41Le.t3Miմ5Mmn7Nq49љNut;OyΓ=O}?P5AP. uC;PK0GGPK[EZFOEBPS/img/orderapp13.gifQZGIF89a}-K/W;F2]8g  x h" q$H@XIcjir D~"oz!~aWuWbfbwww"(%(49:!H!P'U*[1\+g-b5b1h8rCDUTJHUYRlcfrjz"g0iLeRnDnAsa{b|Jz   $+*/=21)6;" 0$,h\\AuGJYIRSccX+X=`/f3m9p=^BkHiTmBxZuC}U|H>4~f{Ydluff&5*03f0D(K0|jz~|D*;/6=;CF$J&R.S2C KPM$T(Y7b:_@fGnRsY|bxe~djZ}NTWdtoz9;<Ҟ@ٴnݸrjr{AwVTz޾˅Ɨ˟ܒíں煉ȂҝΈЊ٤!, …A11FC #BAcŊ-RԈqcƏCvɱ$H'MTreʗ.cɲ&L7mscϟ>*(ѣF"])ӧNB*5ƫXjʵׯ`ÊKٳh=aa 2}w 4#8LÈ+^̸ǐ#KL˘3k̹ϠCMf;p8n 8۸sͻ N<48+O9rn/nh7ËOӫ_Ͼ˟O?GH& 6FVHaw}Cl@  B m]7`0rw8ިcl;>@)dHL&NF OV)T^e\b_v bdifl馚p]D[B B *I UT⢊6裌BhNjV饚v駛ꩨj*Ъꫮ 묲J뭶뮺믾 K&6 Dى'B !tA{ lB*.te覫+k֝y3пǶn𭠫KE+Wlg /cq ,r$lr(r,r0,s4<2C2G>p&`"4&#0I=o` >ƈ qV,FQ{-vdmh}in-wtmx}ya޵^\x>3#yW8[.6'y䙇9# Ү덷n;.{Ϯ{þ{.<O{7< E~?p6 'o=D7"H?z`p D7LvoXk3$aߵm#?m72P @RP_چױuu]U7yx&! EvB,T g<8[pzۘE=NlhD#'xPӀ 9McpQ.z` H2-x?6 nGDbЊ& O"BjЇ9+3L"FjNny?41 !cH$% K<8 QuE:\3XVbZrŖG-X*s0ˈ˲~K19|4IiZؼ6mz8e@21M hd{ uhXsiZl@B}[ /C aYf5HJlƴ<#eW@:̖4?2 "Dh%*I;ҳ y@g:ΑdFڱteT-PTjU3U2jgXXǂRaTemW[ꕵxb$%Iib 9`);ўwP+b#[(FR]&)(AG{d=-Y%ZRmjsd֗g? LܢpK]6Mmru/[U(hsI[7E.s_׉>7ݮJJkUlaC!! u'щ](8Ed6X*J֊7 zRP<úpRصXeJrb KآOД3qBړ:0u .mL4NN蓛cF7Lc{ٵP2Ke?yU6 /̀-&΁T⽓Byh Q|`: e`OPa /% 'mg'Jb:*6=P!gDa]Uȷ~a[cӭu2[ =Kkٺ扇H-ig/.2PeSư-rNvMzLg$&! I0b"A: t >&^~P.N @DӶ(Bn<żn{ BG{ɟC4qX|nGnn3' s[G{JtQsZF{gCwfMxϻvS27;>K dg!Tn*En0v~;cB> >NzLNE~XD2K?6[oݛ^W[{د~+Feu~}|t _?r= ?ɾ{hjǯ~Z` pp '   B% °yh P?RF||,HzǂkׂP*h.q+8e09xE)5?HBwzNCGȄIJG'hX(X_g|VdJa؅PxES}Pȃv!w؃yx؇z|3Xx؈8Xxu` N x 0 qpy10"8  Q%0\,R5H8hf3+؇|ZKdkh(RZ\OVȅhޘA(8hxLX)،HhɈ8 ِȃ&yّ=ȑ$9& y)(ɒ+Y-+0S @("'lA 0 '6!WSh)Zi}+hq( ^iP}qQ\ŕjɖliqeiPkɍqɗdoٕpiY[ٕyx {}阅9x9Qyy٘h)Yriəmٚ9Yy `@ 5 ` h w6p=(- T.!9B r@A kٝi!2!9 fٞYkɕr ž"I%hYy!ɝj zީ:Zz t4ـٜl!./ "4Z8!8P96j/?Z CJC!7<:ڤ;>-JPIyٟi Zg*ih ]p:oZl xzڧ|~pШDל!Ϩf*ozpjکr:j JYtzت ]Zꥠj^ ګ*qJdZ :*:Ū:ݺ jZ⚮ڮ쪮Z~|}}{%* pDw8ҺZ{۱ ";z0(;  r#66 <5۳w>+C{FHHI[x? ٴMR۳X[{BC۵iT^;h[i+j_oq;p[rkt{z|˳n2xƜQ˜ ˰B-a xA3[kNC۹k˹[ۺ;KBoۻ˻{ƛŻ˼ۼ ǫp1pG{G۽!ϙ_-Q.r-뫾{뛿ۿk[<;l <\| "<$\&|(۾ܾ,|+p::<>@B;T\^`b=d]c=:fnpr=t]$<9v~׀؂=؁;ׄ،؎ؐ'm:աٜؒٚٞ ՔB=ɵџ}ڨڪڬ0]qڴ]۶}۸=֯]=۹=10ԥ՝ =]}؝ڽ=]}!m}lڜ ̜ùAܤþ ^} ^~)@Dmߛ}>$^⏬?Mm@ .>⮭-\,|L[lB=HJ4lgk=-GMaceD~g.l~T/:<.@v[@^]-OKÄ^q2N>K^肾肮J掎荎ա艾N.醎類ꪮ^H㰞^m^9^ w0n稞~ǞN^ȎcnЎ֞>~nnnɸ.~,>a-ڎ>˞?ծ_ >>.~<^.d / $_78oN/I(_'W r)K1N36~L;?lm܎t&/tpxV? ^>x>[ No鲎^;oN"O~nl?">OȆ--~lY>]_}^.i > yoܿ_.]K@ DPB >4OD]ĘQF 8|"H~(DRJ-]SL5męSN=}TPEi$ƍ9IU^ŚUV]~VVR^xUjɱmݾW\uޥYviS EW`… FXqҵ+5bʕ-_ƜYfzIx2뜭3tj֫]:kٵiߞ۶nܻ}[7r̕7\sѫOݵ{_~Evzݿ_|ǟ_~0@$@D0Aoӈ#l){A 7C?1DG$Dp"- ðgFo1GwQ%ZԒ,F{D2I%dI'\tL S(3L1$D)E,[@Kts1.k,N,O?4P1ll I8lN>{4@>#uRA/4SM7UеSH$Rۜ7ISOdNX2JguVZmՕSa%L=5+E]TSΓ^}U:{ŵW^mXsE7]JlvgOEu\m :ce/`VuF8a9d3+CpV^S xq=co?9F9eWaQZ.Gy`lA&8ۀKgF:]ЩwMQޛXmV7`ZdF;@fѩGJ9զnޏm!}:f'9&pֻJz駧z{|?G?}'ly秿~i|g `羏O~H@6Ё`%8A VЂ`5AvЂ1'Da UBЅ/a e8CІ7auCЇ?a.@, o D&6щOb8E*VъW\K<]zJb8F2ьgDc՘-G4_8G:юwc!jVg0J{Dd"HF6ґ'lcJh@6'ZV ɏ:a#dcBHRҔDe*pqBP5Ȫ2 sJ^җY .*e.f5KVb\f̟1Eڤmr f89NrSì+DdNS9-zJ>&(9Imܥ9:PT:H—8ӡˬJ0F/yJ(6ωiHE:R4"H\gOΓf,FISԧ<4z̕ӨLiLĖ)GmџVժW*.+jhXhDkSqNz3md7Uծ 8݄wd zWְ̫:Pv {XVֲLlWmhY"hUZ&~|iȶֶ-_Wʶnp;\׸Enrne\h_8]V׺#b{]v׻߽P} ^׼% JY׽oM&9׾uov]y_6p7XqnӌI_ upkzqE!ãUbGu=1Rb)qt?p׋گZ&9'Wz d&7ys/6W%KeNr&S^`mfD)抑9@ռ/]QN9,|lؼg> C='&ӥ"·Z{>7r3li9~虅GwӂⲤ쬛YΙ4YiVZSP1% V9q5M׿Sc,<F"=laү:Kvͣ?qveKwIu2w՝ X[Hfozwo};! 5|p7+>qW]5qOxE>I8zr/ye>\q&j[=s'rGGzYttѕ>uSr1'w빽Ψԣ/ Ŵl^ΰ+niETfʅ:E lk7dO~he26(5햿q%ix _JKy#ûfiُ5{Qѷʕfw/|\q5f_>܃רS㔼S~ԩMԇ.U{4wTr?Oo¿()$obc` ?9q㵳@Z?ؽ;&c>Ӿ{[<)<BL^<ʓD{Ӥl?nbA%''?]tԿ$)Կ0B-(⫿;A?,A=C#C (C;4 Z[ 䵴@+LBN*B'>)|B[3曾N$>P"MLBD=z:ǹD3)C`<8$I],#_*fg,)2D؋kF;RۮoG<Ŭ3ƭ sD4L"swxyz i-#}~@ȁ$H8j,ȄTȅL'ZDcȈȄԫXȌ|8Ǐɐɑ$ɒ |$Gӹtdɖ-i1T9ɚ|mHϲɝZǀ,ʡqɸDKl!` =tJɎ4#ۉ<g k.9.V `BCuDVEfFvڢ5&VuVE]?Md,ۍKM&ebUBR+VV i&`ogSq66>un`Xvcx{|}  Z"z@c܅Vfv艖芦苶&6FVfv阆Vhb(IF -Jhi&6FVfvꦆ %hJE謖&6F~i~j|ݚк>|k9l&6FVlvx@̅QAk~䉈C SѮ!ӆƶvO2*K۾CC^SCB:AYmwljl)1F?'7GWgw'q}wWtv|(you@ Xgc8wwpOzGzgzWzz7G{W_gwo{{|'Wupug0hzʷQ=nb㫎?e& G+nևE+ا}xo`(~:I~Y~Xhi~~w7 g_WowX~~~~o gp(L!ĆJHČ5bp:$QcA"Od%̗29͜3uXsC<ifʢD*mf;9!\*֬2B`!YI`j׮-0$ek.޼zt!ܹgR-\2n1޿sƅl2ƒ)/V9pϙGE ϜC]Y4iٵJV 8|{ٳiZ >O2'_7dQοoown>={ӟojCq>u57[m]W`e`pTUD%timeAPIQHuҕ`bאC D`-(b[4NV8R<>O}(j ( aHN$ܕ!ra-I"0 e݄Y%T&BΨ=Ȗm!o 5*VBuGr EUFyhBPDRvqR)E*:JxǩQv97]餓+ ˪t>hZJ⪪z:ímۂ58U.b,u桜Yeکz*[m'|0*{λZQ> 1Ejo!x!ʊq/r.{-LmxϞ JuO[4}?ݧj~tse6::놻~ 7;w\ӥ 鶣|;׹>|#8ӾdG:#:b4JQԠSr [ jVԼYQfȴ'tq[MJuƑ"ʅ u(ABřr $IU*3rl$GC Gs%%7jƋ}iDaЁvҏmK*I4>)+)ZNw^ԓ)Qu,"msKS-xK*dj1EUdUܱR"K5ZzԀ+^sjѹe&EoTH̬?5XV5~`&^ZѼգ|mc1:X޴SMb*4?%h;^+[¶-lֶ݁oev=q*.p}+R׶pc{]޲c-t]bܽv{ܮwnpK~wo}+_׽e.+8M/{ŋwoy ,Sٍvśw~[8V/S [Ec'Ck@xF1c ӘF>c%3,Jn2(S`1U\3+]7@jP1UA^39'v&IT.g3>K S l(C)ϖ^rMsz|- PyԤֳO}+v_|0`2a K@ƓSfϦ.W_{aАq} mr9HLflSTbW*֞EXt)J]z P;ֲmx!̩mQy DyZiˤeګvm+/ox-z?A7ѽ %?|0-Œdx 䂏Vq |<9c^U~W πu x |w}ی]m'/>ڍĭՆT)ؠy6<} *@u'iԟG=Snd}6@;ߌ/Z|mw>G|+s|//[F-<c  r,, zz0?/GA3^`@(]) E2- ^q^l^ڙe]ŗQ(A @ALF1"&V&FYvb#Fх Z@!djaݢ^._ <#y$]9Vb32_ၢic}"7V( "/(A`@$AL@62 6F=رMH1r9c}cdA䑙aU!ْ92l0P@05=ؕ)! ^/"$!J$υcjM^C:;C.T@1Ď?$_B.%Q7dR"RdS:%LZŘ"]#;>S~cW#PeXXfWrBMUHYb\R\nb]]a^eTX[V^m`&aa&b&b.&c6c>&dFdN&ef_nT$ ߍ5bYY&fej^ gDYYkr^&f p&&9RڣEڤ$j:Ʊuu"tv_vBq6^wzqeff ҚZuޯct\d]c6~'٧g~'-%M[[=^/z%|v?]?e!R42(gX'i_:NEq\ǩ_#%.eٵ˥%2&bov6%il?(ZA`e]'|?i!!cʝ2jf%w)h|y(re9m(njȊgHQQ.rjѨN)Y1bj))飆}*%ȓJIg^{I]#v*jD 3ZVa(J*K(뱺8z   Ҡ )_*"(!:z)+zkj*«qjU`jz b ""TD(k&꣮k.#f"k(_T*+.^Rbfb&㊮n(+"]e../lg؎ޖFn-?&YJZ/yf-ZB'܎]go񞯐CZ'a|CB5](mo~酲)k튬A(9ovn]m\ޯW*2ө_Z뎸,Gfh]:zк$n`2%m7m _J⛔l?thb>#(Zcfpf6k_hݓJ &*4WRJ[S0k1= Jՠ^+f&큫6$3JiJ_r'-킛mDa +!Ң*^Y#-"%6-3r.sc1/"+!WH"sfH0.b,w)6m2Z2Aְ7&9:;#{ŭ>6,0fB4rLa/?-EZ$FjRp(;o:ud^۩@ö;{㻺a*b<+x} }8æ`]C|;/?3=Of_<784u :)7}Ǽ#*zݿ}}=#6η<|<#8C=ӤS=_}c=S&gp;B-x׺{<( &~}wva.a>>ѳ<tg[G<3n\p;kv؋{i5 H1"@G𷿿oe&b>> ;@8`A&TB~ĉD+bX1Ŏ=j EQTe˔`{7V\ԹgO ::2B`!./ +(K(PbA= GZjƕ;Y7[ޡvM`t'+[oFXqe@E|?ܙhҢK.qukӞ)Vtжq֝3ݱeǍ:hK.pU p +P$A@`"Wgo`Ϳ̛S+- ,LPlp@qB9[Z:J(+Q!lGzQHc0)I|lr@'D2J)*d%l[f5($F<ܡ)OJQc-UF;bNac PD Dy? L\­בlԁv Qҕ9YCXӔ,e)әSt꘻%}R(W?n Kp2OHJRЄηDuC3YQ*:<[WFm GQ Op+]5]8]>.kLI)Q #r$L uQІ4N0|`Q"~dGr$JVtv5/-%yT9yܧ(xL~ WPY_ԿJSq|yM/*WšUI-[9%8Tr+G!ؑB.T}YTeUdA Pҳje;#+Α[gKMвIM7_(! O0 `QM 3ЁmN5Yzjmn}7][aא& L* Cm'ߴ58zz;dKWv0~6nX*cC{ n'v(Ca;/ɪG{2yg$mr}=?`uElh\19oy3 Cnx[2@ d{놎u=w3{ w8L%O]qRa.-Ӛ=7\Sr/~ZۜV4EsO]owa=x]eF4ўqSK[u{+5:x=njwZ: 8 x͛||r?=w}So7xqO~oum^^d#+!?oLO_Ռ4/G>mR:>ӭl~᷿Hho;,oʶonNo=pPb"q=+naг'Ppk DO/PjKpoܯypҜ-/ JJ ~ ŰP/ - 1Oư ۈ c ϊ6; PpXP 0  1 g E/no%q (151ռpA119EQ2_0a1=1eq1_1}Q:cG]qW qgk1[0qq񈜮q1 Q r   R![!%'"1!r1#Q"m#ERo$Q$0%]2K"%iARk2'P#Yr!u'&(Rc2g(rWR&Or)0*r2r+s'%2,/+R,,ٲ)-rr.2)/}+,r0Mn/021qGʎ*1-29s3I>s-4Y3 S0[36)4%ȴq3e37-)0u7w6L}n185}97a9ӥ3":)3W;3xS-+;s3$<:9=s|<}=s>3's?;2<3@'?GS@ 4u@z?sA!Tt4B)u7+4C?@5C-L88ECAD1q23:QEA;AaFfBm4G'J