Expression Language

Top  Previous  Next

An expression is like a "sentence", or a line of text, which you let AggreGate process and come up with some result. For example, if someone were to tell you "All apples are blue", you would think about it for a very brief moment and would then conclude that it's wrong (or FALSE, in computing jargon). You just processed an expression, on your very own.

In AggreGate, an expression is a combination of values, also known as literals, ("True", "False", "5", "John"), operators (like +, -, * etc, a full list is below) and references (such as users.admin.deviceservers.ds1:buzz()). You mix all these together in a particular way, and end up with a line of text (an expression) that AggreGate can understand, and thus evaluate.

When AggreGate evaluates an expression, it processes it. It systematically goes through the expression, executing the operations it calls for (getting variable values, running functions included in it and getting their results, etc) until it finishes evaluating and winds up with some result. This is the value of the expression -- its result.

In AggreGate, expressions are used widely throughout the system. They're always written the same way, like in a language. This language (or "way of composing references") is called AggreGate Expression Language.

Here are some examples of expressions usage:

Expressions that evaluate to a Boolean result are used in Event Filters to decide if an event should pass through a filter.
Expressions that evaluate to a Boolean determine when an Alert should be triggered (upon a certain event or condition).
Widgets are based on expressions that define relations between widget components and data coming from various contexts within the server.

Every argument of an expression is also an expression in itself, and thus, expressions may be nested.

Once an expression is evaluated, it gives a certain value (result). This value can be an integer, a string, a Boolean variable or any other date type defined in AggreGate Server. The value type is dependant on whatever is being evaluated: An expression such as 1 + 1 will return an integer (2), while an expression such as "the" + " dog" will return a string ("the dog"). If the expression contains a reference (such as {username} + 1), you can't really know for sure what the value type will be, because it depends on the data type of whatever is being referenced.

Side Effects

Evaluation of an expression may have side effects. For example, if an expression contains a reference to the Buzz function of a Device Server context, its evaluation will cause a hardware Device Server to blink its LEDs. This is what is called side effect.

Type Conversion

The expression language processing engine does its best to perform all necessary type conversion and evaluate an expression to get some result. For example, if a numeric argument is passed to a function that accepts strings, the number is auto-converted to its string representation. Another example: if floating point number is added to an integer number the resulting value is also floating point number. This helps avoid rounding errors.

If proper type conversion is not possible, the evaluation of an expression fails with error.

The explicit type conversion is performed by using type conversion functions.

Types

The expression language internally deals with the following types (and returns values of these types):

Type

Description

Null

Null value means "no value". This value may be written to the Data Table cell only if field is Nullable.

Object

This is a super-type of all types. If some function is declared to return an Object, it may return value of any type, depending to the input parameters.

Integer

32-bit signed integer number.

Long

64-bit signed integer number.

Float

A floating point number.

String

String of any length. Strings may also contain binary data.

Boolean

TRUE or FALSE

Color

An 8-bit RGB color value.

Date

A timestamp that includes both date and time parts. May be consumed by date/time processing functions.

Data Table

A Data Table.

All types have their analogs among Data Table field types.

Elements Of Expression

Every expression may consist of the following elements:

Literals
Operators
Functions
References

Literals

A literal is a constant. It is "taken literally" by AggreGate - the system just takes it as it is, and uses it as a basis for calculations etc. It is a constant value.

AggreGate Expression Language defines several types of literals:

Null Literal: null
Boolean Literals: true of false
Decimal Literals (0, 1, 123, -1234567890, ...)
Hexadecimal Literals (0x0A, 0xFFFF, ...)
Binary Literals (0b01, 0b00110011)
Octal Literals (00, 055, 01234567, ...)
Floating Point Literals (3.1, -44.5, 1.3E12, ...)
String Literals ("This is a String", 'test', ...)

String Escaping

