Skip Headers
Oracle® Business Rules User's Guide
10g Release 3 (10.1.3)
B15986-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

6 Using Oracle Business Rules SDK

Oracle Business Rules SDK (Rules SDK) provides APIs that a developer can use to write customized applications that access, create, or modify rules and data models (and all the information stored in an Oracle Business Rules dictionary). Using Rules SDK APIs, you can create, modify, and access dictionary data using well defined interfaces and you can use the APIs to build customized rules enabled applications.

You can use the Rules SDK APIs in a rule enabled application to access existing rules and then run the rules engine, or in an application that you write to access, create, or edit rules and data model information.

This chapter introduces the Oracle Business Rules SDK APIs.

This chapter covers the following topics:

6.1 Rules SDK building blocks

The top level Rules SDK package, oracle.rules.sdk, includes the following packages:

The Rules SDK interface follows the Java Bean model and includes getters and setters for each bean property. For example, setName("somevalue") sets the name property of the individual instance.

In addition to bean interfaces, the Rules SDK provides a hash get and put style interface. The bean interfaces are generally useful, but there is a least one GUI framework in which the HashMap style is necessary.

6.2 Working with a Repository and a Dictionary

Oracle Business Rules dictionaries are stored in a repository. Prior to accessing a dictionary, access to its repository must be established. This requires specifying the type of repository to access and the initialization parameters required by that specific repository type. As shipped, Rule Author supports a WebDAV (Web Distributed Authoring and Versioning) repository and a file repository.

Table 6-1 shows the initialization parameter keys for a WebDAV repository. The repository type key is oracle.rules.sdk.store.webdav.

Table 6-1 WebDAV Repository Type Parameter Initialization Keys

Parameter Key Description

URL

oracle.rules.sdk.store.webdav.url

The URL for the desired WebDAV rule repository. This parameter is required.

Proxy Host

oracle.rules.sdk.store.webdav.proxyHost

The host name of the proxy server. This is only required if you have a proxy server between the server on which Rule Author is running and the WebDAV server.

Proxy Port

oracle.rules.sdk.store.webdav.proxyPort

The port to use for the proxy server. This is only required if you have a proxy server between the server on which Rule Author is running and the WebDAV server.


Table 6-2 shows the initialization parameter keys for a file repository. The repository type key is oracle.rules.sdk.store.jar.

Table 6-2 File Repository Type Parameter Initialization Key

Parameter Key Description

File Path

oracle.rules.sdk.store.webdav.path

The path to the file that contains the rule repository. This parameter is required.


6.2.1 Establishing Contact with a WebDAV Repository

Example 6-1 shows how to establish access to a WebDAV repository.

Example 6-1 Establishing Access to a WebDAV Repository

String url;     // the URL for the WebDAV repository
Locale locale;  // the desired Locale

// The following code assumes that the url and locale have been set appropriately
RepositoryType rt =
   RepositoryManager.getRegisteredRepositoryType("oracle.rules.sdk.store.webdav");
RuleRepository repos = RepositoryManager.createRuleRepositoryInstance(rt);
RepositoryContext rc = new RepositoryContext();
rc.setLocale(locale);
rc.setProperty("oracle.rules.sdk.store.webdav.url", url);
repos.init(rc);

If the WebDAV repository has been configured to require authentication, then the following must be performed:

  • Configure a wallet with the required user name(s) and password(s).

  • Create an instance of the oracle.rules.sdk.callbacks.WalletCallback class and set it in the RepositoryContext prior to calling the init method.

In Example 6-2, /wallets/rules_wallet is the path to the wallet configured with the credentials for WebDAV authentication:

Example 6-2 Configuring a Wallet for Authentication

WalletCallback callback = new WalletCallback("/wallets/rules_wallet", null);
rc.setSensitiveDataCallback(callback);

6.2.2 Establishing Contact with a File Repository

Example 6-3 shows how to establish access to a file repository.

Example 6-3 Establishing Access to a File Repository

String path;     // the path to the file repository
Locale locale;  // the desired Locale

// The following code assumes that the path and locale have been set appropriately
RepositoryType rt =
   RepositoryManager.getRegisteredRepositoryType("oracle.rules.sdk.store.jar");
RuleRepository repos = RepositoryManager.createRuleRepositoryInstance(rt);
RepositoryContext rc = new RepositoryContext();
rc.setLocale(locale);
rc.setProperty("oracle.rules.sdk.store.jar.path", path);
repos.init(rc);

6.2.3 Loading a Dictionary

Now, a dictionary may be loaded either by specifying the dictionary name, in which case, the default version of the dictionary is loaded with:

RuleDictionary dictionary = repos.loadDictionary(dictionaryName);

or by specifying both the dictionary name and version with:

