Expression

Constant values, entity members, operators, query executions and function calls can be combined into sequences known as expressions. Among other things, expressions are used to navigate and query a domain model.

An expression is evaluated to a value, which can be primitive value (e.g. 42 or "apple"), entity instance or a collection of instances.

Data expressions returns values of primitive types, such as strings or integers. A data expression can be

  • a literal (e.g. "Hello world", 3.14),

  • a field selector (self.firstName, self.orders.orderItems)

  • an expression containing other data expressions and operators, such as self.amount * self.productPrice

Reference expressions returns an entity instance or collection of entity instances.

Examples:

// it is a single line expression
derived String fullName => self.firstName + " " + self.lastName;

// it is a multi-line expression
derived String fullName => self.firstName +
                          " " +
                          self.lastName;

Operators

Operators usually perform a function on two operands. Operators that require two operands are binary operators. For example, the * operator is a binary operator that multiplies the values of the right and left operands.

There are four exceptions that have different numbers of operands. The logical negation (not) has only one operand, the arithmetic minus (-) and plus (+) may have only one operand (e.g. -3, +3), the conditional (ternary) operator has three operands.

An operator also returns a value. The value and its type depends on the operator and the type of its operands. For example, the arithmetic operators (perform basic arithmetic operations such as addition and subtraction) return numbers. The data type returned by the arithmetic operators depends on the type of its operands: if you add two integers, you get an integer back. An operation is said to evaluate to its result.

We can divide operators into these categories:

  • navigation, field selection and query execution (.)

  • function call (!)

  • assignment (=)

  • arithmetic (+, -, *, /, div, mod, ^)

  • relational (==,!=,<,>,>=,<=)

  • conditional (? :) and

  • logical (not, and, or, xor, implies).

The following table summarizes the precedence of operators used in expressions.

Precedence Operator

10

(), ., !

9

not

8

*, /, div, mod

7

+, -

6

>, <, <=, >=

5

==, !=

4

and

3

or

2

? :

1

=

Navigation is used to traverse model relations to access the instance(s) linked to an instance or set of instances.

In expressions, the . (dot) character is used to navigate from an instance or a collection of instances.

The starting point of the navigation can be

  • a static collection of references using the syntax shop::Order, which means all instances of the Order entity, or

  • a static query execution using the syntax shop::MyQuery(), which means all entity instances returned by the query shop::MyQuery

  • the predefined variable called self. The self keyword refers to the current instance in an expression.

Examples:

// a navigation starting from static collection
derived Products[] orderedProducts => shop::Order.orderItems.product;

// a navigation starting from self variable in Order entity
derived Products[] orderedProducts => self.orderItems.product;

Navigation can be chained, which means that you can navigate further from a navigation result.

In the example above, we first navigate from self to the list of order items. We then proceed to the product of the OrderItem. This navigation will result a list of products that are in the order.

Navigation types can also be classified as follows.

Instance navigation

When navigating from a single instance, the result of the navigation depends on the cardinality of the relation being navigated.

  • If the cardinality of the relation being navigated is single, the navigation returns a single entity instance or undefined.

  • If the cardinality of the relation being navigated is collection, the navigation returns a collection even if there is no actual instance or there is only one instance in the collection.

Collection navigation

When navigating from an instance collection, regardless of the cardinality of relation being navigated, the result is always a collection.

Field selection

Both derived and stored field values of an entity can be read in expressions. To read a field value use the . (dot) character. The field selection can be chained for navigation expression. The field selection can only be chained for navigation that returns a single instance.

Examples:

derived String productName => self.product.name;

In the example above, the expression returns the product’s name.

Query execution

Static and instance queries can be used in expressions. To execute an instance query use the . (dot) character before the query name and append the arguments in parentheses. To execute a static query use its name as a navigation starting point and append the arguments in parentheses. If you do not pass arguments to a query append parentheses with no arguments between them.

Query arguments can be literals only (e.g. 121, "apple", true etc.).

Examples:

derived Customer[] havingOrdersBetween0and10 => shop::ordersBetween(min = 0, max = 10).customer;

In the example above, the ordersBetween query is executed with two arguments.

Built-in functions

There are a number of built-in functions that are always available in expressions. To invoke a built-in function use the ! character after a navigation, field or type selection.

Syntax:

<navigation>!<function>([<parameter>],...)

where <navigation> is a valid navigation expression and <function> is the name of the function to be invoked. After the function name, the input parameters of the function are in parentheses.

Examples:

derived Integer count => self.orderItems!size();
derived Integer nameLength => self.fullName!size();

The self.orderItems!size() evaluates to an integer, it returns the number of the ordered items in the order. The expression self.fullName!size() will return the number of characters in the customers’s name field (assuming it is a String type).

Static functions

A special group of functions is static functions. Static functions are invoked on types rather than on instances or collections.

Syntax:

<type>!<function>([<parameter>],...)

where <type> is a valid domain model primitive and <function> is the name of the function to be invoked. After the function name, the input parameters of the function are in parentheses.

Example:

field Time tm = Time!of(hour = 23, minute = 59, second = 59);

The above example sets the tm field to `23:59:59` as default value.

Iterator functions

Functions that handle individual elements in a collection use an iterator variable.

Syntax:

<navigation>!<function>(<variable> | <expr>)

where <variable> is the name of the iterator variable that will iterate through all elements on the result of the <navigation> collection. The <expr> is an expression that will provide the input list for the <function>.

Examples:

derived Integer averagePrice => self.orders!avg(field = price);

In the example above, we navigate to a collection orders and define an iterator variable named order. Then, we read the price field of orders and pass this list to the avg built-in function. The example calculates the average price of the orders.

Functions can also be chained. For example the expression below filters the orders based on their price, then it returns the average price of the filtered orders.

self.orders!filter(order | order.price > 100)!avg(field = price)

The list of available functions can be found in section List of functions.

Iterator variables are only accessible in parentheses where they have been defined. In other words, the scope of the iterator variable is limited to after the | (pipe) character. If the iterator expression contains another iterator function, the iterator variable of the embedding iterator function is not accessible within the embedded iterator function.

Using self in iterator expressions is currently not allowed.

Even though self and the iterators of embedding functions cannot be used in functions, proper modeling can work around this limitation. When we need the value of the self or embedding iterator, use a bidirectional relation. The bidirectional relation can be used to navigate back to self or to any embedding iterator value.

The following example selects a customer’s orders that are cheaper than average order prices.

entity Customer {
	relation Order[] orders opposite customer;

    derived Price avgPrice => self.orders!avg(field = price);
    derived Order[] belowAvgOrders => self.orders!filter(order | order.price < order.customer.avgPrice);
}

External variables

Some expressions require dynamic values that are provided by the surrounding environment and cannot be "wired" to the model as a constant, e.g. current time or OS environment variables. Variables of this type are referred to as external variables.

External variables can be accessed from the model using a category and key pair that are evaluated at runtime.

Syntax:

<primitive>!getVariable(category = <category>, key = <key>)

where <primitive> is a domain primitive that defines the type of the returned value. The valid <category> and <key> pairs a listed in the table below.

Domain primitive constraints are evaluated when “getVariable” is called. If the return value does not meet the primitive constraints, an error occurs.

Category Key Description

SYSTEM

current_date

Returns the current date.

Date!getVariable(category = "SYSTEM", key = "current_date")

Shortcut: Date!now()

SYSTEM

current_timestamp

Returns the current time.

Timestamp!getVariable(category = "SYSTEM", key = "current_timestamp")

Shortcut: Timestamp!now()

SYSTEM

current_time

Returns the current time.

Time!getVariable(category = "SYSTEM", key = "current_time")

Shortcut: Time!now()

ENVIRONMENT

any

Returns an OS environment variable.

Path for the current working directory: String!getVariable(category = "ENVIRONMENT", key = "PWD")

