Using advanced literal expressions (functions in DMN decision elements)

In case you have modeled your first DMN diagram, you are already familiar with DMN expressions for decision logic, e.g. in the form of a simple smaller than statement. These expressions are explained in the chapter Creating and editing DMN diagrams.

You might remember that you selected the corresponding operator from a drop-down list in the Decision Table Editor.

The 'operator' drop-down list

The ‘operator’ drop-down list

In many cases, these basic operators are not sufficient.

A simple example is determining a discount based on the total value of a list of purchased objects.

To determine the sum, we need to use Signavio’s advanced literal expressions. The expressions are based on FEEL, the friendly enough expression language specified as part of the DMN standard, which you can download as PDF at http://www.omg.org/spec/DMN/1.0/PDF.

Read more about:

The single commands can be used in combination, like in the following example:

Product((1 - DiscountRate) * Sum(ListOfItemPrices))

In the example, we calculate the total purchase sum of a list of items, considering a discount. The variables used here correspond to the data types defined in Input Data element’s attributes and can be set when simulating the DMN diagram.

The documentation of all available expressions can be found at Documentation of all literal expressions.

Of course, you can also use standard operators (+, -, *, /, and, or) within literal expressions.

Consequently, the example above can be expressed more concisely:

(1 - DiscountRate) * Sum(ListOfItemPrices)

Using literal expressions in Decision Tables

In our example, we want to determine - as already mentioned above - a discount based on the total value of all purchased items.

First, create the Purchased items Data Input element. The input should be a list of numbers of the type currency:

Create a Data Input element and configure it according to the screenshot.

Create a Data Input element and configure it according to the screenshot.

Now create a Decision, connect it to the data input and label it Determine discount. Click the table icon in the upper left corner of the Decision element to open the Decision Table Editor.

Create a Decision, reference the Data Input element and open the decision table editor.

Create a Decision, reference the Data Input element and open the decision table editor.

To activate the literal expression input, click the header and delete the input reference in the table:

Delete the input reference to be able to insert a literal expression.

Delete the input reference to be able to insert a literal expression.

Type in =. An overview over available variables and functions is displayed:

After inserting an initial '=' sign, available variables and functions are displayed.

After inserting an initial ‘=’ sign, available variables and functions are displayed.

Suggestions appear as you type. Type in Sum and select the Sum function. Then, insert the variable PurchasedItems as a parameter of Sum:

Insert the literal expression 'Sum(PurchasedItems)'.

Insert the literal expression ‘Sum(PurchasedItems)’.

Now, the decision logic’s Input Data is the sum of all purchased items. You can define the decision logic as usual (see: Editing diagrams).

Please mind the first hit policy in our example:

decision logic for determining a discount based on the total sum of purchased items

decision logic for determining a discount based on the total sum of purchased items

Using literal expressions instead of Decision Tables

You can also use literal expressions instead of Decision Tables.

For example, you can split a decision into two daisy-chained elements, one with a decision table and another one with literal expression logic.

'Calculate total sum' and 'Determine discount' as two separate Decision elements.

‘Calculate total sum’ and ‘Determine discount’ as two separate Decision elements.

  • The first element calculates the total sum of purchased items.
  • The second element determines the discount based on the total sum.

We can model the first decision without using a decision table.

Open the decision table editor and switch to the Literal expressions tab. There, insert the literal expression to calculate the sum of items:

Open the 'Literal expression tab' and insert the literal expression.

Open the ‘Literal expression tab’ and insert the literal expression.

Now, the decision element returns the sum of items as a Data Output and can be referenced by the following Decision element.

If we create complex literal expressions, we can define variables - so called boxed contexts and reference them in our decision function:

*Manage complex expressions with boxed contexts.*

Manage complex expressions with boxed contexts.

This improves the readability of our literal expressions.

Important

If a literal expression is defined, it supersedes the decision logic in the decision table.

Documentation of all literal expressions

This section lists all available literal expressions, grouped by operation type.

Arithmetic operations

Abs

Abs(number):NUMERIC

