Using Expressions (Part 3)
An expression is a single Boolean or arithmetic expression that can be evaluated by a special expression evaluation class. The operands in an expression are literals (numbers and strings), paths or functions.
An expression string is analogous to an Excel formula. It encapsules logic, data access, calculations etc
sub-expressions mechanism allows an expression to be defined once with a known name, and then re-used in other expressions.
$Focus:site2contact_role(primary_site=1):role_name = ‘Employee’
dateAdd(‘d’, $Focus:required_date, 3)
If ($Var:Churn = ‘High’) then ‘Gold’ else ‘Silver’
Expressions are a generalisation of the path concept that has always been in Clarify. There are several places in the application where a Boolean expression is stored in the database in three fields – path, operator and value. Expressions are stored as a single text field, containing the expression. All string comparisons are case insensitive.
Expression use ‘contexts’ to read and write data. Its syntax includes functions, operators, operands, logical tests and literals. They can be created dynamically at runtime.
Where Expressions are Used
- Extensively used by Amdocs Process Manager
- Input parameters for Services (Process Manager and Rule Manager)
- Order Management Standard Edition Eligibility rules
- Role Based Authorization
- Flexible Attributes Templates
How Expressions are Used inby APM
- Most places in APM that expose properties that are used directly at runtime
- Operation inputs / outputs
- Pre and post data assignment
- Conditional junctions
- Dynamic subprocess
- Dynamic service
Why Use Expressions?
Expressions encapsulate business logic easily without implementing complex processes. The processes become easier to build, manage, understand and maintain.
Expressions provide improved runtime performance and ease of monitoring
Expressions overcome various Process Manager constraints. Business processes become easier to build, manage, understand and maintain by reducing need to extend code or datamodel.
Expression allow using user-friendly naming, easier implementation and testing
Expressions combine operands which take the form of paths, literals or other expressions.
The following describes an expression. Uppercase and quoted elements are lexical constants.
Keywords are case-sensitive:
not ($Var:Score > 0)
5 * ($Focus:score + 1)
The values for OP are supported, shown in order of precedence:
- Strings are delimited by single quotes
- String Concatenation ( + )
- Escape ( \ ) characters: Newline ( \n ), Return ( \r ), Tab ( \t ), Single quote ( \’ )
- Constants: Boolean true ( true ), Boolean false ( false ), Null ( null )
if ($Var:CaseType contains 'Sales')
The values for UNARY are ‘-‘ and ‘NOT’.
Unary has a higher precedence than OP.
any(<Collection-Path>, ‘$IterativeContextName’, exp) every(<Collection-Path>, ‘$IterativeContextName’, exp)
Takes a Collection-path which returns an array of objects (i.e com.clarify.webframework.CdoCol), iterates through each element from the array and assigning the element from the array to the context named $IterativeContextName.
Then it evaluates the expression which may contain a DataPath with a context name of $IterativeContextName.
The any function iterates over the row, access a value from each row and evaluates the value against some rule specified in the any function. As soon as a row from the table whose values cause the rule to evaluate to true, any function will return immediately with a true.
The every function is the opposite of any function. As soon as a row from the table whose values cause the rule to evaluate to non-true, every function will return immediately with a false.
The countWhere function iterates through each element in the Collection and for each element, applies the element from the context to the Expression and increments the total count value by 1 if the Expression evaluates to a boolean true, else no increment. The result from countWhere is an Integer object.
any, countWhere and every take a Collection-path which returns an array of objects or a com.clarify.webframework.CdoCol, iterates through each element from the array and assigning the element from the array to the context named $IterativeContextName. Then it evaluates the expression which may contain a DataPath with a context name of $IterativeContextName. Multiple any/every functions are allowed in a single expression.
any and every returns a Boolean object
countWhere returns a Integer object.
If the Collection-path returns a CdoCol, then to address the individual Cdo within the expression, the Path must be prefixed as follows:
If the Collection-Path expression returns null or unknown is set as a result of evaluating the expression, then unknown will be set to true and a Boolean false with be returned.
The following rules determine the return value for any function:
The following rules determine the return value for every function:
any($Focus:case2subcase, ‘$subcase’, $subcase:status2gbst_elm = ‘Open’)
count( exp )
Takes an expression returning a row set, and returns the count of rows.
Returns number of defined flexible attributes based on flags value.
Please see bellow for more details.
countWhere(<Collection-Path>, ‘IterativeContextName’, exp)
Iterates through each element in the Collection and for each element, applies the element from the context to the Expression and increments the total count value by 1 if the Expression evaluates to a boolean true, else no increment.
Returns the current date/time, using Session.getCurrentDate().
dateAdd( units, date, interval )
Add a number of units to a Calendar. Default is seconds
Interval: y (years), m (months), d (days), h (hours), n (minutes), s (seconds)
dateAdd(‘d’, currentDate(), 3)
dateDiff( units, startdate, enddate )
Subtract two dates, returning a signed number of units, default is seconds.
isNumber( exp )
Returns true if the expression is numeric according to Session.fromString(cboTypeDecimal)
Returns true if the expression is null
isUnknown( exp )
Returns true if the expression is unknown (see below)
toNumber( exp )
Convert the expression to a number – expression should be a string or a number.
toDate( exp )
Convert the expression to a Calendar.
Expression should be a string or a date. Uses Session.fromString(cbotypeDateTime)
toJavaDate( exp )
Convert the expression to a Date. Expression should be a string or a Calendar. Similar to toDate but returns value as a Date.
toDisplayString(exp1, exp2, exp3)
Converts the expression (exp1) to a localized string. Exp2 and exp3 are optional parameters.
If the object type for exp1 are: GregorianCalendar or Date Java class, then Session.toDateString is called.
Exp2 will be PictureString parameter. If Exp3 is specified, then it will be the MaskString parameter.
If the object type for exp1 is Money object, then Session.toCurrencyString is called.
If the object type for exp1 are BigDecimal, Float, Integer or Double, then Session.toNumberString is called.
Otherwise, the default toString() is returned
Convert arbitrary strings to Focus Object.
toFocusObject function can be used to convert arbitrary strings to Focus Object for passing to services.
Exp1: can be either a database Object Name or an expression. If it is expression then it should be given in such a way that the evaluated result value of this parameter should resolve to a DB Object Name.
Exp2: can be either a DB Objid or an expression. If it is an expression then it should be given in such a way that the evaluated result value of this parameter should resolve to an Objid of the row in the corresponding table.
toFocusObject function takes 2 parameters. These parameters can be either expressions or they may be just a table name and Objid. If the parameters are expressions then it will evaluate these expressions and constructs a new Focus Object based on the evaluated values of the input parameters.
Input expressions should be evaluated to the proper table name and corresponding Objid of the row. The return value of this function will be a FocusObject of type com.clarify.sam.FocusObjectImpl. It returns null if there is any exception.
A: toFocusObject ('user', $case:case_wip2wipbin:wipbin_owner2user:objid)
The above expression returns a focus object of type “user”
B: toFocusObject ('con’ + ’tact', $case:case_reporter2contact:objid)
The above expression returns a focus object of type “contact”
If we know the Objid of the focus object then we can also specify toFocusObject function like below:
C: toFocusObject ('contact', ‘268435501’)
The above expression returns a focus object of type “contact” which will have the table name as ‘contact’ and Objid as ‘268435501’
Site which has an objid from CDO / XVO
D: toFocusObject(‘site’, $Cdo:myCdoVariable:siteObjid)
CDO to XVO type conversion is already supported, so a real bona-fide site CDO could be passed
where an XVO parameter is needed.
toString( exp )
Convert an expression to a string. Uses Session.toString.
toInteger( exp )
Take the integer result of an expression, discarding the fractional part.
The intervals for date calculations are one of the following:
y (years), m (months), d(days), h (hours), n(minutes), s (seconds = default)
Constants are defined as numeric, or string.
- All numeric constants must be represented in locale independent format.
- All string literal must be represented in locale independent format.
- String must be delimited single quotes (‘’). The following escape sequences may be embedded inside a string: \n \r \t \’
- #<nmToken> is identified as string literal whose value will be looked up in table_string_db in current locale using <nmToken>. Exception are thrown if lookup is failed.
- true is used to represent Boolean true value
- false is used to represent Boolean false value
- null is the null value
Experssion returns Java null in the following conditions:
If <operand1> then < operand2> else < operand3>
- operand1 is not a Boolean class
- operand1 is a Boolean class and operand2 or operand3 is a null< operand1> AddOp < operand2>
< operand1> MultOp < operand2>
- operand1 is null and operator is Mul/Div/Mod.
- operand1 is null and operator is Add/Sub and operand2 is null
- operand1 is not null and operand2 is null and operator is Add/Sub/Div/Mod
- operand1 is not null and operand2 is null and operator is Mul
Unary < operand >
Operand is NULL
Named Expression evaluates to NULL
Constant is a Null Literal
A CboError from DataPath or DataPath returns a null as a value
There are some circumstances where a path cannot be evaluated. In these cases, the result of the expression is not known. For certain cases, it may be possible to default a value (for example Process Manager returns the first row when multiple rows are returned when a single row is expected).
- A single row is called for, but multiple rows are returned. For example, a path traverses a one-to-many relation with no qualifier, and is not used in a Count() function. The first value returned by the database read is returned – the value is known
- No database row is returned - A relation is not set (Data path returns null value)
- The field or item is not defined - A path tries to access a field (e.g. in a CDO or CBO), property or attribute that is not defined.
- Flexible attribute not defined - The path refers to a flexible attribute that does not exist
- DataPath returns null value - A data path that returns a null value is also considered an unknown value
When a path cannot be resolved, it will have the value unknown. Any expression involving an unknown value becomes unknown. Unknown is returned from the expression evaluator.
The followings list the exception type and conditions under which exceptions will be thrown by Expr.
Using Expressions – Examples
- The Collection-Path is a hashmap that points to an array of hashmap. ‘Tables’ is a key in the contextMap and the value of ‘Tables’ points to a HashMap called Tables.The TablesHashMap has a key called ‘Products’ whose the value is an array of hashmap.
The following illustrates an example on how to setup the contextMap properly:
The context “Tables” from above is setup similar to a database table as follows:
- The collection-path is a hashmapthat points to an array of Focus objects. ‘NewCases’ is a key in the ‘Row’ hashmap and the value of ‘NewCases’ is an array of Focus objects which points to a case object.The following illustrates an example on how to setup the contextMap properly:
- The collection-path is a rowset path that returns an array of Focus objects (which points to a site schema type).
$Focus is set to a case object.
- The collection-path, $CdoCases:openCases, returns a CdoCol which constains a collection of Cdo objects. $CdoCases is set to a CdoManager in the contextMap.
The following illustrates an example on how to setup the contextMap properly:
- The example illustrates how to use countWhere. Using the context “Tables” from example1, the following countWhere expressions returns:
countFlex Syntax: countFlex(Path [, eflags [, enumType])
Path is a DataPath that returns a valid focus object (with valid DbObjectName and objid). If an array of focus objects are return, countFlex returns the count for the first element from the array.
If Path is the only parameter specified, then it returns the number of defined flexible attributes.
eflags is an optional parameter, if specified, returns the number of defined flexible attributes whose flexible definition flags value matches (bitwise) with eflags. eflags can be any expression.
If eflags < 0, then eflags is ignored.
enumType is an optional parameter and have one of the following values:
If enumType is not one of the above values, then the set should be the defined flexible attributes set.
If enumType and eflags are defined and have valid values, then the flexible attributes set defined by enumType should be used to match against the eflags value.
If Path evaluates to a valid path and focus object returns a valid object, then a count value is returned, else a null is returned and Unknown is set to true.
The followings list the exception type and conditions under which exceptions will be thrown by Expr.
1) $Site points to a site Focus object.
countFlex returns the number of defined flexible attributes.
2) $Focus points to an order_action Focus object. countFlex returns the number of defined flexible attributes
with eflags bit 8 (External System) set.
3) The first element from the Focus array should be used to evalaute against the eflags value
(pre and post set). The flexible attribute set is restricted to attributes which have Data.
countFlex( $OpenCase:case_reporter2subcase, 3, cboConstants.cboFieldSetHasData )
In order to facilitate an easy to use end user interface, expressions are able to contain named-expressions, stored in the database.
A named-expression is denoted by a domain and a name.
Optional parameter(s) can be specified with named-expression. The domain is a logical grouping of named-expressions to enable different applications of the same name. Recursive Named Expression is not supported.
The syntax is:
Named expression is an expression that has been defined in the database. Use the CRM Administrator module to manage Named Expressions
- Domain – logical grouping
- Name – User-friendly name
- Expression – the actual expression itself
Named Expression Parameters
The Named Expressions parameters mechanism addresses the following:
- Use multiple parameters syntactically
- Support parameter type checking during Expr evaluation phase
- Support UI design time type validation for parameters
- Support UI design time retrieval of parameter list for a given Named Expression
Parameterized Named Expression Syntax
?domain.name( <ParamName> :=expression, ...)
<ParamName> is the parameter name.
Multiple parameterized Named Expressions are allowed inside a single expression, but all ParamName must be unique within the Named Expression. Parameter name/value pairs are mandatory.
For basic Java type (java.*), Expression do type checking and conversion to the type as defined in TABLE_EXPR.Type and throws an error if type checking or conversion fails.
For non basic Java types, Expression just do type checking.
The followings list the exception type and conditions under which the exception is thrown by Expr during the prepare phase:
Parameter Binding Variable Syntax
To facilitate binding the identifiers from the Named Expression to the actual expression text defined in table_expr.Expr, parameter binding variables are created.
The syntax for parameter binding variable is:
Database Schema Definition
Expression information is stored in table_expr as follows:
Parameter information is stored in table_expr_param as follows:
Optional Parameters in Named Expressions
This feature allows named expressions to contain optional parameters, which means if any parameter is not specified in the named expression, then default value of the parameter will be substituted in the missing parameter. If the default value cannot be converted to the expected data type then the result of the expression will be unknown.
While parsing the sub expression, if parser finds any parameter is missing then it tries to get the specified default parameter value from table EXPR_PARAM.default_value. If it finds any default value for the missing parameter then it substitutes the default value in the missing parameter. If the default value cannot be converted to the expected data type then the result of the expression will be unknown.
Suppose existing expression component handles named expression like:
Optional parameter feature allows the above expression to be specified in the following ways:
?morder.isHandset(Territory:=’EastCoast’, DeptId:=12 )
The above expression is same as the expression without optional parameter.
The above expression assumes the default value of parameter DeptId is specified in the database.
The above expression assumes the default value of parameter Territory is specified in the database.
The above expression assumes the default values of parameters Territory and DeptId is specified in the database.
Dynamic path modifiers, the Path modifier determined at runtime.
A value assigned to the $Var.
Assign ‘C123’ to $Var:SubCaseId
The $Var is used in the iteration
An expression that points to a path
Build the path:
- Set the process variable CasePath with the contents of Case title field.
- Case record is identified by the variable CaseObjid:
Assign ‘$Db:case(objid=’ + $Var:CaseObjid + ‘):title’ to $Var:CasePath
Use the path:
Caching iterative data path values inside array functions
Expr object contains an array of objects which hold cached data path values. Attempt to get data path value from cache, if not present, and then cache it. Incrementally cache data path array values as they are iterated over.
The cache is optimized — if data path values are not reused within the expression, then they are not cached. However it may not be possible to predetermine if data path values will be reused (e.g. reference path) so must cache it those cases.
Array functions like ‘any’ and ‘every’ are iterates over the row, access a value from each row and evaluates the value against some rule specified in the function. When it iterates over the row the condition (rule) may have an expression and expression may refer to the same data path more than once. In these cases currently, when each time it encounters the same data path in the condition it calls Datapath.readItem API to read the path value.
By caching the data path value once it read, then the next time when it sees the same data path in the condition (rule) then it will get the path value from the cache instead of calling Datapath.readItem API, so the performance of expression evaluation can be improved while handling array functions.
While evaluating array function, when it first time encounters a data path in the condition it gets the path value by calling Datapath.readItem API and stores data path value in cache. It uses the key as a combination of Collection-Path plus column name of IterativeContextName plus iteration row number.
For example, in the following example ‘every’ function iterates through each row and executes the rule. In this example data path $eachcase:title is refereed twice, so while executing each row first time it gets the path value by calling readItem API and stores it in the cache, then from the second time onwards for the same data path it gets the path value from cache.
every($Row:case, '$eachcase', ($eachcase:title = 'Test LAB') or ($eachcase:title+'-'+'LAB Test' = 'First case from thin client-LAB Test'))
Cache will be cleared once the expression is evaluated and its lifetime is only for the current expression.
Next Part: Using Paths and Expressions in Smart Client
No comments yet.