Skip to main content
Version: Current

Transforming Data

note

Functions and methods can be used in all expression types that support SpEL evaluation.

note

Check here how to handle Unknown data type.

Introduction

Expressions in Nussknacker can use a wide range of built-in functions and methods which can be used to test for specific conditions, perform computations, convert between data types, manipulate lists (collections) and many more.

This page lists available functions and methods.

Methods

Methods operate on specific data types (for example, string or list values) and are invoked using the dot notation, for example:

"John".length
#stringVariable.contains("my")
note

You can check methods available in particular context ("on the data type of the current value") by typing dot (".") at the end of the current expression (no space characters in between)

Methods can also be chained, meaning the result of one method becomes the input to the next: "myString".contains("my").toString.length Here the result of the contains method (true) is chained to toString method which yields "true" and in turn chained to length method yielding integer value of 4.

See also here for more examples of chaining.

Functions

Functions are organized into themed function groups - such as NUMERIC, DATE or GEO- each group providing a set of related functions.

Below is an example of calling an abs() function; this function is the NUMERIC function group.

#NUMERIC.abs(-6.7)

The function group name must be preceded with the hash (#) character.

note

You can check functions available in a function group by typing dot (".") after the function group name (no space in between)

Built-in function groups

Nussknacker comes with the following function groups:

Function groupFunctions
BASE64Encoding & decoding Base64
COLLECTIONOperations on collections
CONVGeneral conversion functions
DATEDate conversions and computations
DATE_FORMATDate formatting/parsing operations
GEOSimple distance measurements
NUMERICNumber parsing
RANDOMRandom value generators
UTILVarious utilities (e.g. identifier generation)

BASE64 encoding and decoding

  • #BASE64.decode(String) - decode Base64 value to String
  • #BASE64.encode(String) - encode String value to Base64
  • #BASE64.urlSafeDecode(String) - decode URL-safe Base64 value to String
  • #BASE64.urlSafeEncode(String) - encode String value to URL-safe Base64

COLLECTION - operations on collections

  • #COLLECTION.(List, List) - concatenates lists, returns List
  • #COLLECTION.diff(List,List) - returns a list that contains all elements contained in list1, that don't appear in list2
  • #COLLECTION.distinct(List) - returns a list that contains unique elements from the given list
  • #COLLECTION.flatten(Collection) - returns a list of all elements from all lists in the given list
  • #COLLECTION.intersect(List,List) - returns a list that contains all unique elements that are contained by both list1 and list2
  • #COLLECTION.join(List,String) - creates a string made of all elements of the list separated with the given separator
  • #COLLECTION.max(Collection) - returns the largest element (elements must be comparable)
  • #COLLECTION.merge(Map) - merges maps. Values in the first map will be overwritten with values from the other one if keys are the same
  • #COLLECTION.min(Collection) - returns the smallest element (elements must be comparable)
  • #COLLECTION.product(List,List) - cross joins two lists of maps: eg. product({{a: 'a'},{b: 'b'}}, {{c: 'c'},{d: 'd'}}) => {{a: 'a',c: 'c'},{b: 'b',c: 'c'},{a: 'a',d: 'd'},{b: 'b',d: 'd'}}
  • #COLLECTION.reverse(List) - returns a list that contains elements in reversed order from the given list
  • #COLLECTION.shuffle(Collection) - returns a copy of the list with its elements shuffled
  • #COLLECTION.slice(Collection,Integer,Integer) - returns a slice of the list starting with start index (inclusive) and ending at stop index (exclusive)
  • #COLLECTION.sortedAsc(Collection) - returns a list of all elements sorted in ascending order (elements must be comparable)
  • #COLLECTION.sortedAscBy(Collection,String) - returns a list of all elements sorted by record field in ascending order (elements must be comparable)
  • #COLLECTION.sortedDesc(Collection) - returns a list of all elements sorted in descending order (elements must be comparable)
  • #COLLECTION.sum(Collection) - returns a sum of all elements
  • #COLLECTION.take(List,Integer) - returns a list made of first n elements of the given list
  • #COLLECTION.takeLast(List,Integer) - returns a list made of last n elements of the given list

CONV - conversion functions

  • #CONV.toAny(Unknown) - wrap param in 'Unknown' type to make it usable in places where type checking is too much restrictive; returns Unknown
  • #CONV.toJson(String) - convert String value to JSON; returns Unknown; check here how to access fields in this case
  • #CONV.toJsonOrNull(String) - convert String value to JSON or null in case of failure; returns Unknown
  • #CONV.toJsonString(Unknown) - convert JSON to String
  • #CONV.toNumber(String or Number) - deprecated - will be removed in 1.19

DATE and DATE_FORMAT - date/time utility functions

DATE function group contains functions for date range checks and computations of periods and durations e.g.:

  • #DATE.isBetween(#localTime, '09:00', '17:00') - checks if LocalTime is in (inclusive) range <09:00, 17:00>
  • #DATE.isBetween(#dayOfWeek, #DATE.MONDAY, #DATE.FRIDAY) - checks if DayOfWeek is in (inclusive) range <MONDAY, FRIDAY>
  • #DATE.isBetween(#localDate, '2020-06-01', '2020-07-01') - checks if LocalDate is in (inclusive) range <2020-06-01, 2020-07-01>
  • #DATE.isBetween(#localDateTime, '2020-06-01T11:00:00', '2020-07-01T11:00:00') - checks if LocalDateTime is in (inclusive) range <2020-06-01T11:00:00, 2020-07-01T11:00:00>
  • #DATE.periodBetween(#from, #to).getMonths - computes Period between from and to and return number of full months between those two dates
  • #DATE.durationBetween(#from, #to).toDays - computes Duration between from and to and return number of full days between those two dates. Keep in mind that Duration is not daylight saving time aware - it computes seconds difference and divide it by number of seconds in given period.
  • In case of days it will be 86400 seconds.

Some useful constants are also available:

  • #DATE.MONDAY, #DATE.TUESDAY, ... - day of weeks
  • #DATE.JANUARY, #DATE.FEBRUARY, ... - months
  • #DATE.zuluTimeZone - Zulu timezone which always has time zone offset equals to UTC
  • #DATE.UTCOffset - UTC offset
  • #DATE.defaultTimeZone - Default time zone for Nussknacker application

Parsing of date/time

Also, #DATE_FORMAT functions can be used to parse or format certain data type from/to the String. It is not recommended to use parsing in scenarios because it will obfuscate logic. A better way is to properly configure message schema. But sometimes it is the only way to handle it. Available functions:

  • #DATE_FORMAT.parseOffsetDateTime('2020-01-01T11:12:13+01:00') - parse OffsetDateTime in ISO-8601 format
  • #DATE_FORMAT.parseOffsetDateTime('2020-01-01T11:12:13+01:00', 'yyyy-MM-dd'T'HH:mm:ssXXX') - parse OffsetDateTime in given DateTimeFormatter format
  • #DATE_FORMAT.parseOffsetDateTime('2020-01-01T11:12:13+01:00', #dateTimeFormatter) - parse OffsetDateTime using given DateTimeFormatter

Equivalent variants of parse functions are available also for other date/time types: LocalTime, LocalDate, LocalDateTime, Instant and ZonedDateTime.

Formatting of date/time

To format date/time can be used #DATE_FORMAT.format(#dateTime) function which accept various date/time types and formats it in ISO-8601 format. Also DateTimeFormatter can be used directly via e.g. #DATE_FORMAT.formatter('EEEE').format(#date). Other formatter factory functions:

  • #DATE_FORMAT.formatter('EEEE', 'PL') - creates DateTimeFormatter using given pattern (EEEE) and locale (PL)
  • #DATE_FORMAT.lenientFormatter('yyyy-MM-dd') - creates lenient version of DateTimeFormatter using given pattern. Lenient parser may use heuristics to interpret inputs that do not precisely match format e.g. format E will accept: mon, Mon and MONDAY inputs. On the other hand, formatter created using #DATE_FORMAT.formatter() functions accepts only Mon input.
  • #DATE_FORMAT.lenientFormatter('yyyy-MM-dd EEEE', 'PL') - creates lenient version DateTimeFormatter using given pattern and locale

For full list of available format options take a look at DateTimeFormatter api docs.

GEO - simple distance measurements

  • #GEO.distanceInKm(Number,Number,Number,Number) - calculate distance in km between two points (with decimal coordinates), using haversine algorithm
  • #GEO.distanceInKm(pl.touk.nussknacker.engine.util.functions.Point,pl.touk.nussknacker.engine.util.functions.Point) - calculate distance in km between two points (with decimal coordinates), using haversine algorithm
  • #GEO.toPoint(Number,Number) -> pl.touk.nussknacker.engine.util.functions.Point

NUMERIC - number parsing

  • #NUMERIC.abs(Number) - returns the absolute value of a value.
  • #NUMERIC.ceil(Double) - returns the smallest (closest to negative infinity) double value that is greater than or equal to the argument and is equal to a mathematical integer.
  • #NUMERIC.divide(Number,Number)
  • #NUMERIC.equal(Number,Number)
  • #NUMERIC.floor(Double) - returns the largest (closest to positive infinity) value that is less than or equal to the argument and is equal to a mathematical integer.
  • #NUMERIC.greater(Number,Number)
  • #NUMERIC.greaterOrEqual(Number,Number)
  • #NUMERIC.largeSum(Number,Number)
  • #NUMERIC.lesser(Number,Number)
  • #NUMERIC.lesserOrEqual(Number,Number)
  • #NUMERIC.max(Number,Number)
  • #NUMERIC.min(Number,Number)
  • #NUMERIC.minus(Number,Number)
  • #NUMERIC.multiply(Number,Number)
  • #NUMERIC.negate(Number)
  • #NUMERIC.notEqual(Number,Number)
  • #NUMERIC.plus(Number,Number)
  • #NUMERIC.pow(Double,Double) - returns the value of the first argument raised to the power of the second argument
  • #NUMERIC.remainder(Number,Number)
  • #NUMERIC.round(Double) - returns the closest long to the argument. The result is rounded to an integer by adding 1/2, taking the floor of the result, and casting the result to type long.
  • #NUMERIC.sum(Number,Number)
  • #NUMERIC.toNumber(String or Number) - parse string to number

RANDOM - random values generators

  • #RANDOM.nextBoolean - returns an uniformly distributed boolean value
  • #RANDOM.nextBooleanWithSuccessRate(Double) - returns a boolean value with a success rate determined by the given parameter. Success rate should be between 0.0 and 1.0. For 0.0 always returns false and for 1.0 always returns true
  • #RANDOM.nextDouble - returns an uniformly distributed double value between 0.0 (inclusive) and 1.0 (exclusive)
  • #RANDOM.nextDouble(Double,Double) - returns an uniformly distributed double value between fromInclusive and toExclusive
  • #RANDOM.nextDouble(Double) - returns an uniformly distributed double value between 0.0 and toExclusive
  • #RANDOM.nextInt(Integer,Integer) - returns an uniformly distributed integer value between fromInclusive and toExclusive
  • #RANDOM.nextInt(Integer) - returns an uniformly distributed integer value between 0 and toExclusive
  • #RANDOM.nextLong(Long,Long) - returns an uniformly distributed long value between fromInclusive and toExclusive
  • #RANDOM.nextLong(Long) - returns an uniformly distributed long value between 0 and toExclusive

UTIL - utilities

  • #UTIL.split(String,String) - splits given text into a List of Strings using given regular expression. Note that trailing empty strings won't be discarded; e.g. split('a|b|', '|') returns a list of three elements, the last of which is an empty string
  • #UTIL.uuid - generate unique identifier (https://en.wikipedia.org/wiki/Universally_unique_identifier)