RuleDictionary dictionary = repos.loadDictionary(dictionaryName,
                                                 dictionaryVersion);

These examples are applicable to both file and WebDAV repositories.

6.3 Working with a Data Model

The Rules SDK data model contains the fact types, internal variables, constraints, and functions that you use to create rules. The fact types from the data model can be reasoned on in corresponding rules. Oracle Business Rules variables contain information that rules share. Oracle Business Rules functions provide for logic reuse for rules. Constraints limit the set of valid values for rule customization.


Note:

To import existing Java classes or XML schemas, the Rule Author application must be used. After the classes or schemas are imported with Rule Author, the repository may be used by the SDK. Future versions of the SDK will have extensions to allow for Java classes and XML schemas to be imported directly.

After you use a repository to create or open a RuleDictionary, you can use the Rules SDK to create a data model in the dictionary. A RuleDictionary can access the internal data structures necessary to create a DataModel instance.

The data model shown in the examples is this chapter includes the Java FactTypes that are imported from a sample package named email. The email package was imported using Rule Author. The classes and properties shown in Table 6-3 were populated by importing email.jar.

Table 6-3 Sample email Package Classes

Name Description Type

email.ElectronicMessage

Represents the occurrence of a message

Java FactType

email.EmailAddress

Represents an email address

Java FactType

email.EmailAddressList

Represents a list of email addresses

Java FactType


In the data model for the spam processing example, using the email package, the data model supports inferencing by creating an RLFact named SpamFound. To contain a global count, we create a variable named spamCounter, and the constant String variable indicates spam. A function named killSpam provides an action when the rules detect that an email message is spam. Table 6-4 shows these data model components.

Table 6-4 Sample Data Model Types for Handling email Package

Name Description Type

SpamFound

Asserted when email message is determined to be spam

RL FactType

spamCounter

Accumulates count of spam messages

variable

SpecialOffer_CONST

Constant containing the String "Special Offer"

constant variable

fKillSpam

Called when spam found to delete spam

RL Function


6.3.1 Creating a DataModel

After you create and open a RuleDictionary, you can use the Rules SDK to create an editor.DataModel. The RuleDictionary can access the internal data structures necessary to create a DataModel instance.

For example,

eDM = new oracle.rules.sdk.editor.datamodel.DataModel(m_dict);

The basis of the DataModel type system is the FactType. A FactType is defined as a primitive, Java, XML, or RL FactType. A Primitive FactType is fixed, and includes Java primitives (for example: String, int, or double). The Rules SDK automatically creates primitive types when you create a RuleDictionary. You create Java and XML FactTypes when you import classes from jar file, a class, or a schema file. You can create RL FactTypes directly using the Rules SDK. The Java, XML, and RL FactTypes define classes and may have associated properties, which represent the JavaBean defined properties, and methods.

6.3.2 Creating DataModel Components

You create each part of the data model using the appropriate ModelComponentTable. The sequence required to create a new instance, Function, FactType, Variable, or Constraint, is the same:

  • Instantiate the appropriate table in the data model.

  • Invoke the table instance add() method.

Example 6-4 shows how you create a Function instance:

Example 6-4 Creating a Function Instance

FunctionTable ft = eDM.getFunctionTable();
Function fKillSpam = ft.add();

To import existing Java classes or XML schemas, the Rule Author application must be used. After the classes or schemas are imported with Rule Author, the repository may be used by the SDK. Future versions of the SDK will have extensions to allow for Java classes and XML schemas to be imported directly.

6.3.3 Creating a Function Argument List

Using the Rules SDK you create argument lists for functions using a FormalParameterTable. Each FormalParameter entry represents a parameter. The first parameter is the first (zero) entry in the FormalParameterTable, the second parameter is the second Entry, and so on. Variables may be constants, which may not be assigned a value after the original initialization. The setFinal() method controls the constant behavior. Each FormalParameter has a type and a name. The type of a formal parameter is selected from the available FactTypes.

The code in Example 6-5 creates a FormalParameterTable for the email sample.

Example 6-5 Creating a FormalParameterTable

// define the parms of the function
// basically just an instance of ElectronicMessage
// and a String to explain what triggered this
FormalParameterTable fKillSpamParmTable = fKillSpam.getFormalParameterTable();
FormalParameter fp1 = fKillSpamParmTable.add();
FormalParameter fp2 = fKillSpamParmTable.add();
fp1.setName("emsg");
fp1.setAlias("Email Message");

// use the alias for the email.ElectronicMessage fact type
// will be in the getType_Options list
fp1.setType("email.ElectronicMessage");
fp2.setName("reason");
fp2.setAlias("reason");

 // use the primitive type for String
 // will be in the getType_Options list
fp2.setType("String");

6.3.4 Creating an Initializing Expression