Returns the absolute value of a number.

Example: Abs(-5) returns 5.

Count

Count([num1 ,num2, num3]):NUMERIC

Returns the number of elements of the given list.

Example: Count(["item1", "item2", "item3"]) returns 3.

Round

Round(number,digits):NUMERIC

Returns a number rounded to the corresponding number of digits.

Example: Round(3.44,1) returns 3.4.

Ceiling

Ceiling(number):NUMERIC

Returns a number rounded up to the next integer.

Example: Ceiling(1.3) returns 2.

Floor

Floor(number):NUMERIC

Returns a number rounded down to the next integer.

Example: Floor(1.6) returns 1.

Integer

Integer(number): NUMERIC

Returns the integer part of a number.

Example: Integer(1.34) returns 1.

Modulo

Modulo(divident, divisor):NUMERIC

Returns the remainder of the divident divided by the divisor.

Example: Modulo(4, 3) returns 1.

Percent

Percent(number):NUMERIC

Returns the number divided by 100.

Example: Percent(10) returns 0.1.

Power

Power(base, exponent):NUMERIC

Returns the base raised to the power of the exponent.

Example: Power(2, 3) returns 8.

Product

Product([factor1, factor2, factor3]):NUMERIC

Returns the product of a list of factors.

Example: Product([2, 3, 4]) returns 24.

RoundDown

RoundDown(number, digits):NUMERIC

Returns a number rounded down to the corresponding number of digits.

Example: RoundDown(1.3674, 2) returns 1.36.

RoundUp

RoundUp(number, digits):NUMERIC

Returns a number rounded up to the corresponding number of digits.

Example: Abs(1.344, 2) returns 1.35.

Sum

Sum([number1, number2, number3]):NUMERIC

Returns the sum of a list of values.

Example: Sum([1, 2, 3, 4, 5]) returns 15.

Date & time operations

Day

Day(datetime):NUMERIC

Returns the day part of a datetime.

Example: Day(2015-12-24T12:15:00.000+01:00) returns 24.

DayAdd

DayAdd(datetime, days to add):DATE

Returns the date plus the provided number of days.

Example: DayAdd(2015-12-24T12:15:00.000+01:00, 1) returns 2015-12-25T12:15:00.000+01:00.

DayDiff

DayDiff(datetime1, datetime2):NUMERIC

Returns the amount of full days between two dates.

Example: DayDiff(2015-12-24T12:15:00.000+01:00, 2015-12-25T12:15:00.000+01:00) returns 1.

Date

Date(year, month, day):DATE

Returns a date using the standard parameters of a date: year, month, day

Example: Date(2015, 12, 25) returns 2015-12-25.

DateTime

DateTime(day, month, year, hour, minute, second, hourOffsett):DATE

Returns the dateTime using the standard parameters of a data time. The last parameter ‘hourOffset’ is optional.

Example: DateTime(25, 12, 2015, 12, 15, 0, 1) returns 2015-12-24T12:15:00.000+01:00.

Hour

Hour(datetime):NUMERIC

Returns the hour part of a datetime.

Example: Hour(2015-12-24T12:15:00.000+01:00) returns 12.

HourDiff

Hour(time):NUMERIC

Returns the amount of full hours between two dates.

Example: HourDiff(2015-12-24T12:15:00.000+01:00, 2015-12-24T14:15:00.000+01:00) returns 2.

Minute

Minute(time):NUMERIC

Returns the minute part of a datetime.

Example: Minute(2015-12-24T12:15:00.000+01:00) returns 15.

MinutesDiff

MinutesDiff(datetimes1, date2times):NUMERIC

Returns the amount of full minutes between two dates.

Example: MinutesDiff(2015-12-24T12:15:00.000+01:00, 2015-12-24T13:15:00.000+01:00) returns 60.

Month

Month(datetime):NUMERIC

Returns the month part of a datetime.

Example: Month(2015-12-24T12:15:00.000+01:00) returns 12.

MonthAdd

MonthAdd(datetime, months_to_add):DATE

