Transforming Data
Functions and methods can be used in all expression types that support SpEL evaluation.
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")
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.
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 group | Functions |
|---|---|
BASE64 | Encoding & decoding Base64 |
COLLECTION | Operations on collections |
CONV | General conversion functions |
DATE | Date conversions and computations |
DATE_FORMAT | Date formatting/parsing operations |
GEO | Simple distance measurements |
NUMERIC | Number parsing |
RANDOM | Random value generators |
UTIL | Various 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 ifLocalTimeis in (inclusive) range<09:00, 17:00>#DATE.isBetween(#dayOfWeek, #DATE.MONDAY, #DATE.FRIDAY)- checks ifDayOfWeekis in (inclusive) range<MONDAY, FRIDAY>#DATE.isBetween(#localDate, '2020-06-01', '2020-07-01')- checks ifLocalDateis in (inclusive) range<2020-06-01, 2020-07-01>#DATE.isBetween(#localDateTime, '2020-06-01T11:00:00', '2020-07-01T11:00:00')- checks ifLocalDateTimeis in (inclusive) range<2020-06-01T11:00:00, 2020-07-01T11:00:00>#DATE.periodBetween(#from, #to).getMonths- computesPeriodbetweenfromandtoand return number of full months between those two dates#DATE.durationBetween(#from, #to).toDays- computesDurationbetweenfromandtoand return number of full days between those two dates. Keep in mind thatDurationis 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
86400seconds.
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')- parseOffsetDateTimein ISO-8601 format#DATE_FORMAT.parseOffsetDateTime('2020-01-01T11:12:13+01:00', 'yyyy-MM-dd'T'HH:mm:ssXXX')- parseOffsetDateTimein givenDateTimeFormatterformat#DATE_FORMAT.parseOffsetDateTime('2020-01-01T11:12:13+01:00', #dateTimeFormatter)- parseOffsetDateTimeusing givenDateTimeFormatter
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')- createsDateTimeFormatterusing given pattern (EEEE) and locale (PL)#DATE_FORMAT.lenientFormatter('yyyy-MM-dd')- creates lenient version ofDateTimeFormatterusing given pattern. Lenient parser may use heuristics to interpret inputs that do not precisely match format e.g. formatEwill accept:mon,MonandMONDAYinputs. On the other hand, formatter created using#DATE_FORMAT.formatter()functions accepts onlyMoninput.#DATE_FORMAT.lenientFormatter('yyyy-MM-dd EEEE', 'PL')- creates lenient versionDateTimeFormatterusing 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)