Backslashes ("\") that appear within strings must be escaped using another backslash (i.e. \ becomes \\).1

Quotes must be also escaped using backslash character (\" , \') if the same type of quotes was used to quote the string.

Examples:

"There are double quotes \"inside\" this string"
'There are single quotes \'inside\' this string'

Operators and Operator Precedence

An operator is a symbol which applies to certain data (such as numbers or strings) and tells the system what it should do with it. Once the system executes the operator on the data (i.e, once the operator "operates"), you always get some result, or value. Common operators include + (addition, as in 1+1), - (subtraction, such as 2-1), etc.

A single expression may contain many operators, such as 1 + 2 * 3. The operators are evaluated in a certain sequence -- not as they're written in the line (from left to write). For example, 1 + 2 * 3 evaluates to 7 and not to 9, because the multiplication operator has a higher precedence than addition operator. The following table also shows operator precedence - the topmost operators are the first to be evaluated when the system evaluates an expression.

Description

Syntax

Example

Argument Types

Result Type

Parenthesis

()

(1 + 2) * 3

Any

Any

Bitwise NOT operator

~

~{a}

Numeric

Numeric

Logical NOT operator

!

!{x} > 0

Boolean

Boolean

Multiplicative operators

*   /   %

{d} * 3

Numeric

Numeric

Additive operators

+   -

{b} + {c}

Numeric (or Strings for "+")

Numeric (or String for "+")

Relational operators

>   <   >=   <=  

{a} >= 123

Numeric

Boolean

Equality operators and regular expression match operator

==   !=   ~=

{name} == "test"

Any (Strings only for "!=")

Boolean

Bitwise AND operator

&

{z} & 0xFFFF

Numeric

Numeric

Bitwise XOR operator

^

{y} ^ 0x1A

Numeric

Numeric

Bitwise OR operator

|

{x} | 0xFF

Numeric

Numeric

Logical AND operator

&&

{z} = 1 && {x} > 0

Boolean

Boolean

Logical OR operator

||

{x} > 5 || {y} < 1

Boolean

Boolean

Conditional operator

? :

{y} > 5 ? 1 : 0

Boolean for first argument, any type for other arguments

Any

Parenthesis

Expressions may also include parenthesis that change operators precedence.

note_example-wt

Example:

1 + 2 * 3     evaluates to 7

but

 

(1 + 2) * 3        evaluates to 9

Conditional Operator

The conditional operator, ?:, can be used to conditionally evaluate expressions. It has three agruments: The first argument should evaluate to a Boolean value. If it evaluates to TRUE, the operator result is the second argument. If the first argument is FALSE, the operator result is the third argument.

condition ? value_if_true : value_if_false

note_example-wt

Example:

2 * 2 == 4 ? "Yes" : "No"

Resolves to a String, "Yes".

Regular Expression Match Operator

Both arguments are strings. Evaluates to true is first string matches to the regular expression defined by the second argument.

Example:

"abXXXX" ~= "^abc.*"

resolves to Boolean false.

Additive Operator

If at least one of arguments is String, second argument is converted to its string representation. In this case evaluation result is result of concatenation of these strings.

note_example-wt

Example:

"test" + 123

resolves to String "test123".

References

References must be enclosed into curly brackets when inserted into expressions. They're resolved when the expression is evaluated. It looks like this: {temperature} <= 100. In this case, temperature is a reference.

See the references chapter for a detailed description of references and their syntax.

Evaluation Environment

When an expression is evaluated in AggreGate, there are a number of parameters that may affect the result. The whole set of these parameters is called "evaluation environment". Most of these parameters affect the resolution of references that may appear inside the expression.

Evaluation environment includes:

Default Context

The default context that is used to resolve relative context paths that may appear in standard references.

Default Data Table

The default data table that is used to resolve standard references that do not explicitly point to variable/function of a certain context.

Default Row

The default row that is used to determine what data table row should be accessed when resolving standard references that do not explicitly specify a row.

Environment Variables

Any environment variables that may be retrieved by using environment references inside the expression.

Examples

Expressions that are used in Event Filter and Alert definitions must produce a Boolean result. This allows AggreGate Server to decide if an event may pass through a filter or if an alert should be raised upon a certain event.

Expression

Evaluation Result

Result Type

5 + 5 > 7

true

Boolean

3 + 2

5

Integer

"Red" + " " + "Line"

"Red Line"

String

{speed}>5

true is reference speed resolves to Integer that is greater the 5.

Boolean

{name} == "admin"

true if reference name resolves to String “admin”.

Boolean

{failed[3]} == false

true if reference failed[3] resolves to Boolean value "false".

Boolean

{env/context} ~= "^abc.*"

true if reference env/context resolves to String that matches regular expression "^abc.*", i.e. starts with "abc".

Boolean

{int[1]} == {int[2]}

true if both references resolve to values that may be compared to each other (i.e. two numbers, or two strings) and these values are equal.

Boolean

({field} + 5) * ({field2} - 1) / 2 == {field[1]} + 1

true or false, depending to the values of resolved references, that must resolve to numbers.

Boolean

substring("smiles", 1, 5)

"mile"

String

max(100, {pressure})

Value of pressure reference if it is greater than 100 or 100 otherwise.

Number

Calculating Distance Between Points

Let's assume we own a small car rental company and don't want our cars to drive far from a base station. For monitoring purposes, every car is equipped with smart controller that reads car location from GPS receiver and sends it to AggreGate server via cellular network using GPRS. In our system, we have the coordinates of two points: car and base station. We can calculate the distance between them using an expression, or create an expression that triggers an alert when distance is greater than certain limit.

If our coordinates are expressed in radians, we can use the following formula to trigger an alert if distance between car and base station is more than 500 kilometers:

 

acos(sin({car_latitude}) * sin({base_latitude}) + cos({car_latitude}) * cos({base_latitude}) * cos({car_longitude} - {base_longitude})) * 6371  > 500

 

6371 is Earth's radius in kilometers

500 is maximum allowed distance between car and base station in kilometers

 

If coordinates are expressed in degrees (that is more likely in the case of GPS receiver data), we just convert degrees to radians, e.g. by writing

 {car_latitude} / 180 * 2 * 3.1415926

instead of

 {car_latitude}