Using the Rules SDK, variables contain state internal to a RuleSet. Each variable must have a type and an initializing Expression. The variable type of is chosen from the list of possible FactTypes (all FactTypes defined in the DataModel).

There are two types of expressions:

  • Expression

    This type of expression must follow the form:

    operand operator operand
    
    

    The operands and operators available for an Expression are more limited than than those for an AdvancedExpression. For example, an Expression does not allow an operand to be a function requiring parameters.

  • AdvancedExpression

    This type of expression allows for the full range of operands and operators.

It is recommended that you use an AdvancedExpression to initialize an expression. Example 6-6 shows how to set a variable's initial value.

Example 6-6 Setting a Variable's Initial Value

InitialValue iv = var.getValue();
AdvancedExpression adv = iv.getAdvancedExpression();
adv.insert(0, "\"FIXEDVALUE\"");

6.3.5 Creating RL Function Bodies

RL Function bodies are composed of strings of RL Language. They may refer to any of the Function parameters, or any global Variable. Enter function bodies as a String that must be syntactically correct RL Language (see Example 6-7).

Example 6-7 Creating a Function Body

//set the body of the function
// in this case just pretty print a message
fKillSpam.setBody(" println(\" email from: \" + emsg.getSender() + \"  because \" + reason)" );

6.4 Using RuleSets and Creating and Modifying Rules

Using the Rules SDK, a rule is a conditional expression, referred to as a condition, and a set of actions that execute if the condition evaluates to true. A rule condition is composed of a set of patterns. A pattern delineates the match type and includes tests against that type and other types that appear in preceding pattern (order has meaning). Rule actions can be calls, assignments, retractions, and assertions.

Figure 6-1 shows the general container hierarchy for a RuleSet.

Figure 6-1 Rules SDK RuleSet Container Hierarchy

Rules SDK RuleSet Container Hierarchy
Description of "Figure 6-1 Rules SDK RuleSet Container Hierarchy"

The Rules SDK provides classes that represent each of these objects, all classes descend from RuleComponent. For collections, for example rules in a ruleset, patterns in a rule, or actions in a rule, the Rules SDK provides a class that is descended from RuleComponentTable to manage a specific collection (see Figure 6-2). The RuleComponentTable sub-class provides a specialized add() method for the particular sub-class that the table represents.

Figure 6-2 Rules SDK RuleComponents

Rule SDK RuleComponents
Description of "Figure 6-2 Rules SDK RuleComponents"

The Rules SDK components describing the XML schemas, Java Classes, RL Global variables, and RL Functions are located in the data model (stored in the dictionary). Typically, RuleComponent instances refer to data model entities.

6.4.1 Creating a RuleSet

Generally, the sequence you use to create a RuleComponent is:

  • Create a RuleSet by use of a RuleSet constructor.

  • Create any children of the RuleSet by add() methods on the appropriate table (PatternTable, ActionTable, ExpressionTable, SimpleTestTable).

The Rules SDK API provides classes that represent collections in a RuleSet. Each of these objects descend from RuleComponent. For collections, for example rules in a ruleset, or patterns in a rule or actions in a rule, the Rules SDK provides classes that are descended from RuleComponentTable class to manage a specific collection. The RuleComponentTable sub-class provides a specialized add() method for the particular sub-class represented by the table.

The code in Example 6-8 creates a RuleSet for the email sample,

Example 6-8 Creating a RuleSet

oracle.rules.sdk.editor.ruleset.RuleSet rs = null;
  try
    {
      rs = new oracle.rules.sdk.editor.ruleset.RuleSet(m_dict);
      m_curBean = rs;
      rs.setName("SpamRuleSet");
    }
    catch (Exception e)
    {
      System.out.println(" create RuleSet FAILED");
      addException(e);
      return;
    }

6.4.2 Adding a Rule to a Ruleset

The Rules SDK API provides classes that represent the objects in a RuleSet. Each of these objects descend from RuleComponent. For collections, for example rules in a ruleset, or patterns in a rule or actions in a rule, the Rules SDK provides classes that are descended from RuleComponentTable class to manage a specific collection. The RuleComponentTable sub-class provides a specialized add() method for the particular sub-class represented by the table.

There are several classes that are not parts of collections. To access these classes use the the parent bean with the getter interface. For example, acquire the AdvancedExpression by invoking getAdvancedExpression() on the correct Pattern instance.

The code in Example 6-9 shows how to add a rule to a table in RuleSet.

Example 6-9 Adding a Rule to a Table in a RuleSet

//add rule to the table
oracle.rules.sdk.editor.ruleset.Rule r = rs.getRuleTable().add();
r.setName("DetectSpamRule");

6.4.3 Adding a Pattern to a Rule

The Rules SDK API provides the Pattern class that represents a pattern. The getPatternTable sub-class provides a specialized add() method for adding a pattern object, as shown in Example 6-10.

