BEA Logo BEA WebLogic Portal Release 4.0

  BEA Home  |  Events  |  Solutions  |  Partners  |  Products  |  Services  |  Download  |  Developer Center  |  WebSUPPORT

 

   WebLogic Portal Documentation   |   Building Personalized Applications   |   Previous Topic   |   Next Topic   |   Contents   |   Index

Using the Expression Package

 

This topic illustrates how to use the services of the Expression Package. Any arithmetic, boolean, relational or conditional statement can be represented in the Java object model by using an Expression Package. You can use the Expression Package to dynamically assemble and evaluate your own business logic.

This topic includes the following sections:

 


Introducing the Expression Package

The Expression Package allows users to dynamically assemble and execute Java-based expressions. The package defines a set of Java classes that represent various types of expression operators, and contains services for evaluating expressions consisting of instances of these operators.

What Is the Expression Package?

The Expression Package includes a base Expression class, a Variable class, and the following operator classes for operating on Expressions and Variables:

The Expression Package also includes the following services for operating on expressions:

Unlike an expression written directly in Java and executed from within a Java program, the Expression Package allows you to dynamically assemble and modify expressions from within your Java programs. An expression may be modified any number of times both before and after evaluation. When you assemble expressions using the Expression Package you can also take advantage the advanced features of the Expression Package, such as expression caching, validation, and optimization.

The Expression Package serves as the foundation of the BEA Rules Engine. The Rules Engine leverages the package in order to represent and evaluate rule condition and action expressions. Likewise, you can use the Expression Package to dynamically assemble and evaluate your own business logic.

The Package Structure for the Expression Package

The Expression Package interfaces and abstract classes can be found in the following package: com.bea.p13n.expression

The Expression Package operators are organized in the following packages:

Basic language operators-com.bea.p13n.expression.operators

Logical operators-com.bea.p13n.expression.operators.logical

String operators-com.bea.p13n.expression.operators.string

Mathematical operators-com.bea.p13n.expression.operators.math

Comparative operators-com.bea.p13n.expression.operators.comparative

Collection operators-com.bea.p13n.expression.operators.collection


 

The Expression Package related classes are packaged in the p13n_util.jar archive.

 


Assembling and Managing Expressions

Before you can begin using expressions, you must first learn how to programmatically assemble them using the various operator classes provided in the Expression Package.

An expression is represented as a tree, where each node is another expression itself or a plain Java object. Expression trees are assembled in a bottom-up manner; a child expression or Java object is first created, and then added to a parent expression.

Figure 5-1 illustrates the steps required to build an expression tree.

Maintaining Parent-child Relationships

Each of the operator classes defined in the Expression Package extends a common base class that contains the necessary logic for maintaining parent-child relationships; therefore, you do not have to worry about maintaining these relationships while assembling expressions. However, it is possible to modify the structure of an expression after it has been created.

Table 5-5 shows the operators provided in the Expression interface for adding, modifying, or removing subexpressions in an expression.

Table 5-5 Methods for Building an Expression Tree

Java Method

Description

addSubExpression

Adds a child (can be a subexpression) to an expression object.

removeSubExpression

Removes an object (can be a subexpression) of the expression object.

setSubExpression

Replaces existing object (of an expression) by the given object (can be a subexpression).

getSubExpression

Can be used to access the children of an expression object.

getParent

Can be used to access the parent expression of an expression object.


 

See the Javadoc API documentation for more information about the Expression interface.

Managing the Expression Cache

The expression interface also includes methods to manage the caching of results. The result of evaluating an expression may be cached in each expression object. When the cache is enabled for an expression, trying to evaluate the same expression a second time will return the cached value.

Note: By default, caching is turned off. You may want to keep the cache turned off for some operators, such as MethodCall.

Table 5-6 shows the methods provided in the Expression interface to manage the caching of results.

Table 5-6 Methods to Manage Caching of Results

Java Method

Description

setCacheEnabled

Can be used to enable or disable the cache for an expression.

isCacheEnabled

Can be used to check if the cache is enabled for an expression.

isCached

Can be used to check if a result is currently cached for an expression.

getCachedValue

Can be used to get the current cached result of evaluating the expression.


 

See the Javadoc API documentation for more information about the Expression interface.

 


Expression Package Operators

