Sapphire Developer Guide

Sapphire Expression Language

The expression language provides a convenient way to embed a bit of custom logic in various parts of Sapphire without resorting to Java. Expressions can be used in some of the modeling annotations as well as in UI definitions.

The syntax and semantics borrow extensively from JSP expression language and its precursors, however there are a number of deviations. This document is the definitive reference.

Expressions

There are three types of expressions: literal expressions, eval expressions and composite expressions. A literal expression is simply a string such as Abc. No quotation is necessary. An eval expression is anything enclosed between ${ and }. The syntax and semantics of eval expressions is discussed in detail in the following sections. A composite expression is one that combines zero or more literal expressions with one or more eval expressions.

The following are all examples of valid expressions:

Literals

There are literals for boolean, integer, floating point, string, and null in the expression language.

Child Property Operator : A.B and A["B"]

The expression language follows ECMAScript in unifying the treatment of the . and [] operators. So expr-a.identifier-b is equivalent to expr-a["identifier-b"].

Arithmetic Operators

Arithmetic operators are provided to act on integer (BigInteger and Long) and floating point (BigDecimal and Double) values.

The evaluation of arithmetic operators is described in the following sections. A and B are the evaluation of subexpressions.

Addition : A + B

Subtraction : A - B

Multiplication : A * B

Division : A { /, div } B

Remainder (Modulo) : A { %, mod } B

Unary Minus : -A

Relational Operators

Relational operators are provided to compare two values.

The evaluation of relational operators is described in the following sections. A and B are the evaluation of subexpressions.

Equal : A { ==, eq } B

Not Equal : A { !=, ne } B

Less Than : A { <, lt } B

Less Than or Equal : A { <=, le } B

Greater Than : A { >, gt } B

Greater Than or Equal : A { >=, ge } B

In : A in B

Logical Operators

Logical operators are provided to perform boolean logic.

The evaluation of logical operators is described in the following sections. A and B are the evaluation of subexpressions.

And : A { &&, and } B

Or : A { ||, or } B

Not : A { !, not } B

Empty Operator : empty A

The empty operator is a prefix operator that can be used to determine if a value is null or empty.

Conditional Operator : A ? B : C

Return B or C, depending on the result of the evaluation of A.

Parentheses

Parentheses can be used to change precedence, as in: ${(a*(b+c))}.

Operator Precedence

Highest to lowest, left to right.

Qualified functions with a namespace prefix have precedence over the operators. Thus the expression ${c?b:f()} is illegal because b:f() is being parsed as a qualified function instead of part of a conditional expression. As usual, () can be used to make the precedence explicit, e.g ${c?b:(f())}.

Functions

The expression language supports functions, whose names can be qualified with a namespace.

The full syntax of qualified n-ary function is as follows:

[ns:]f([a1[,a2[,...[,an]]]])

Where ns is the namespace prefix, f is the name of the function, and a is an argument.

The following functions are available for use:

Name Description
Avg Computes the average of numbers in a collection. Typically, this function takes the collection as the sole parameter. However, when the collection is a model element list, a second parameter may be necessary to specify the name (in the form of a string) of the list entry's value property to use in aggregation. If the the collection is a model element list and the second parameter is not specified, this function will use list entry's first value property for aggregation. An average of an empty collection is 0.
Concat Concatenates two or more strings into a single string. Particularly useful in contexts where composite expressions cannot be used, such as where the result of concatenation needs to feed into another function or operator.
Enabled Determines if a property is enabled. Can be used either with two arguments (element and property name) or with a single property name argument. In the single argument form, the context element is used.
FirstSegment Breaks a string into segments using the provided separators and returns the first segment. If no separators are found in the string, the entire string is returned. This function takes two string operands. The first is the string to tokenize. The second is a sequence of characters that individually should be treated as valid separators.
Image Returns the image associated with the context model element.
InstanceOf Determines if an object is of specified type. The object to be checked is the first operand and the type is the second operand. The type must be a fully-qualified Java class name.
LastSegment Breaks a string into segments using the provided separators and returns the last segment. If no separators are found in the string, the entire string is returned. This function takes two string operands. The first is the string to tokenize. The second is a sequence of characters that individually should be treated as valid separators.
List Constructs a list from arbitrary number of operands.
LowerCase Converts a string to lower case. Can be used either as LowerCase( Name ) or as Name.LowerCase().
Max Finds the largest number in a collection. Typically, this function takes the collection as the sole parameter. However, when the collection is a model element list, a second parameter may be necessary to specify the name (in the form of a string) of the list entry's value property to use in aggregation. If the the collection is a model element list and the second parameter is not specified, this function will use list entry's first value property for aggregation.
Min Finds the smallest number in a collection. Typically, this function takes the collection as the sole parameter. However, when the collection is a model element list, a second parameter may be necessary to specify the name (in the form of a string) of the list entry's value property to use in aggregation. If the the collection is a model element list and the second parameter is not specified, this function will use list entry's first value property for aggregation.
Parent Returns the parent of the current model element.
Root Returns the root of the model.
SapphireVersionMatches Determines whether Sapphire version matches a version constraint. A version constraint is a comma-separated list of specific versions, closed ranges (expressed using "[1.2.3-4.5)" syntax and open ranges (expressed using "[1.2.3" or "4.5)" syntax). The square brackets indicate that the range includes the specified version. The parenthesis indicate that the range goes up to, but does not actually include the specified version.
Scale Changes the scale of a decimal.
Sum Computes the sum of numbers in a collection. Typically, this function takes the collection as the sole parameter. However, when the collection is a model element list, a second parameter may be necessary to specify the name (in the form of a string) of the list entry's value property to use in aggregation. If the the collection is a model element list and the second parameter is not specified, this function will use list entry's first value property for aggregation. A sum of an empty collection is 0.
UpperCase Converts a string to upper case. Can be used either as UpperCase( Name ) or as Name.UpperCase().
VersionMatches Determines whether a version matches a version constraint. A version constraint is a comma-separated list of specific versions, closed ranges (expressed using "[1.2.3-4.5)" syntax and open ranges (expressed using "[1.2.3" or "4.5)" syntax). The square brackets indicate that the range includes the specified version. The parenthesis indicate that the range goes up to, but does not actually include the specified version.

Custom functions can be contributed via Sapphire Extension System.

Enums

The expression language supports Java enumerations. Coercion rules for dealing with enumerated types are included in the following section. Also, when referring to values that are instances of an enumerated type from within an expression, use the literal string value to cause coercion to happen via the below rules. For example, Let’s say we have an enum called Suit that has members Heart, Diamond, Club, and Spade. Furthermore, let’s say we have a reference in the expression, mySuit, that is a Spade. If you want to test for equality with the Spade enum, you would say ${mySuit == 'Spade'}. The type of the mySuit will trigger the invocation of Enum.valueOf( Suit.class, "Spade" ).

Type Conversion

Every expression is evaluated in the context of an expected type. The result of the expression evaluation may not match the expected type exactly, so the rules described in the following sections are applied.

Coerce A to String

Coerce A to Number type N

Coerce A to Character

Coerce A to Boolean

Coerce A to an Enum Type T

Coerce A to List

Coerce A to Any Other Type T

String Concatenation

The subject of string concatenation in an expression can be a source of confusion. In particular, expressions like ${ "A" + "B" } cause an error during evaluation. That's because the + operator is exclusively arithmetic addition. It is not overloaded to also mean string concatenation, like it is in some other languages such as Java.

String concatenation in an expression can be accomplished in one of two ways:

Using the concat function is particularly necessary in cases where the result of concatenation should feed into another function or operator.