Example 6-10 Adding a Pattern to a Rule

//add pattern to the rule
oracle.rules.sdk.editor.ruleset.Pattern p = r.getPatternTable().add();

//set pattern
p.setVariable("xx");
p.setFactType( "email.ElectronicMessage");
p.setTestForm("Advanced");

The TestForm property defines the type of test associated with the pattern.

6.4.4 Adding a Test to a Pattern

Every Pattern may have Tests associated with the Pattern. Tests may take the form of SimpleTest or AdvancedExpression. A Pattern may have an unlimited number of Tests.

The Rules SDK "ANDs" Tests together when generating the RL Language. For example, the test used for the email example requires a function with parameters. This requires an AdvancedExpression (see Example 6-11).

Example 6-11 Adding a Test to a Pattern

AdvancedExpression adv = (AdvancedExpression)p.get("AdvancedExpression");

// FUNCTION and Variable complex expression
adv.put("Function", "containsString");
adv.insert(0, adv.getFunctionDescription());

//System.out.println(" function is: <<" + adv.getFunctionDescription() + ">>");
//set the function parms
// normally the cursor position is set by user input actions
adv.setVariable("SPECIAL OFFER");
adv.replace(17, 57, adv.getVariable() );
adv.insert( ((String)adv.getValue()).length() , "," );
adv.setVariable("message.subject");
adv.insert( ((String)adv.getValue()).length() + 1,
adv.getVariable() );
adv.insert( ((String)adv.getValue()).length() , " )" );
//since boolean, this is a single operator no need for anything else

If the test is of the form:

operand operator operand

where neither operand is a function requiring parameters, then a SimpleTest may be used. For example, if the pattern variable name is "emsg" and the test is "emsg.sender == david@fun.com," a simple test would look like Example 6-12:

Example 6-12 A Simple Test

// use the simple form of tests
p1.put("TestForm", Pattern.TEST_FORM_SIMPLE);

//////////////////////////////////////////////////////////////////////
// add a SimpleTest to the Pattern
// emsg.sender == "david@fun.com"
//////////////////////////////////////////////////////////////////////

//create a simple test
SimpleTest simple = p1.getSimpleTestTable().add();

// 
// emsg.sender == "david@fun.com"

// set the left side
Expression lhs = simple.getLeft();
lhs.setForm(Expression.FORM_SINGLE_TERM);

lhs.setSingleTermValue("emsg.sender");

// set the operator 
simple.setOperator("==");

// set the right hand side
Expression rhs = simple.getRight();
rhs.setForm(Expression.FORM_ADVANCED);

AdvancedExpression radv = rhs.getAdvancedExpression();
radv.insert(0, "\"david@fun.com\"");

6.4.5 Adding an Action to a Rule

The Rules SDK supports the following types of Actions:

  • Assert New

  • Assert

  • Assign

  • Call

  • Retract

  • RL

The setting in the setForm property of an action defines the type of action. Add an action using the add() method of the getActionTable instance associated with a particular rule (see Example 6-13).

Example 6-13 Defining an Action Type

//////////////////////////////////////////////////////////////////////
// Add a action to retract the instance of SpamFound
//////////////////////////////////////////////////////////////////////
act = spamRule.getActionTable().add();
act.setForm(Action.FORM_RETRACT);
act.setTarget("spamMessage");  // see above setVariable

//////////////////////////////////////////////////////////////////////
// Add a action to call the kill spam function
//////////////////////////////////////////////////////////////////////
act = spamRule.getActionTable().add();
act.setForm(Action.FORM_CALL);
act.setTarget("kill spam");
//see the datamodel fn definitions, alias for fnKillSpam

Expression exp1 = act.getExpression(0);
Expression exp2 = act.getExpression(1);

exp1.setForm(Expression.FORM_ADVANCED);
exp2.setForm(Expression.FORM_ADVANCED);
AdvancedExpression adv1 = exp1.getAdvancedExpression();
AdvancedExpression adv2 = exp2.getAdvancedExpression();

adv1.setVariable("spamMessage.Spam Email");
adv1.insert(0, adv1.getVariable());

adv2.setVariable("spamMessage.Why is this spam");
adv2.insert(0, adv2.getVariable());

6.4.6 Notes for Adding RuleSets and Rules

The order in which you add components to a RuleSet is important. Use the parent object to create a required child object. For example, after you create a RuleSet instance, you can add rules the RuleTable instance for the RuleSet. After you create the RuleSet, then you can add a Rule to the RuleSet using the add() method for the RuleTable. In turn, then add a rule pattern to the rule using the PatternTable.add() method. Finally, to create a test in the Pattern access the AdvancedExpression using getAdvancedExpression() or for standard mode tests, use SimpleTestTable.add().