The 'dollar notation'

using variables with the dollar notation

This 'notation' is used in the attribute values of the expressions to achieve a greater flexibility. Consider the following example :


<?xml version="1.0" encoding="UTF-8"?> 
<process-definition 
    name="var_dollar" 
    revision="0.1"
>
    <description>
Showing how variable values might be used with the dollar notation.
    </description>

    <!-- main -->

    <sequence>

        <!-- preparing the initial workitem values -->

        <iterator
            on-value="alice, bob, charles"
            to-variable="user-name"
        >
            <set 
                field="${user-name} comment" 
                value="(please fill this field)"
            />
        </iterator>

        <!-- the flow itself -->

        <participant ref="role-alpha" />
        <participant ref="role-bravo" />
        <participant ref="role-charly" />
    </sequence>

</process-definition>

The initial workitem (as transmitted to 'role-alpha' will contain three fields respectively named 'alice comment', 'bob comment' and 'charles comment' with each the value '(please fill this field)' in them.

Every workflow definition tag attribute is subject to this dollar notation alteration, making it a very powerful technique.

${v:myvarname} is equivalent to ${var:myvarname} which is equivalent to ${myvarname}.

Slash prefixes for the variable name

OpenWFE 1.6.0 introduces the concept of Environment expressions. Before environments, variables were bound in expressions directly. Now each process and subprocess has its own environment as well as the engine.

There are four ways to use the slash prefix for variables :


var     (local binding)
/var    (root process binding)
//var   (engine binding)
./var   (forcing to bind locally)

There are two general cases : looking for a variable and binding it. When looking for a variable, the slash prefixing tells at which point the search should begin, so that you can skip values bound too locally.

var (local binding) :

With no slash prefix, binding will occur in the nearest environment, ie the environment of the process or subprocess holding the 'set' expression.


<process-definition name="nemo">
    <sequence>
        <set variable="a" value="nada" />
    </sequence>
</process-definition>

will bind the variable 'a' in the environment tied to the 'nemo' process-definition. Looking for a variable without any slash prefix will look up all the tree, starting from the current scope (environment).

/var (root process binding) :


<process-definition name="main" revision="x">

    <subprocess ref="sub0" />

    <process-definition name="sub0">
        <sequence>
            <set variable="/a" value="nada" />
        </sequence>
    </process-definition>

</process-definition>

Here the variable 'a' will be bound in the environment tied to the 'main' process definition. It will be visible to all the expressions in the 'main' definition and in its sub-definitions (subprocesses). Looking for '/a' implies looking at the root process ('main'), if it's not found there, the root environment (engine level) will be consulted.

//var (engine binding)

Sets a var at the engine level. With other slash prefixes, binding was done inside the process instance, thus, the bindings vanished when the expressions and finally the whole flow instance vanished (the end of the flow). An engine binding subsist as long as the engine is up and running. If you chose a persistent storage for the expression pool (fs persistence is the out-of-the-box default), engine variables even survive engine stop and restart. As such, engine-level bound variables may be used for different processes or different instances of the same process to communicate.

./var (forcing local binding)

The <set> and <inc> expressions, upon having to modify the binding for an already set variable, will do it in the environment (scope) where it is currently bound. Using the './' prefix forces the bound to occur at the local level, potentially shadowing a variable with the same name in a previous (upwind) environement.

Some remarks :

You can use the 'unset' expression to unbind a variable. Beware of not stuffing the engine and the expressions with unnecessary values : a good balance has to be kept between the values stored in variables (process or engine) and in the payload of workitems. Variables values are not seen outside of the engine, but stuffing everything in workitems may make then 'heavy' to transmit over the wire (in highly distributed settings) (but you could use filters...) You case use the expressions 'save' and 'restore' to transmit copies of whole workitems through variables.

Last example :


<process-definition name="x" revision="y" >

    <sequence>
	<set variable="v" value="alpha" />
	<set variable="/v" value="bravo" />
	<set variable="//v" value="charly" />

	<set field="target" variable-value="/v" />
	    <!-- target is now set to 'bravo' -->

	<subprocess ref="z" />
    </sequence>

    <process-definition name="z" >
	<sequence>
	    <set field="target" value="${v}" />
		<!-- target is now set to 'bravo' -->
	    <set field="target" value="${/v}" />
		<!-- target is now set to 'bravo' -->
	    <set field="target" value="${//v}" />
		<!-- target is now set to 'charly' -->
	</sequence>
    </process-definition>

</process-definition>

using fields with the dollar notation

You can also access fields (attributes) of the workitem with the dollar notations.

Here are a few examples :


    <sequence>

        <set variable="customer" value="${field:customer}" />
        <set variable="dpt" value="${f:department}" />

        <set variable="customer_name" value="${f:customer.name}" />

        <set variable="chosen_customers" value="${f:customers.3:${i}}" />

    </sequence>

The two last 'set' lines show that fetching sub-fields is possible. The last line is an example of fetching a range in the ListAttribute field 'customers'. There are more example of this notation at the section called “nesting the values inside of the 'set'”

This 'sub-field' concept may also be used with field containing XML fragments :


    <sequence>

        <set field="fxml">
            <a>
            <raw-xml>
                <customers>
                    <customer id="0" lang="es">
                        <name>Karpenter</name>
                    </customer>
                    <customer id="3" lang="fr">
                        <name>Karnoiov</name>
                    </customer>
                </customers>
            </raw-xml>
            </a>
        </set>

        <print>${f:fxml.customer.name.}</print>
        <print>${f:fxml.customer.@id}</print>
        <print>${f:fxml.customer.@lang}</print>
        <print>${f:fxml.e1.name.}</print>

    </sequence>

This example uses the 'print' expression, which outputs its content the system stdout, it's not very useful for a real process case, but it should be straightforward to understand. The @ symbol was used to fetch the value of an XML element's attribute. These four print statements will output


Karpenter
0
es
Karnoiov

combining fields and variables in the dollar notation

A value can be fetched from a field and then from the variable of the same name if it's not available as a field.


    <sequence>

        <set variable="c1" value="${fv:customer}" />
        <set variable="c2" value="${vf:customer}" />

    </sequence>

The variable 'c1' will receive the same value as the field 'customer'. If this field is not set, 'c1' will receive the value of the variable 'customer'. The second 'set' is equivalent, but it looks first in the variable 'customer', and then in the field 'customer'.

using constants with the dollar notation

Suppose you would like to insert in a workitem the version of the OpenWFE engine you are using. You could do it this way :


    <set field="openwfe_version" value="${const:openwfe.org.engine.Definitions.OPENWFE_VERSION}" />

Of course, if your code is in the engine's classpath (or that your using an embedded engine), you could use your own java constants.

using engine parameters or system properties with the dollar notation

There's a 'p:' prefix for fetching engine parameters from the application context or Java system properties (in that order of priority).


    <set field="hostname" value="${p:hostname}" />

Where the parameter 'hostname' could be set in etc/engine/engine-configuration.xml :


    <param>
        <param-name>hostname</param-name>
        <param-value>swiss.ai.mit.edu</param-value>
    </param>

Or (lowest priority) from a -D JVM system property :


#!/bin/sh
java -Dhostname=`hostname` openwfe.org.Application etc/engine/engine-configuration.xml

(of course this java command line is an over-simplification and there are other ways to set a JVM system properties).

This 'p:' prefix stands for 'parameter' or 'property'. Unlike other dollar notation prefixes there's no 'long version' of it (like 'v:' has 'variable:').

using functions with the dollar notation

The next section covers function invocations. Functions are shortcuts for easily manipulating strings directly from the process definition language. There is a 'dollar notation' syntax for calling functions.


    <set field="customer_name" value="${call:uppercase(${f:customer_name})}" />

    <set field="customer_name" value="${c:uppercase(${f:customer_name})}" />

This 'set' will put the value of the field 'customer_name' in upper case. The second line has exactly the same effect, but the 'call' has been reduced to 'c'.