Returns the datetime plus the number of months.

Example: MonthAdd(2015-10-10T12:15:00.000+01:00, 1) returns 2015-11-10T12:15:00.000+01:00.

MonthDiff

MonthDiff(datetime1, datetime2):NUMERIC

Returns the amount of full months between two dates.

Example: MonthDiff(2015-10-10T12:15:00.000+01:00, 2015-11-10T12:15:00.000+01:00) returns 1.

Now

Now():DATE

Returns current datetime.

Example: Now() could have returned 2015-11-10T12:15:00.000+01:00.

Today

Today():DATE

Returns the current date.

Example: Today() could have returned 2015-11-10.

Weekday

Weekday(datetime):NUMERIC

Returns a number (1 to 7) representing the day of the week.

Example: weekday(2016-02-09T12:15:00.000+01:00) returns 3.

Year

Year(datetime):NUMERIC

Returns the year part of a datetime.

Example: Year(2016-02-09T12:15:00.000+01:00) returns 2016.

YearAdd

YearAdd(datetime, years_to_add):DATE

Returns the datetime plus the number of years.

Example: YearAdd(2016-02-09T12:15:00.000+01:00, 1) returns 2017-02-09T12:15:00.000+01:00.

YearDiff

YearDiff(datetime1, datetime2):NUMERIC

Returns the amount of full years between two dates.

Example: YearDiff(2016-02-09T12:15:00.000+01:00, 2017-02-09T12:15:00.000+01:00) returns 1.

List operations

Append

Append(list, element): LIST

Adds the element to a copy of the provided list. Returns the manipulated copy.

Example: Append([2.5, 5.8, 4.3], 6.7) returns [2.5, 5.8, 4.3, 6.7].

AppendAll

AppendAll(list1, list2): LIST

Adds all elements from the second provided list to a copy of the first one. Returns the manipulated copy.

Example: AppendAll([2.5, 5.8, 4.3], [2.1, 3.5, 7.4]) returns [2.5, 5.8, 4.3, 2.1, 3.5, 7.4].

Zip

Zip(attributes, values1, ..., valuesN): LIST

Assembles a list of objects out of a list of attributes and multiple lists of values.

Example: Zip(["id", "value"], [23a3e98, c45da1b], [40, 120]) returns [{id: 23a3e98, value: 40},{ id: c45da1b, value: 120}].

Important

Before version 10.11.0 of the Decision Manager, the values were passed to the function as a list of lists, for example:

Zip(["id", "value"], [[23a3e98, c45da1b], [40, 120]])

Literal expressions that used the old Zip function have been automatically transformed to the new syntax.

NotContainsAny

NotContainsAny(list1, list2): BOOLEAN

Determines whether list1 contains any element of list2.

Example: NotContainsAny(["item1", "item2"], ["item2", "item3"]) returns false.

ContainsOnly

ContainsOnly(list1, list2): BOOLEAN

Determines whether list1 contains only elements of list2.

Example: ContainsOnly(["item1", "item2"], ["item2", "item3"]) returns false.

AreElementsOf

AreElementsOf(list1, list2): BOOLEAN

Determines whether list2 contains all elements of list1.

Example: AreElementsOf(["item2, item3"], ["item1", "item2", "item3"]) returns true.

Remove

This expression is available only in the Literal Expressions Editor (not in the Decision Table Editor).

Remove(list, element): LIST

Removes the specified element from the specified list.

Example: Remove(["item1", "item2"], "item1") returns ["item2"].

RemoveAll

This expression is available only in the Literal Expressions Editor (not in the Decision Table Editor).

RemoveAll(list1, list2): LIST

Removes all elements of list2 from list1.

Example: Remove(["item1", "item2", "item3"], ["item1", "item2"]) returns ["item3"].

Statistical operations

Avg

Avg([number1, number2, number3]):NUMERIC

Returns the average of the values of the given list.

Example: Avg([3,5]) returns 4.

Max

Max([number1, number2, number3]):NUMERIC

Returns the maximum value of the given list.

Example: Max([5, 4, 10]) returns 10.