UID of running OS user: Integer!getVariable(category = "ENVIRONMENT", key = "UID")

SEQUENCE

sequence name

A continuously increasing integer is returned with each call. The maximum value cannot exceed the range of an eight-byte integer. Sequences are constant and optimized for concurrency. Sequences cannot be used for "gap-free" assignment of sequence numbers.

If the sequence does not already exist, it creates the sequence and returns the first sequence value.

Get next Order number: Long!getVariable(category = "SEQUENCE", key = "Order")

Undefined

Field selectors, navigations and expressions can evaluate to undefined. Since undefined is not a possible value of any data type, it is not considered a value, but rather a marker (or placeholder) indicating the absence of value.

In arithmetic expressions, any occurrence of undefined results in an undefined value. The expression self.a + self.b results in undefined if self.a or self.b is undefined.

The expression self.firstName + " " + self.lastName results in an undefined string if self.firstName or self.lastName is undefined.

In the case of logical values, the comparison with undefined can never result in either true or false, but always a third logical result, undefined.

Navigations from undefined references will also result in undefined. In other words, if any part of a navigation or function chain results undefined, the result of the whole navigation will be undefined. For example, self.customer.name will evaluate to undefined, when self.customer is undefined.

Functions applied on undefined references will also result in undefined. For example, self.name!size() will evaluate to undefined instead of 0, when self.name is undefined. The only exceptions are the isDefined(), isUndefined() and orElse() functions:

  • self.name!isDefined() will evaluate to false if self.name is undefined.

  • self.name!isUndefined() will evaluate to true if self.name is undefined.

  • self.name!orElse(value = "unknown") will evaluate to "unknown" if self.name is undefined.

The conditional ternary operator executes the false branch if the condition evaluates to undefined. self.name == "" ? "A" : "B" is "B" if the self.name is undefined.

There is no literal for undefined in JSL, thus to check if a field, relation or the result of an expression is undefined use the isDefined() or isUndefined() functions. See Any type functions.

List of functions

Any type functions

Any type functions can be applied to any type or instance except collections.

isDefined() : boolean

Evaluates to true if the value exists. Note, that isDefined() cannot be used for collections.

Example:

"apple"!isDefined() is true

self.line2!isDefined() is true if line2 field has a value, otherwise false.

isUndefined() : boolean

Evaluates to true if the value does not exist, e.g. it is undefined. Note, that isUndefined() cannot be used for collections.

Example:

"apple"!isUndefined() is false

self.line2!isUndefined() is false if line2 field has a value, otherwise true.

orElse(value = <value>) : <type>

Returns <value> if the given expression to which it is applied returns undefined. Otherwise, it returns the value of the given expression. The type of <value> must be the same as the given expression.

Examples:

"apple"!orElse(value = "grape") is "apple"

2!orElse(value = 3) is 2

self.name!orElse(value = "unknown") is "unknown" if self.name is undefined, otherwise it returns the value of self.name.

getVariable(category = <value>, key = <key>) : <type>

Static function, returns the value of an external variable using <category> and <key> pair that are evaluated at runtime.

See more details and the examples in chapter External variables.

String functions

size() : numeric

Returns the number of characters in the string.

Example: "apple"!size() is 5

first(count = <count>) : string

Returns the first <count> characters of the original string, or returns the original string if its size is less than <count>. <count> must be an integer. If <count> is less than 1, it returns an empty string.

Example: "apple"!first(count = 2) is "ap"

last(count = <n>) : string

Returns the last <count> characters of the original string, or returns the original string if its size is less than <count>. <count> must be an integer. If <count> is less than 1, returns an empty string.

Example: "apple"!last(count = 1) is "e"

position(substring = <substring>) : numeric

Returns the position of the first occurrence of the <substring> in the original string, or 0 if the original string does not contain the <substring>. <substring> must be a string. Position of the first character is 1.

Example: "apple"!position(substring = "p") is 2

substring(offset = <offset>, count = <count>) : string

