This section presents examples of some of the more common usages of expressions within Identity Manager, in particular:
Controlling field visibility
Calculating default field values
Deriving field values
Generating field values
Workflow transition conditions
Invoking Java methods from workflow actions
A common form design problem requires suppressing the display of certain fields until a particular condition is met. For example, certain resource-specific fields are relevant only when a particular resource is assigned to the user. These fields should be visible only when the resource is assigned. Otherwise, these fields should be hidden from view and not evaluated. The following example illustrates a field definition that uses an expression within the <Disable> element to control the visibility of such a field.
<Field name=’HomeDirectory’> <Display class=’Text’/> <Property name=’title’ value=’HomeDirectory’/> </Display> <Disable> <not> <contains> <ref>accountInfo.typeNames</ref> <s>Solaris</s> </contains> </not> </Disable> </Field>
The <Disable> element is part of the Form XML language. The contents of the <Disable> element can be any expression in the XPRESS language. In this case, the expression is testing to see if the string Solaris appears in a list stored in the external variable named accountInfo.typeNames. With forms, this variable contains a list of all resource types currently assigned to the user.
When the form is processed for display, the expression in the <Disable> element is evaluated. If it returns true, this field is not displayed.
The values null and 0 are logically false. Non-null or non-zero fields are logically true. This means that the sting represented with the expression <s>false</s> is logically true because it is non-null.
Field values can be calculated by XPRESS using one of three elements specified in the field declaration: Derivation, Default, and Expansion.
Field values can be calculated from other fields or simply set to an initial value using the <Default> element. The <Default> element is typically used to initialize an editable field and is evaluated only if the field does not already have a value assigned to it. The <Default> element is often used to calculate an account ID based on the first and last name of the user. The following example shows a field definition that uses string manipulation expressions to calculate a default account ID consisting of the first letter of the user’s first name concatenated with the user’s last name.
<Field name=’waveset.accountId’> <Display class=’Text’/> <Property name=’title’ value=’AccountID’/> </Display> <Default> <concat> <substr> <ref>accounts[AD].firstname</ref> <i>0</i> <i>1</i> </substr> <ref>accounts[AD].lastname</ref> </concat> </Default> </Field>
The <Default> element is part of the Form XML language. This element can contain either an XPRESS expression or elements in another language called XML Object. (For more information on XML Object language, see the chapter titled Chapter 6, XML Object Language)
When this field is processed, the system checks to see if a value already exists for the waveset.accountId attribute. If no value exists, it evaluates the expression in the <Default> element. In this case, a value is calculated by concatenating the first letter of the first name with the last name.
You may need to make sure that firstname and lastname fields have values, as demonstrated by the following example:
<cond> <and> <notnull><ref>accounts[AD].firstname</ref></notnull> <notnull><ref>accounts[AD].lastname</ref></notnull> </and> <concat> <substr> <ref>accounts[AD].firstname</ref> <i>0</i> <i>1</i> </substr> <ref>accounts[AD].lastname</ref> </concat> </cond>
The preceding code is structured as an if-then statement in other programming languages. This cond expression has two arguments:
First, the conditional expression is evaluated. If the result of this expression is logically true, the value of cond will be the value of the then expression. If the result of the conditional expression is false, the value of cond will be null.
In this example, the cond statement ensures that values exist for two account attributes before using them to calculate accountID. The Default expression will continue to be evaluated each time the form is refreshed or saved until the prerequisites are finally set or until the user provides a value in the field. The Default expression will not be evaluated if the associated field contains a non-null value.
A <Derivation> expression is similar to a <Default> expression except that it always calculates a value for the field, even if the field already has a non-null value. This is typically used to display a field whose value is a permutation of another field’s value. This is a valuable design feature if the resource attribute value is encoded and would not be obvious to the user.
The following example shows a field definition that uses conditional logic to map one set of values into another set.
<Field name=’location’ prompt=’Location’> <Display class=’Text’/> <Derivation> <switch> <ref>accounts[Oracle].locCode</ref> <case> <s>AUS</s> <s>Austin</s> </case> <case> <s>HOU</s> <s>Houston</s> </case> <case> <s>DAL</s> <s>Dallas</s> </case> <case default=’true’> <s>unknown</s> </case> </switch> </Derivation> </Field>
The <Derivation> element is part of the Form XML language that can contain an expression. When this field is processed, the expression in the <Derivation> element is evaluated to determine the value to be displayed for this field.
In the preceding example, the value of the resource account attribute accounts[Oracle].locCode is compared to the first value in each case expression. If a match is found, the result of the switch expression is the second value in the matching case expression.If no matches are found, the result of the switch is the value within the default case.
In certain forms, you might want to first display a set of abstract derived fields to the user, then generate a different set of concrete resource account attribute values when the form is submitted. This is known as form expansion. An <Expansion> element is typically used in hidden fields that depend on editable fields in the form. One purpose of the <Expansion> element is to convert data that is familiar and readable to an end-user into data that is recognized by a resource. For example, a user can see a manager’s full name in the form, but the system receives a unique ID that it recognizes as belonging to a manager.
The following example shows a field definition that uses conditional logic to convert the value derived for the location field in the previous example back into a three-letter abbreviation.
<Field name=’accounts[Oracle].locCode’> <Expansion> <switch> <ref>location</ref> <case> <s>Austin</s> <s>AUS</s> </case> <case> <s>Houston</s> <s>HOU</s> </case> <case> <s>Dallas</s> <s>DAL</s> </case> </switch> </Expansion> </Field>
The <Expansion> element is part of the Form XML language and can contain an expression. When this field is processed, the expression in the <Expansion> element is evaluated to determine the value of the field.
In this example, this element performs the reverse of the mapping performed by the location field. This field is also hidden by the absence of an assigned Display class. This lack of Display class prevents the field from being displayed in the form, but the field is still considered to be an active part of the form and will generate values for resource attributes through its <Expansion> expression.
For all forms except the User view, Expansion rules are run whenever the page is recalculated or the form is saved. For the User view, an <Expansion> tag runs when the userform is first loaded as well.
When defining a workflow process, you must specify the rules by which control passes from one workflow activity to another. A path between two activities is called a transition. A rule that governs the use of the transition is called a transition condition.
For example, consider the following activity definition:
<Activity name=’Check Results’> <Transition to=’Log Errors’> <gt> <ref>ERROR_COUNT</ref> <i>0</i> </gt> </Transition> <Transition to=’end’/> </Activity>
This activity defines two distinct transitions to separate activities: an activity named Log Errors and another named end. When workflow processes this activity, it will take the first transition for which the transition condition returns true.
In this example, the first transition has a condition that tests the value of the variable ERROR_COUNT to see if it is greater than zero. That transition is taken only if there is a positive error count. The second transition has no condition, and consequently will always be taken if the first transition condition is false.
A workflow activity can perform one or more actions. One possible action is the evaluation of an XPRESS expression, as shown in the example below.
<Activity name=’Increment Counter’> <Action> <expression> <set name=’counter’> <add> <ref>counter</ref> <i>1</i> </add> </set> </expression> </Action> <Transition to=’Next’/> </Activity>
When a workflow action is implemented in XPRESS, an XPRESS expression is wrapped in an expression element that is then placed within an Action element. In this example, the expression references the current value of a variable named counter, adds one to that value, then assigns the incremented value to the variable with the same name.
Complex workflow actions can be implemented in Java. Typical examples of complex workflow actions include storing data in a relational database or sending a message to a help desk system. These Java classes can be integrated with workflow using XPRESS.
<Activity name=’Log Status’> <Action> <expression> <invoke name=’logStatus’ class=’custom.OracleStatusLog’> <ref>accountId</ref> <ref>email</ref> <ref>status</ref> </invoke> </expression> </Action> <Transition to=’Next’/> </Activity>
In this example, the XPRESS invoke function is used to call a static method named logStatus, which is defined in the custom Java class custom.OracleStatusLog. Three arguments are passed to this method, the values of which are taken from workflow variables.
In these types of cases, the primary computation is performed in the Java class, while XPRESS acts to integrate the class into the workflow.
Testing expressions involves two steps:
Check the syntax with the lh command.
Enable tracing to ensure the expression is working as intended.
Confirm that you have %WSHOME%\bin in your PATH environment variable. (For information on changing environment variables to work with Identity Manager, see the section of Installation Guide that describes using command-line tools.)
If %WSHOME%\bin is not in your path, then you must change to %WSHOME%\bin before you can run the tools.
From the command line, enter lh xmlparse <xpress_file> where xpress_file represents the name of the file that contains the XML you want to test. This command parses the file for XML correctness and displays error messages in the console.
Consider putting %WSHOME%\bin in your PATH environment variable. This will permit you to use whichever directory you are currently in as your working directory. This will also allow you to run the Identity Manager lh command from any current working directory.
Once you have written and successfully stored an expression in the repository, you can turn on XPRESS tracing to determine if the expression is functioning correctly. XPRESS trace messages are sent to the standard output device. Since XPRESS is typically evaluated within the application server, the trace messages are sent to the console window or log file that was active when the application server was started.
There are two forms of XPRESS tracing:
Global trace. When global trace is enabled, all XPRESS expressions are traced.
Block-level trace. When block level tracing is used, only expressions within designated blocks are traced. Block tracing can be set only within a field element in a form or within an expression in a workflow.
Typically, block-level tracing is preferable because it reduces the amount of trace output, which is then easier to analyze.
To enable global trace, set a Waveset.properties file entry named xpress.trace to the value true. If you change the Waveset.properties file while the application server is running, you must either restart the application server, or go to the Debug Page and click Reload Properties.
To perform block-level trace, wrap the expressions you want to trace in a <block> expression and include the attribute trace=’true’ in the block start tag.
<block trace=’true’> <invoke name=’getTime’ class=’java.util.Date’/> </block> or <Default> <block trace = ’true’> <ref>global.accountId</ref> </block> </Default>
Do not use the <block> element in the following ways.
<block trace=’true’> <Field name =’field1’> … </Field> </block> or <Field name=’Field2’> <block trace=’true’> <Default> <ref>global.accounts</ref> </Default> </block> </Field>
The trace messages include the names of the functions, the values of each argument, and the return values.
To turn tracing off for XPRESS, set the xpress.trace value to false, and reload the Waveset.properties file.