Median

Median([number1, number2, number3]):NUMERIC

Returns the median value of the given list.

Example: Median([2, 5, 10, 12, 34, 35]) returns 11.

Min

Min([number1, number2, number3]):NUMERIC

Returns the minimum value of the given list.

Example: Min([5, 4, 10]) returns 4.

Mode

Mode([number1, number2, number3]):NUMERIC

Returns the most frequently occurring value of the given list. Returns the first (most left) most frequent value, if several values occur most frequently (e.g. two values appear each two times).

Example: Mode([1, 2, 4, 4, 5, 6]) returns 4.

Text handling

Concat

Concat([text1, text2, text3]):TEXT

Returns the concatenation of the given list of text values.

Example: Concat(["Hello ", "World", "!"]) returns "Hello World!".

IsAlpha

IsAlpha(text):BOOLEAN

Determines whether the text contains only alphabetic characters (A-Z, a-z). Umlauts and similar characters (e.g. Ä, Å ß) must not be included.

Example: IsAlpha("abcdefg5") returns false.

IsAlphanumeric

IsAlphanumeric(text):BOOLEAN

Determines whether the text contains only alphanumeric characters (A-Z, a-z, 0-9). Umlauts and similar characters (e.g. Ä, Å ß) must not be included.

Example: isAlphanumeric("abcdefg5") returns true.

IsNumeric

IsNumeric(text):BOOLEAN

Determines whether the text is a valid number containing only plus or minus sign, digits, commas, and decimal points.

Example: IsNumeric("2.3.5") returns false

IsSpaces

IsSpaces(text):BOOLEAN

Determines whether the text contains only spaces.

Example: IsSpaces("     ") returns true.

Len

Len(text):NUMERIC

Returns the number of characters in a text string.

Example: Len("five") returns 4.

Lower

Lower(text):TEXT

Returns the text string with all letters converted to lowercase.

Example: Lower("UPPER") returns upper.

Trim

Trim(text):TEXT

Returns the text string with all spaces removed except single spaces between words.

Example: Trim("Hello         World! ") returns "Hello World!".

Upper

Upper(text):TEXT

Returns the text string with all letters converted to uppercase.

Example: Upper("lower") returns "LOWER".

Number

Number(text):NUMERIC

Returns the numerical value represented in the text string. Only a period (.) is allowed as a separator.

Example: Number("5") returns 5.

Number

Number(text, default_value):NUMERIC

Returns the numerical value represented in the text string. Only a period (.) is allowed as a separator. Returns default_value if unable to convert text into number.

Example: Number("5,5", 10) returns 10 (Number("5.5", 10) returns 5.5).

Mid

Mid(text, start, num_chars):TEXT

Returns the character sequence of the length num_chars from the corresponding starting position of a text string.

Example: Mid("Hello World!", 6, 5) returns "World".

Left

Left(text, num_chars):TEXT

Returns the character sequence of the length num_chars from the start of a text string.

Example: Left("Hello World!", 5) returns "Hello".

Text

Text(num, format_text):TEXT

Returns a numeric value as a text string in a specific format. The format is specified by the placeholders # and 0 and a decimal point ..

Example: Text(1, "#.000") returns "1.000".

TextOccurrences

TextOccurrences(find_text, within_text):NUMERIC

Returns the number of occurrences of find_text within within_text.

Example: TextOccurrences("can", "Can you can a can as a canner can can a can?") returns 6.

Contains

Contains(text, substring): BOOLEAN

Determines whether text``contains the ``substring.

Example: Contains("Hello World!", "o World") returns true.

StartsWith

StartsWith(text, prefix): BOOLEAN

Determines whether text``starts with the ``prefix.

Example: StartsWith("Hello World!", "Hello") returns true.

EndsWith

EndsWith(text, suffix): BOOLEAN

Determines whether text ends with the suffix.

Example: endsWith("Hello World!", "!") returns true.

Logical operators

Not

Not(boolean): BOOLEAN

Negates the input boolean.

Example: Not(true) returns false.