Returns a substring of length <count> starting at <offset>. The offset of the first character is 1. Both <offset> and <count> must be integers.

Example: "apple"!substring(offset = 2, count = 3) is "ppl"

lower() : string

Returns the original string with all alphabetic characters in lowercase. Note that the actual locale of the database affects the behavior of this function.

Example: "ApPlE"!lower() is "apple"

upper() : string

Returns the original string with all alphabetic characters in uppercase. Note that the actual locale of the database affects the behavior of this function.

Example: "ApPlE"!upper() is "APPLE"

capitalize() : string

Returns a string with the first letter capitalized and all other characters lowercased. Note that the actual locale of the database affects the behavior of this function.

Example: "apPlE"!capitalize() is "Apple"

matches(pattern = <pattern>) : boolean

Returns true if the string matches a given regular expression <pattern>, false otherwise. A detailed description of the regular expression can be found in the String section.

Example: "apple"!matches(pattern = r".*pl.") is true

like(pattern = <pattern> [, exact = <exact>]) : boolean

Returns true if the string matches a given <pattern>, false otherwise. The optional <exact> is a boolean parameter. If <exact> is true the pattern matching is case-sensitive. If <exact> is false the pattern matching is case-insensitive. If no <exact> argument is passed, the pattern matching is case-sensitive.

There are two wildcards used in the <pattern>:

  • percent sign (%)

  • underscore (_)

The percent sign represents zero, one, or multiple numbers or characters. The underscore represents a single number or character. These symbols can be used in combinations.

If either of these two signs is not used in the <pattern>, then the function acts like the equals operator.

Examples:

"apple"!like(pattern = "%pl_") is true

"apPLe"!like(pattern = "_pple", exact = false) is true

replace(oldstring = <oldstring>, newstring = <newstring>) : string

Returns a string where all occurrences of <oldstring> in the original string replaced by <newstring>. Note that <oldstring> is not a regular expression pattern or a like pattern, but a simple string.

Example: "apple"!replace(oldstring = "le", newstring = "endix") is "appendix"

trim() : string

Returns the original string with all leading and trailing whitespace characters removed.

Example: " apple "!trim() is "apple"

ltrim() : string

Returns the original string with all leading whitespace characters removed.

Example: " apple "!ltrim() is "apple "

rtrim() : string

Returns the original string with all trailing whitespace characters removed.

Example: " apple "!rtrim() is " apple"

lpad(size = <size> [, padstring = <padstring>]) : string

Fills up a string on the left to the specified <size> with <padstring>. If the length of <padstring> is less than the remaining length, the <padstring> is repeated until it is not filling up. If the length of <padstring> is longer than the remaining length, it will be truncated on the right. If <padstring> is not defined, one space character (" ") is used by default.

Examples:

"apple"!lpad(size = 6) is `" apple"

"ple"!lpad(size = 5, padstring = "ap") is "apple"

"ple"!lpad(size = 6, padstring = "ap") is "apaple"

"ple"!lpad(size = 7, padstring = "ap") is "apapple"

rpad(size = <size> [, padstring = <padstring>]) : string

Fills up a string on the right to the specified <size> with <padstring>. If the length of <padstring> is less than the remaining length, the <padstring> is repeated until it is not filling up. If the length of <padstring> is longer than the remaining length, it will be truncated on the left. If <padstring> is not defined, one space character (" ") is used by default.

Examples:

"apple"!rpad(size = 6) is "apple "

"app"!rpad(size = 5, padstring = "le") is "apple"

"app"!rpad(size = 6, padstring = "le") is "applel"

"app"!rpad(size = 7, padstring = "le") is "applele"

Numeric functions

round([scale = <scale>]) : numeric

Returns the closest number. The optional <scale> argument is an integer that determines the number of decimal places of rounding. The default value of <scale> is 0.

Example:

1!round() is 1

7.89!round() is 8

7.89!round(scale = 1) is 7.9

2.50!round() is 3

(-2.5)!round() is -3

(-7.89)!round() is -8

floor() : numeric

Returns the largest integer that is less than or equal to the argument.

Example:

1!floor() is 1

2.9!floor() is 2

(-2.9)!floor() is -3

ceil() : numeric

Returns the smallest integer that is greater than or equal to the argument.

Example:

1!ceil() is 1

2.9!ceil() is 3

(-2.9)!ceil() is -2

abs() : numeric

Returns the absolute value of the argument.

Example:

1!abs() is 1

2.9!abs() is 2.9

(-3)!abs() is 3

asString() : string

Numeric value as string.

Example: 123456.789!asString() is "123456.789"

Be careful when calling numeric functions on negative constant values! Since the precedence of the function call (!) is higher than the precedence of the minus operator (-), the functions are called first and only then is the arithmetic negation performed. For example, if you want to calculate the absolute value of -3, enclose the constant in parentheses: (-3)!abs(). Without parentheses, the expression -3!abs() returns -3.

Boolean functions

asString() : string

Boolean value as string.

Example: true!asString() is "true"

Date functions

year() : numeric

Returns the year part of date.

Example: `2021-03-02`!year() is 2021

month() : numeric

Returns the month part of date.

Example: `2021-03-02`!month() is 3

day() : numeric

Returns the day part of date.

Example: `2021-03-02`!day() is 2

of(year = <year>, month = <month>, day = <day>) : date

Static function, constructs a date value from the numeric parameters <year>, <month> and <day>. If any of the parameters is not integer, the result will be undefined. If <month> or <day> is less than 1, the result will be undefined. If <month> is greater than 12, or <day> is greater than the last day of the month, it gives an undefined result.

Example: Date!of(year = 2011, month = 1, = day = 28) is `2011-01-28`

dayOfWeek() : numeric

Returns an integer representing the weekday index for a date. The return value follows the ISO-8601 standard, from 1 (Monday) to 7 (Sunday).

Example: `1970-01-01`!dayOfWeek() is 4, i.e. it was Thursday.

dayOfYear() : numeric

Returns the day of the year for a given date (a number from 1 to 366).

Example: `2020-02-01`!dayOfYear() is 32

asString() : string

Date value as string according to the ISO-8601 standard.

Example: `2021-03-02`!asString() is "2021-03-02"

Time functions

hour() : numeric

Returns the hour part of time.

Example: `23:15:59`!hour() is 23

minute() : numeric

Returns the minute part of time.

Example: `23:15:59`!minute() is 15

second() : numeric

Returns the second part of time.

Example: `23:15:59`!second() is 59

of(hour = <hour>, minute = <minute>, second = <second>) : time

Static function, constructs a time value from the numeric parameters <hour>, <minute> and <second>. If any of the parameters is not integer, the result will be undefined. If any parameter is less than 0, the result will be undefined. If <hour> is greater than 23, or <minute> or <second> is greater than 59, it gives an undefined result.

Example: Time!of(hour = 13, minute = 45, second = 00) is `13:45:00`

asString() : string

Time value as string according to the ISO-8601 standard.

Example: `23:15:59`!asString() is "23:15:59"

Timestamp functions

date() : date

Returns the date part of the timestamp in UTC+0 timezone.

Example:

`2019-07-18T01:11:12Z`!date() is `2019-07-18`

`2019-07-18T01:11:12+02:00`!date() is `2019-07-17`

time() : time

Returns the time part of the timestamp in UTC+0 timezone.

Example:

`2019-07-18T01:11:12Z`!time() is `01:11:12`

`2019-07-18T01:11:12+02:00`!time() is `23:11:12`

of(date = <date> [, time = <time>]) : timestamp

Static function, constructs a timestamp value from the parameters <date> and <time>, where <date> is a date primitive and <time> is a time primitive. The <time> parameter is optional, if <time> is omitted the time part of the timestamp will be set to `00:00:00`.

Example:

Timestamp!of(date = `2021-02-28`, time = `10:30:01`) is `2021-02-28T10:30:01Z`

Timestamp!of(date = `2021-02-28`) is `2021-02-28T00:00:00Z`

asMilliseconds() : numeric

Returns the timestamp in milliseconds from 1970-01-01T00:00:00Z.

Example: `1970-01-01T00:01:00Z`!asMilliseconds() is 60000

fromMilliseconds(milliseconds = <milliseconds>) : timestamp

Static function, creates a timestamp and sets the value in <milliseconds> from 1970-01-01T00:00:00Z. <milliseconds> must be an integer

Example: Timestamp!fromMilliseconds(milliseconds = 60000) is `1970-01-01T00:01:00Z`

plus([milliseconds = <milliseconds>][, seconds = <seconds>][, minutes = <minutes>][, hours = <hours>][, days = <days>][, months = <months>][, years = <years>]) : timestamp

Adds duration expressed in <milliseconds>, <seconds>, <minutes>, <hours>, <days>, <months> or <days> to the original timestamp.

At least one parameter is required, but any parameter can be used in conjunction with the others. All arguments passed must be integers. If any argument is less than 0, its value is subtracted from the original timestamp.

Examples:

`2019-07-18T01:11:12Z`!plus(days = 1) is "2019-07-19T01:11:12Z"

`2019-07-18T01:11:12Z`!plus(days = 1, hours = 2) is "2019-07-19T03:11:12Z"

`2019-07-18T01:11:12Z`!plus(days = 1, hours = -24) is "2019-07-18T01:11:12Z"

asString() : string

Timestamp value as string according to the ISO-8601 standard.

Example: `2019-07-18T01:11:12Z`!asString() is "2019-07-18T01:11:12Z"

Binary functions

There are no binary functions.

Enumeration functions

asString() : string

Enumeration literal as string.

Example: OrderStatus#OPEN!asString() is "OPEN"

Instance functions

typeOf(entityType = <entityType>) : boolean

Evaluates to true if the given instance conforms to the <entityType> but not any subtype of the <entityType>. That is, an instance of <entityType> and not an instance of any subtype of <entityType>.

Example:

self.customer!typeOf(entityType = shop::Customer) is true if self.customer is a customer, but neither an enterprise nor a person. For the model, see the Introduction chapter.

kindOf(entityType = <entityType>) : boolean

Evaluates to true if the given instance conforms to the <entityType>. That is, an instance of <entityType> or an instance of any subtype of <entityType>.

Example:

self.customer!kindOf(entityType = shop::Customer) is true if self.customer is either a customer, an enterprise, or a person. For the model, see the Introduction chapter.

container(entityType = <entityType>) : instance

Returns the container of the instance if that matches the given <entityType>. Type matching works according to the kindOf() function.

Example:

self!container(entityType = shop::Customer) navigates from the Address to the Customer if the container is an instance of Customer or any subtype of Customer (Enterprise or Person). For the model, see the Introduction chapter.

asType(entityType = <entityType>) : instance

Returns the given instance as the <entityType> if the type of the given instance matches to <entityType>, otherwise evaluates as undefined. In other words, the function "casts" the instance. Type matching works according to the kindOf() function.

Example:

self.customer!asType(entityType = shop::Enterprise) navigates from Order to Customer and it returns an Enterprise instance. If the result of the navigation is a Person, it returns undefined. For the model, see the Introduction chapter.

memberOf(instances = <instances>) : boolean

Indicates if the <instances> collection contains the given instance.

Example:

self!memberOf(shop::Enterprise.orders.orderItems.product) within a product, it checks whether it has ever been ordered by any enterprise. For the model, see the Introduction chapter.

Collection functions

head(field = <field> [, reverse = <reverse>]) : collection

First, it sorts the given collection by the <field>, and then it returns a collection containing the first elements. If there is more than one element in the first place, all elements in the first place will be included in the result. The <field> is the name of an entity field or derived. The field must have a primitive type. The optional <reverse> is a boolean value. If <reverse> is true the collection will be sorted in descending order, otherwise in ascending order.

Example:

self.orderItems.product!head(field = price, reverse = true) returns the highest priced products of an order.

tail(field = <field> [, reverse = <reverse>]) : collection

First, it sorts the given collection by the <field>, and then it returns a collection containing all of the non-first elements. If there is more than one element in the first place, all elements in the first place will be omitted from the result. The <field> is the name of an entity field or derived. The field must have a primitive type. The optional <reverse> is a boolean value. If <reverse> is true the collection will be sorted in descending order, otherwise in ascending order.

Example:

self.orderItems.product!tail(field = price, reverse = true) returns all products in the order except the highest priced products.

any() : instance

Returns an arbitrary element of a collection.

Example:

self.orderItems!any() returns one of the items in the order.

size() : numeric

Returns the number of elements of a collection.

self.orderItems!size() returns the number of the items in the order.

asCollection(entityType = <entityType>) : collection

Filters the collection according to <entityType> and returns a collection of the parameter <entityType>. Members of the collection that are not of that <entityType> are not included in the result. Type matching works according to the kindOf() function.

Example:

shop::Order.customer!asCollection(entityType = shop::Enterprise) returns all enterprises that have at least one order.

contains(instance = <instance>) : boolean

Indicates if the given collection contains the given <instance>.

Example:

shop::Enterprise.orders.orderItems.product!contains(shop::Product!filter(p | p.name == "gadget").any()) checks whether there is an enterprise that has already ordered the product named "gadget".

filter(<variable> | <logical expression>) : collection

Filters the collection according to the <logical expression> and returns a collection. Members of the collection that do not match the logical expression are not included in the result.

Example:

self.orderItems!filter(od | od.price > 10) collects order items more expensive than 10.

anyTrue(<variable> | <logical expression>) : boolean

Returns true if the logical expression is true for any element in the collection. Note that the return value is false for an empty collection.

Example:

self.orderItems!anyTrue(od | od.price > 10) checks if there is an item in the order that is more expensive than 10.

allTrue(<variable> | <logical expression>) : boolean

Returns true if the logical expression is true for all the collection elements. If there is an element for which <logical expression> is false or undefined, then the return value is false. Note that the return value is true for an empty collection.

Example:

self.orderDetails!allTrue(od | od.price > 10) checks that all items in the order are more expensive than 10.

anyFalse(<variable> | <logical expression>) : boolean

Returns true if the logical expression is false for any element in the collection. Note that the return value is false for an empty collection.

Example:

self.orderDetails!anyFalse(od | od.price > 10) returns true if there is an item in the order that is equal to or cheaper than 10.

allFalse(<variable> | <logical expression>) : boolean

Returns true if the logical expression is false for all the collection elements. If there is an element for which <logical expression> is true or undefined, then the return value is false. Note that the return value is true for an empty collection.

Example:

self.orderDetails!allFalse(od | od.price > 10) returns true if all items in the order are 10 or less cheaper.

min(field = <field>) : numeric

Returns the minimum value from the set of values selected by the <field>. The <field> is the name of an entity field or derived. The field must have a numeric type.

Example:

self.orderItems!min(field = price) returns the lowest price from the prices of elements of orderItems list.

max(field = <field>) : numeric

Returns the maximum value from the set of values selected by the <field>. The <field> is the name of an entity field or derived. The field must have a numeric type.

Example:

self.orderItems!max(field = price) returns the highest price from the prices of elements of orderItems list.

avg(field = <field>) : numeric

Returns the average of the set of values selected by the <field>. The <field> is the name of an entity field or derived. The field must have a numeric type.

Example:

self.orderItems!avg(field = price) returns the average price of the elements of orderItems list.

sum(field = <field>) : numeric

Returns the sum of the set of values selected by the <field>. The <field> is the name of an entity field or derived. The field must have a numeric type.

Example:

self.orderItems!sum(field = price) returns the sum of price of the elements of orderItems list.