The following section describes the inheritance hierarchy of the Expression Package operators and contains detailed information on each operator class:

Operator Inheritance Hierarchy

Before you start using operator classes, it is important to first understand the operator inheritance hierarchy.

All operator classes must implement the com.bea.p13n.expression.Expression interface. As explained previously, the Expression interface contains methods for maintaining result caching and parent-child relationships. Rather than having each operator implement the methods on the Expression interface directly, each operator class eventually extends from an abstract base class (ComplexExpressionImpl) that contains implementations for all Expression methods.

Each operator sub-package contains an abstract base expression class that all operators within the package extend. For example, the com.bea.p13n.expression.operator.logical package contains an abstract operator base class LogicalOperator from which all logical operators extend.

Finally, in order to differentiate between unary and binary operators, two interfaces, com.bea.p13n.expression.operator.UnaryOperator and BinaryOperator, are implemented by the corresponding operator types.

The Operator Inheritance Hierarchy is illustrated in Figure 5-2.

Figure 5-2 Operator Inheritance Hierarchy Diagram


 

Basic Language Operators

The com.bea.p13n.expression.operator package contains basic Java language operators for branching, dynamic class loading, object creation and introspection, class and object method calls, and system information retrieval.

An important class in this category is Variable. This class is used to represent Java variables, and as such, has an associated name and class type. It can be used to build expressions that contain variables that are bound to values (of an appropriate class) during the evaluation process (via the Unifier service).

Table 5-7 shows the complete list of available operators in this category.

Table 5-7 Miscellaneous Operators

Java Class

Description

ClassForName

Dynamically loads the class with the given name.

ClassGetName

Returns the name of a given class.

If

IF operator (if-then-else in Java)

Instanceof

Creates a new instance of a given class.

MethodCall

Invokes a method on a given object or class.

ObjectGetClass

Returns the class of a given object.

ObjectHashCode

Returns the hash code of a given object.

ObjectToString

Returns the string representation of a given object.

SystemCurrentTimeMillis

Return the current time in milliseconds according to the system clock.

SystemGetProperty

Returns the value of the system property with a given name.

Variable

Used to represent expression variables. A variable has an associated name and type and is bound to a value during evaluation.


 

Examples of Basic Language Operators

The if-then-else statement:

if (9 > 8) then true else false;

can be represented as:

new If(new GreaterThan(new Integer(9), new Integer(8)), Boolean.TRUE, new Boolean.FALSE);

Logical Operators

The com.bea.p13n.expression.operator.logical package contains all the operators necessary to construct logical (boolean) expressions.

Table 5-8 contains a list of operators in this package.

Table 5-8 Logical Operators

Java Class

Description

LogicalAnd

Binary Logical AND operator (&& in Java)

LogicalOr

Binary Logical OR operator (|| in Java)

LogicalMultiAnd

Logical AND operator (multiple && in Java)

LogicalMultiOr

Logical OR operator (multiple || in Java)

LogicalNot

Logical NOT operator (! in Java)


 

Examples of Logical Expressions

String Operators

The com.bea.p13n.expression.operator.string package contains operators that perform string operations.

Table 5-9 contains a list of operators in this package.

Table 5-9 String Operators

Java Class

Description

StringCharAt

Returns the character at the specified index within a string.

StringCompareToIgnoreCase

Compares two strings lexicographically, ignoring case considerations.

StringConcat

Concatenates a specified string to the end of another string.

StringContains

Tests if a string contains a given sub-string.

StringEndsWith

Tests if a string ends with a specified suffix.

StringEqualsIgnoreCase

Compares two strings, ignoring case considerations.

StringLength

Returns the length of a string.

StringLike

Tests if a string contains a given sub-string, ignoring case considerations.

StringReplace

Returns a new string resulting from replacing all occurrences of a given character with another given character in a target string.

StringStartsWith

Tests if a string starts with the specified prefix.

StringSubString

Returns a new string that is a substring of a given string.

StringToLowerCase

Converts all of the characters in a string to lower case.

StringToUpperCase

Converts all of the characters in a string to upper case.

StringTrim

Removes white space from both ends of a string.


 

Examples of String Operators

The following statement:

String string = new String(FooBar");
string.contains("Foo");

can be represented as:

new StringContains(new String ("FooBar"), "Foo");

Mathematical Operators

The com.bea.p13n.expression.operator.math package contains mathematical operators that operate on java.lang.Number instances. Analogs to all the operations exposed by the java.lang.Math class are provided in this package as well as operators for addition, subtraction, multiplication, and division.

Table 5-10 contains a list of operators in this package.

Table 5-10 Math Operators

Java Class

Description

MathAbs

Operator analogous to the java.lang.Math.abs() method.

MathAcos

Operator analogous to the java.lang.Math.acos() method.

MathAdd

Mathematical addition.

MathAsin

Operator analogous to the java.lang.Math.asin() method.

MathAtan

Operator analogous to the java.lang.Math.atan() method.

MathAtan2

Operator analogous to the java.lang.Math.atan2() method.

MathCeil

Operator analogous to the java.lang.Math.ceil() method.

MathCos

Operator analogous to the java.lang.Math.cos() method.

MathDivide

Mathematical division.

MathExp

Operator analogous to the java.lang.Math.exp() method.

MathFloor

Operator analogous to the java.lang.Math.floor() method.

MathIeeeRemainder

Operator analogous to the java.lang.Math.IEEEremainder() method.

MathLog

Operator analogous to the java.lang.Math.log() method.

MathMax

Operator analogous to the java.lang.Math.max() method.

MathMin

Operator analogous to the java.lang.Math.min() method.

MathMultiply

Mathematical multiplication.

MathPow

Operator analogous to the java.lang.Math.pow() method.

MathRandom

Operator analogous to the java.lang.Math.random() method.

MathRint

Operator analogous to the java.lang.Math.rint() method.

MathRound

Operator analogous to the java.lang.Math.round() method.

MathSin

Operator analogous to the java.lang.Math.sin() method.

MathSqrt

Operator analogous to the java.lang.Math.sqrt() method.

MathSubtract

Mathematical subtraction.

MathTan

Operator analogous to the java.lang.Math.tan() method.

MathToDegrees

Operator analogous to the java.lang.Math.toDegrees() method.

MathToRadians

Operator analogous to the java.lang.Math.toRadians() method.


 

Examples of Mathematical Operators

The arithmetic statement:

int a = 1;
int b = 2;
int c = 3;
a + (b - c);

can be represented as:

Integer a = new Integer(1);
Integer b = new Integer(2);
Integer c = new Integer(3);
new MathAdd(a, new MathSubtract(b, c));

Comparative Operators

The com.bea.p13n.expression.operator.comparative package contains operators for performing comparative operations.

Table 5-11 contains a list of operators in this package.

Table 5-11 Comparative Operators

Java Class

Description

Equals

Tests two objects for equality.

GreaterOrEquals

Tests if one object is greater or equal to another object.

GreaterThan

Tests if one object is greater than another object.

LessOrEquals

Tests if one object is less than or equal to another object.

LessThan

Tests if one object is less than another object.

NotEquals

Tests two objects for inequality.


 

Example of Comparative Operators

The comparative statement:

(9 < 10)

can be represented as:

new LessThan(new Integer(9), new Integer(10));

Collection Operators

The com.bea.p13n.expression.operator.collection package contains operators that operate on java.util.Collection instances.

Table 5-12 contains a list of operators in this package.

Table 5-12 Collection Operators

Java Class

Description

CollectionContains

Returns true if a given collection contains a specified element.

CollectionContainsAll

Returns true if a given collection contains all of the elements in another specified collection.


 

Example of Collection Operators

The following statement:

Collection container = new LinkedList(); 
Object element = new Object();
container.contains(element);

can be represented as:

new CollectionContains(new LinkedList(), new Object());

 


Working with Expressions

After you have assembled an expression, you are ready to work with it using the various Expression Package services. These services allow you to prepare an assembled expression for evaluation, validate that the expression is well-formed, optimize its structure, and finally, evaluate the expression.

The following information is presented in this section:

The Expression Factory

The ExpressionFactory provides methods to create the various Expression Package services and data structures used by these services.

For example, the following method will create an instance of the Validator service:

ExpressionFactory.createValidator(null);

For more detail on how to construct the various Expression Package services, see the Javadoc API documentation.

Expression Package Services

The Expression Package offers services which can be used on any expression that is built using the operators in the Expression Package.

Unification Service

The Unifier is used to unify variables (assign values to variables) present in an expression. The Unifier uses a data structure known as a UnificationList that stores the variable name and the corresponding value of the variable. Like the Unifier, the UnificationList instances are created via the ExpressionFactory. The Unifier gets the value from the list for a particular variable using the variable name as a key to search the UnificationList, and binds the retrieved value to the variable.

See the Javadoc API documentation for more information about the Unifier interface and the ExpressionFactory class.

Optimization Service

The Optimizer is used to optimize an expression. The default optimization algorithm used by the Optimizer is shown below.

See the Javadoc API documentation for more information about the Optimizer interface and the ExpressionFactory class.

Validation Service

The Validator is used to validate an expression. The default validation algorithm used by the Validator is as follows:

For each operand of an operator:

The Validator can be used in a stateless or stateful mode. In stateless mode, any expression evaluations necessary to perform validation will be executed in stateless mode.

For more information about stateless and stateful evaluation modes, see the Evaluation Service section below.

See the Javadoc API documentation for more information about the Validator interface and the ExpressionFactory class.

Evaluation Service

The Evaluator is used to evaluate an expression. An expression can be evaluated in stateful or stateless mode:

Stateful mode

In this mode, the value of each variable that appears in the expression is determined by retrieving the value set within the variable.

In other words, stateful mode relies upon the expression having been previously unified by a Unifier.

When an expression is evaluated in stateful mode and results caching is turned on, the results of evaluation will be cached within the expression.

Stateless mode

In this mode, the value of each variable that appears in the expression is determined by looking up a value that is bound to the name of the variable in an external data structure.

In other words, the evaluation process does not rely upon state associated with the expression, and as such, does not require the expression to be unified before evaluation.

The data structure that contains the name-value mappings for variables is known as a UnificationList and is associated with the Evaluator. Like the Evaluator, the UnificationList instances can be created using the ExpressionFactory.

A side effect of stateless mode is that expression evaluation cannot take advantage of results caching.

You can use of stateful mode in a situation where an expression need only be evaluated within a single thread of execution. In the case of multithreaded evaluation of a single expression, you must use stateless mode.

Note: If an expression does not contain variables, then there is no difference between the two evaluation modes.

See the Javadoc API documentation for more information about the Evaluator interface and the ExpressionFactory class.

Execution Service

The Executor aggregates the Unification Service, Validation Service and Evaluation Service. The execute method on an Executor takes a Unifier, a Validator and an Evaluator to execute a cycle of unification-validation-evaluation operations.

The algorithm used by the Executor is shown below:

Unification

Note: The Unifier should be null in the case where the expression passed to the Executor is already unified, or the expression is to be evaluated in stateless mode.

Validation

Evaluation

Note: If the Evaluator passed is stateless, then the Unifier should be null.

See the Javadoc API documentation for more information about the Executor interface and the ExpressionFactory class.

 


Code Examples

This section contains examples that illustrate how to construct expressions programmatically and use the Expression Package services.

This section contains the following four code examples:

Stateful Evaluation of a Simple Expression

A logical expression is constructed and executed in stateful mode. The expression does not contain any variables.

Example

The source code for creating and executing the expression is shown below:

Expression expression = new LogicalAnd(Boolean.TRUE, Boolean.FALSE); 
// Prepare for creating an executor by creating a stateful
// evaluator. Since the expression does not contain variables,
// we are not using a validator or a unifier in this example,
// so we will not create them.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null); 
// null is passed for the environment Map.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing null for both the unifier
// and validator parameters.
Object result = executor.execute(expression, null, null, evaluator);
// The result should be Boolean.FALSE.

Stateful Evaluation of an Expression Containing Variables

An expression containing variables is constructed and evaluated in stateful mode.

Example

The source code for creating and executing the expression in stateful mode is shown below.

// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now, we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable); 
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case, there is one
// variable in the expression so the variable needs to be assigned a
// value. This is shown below.
// Create a UnificationList to store the variable name and value as
// key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE);
// Create a unifier.
Unifier unifier = ExpressionFactory.createUnifier(null, unificationList);
// Prepare for creating an executor by creating a stateful
// evaluator. We are not using a validator in this example,
// so we will not create one.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null); 
// null is passed for environment Map.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing a unifier and a null
// validator.
Object result = executor.execute(expression, unifier, null, evaluator);
// The result should be Boolean.FALSE.

Note: The expression can be unified before calling the execute method by calling the unify method on the Unifier. Once the expression is unified there is no need to pass a unifier to the execute method of the executor.

Stateless Validation and Evaluation of an Expression
Containing Variables

An expression containing variables is constructed and evaluated in stateless mode. The Validator service is also used to validate the expression.

Example

The source code for creating and executing the expression in stateless mode is shown below.

// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable); 
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case there is one
// variable in the expression, so the variable needs to be assigned
// a value. This is shown below.
// Create a UnificationList to store the variable name and value as
// key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE); 
// Prepare for creating an executor by creating a stateless
// evaluator. We are not using a unifier in this example,
// so we will not create one.
// Creating a stateless evaluator by passing null for the
// environment Map and the UnificationList.
Evaluator evaluator = ExpressionFactory.createEvaluator(null, unificationList); 
// Creating a stateless validator.
Validator validator = ExpressionFactory.createValidator(null, evaluator);
// Creating an executor.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing null for the unifier and
// a non-null validator.
Object result = executor.execute(expression, null, validator, evaluator)
// The result should be Boolean.FALSE.
// After calling execute method, the given expression will not be
// modified by any services that were used above.
// The stateless execution mode is useful if an expression is shared
// between multiple threads.

Stateful Validation and Evaluation of an Expression
Containing Variables

An expression containing variables is constructed and evaluated in stateful mode. The Validator service is also used to validate the expression.

Example

The source code for creating and executing the expression in a stateful mode is shown below.

// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable); 
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case, there is one
// variable in the expression, so the variable needs to be assigned
// a value. This is shown below.
// Create a UnificationList to store the variable name and value
// as key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE);
// Create a unifier.
Unifier unifier = ExpressionFactory.createUnifier(null, unificationList);
// Prepare for creating an executor by creating a stateful
// evaluator and validator.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null); 
// null is passed for the environment Map.
// Creating a validator.
Validator validator = ExpressionFactory.createValidator(null);
// Creating an executor.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing a unifier and a non-null
// validator.
Object result = executor.execute(expression, unifier, validator, evaluator);
// The result should be Boolean.FALSE.

Note: The expression can be unified before calling the execute method by calling the unify method on the Unifier. Once the expression is unified there is no need to pass a unifier to the execute method of the Executor. The validation service can be used directly by calling the validate method. The validate method throws an InvalidExpressionException if the given expression is invalid.

 


Expression Package Configuration Settings

The expression.properties file contains configuration settings for the Expression Package and should be modified with care.

This file is archived in p13n_util.jar under the package com.bea.p13n.expression.

##
# Expression Comparator null handling
#
# If the following property is set to true the Expression
# Comparator will return false as the result of comparing
# any non-null value to a null, regardless of the
# comparison being performed.
#
# Defaults to true.
##
expression.comparator.nullcheck=true
##
# Expression Comparator equality epsilon.
#
# The following property determines the epsilon value for
# numeric equality comparisons.
#
# Defaults to 0.
##
expression.comparator.epsilon=0.00001
##
# Expression Introspector Method Array Caching
#
# If the following property is set to true the Expression
# Introspector will cache the array of Methods implemented by a
# Java Class.
#
# Defaults to true. 
##
expression.introspector.method.array.cache=true
##
# Expression Introspector Method Caching
#
# If the following property is set to true the Expression
# Introspector will cache Methods by signature.
#
# Defaults to true.
##
expression.introspector.method.cache=true
##
# Expression Parser Node Support Classes
#
# This property supports a comma-delimited list of classes
# extending the base AST NodeSupport class. Such classes
# provide node creation support for expression-schema namespaces
# required for constructing the intermediate AST representing a
# given Expression instance.
#
# All NodeSupport subclasses must co-exist peacefully with the
# required CoreNodeSupport instance.
##
parser.node.support.list=\ 
com.bea.p13n.expression.internal.parser.expression.ExpressionNodeSupport
##
# Expression Parser Transform Visitor Class
#
# This property specifies the ExpressionTranformVisitor or
# subclass to be used for intermediate AST-to-Expression
# transformations.
#
##
parser.transform=\
com.bea.p13n.expression.internal.parser.expression.ExpressionTransformVisitor

 

back to top previous page next page