diff --git a/kie-dmn/FEELbuiltinfunctions.adoc b/kie-dmn/FEELbuiltinfunctions.adoc deleted file mode 100644 index eeb2a34e304..00000000000 --- a/kie-dmn/FEELbuiltinfunctions.adoc +++ /dev/null @@ -1,1593 +0,0 @@ -// If changing name, location, and structure of this document, align with Docs team - -= FEEL built-in functions - -To promote interoperability, FEEL includes a library of built-in functions, described below. -The built-in functions are implemented and available to be used in the Drools DMN engine; this document provides and overall description and helpful examples. -The formal specification of these functions can be referenced in the original DMN Specification document from OMG. - -== Conversion functions - -These functions support conversion between values of different types. -Some specific string formats are used, such as: - -* `date string` as specified by XML Schema Part 2 Datatypes, for example `2020-06-01` -* `time string` either -** as specified by XML Schema Part 2 Datatypes, for example `23:59:00z` -** a local time as specified by ISO 8601 followed by `@` and a IANA Timezone, for example `00:01:00@Etc/UTC` -* `date time string` a composite of a `date string` followed by `T` and a `time string`, for example `2012-12-25T11:00:00Z` -* `duration string` as a date time duration or year month duration as specified by the XQuery 1.0 and XPath 2.0 Data Model, for example `P1Y2M` - -=== date(from) - -Convert `from` to a `date`. - -.Parameters -* `from` of type `string` of `date string` format - -.Examples -[source,FEEL] ----- -date("2012-12-25") - date("2012-12-24") = duration("P1D") ----- - -// ---------------------------------------------------------------------------- - -=== date(from) - -Convert `from` to a `date`, setting time components to null. - -.Parameters -* `from` of type `date and time` - -.Examples -[source,FEEL] ----- -date(date and time("2012-12-25T11:00:00Z")) = date("2012-12-25") ----- - -// ---------------------------------------------------------------------------- - -=== date(year, month, day) - -Produce a `date` from year, month and day values. - -.Parameters -* `year` of type `number` -* `month` of type `number` -* `day` of type `number` - -.Examples -[source,FEEL] ----- -date(2012, 12, 25) = date("2012-12-25") ----- - -// ---------------------------------------------------------------------------- - -=== date and time(date, time) - -Produce a `date and time` from the given date ignoring any time components and the given time. - -.Parameters -* `date` of type `date` or `date and time` -* `time` of type `time` - -.Examples -[source,FEEL] ----- -date and time ("2012-12-24T23:59:00") = date and time(date("2012-12-24"), time("23:59:00")) ----- - -// ---------------------------------------------------------------------------- - -=== date and time(from) - -Produce a `date and time` from the given string. - -.Parameters -* `from` of type `string` of `date time string` format - -.Examples -[source,FEEL] ----- -date and time("2012-12-24T23:59:00") + duration("PT1M") = date and time("2012-12-25T00:00:00") ----- - -// ---------------------------------------------------------------------------- - -=== time(from) - -Produce a `time` from the given string. - -.Parameters -* `from` of type `string` of `time string` format - -.Examples -[source,FEEL] ----- -time("23:59:00z") + duration("PT2M") = time("00:01:00@Etc/UTC") ----- - -// ---------------------------------------------------------------------------- - -=== time(from) - -Produce a `time` from the given parameter, ignoring any date components - -.Parameters -* `from` of type `time` or `date and time` - -.Examples -[source,FEEL] ----- -time(date and time("2012-12-25T11:00:00Z")) = time("11:00:00Z") ----- - -// ---------------------------------------------------------------------------- - -=== time(hour, minute, second, offset?) - -Produce a `time` from the given hour, minute and second component values - -.Parameters -* `hour` of type `number` -* `minute` of type `number` -* `second` of type `number` -* `offset` and optional parameter of type `days and time duration` or null - -.Examples -[source,FEEL] ----- -time("23:59:00z") = time(23, 59, 0, duration("PT0H")) ----- - -// ---------------------------------------------------------------------------- - -=== number(from, grouping separator, decimal separator) - -Converts `from` into a `number` using the specified separators. - -.Parameters -* `from` of type `string` representing a valid number -* `grouping separator` one of space (` `) or comma (`,`) or period (`.`) or null -* `decimal separator` as above, but different from the group separator, or also null - -.Examples -[source,FEEL] ----- -number("1 000,0", " ", ",") = number("1,000.0", ",", ".") ----- - -// ---------------------------------------------------------------------------- - -=== string(from) - -Provide a string representation of the supplied parameter. - -.Parameters -* `from` a non-null value - -.Examples -[source,FEEL] ----- -string(1.1) = "1.1" -string(null) = null ----- - -// ---------------------------------------------------------------------------- - -=== duration(from) - -Convert `from` to a `days and time` or `years and months duration`. - -.Parameters -* `from` of type `string` of `duration string` format - -.Examples -[source,FEEL] ----- -date and time("2012-12-24T23:59:00") - date and time("2012-12-22T03:45:00") = duration("P2DT20H14M") -duration("P2Y2M") = duration("P26M") ----- - -// ---------------------------------------------------------------------------- - -=== years and months duration(from, to) - -Calculate the years and months duration between the two supplied parameters - -.Parameters -* `from` of type `date` or `date and time` -* `to` same type as above - -.Examples -[source,FEEL] ----- -years and months duration( date("2011-12-22"), date("2013-08-24") ) = duration("P1Y8M") ----- - -// ---------------------------------------------------------------------------- - -== Boolean functions - -Function for Boolean operations. - -=== not(negand) - -Perform the logical negation of the `negand` operand. - -.Parameters -* `negand` of type `boolean` - -.Examples -[source,FEEL] ----- -not(true) = false -not(null) = null ----- - -// ---------------------------------------------------------------------------- - -== String functions - -Functions for string operations. - -NOTE: in FEEL, Unicode characters are counted using their codepoints. - -=== substring(string, start position, length?) - -Returns the substring from start position for the given length; the first character is at position value `1`. - -.Parameters -* `string` of type `string` -* `start position` of type `number` -* `length` optional parameter of type `number` - -.Examples -[source,FEEL] ----- -substring("foobar",3) = "obar" -substring("foobar",3,3) = "oba" -substring("foobar", -2, 1) = "a" -substring("\U01F40Eab", 2) = "ab" ----- - -NOTE: in FEEL the string literal ``"\U01F40Eab"`` is the `🐎ab` string - -// ---------------------------------------------------------------------------- - -=== string length(string) - -Calculates the length of the string - -.Parameters -* `string` of type `string` - -.Examples -[source,FEEL] ----- -string length("foo") = 3 -string length("\U01F40Eab") = 3 ----- - -// ---------------------------------------------------------------------------- - -=== upper case(string) - -Produce an upper case version of the string - -.Parameters -* `string` of type `string` - -.Examples -[source,FEEL] ----- -upper case("aBc4") = "ABC4" ----- - -// ---------------------------------------------------------------------------- - -=== lower case(string) - -Produce an lower case version of the string - -.Parameters -* `string` of type `string` - -.Examples -[source,FEEL] ----- -lower case("aBc4") = "abc4" ----- - -// ---------------------------------------------------------------------------- - -=== substring before(string, match) - -Calculates the substring before the match - -.Parameters -* `string` of type `string` -* `match` of type `string` - -.Examples -[source,FEEL] ----- -substring before("foobar", "bar") = "foo" -substring before("foobar", "xyz") = "" ----- - -// ---------------------------------------------------------------------------- - -=== substring after(string, match) - -Calculates the substring after the match - -.Parameters -* `string` of type `string` -* `match` of type `string` - -.Examples -[source,FEEL] ----- -substring after("foobar", "ob") = "ar" -substring after("", "a") = "" ----- - -// ---------------------------------------------------------------------------- - -=== replace(input, pattern, replacement, flags?) - -Calculates the regular expression replacement - -.Parameters -* `input` of type `string` -* `pattern` of type `string` -* `replacement` of type `string` -* `flags` optional parameter of type `string` - -NOTE: uses regular expression parameters as defined in XQuery 1.0 and XPath 2.0 - -.Examples -[source,FEEL] ----- -replace("abcd", "(ab)|(a)", "[1=$1][2=$2]") = "[1=ab][2=]cd" ----- - -// ---------------------------------------------------------------------------- - -=== contains(string, match) - -Returns true if the string contains the match - -.Parameters -* `string` of type `string` -* `match` of type `string` - -.Examples -[source,FEEL] ----- -contains("foobar", "of") = false ----- - -// ---------------------------------------------------------------------------- - -=== starts with(string, match) - -Returns true if the string starts with the match - -.Parameters -* `string` of type `string` -* `match` of type `string` - -.Examples -[source,FEEL] ----- -starts with("foobar", "fo") = true ----- - -// ---------------------------------------------------------------------------- - -=== ends with(string, match) - -Returns true if the string ends with the match - -.Parameters -* `string` of type `string` -* `match` of type `string` - -.Examples -[source,FEEL] ----- -ends with("foobar", "r") = true ----- - -// ---------------------------------------------------------------------------- - -=== matches(input, pattern, flags?) - -Returns true if the input matches the regular expression - -.Parameters -* `input` of type `string` -* `pattern` of type `string` -* `flags` optional parameter of type `string` - -NOTE: uses regular expression parameters as defined in XQuery 1.0 and XPath 2.0 - -.Examples -[source,FEEL] ----- -matches("foobar", "^fo*b") = true ----- - -// ---------------------------------------------------------------------------- - -=== split(string, delimiter) - -Returns a list of the original string, splitted at the delimiter regexp pattern. - -.Parameters -* `string` of type `string` -* `delimiter` of type `string` for a regular expression pattern - -NOTE: uses regular expression parameters as defined in XQuery 1.0 and XPath 2.0 - -.Examples -[source,FEEL] ----- -split( "John Doe", "\\s" ) = ["John", "Doe"] -split( "a;b;c;;", ";" ) = ["a","b","c","",""] ----- - -// ---------------------------------------------------------------------------- - -== List functions - -Functions for list operations. - -NOTE: in FEEL, the index of the first elements in a list is `1`, the index of the last element in a list cab also be identified as `-1`. - -=== list contains(list, element) - -Returns true if the list contains the element - -.Parameters -* `list` of type `list` -* `element` of any type, including null - -.Examples -[source,FEEL] ----- -list contains([1,2,3], 2) = true ----- - -// ---------------------------------------------------------------------------- - -=== count(list) - -Counts the element in the list - -.Parameters -* `list` of type `list` - -.Examples -[source,FEEL] ----- -count([1,2,3]) = 3 -count([]) = 0 -count([1,[2,3]]) = 2 ----- - -// ---------------------------------------------------------------------------- - -=== min(list) - -Returns the minimum comparable element in the list - -.Parameters -* `list` of type `list` - -.Alternative signature ----- -min(e1, e2, ..., eN) ----- - -.Examples -[source,FEEL] ----- -min([1,2,3]) = 1 -min(1) = 1 -min([1]) = 1 ----- - -// ---------------------------------------------------------------------------- - -=== max(list) - -Returns the maximum comparable element in the list - -.Parameters -* `list` of type `list` - -.Alternative signature ----- -max(e1, e2, ..., eN) ----- - -.Examples -[source,FEEL] ----- -max(1,2,3) = 3 -max([]) = null ----- - -// ---------------------------------------------------------------------------- - -=== sum(list) - -Returns the sum of the numbers in the list - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -sum(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -sum([1,2,3]) = 6 -sum(1,2,3) = 6 -sum(1) = 1 -sum([]) = null ----- - -// ---------------------------------------------------------------------------- - -=== mean(list) - -Calculates the average (arithmetic mean) of the element in the list - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -mean(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -mean([1,2,3]) = 2 -mean(1,2,3) = 2 -mean(1) = 1 -mean([]) = null ----- - -// ---------------------------------------------------------------------------- - -=== all(list) - -Returns true if and only if all elements in the list are true - -.Parameters -* `list` of type `list` of `boolean` elements - -.Alternative signature ----- -all(b1, b2, ..., bN) ----- - -.Examples -[source,FEEL] ----- -all([false,null,true]) = false -all(true) = true -all([true]) = true -all([]) = true -all(0) = null ----- - -// ---------------------------------------------------------------------------- - -=== any(list) - -Returns true if any of the elements in the list is true - -.Parameters -* `list` of type `list` of `boolean` elements - -.Alternative signature ----- -any(b1, b2, ..., bN) ----- - -.Examples -[source,FEEL] ----- -any([false,null,true]) = true -any(false) = false -any([]) = false -any(0) = null ----- - -// ---------------------------------------------------------------------------- - -=== sublist(list, start position, length?) - -Returns the sublist from start position, limited to length elements - -.Parameters -* `list` of type `list` -* `start position` of type `number` -* `length` an optional parameter of type `number` - -.Examples -[source,FEEL] ----- -sublist([4,5,6], 1, 2) = [4,5] ----- - -// ---------------------------------------------------------------------------- - -=== append(list, item...) - -Creates a list appended with the item(s) - -.Parameters -* `list` of type `list` -* `item` parameters of any type - -.Examples -[source,FEEL] ----- -append([1], 2, 3) = [1,2,3] ----- - -// ---------------------------------------------------------------------------- - -=== concatenate(list...) - -Creates a list which is the result of the concatenated lists - -.Parameters -* `list` parameters of type `list` - -.Examples -[source,FEEL] ----- -concatenate([1,2],[3]) = [1,2,3] ----- - -// ---------------------------------------------------------------------------- - -=== insert before(list, position, newItem) - -Creates a list with the newItem inserted at the specified position - -.Parameters -* `list` of type `list` -* `position` of type `number` -* `newItem` of any type - -.Examples -[source,FEEL] ----- -insert before([1,3],1,2) = [2,1,3] ----- - -// ---------------------------------------------------------------------------- - -=== remove(list, position) - -Creates a list which the removed element from the specified position - -.Parameters -* `list` of type `list` -* `position` of type `number` - -.Examples -[source,FEEL] ----- -remove([1,2,3], 2) = [1,3] ----- - -// ---------------------------------------------------------------------------- - -=== reverse(list) - -Returns a reversed list - -.Parameters -* `list` of type `list` - -.Examples -[source,FEEL] ----- -reverse([1,2,3]) = [3,2,1] ----- - -// ---------------------------------------------------------------------------- - -=== index of(list, match) - -Returns indexes matching the element - -.Parameters -* `list` of type `list` -* `match` of any type - -.Examples -[source,FEEL] ----- -index of([1,2,3,2],2) = [2,4] ----- - -// ---------------------------------------------------------------------------- - -=== union(list...) - -Returns a list of all the elements from the lists without duplicates - -.Parameters -* `list` parameters of type `list` - -.Examples -[source,FEEL] ----- -union([1,2],[2,3]) = [1,2,3] ----- - -// ---------------------------------------------------------------------------- - -=== distinct values(list) - -Returns a list without duplicates - -.Parameters -* `list` of type `list` - -.Examples -[source,FEEL] ----- -distinct values([1,2,3,2,1]) = [1,2,3] ----- - -// ---------------------------------------------------------------------------- - -=== flatten(list) - -Returns a flattened list - -.Parameters -* `list` of type `list` - -.Examples -[source,FEEL] ----- -flatten([[1,2],[[3]], 4]) = [1,2,3,4] ----- - -// ---------------------------------------------------------------------------- - -=== product(list) - -Returns the product of the numbers in the list - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -product(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -product([2, 3, 4]) = 24 -product(2, 3, 4) = 24 ----- - -// ---------------------------------------------------------------------------- - -=== median( list ) - -Returns the median of the numbers in the list. -After sorting the elements, in the case of an odd number of elements, the result is the middle element; -in the case of even number of elements, the result is the average of the two middle elements. - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -median(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -median( 8, 2, 5, 3, 4 ) = 4 -median( [6, 1, 2, 3] ) = 2.5 -median( [ ] ) = null ----- - -// ---------------------------------------------------------------------------- - -=== stddev( list ) - -Returns the sample standard deviation of the numbers in the list. - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -stddev(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -stddev( 2, 4, 7, 5 ) = 2.081665999466132735282297706979931 -stddev( [ 47 ] ) = null -stddev( 47 ) = null -stddev( [ ] ) = null ----- - -// ---------------------------------------------------------------------------- - -=== mode( list ) - -Returns the mode of the numbers in the list; in case of multiple elements, these are returned in their ascending order. - -.Parameters -* `list` of type `list` of `number` elements - -.Alternative signature ----- -mode(n1, n2, ..., nN) ----- - -.Examples -[source,FEEL] ----- -mode( 6, 3, 9, 6, 6 ) = [ 6 ] -mode( [6, 1, 9, 6, 1] ) = [ 1, 6 ] -mode( [ ] ) = [ ] ----- - -// ---------------------------------------------------------------------------- - -== Numeric functions - -Functions for number operations. - -=== decimal(n, scale) - -Returns number with the given scale - -.Parameters -* `n` of type `number` -* `scale` of any `number` in the range ` [−6111..6176]` - -.Examples -[source,FEEL] ----- -decimal(1/3, 2) = .33 -decimal(1.5, 0) = 2 -decimal(2.5, 0) = 2 ----- - -// ---------------------------------------------------------------------------- - -=== floor(n) - -Returns the greatest integer less or equal to the number - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -floor(1.5) = 1 -floor(-1.5) = -2 ----- - -// ---------------------------------------------------------------------------- - -=== ceiling(n) - -Returns the smallest integer greater or equal to the number - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -ceiling(1.5) = 2 -ceiling(-1.5) = -1 ----- - -// ---------------------------------------------------------------------------- - -=== abs(n) - -Returns the absolute value - -.Parameters -* `n` of type `number`, `days and time duration` or `year and month duration` - -.Examples -[source,FEEL] ----- -abs( 10 ) = 10 -abs( -10 ) = 10 -abs(@"PT5H") = @"PT5H" -abs(@"-PT5H") = @"PT5H" ----- - -// ---------------------------------------------------------------------------- - -=== modulo( dividend, divisor ) - -Returns the remainder of the division of the dividend by divisor. -In the case either dividend or divisor is negative, the result will be of the same sign as the divisor. - -NOTE: this can be equivalently be exprssed as: `modulo(dividend, divisor) = dividend - divisor*floor(dividen d/divisor)`. - -.Parameters -* `dividend` of type `number` -* `divisor` of type `number` - -.Examples -[source,FEEL] ----- -modulo( 12, 5 ) = 2 -modulo(-12,5)= 3 -modulo(12,-5)= -3 -modulo(-12,-5)= -2 -modulo(10.1, 4.5)= 1.1 -modulo(-10.1, 4.5)= 3.4 -modulo(10.1, -4.5)= -3.4 -modulo(-10.1, -4.5)= -1.1 ----- - -// ---------------------------------------------------------------------------- - -=== sqrt( number ) - -Returns the square root of the number - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -sqrt( 16 ) = 4 ----- - -// ---------------------------------------------------------------------------- - -=== log( number ) - -Returns the natural logarithm of the number - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -decimal( log( 10 ), 2 ) = 2.30 ----- - -// ---------------------------------------------------------------------------- - -=== exp( number ) - -Returns the Euler’s number e raised to the power of the number - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -decimal( exp( 5 ), 2 ) = 148.41 ----- - -// ---------------------------------------------------------------------------- - -=== odd( number ) - -Returns true if the number is odd - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -odd( 5 ) = true -odd( 2 ) = false ----- - -// ---------------------------------------------------------------------------- - -=== odd( number ) - -Returns true if the number is even - -.Parameters -* `n` of type `number` - -.Examples -[source,FEEL] ----- -even( 5 ) = false -even ( 2 ) = true ----- - -// ---------------------------------------------------------------------------- - -== Date and time functions - -Functions for date and time specific operations. - -=== is(value1, value2) - -Returns true if both values are the same element in the FEEL semantic domain - -.Parameters -* `value1` of any type -* `value2` of any type - -.Examples -[source,FEEL] ----- -is(date("2012-12-25"), time("23:00:50")) = false -is(date("2012-12-25"), date("2012-12-25")) = true -is(time("23:00:50z"), time("23:00:50")) = false ----- - -// ---------------------------------------------------------------------------- - -== Range functions - -Temporal ordering functions to establish relationships between single scalar values and ranges of such values. -These functions are heavily inspired by their equivalent in the HL7 CQL (Clinical Quality Language) standard version 1.4. - -=== before() - -A before B - -.Signatures -a. before(point1 point2) -b. before(point range) -c. before(range point) -d. before(range1,range2) - -.Evaluates to true if and only if -a. `point1 < point2` -b. `point < range.start or (point = range.start and not(range.start included) )` -c. `range.end < point or (range.end = point and not(range.end included) )` -d. `range1.end < range2.start or (( not(range1.end included) or not(range2.start included)) and range1.end = range2.start)` - -.Examples -[source,FEEL] ----- -before( 1, 10 ) = true -before( 10, 1 ) = false -before( 1, [1..10] ) = false -before( 1, (1..10] ) = true -before( 1, [5..10] ) = true -before( [1..10], 10 ) = false -before( [1..10), 10 ) = true -before( [1..10], 15 ) = true -before( [1..10], [15..20] ) = true -before( [1..10], [10..20] ) = false -before( [1..10), [10..20] ) = true -before( [1..10], (10..20] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== after() - -A after B - -.Signatures -a. after(point1 point2) -b. after(point range) -c. after(range, point) -d. after(range1 range2) - -.Evaluates to true if and only if -a. `point1 > point2` -b. `point > range.end or (point = range.end and not(range.end included) )` -c. `range.start > point or (range.start = point and not(range.start included) )` -d. `range1.start > range2.end or (( not(range1.start included) or not(range2.end included) ) and range1.start = range2.end)` - -.Examples -[source,FEEL] ----- -after( 10, 5 ) = true -after( 5, 10 ) = false -after( 12, [1..10] ) = true -after( 10, [1..10) ) = true -after( 10, [1..10] ) = false -after( [11..20], 12 ) = false -after( [11..20], 10 ) = true -after( (11..20], 11 ) = true -after( [11..20], 11 ) = false -after( [11..20], [1..10] ) = true -after( [1..10], [11..20] ) = false -after( [11..20], [1..11) ) = true -after( (11..20], [1..11] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== meets() - -A meets B - -.Signatures -a. meets(range1, range2) - -.Evaluates to true if and only if -a. `range1.end included and range2.start included and range1.end = range2.start` - -.Examples -[source,FEEL] ----- -meets( [1..5], [5..10] ) = true -meets( [1..5), [5..10] ) = false -meets( [1..5], (5..10] ) = false -meets( [1..5], [6..10] ) = false ----- - -// ---------------------------------------------------------------------------- - -=== met by() - -A met by B - -.Signatures -a. met by(range1, range2) - -.Evaluates to true if and only if -a. `range1.start included and range2.end included and range1.start = range2.end` - -.Examples -[source,FEEL] ----- -met by( [5..10], [1..5] ) = true -met by( [5..10], [1..5) ) = false -met by( (5..10], [1..5] ) = false -met by( [6..10], [1..5] ) = false ----- - -// ---------------------------------------------------------------------------- - -=== overlaps() - -A overlaps B - -.Signatures -a. overlaps(range1, range2) - -.Evaluates to true if and only if -a. `(range1.end > range2.start or (range1.end = range2.start and (range1.end included or range2.end included))) and (range1.start < range2.end or (range1.start = range2.end and range1.start included and range2.end included))` - -.Examples -[source,FEEL] ----- -overlaps( [1..5], [3..8] ) = true -overlaps( [3..8], [1..5] ) = true -overlaps( [1..8], [3..5] ) = true -overlaps( [3..5], [1..8] ) = true -overlaps( [1..5], [6..8] ) = false -overlaps( [6..8], [1..5] ) = false -overlaps( [1..5], [5..8] ) = true -overlaps( [1..5], (5..8] ) = false -overlaps( [1..5), [5..8] ) = false -overlaps( [1..5), (5..8] ) = false -overlaps( [5..8], [1..5] ) = true -overlaps( (5..8], [1..5] ) = false -overlaps( [5..8], [1..5) ) = false -overlaps( (5..8], [1..5) ) = false ----- - -// ---------------------------------------------------------------------------- - -=== overlaps before() - -A overlaps before B - -.Signatures -a. overlaps before(range1 range2) - -.Evaluates to true if and only if -a. `(range1.start < range2.start or (range1.start = range2.start and range1.start included and range2.start included)) and (range1.end > range2.start or (range1.end = range2.start and range1.end included and range2.start included)) and (range1.end < range2.end or (range1.end = range2.end and (not(range1.end included) or range2.end included )))` - -.Examples -[source,FEEL] ----- -overlaps before( [1..5], [3..8] ) = true -overlaps before( [1..5], [6..8] ) = false -overlaps before( [1..5], [5..8] ) = true -overlaps before( [1..5], (5..8] ) = false -overlaps before( [1..5), [5..8] ) = false -overlaps before( [1..5), (1..5] ) = true -overlaps before( [1..5], (1..5] ) = true -overlaps before( [1..5), [1..5] ) = false -overlaps before( [1..5], [1..5] ) = false ----- - -// ---------------------------------------------------------------------------- - -=== overlaps after() - -A overlaps after B - -.Signatures -a. overlaps after(range1 range2) - -.Evaluates to true if and only if -a. `(range2.start < range1.start or (range2.start = range1.start and range2.start included and not( range1.start included))) and (range2.end > range1.start or (range2.end = range1.start and range2.end included and range1.start included )) and (range2.end < range1.end or (range2.end = range1.end and (not(range2.end included) or range1.end included)))` - -.Examples -[source,FEEL] ----- -overlaps after( [3..8], [1..5] )= true -overlaps after( [6..8], [1..5] )= false -overlaps after( [5..8], [1..5] )= true -overlaps after( (5..8], [1..5] )= false -overlaps after( [5..8], [1..5) )= false -overlaps after( (1..5], [1..5) )= true -overlaps after( (1..5], [1..5] )= true -overlaps after( [1..5], [1..5) )= false -overlaps after( [1..5], [1..5] )= false -overlaps after( (1..5), [1..5] )= false -overlaps after( (1..5], [1..6] )= false -overlaps after( (1..5], (1..5] )= false -overlaps after( (1..5], [2..5] )= false ----- - -// ---------------------------------------------------------------------------- - -=== finishes() - -A finishes B - -.Signatures -a. finishes(point, range) -b. finishes(range1, range2) - -.Evaluates to true if and only if -a. `range.end included and range.end = point` -b. `range1.end included = range2.end included and range1.end = range2.end and (range1.start > range2.start or (range1.start = range2.start and (not(range1.start included) or range2.start included)))` - -.Examples -[source,FEEL] ----- -finishes( 10, [1..10] ) = true -finishes( 10, [1..10) ) = false -finishes( [5..10], [1..10] ) = true -finishes( [5..10), [1..10] ) = false -finishes( [5..10), [1..10) ) = true -finishes( [1..10], [1..10] ) = true -finishes( (1..10], [1..10] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== finished by() - -A finished by B - -.Signatures -a. finished by(range, point) -b. finished by(range1 range2) - -.Evaluates to true if and only if -a. `range.end included and range.end = point` -b. `range1.end included = range2.end included and range1.end = range2.end and (range1.start < range2.start or (range1.start = range2.start and (range1.start included or not(range2.start included))))` - -.Examples -[source,FEEL] ----- -finished by( [1..10], 10 ) = true -finished by( [1..10), 10 ) = false -finished by( [1..10], [5..10] ) = true -finished by( [1..10], [5..10) ) = false -finished by( [1..10), [5..10) ) = true -finished by( [1..10], [1..10] ) = true -finished by( [1..10], (1..10] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== includes() - -A includes B - -.Signatures -a. includes(range, point) -b. includes(range1, range2) - -.Evaluates to true if and only if -a. `(range.start < point and range.end > point) or (range.start = point and range.start included) or (range.end = point and range.end included)` -b. `(range1.start < range2.start or (range1.start = range2.start and (range1.start included or not(range2.start included)))) and (range1.end > range2.end or (range1.end = range2.end and (range1.end included or not(range2.end included))))` - -.Examples -[source,FEEL] ----- -includes( [1..10], 5 ) = true -includes( [1..10], 12 ) = false -includes( [1..10], 1 ) = true -includes( [1..10], 10 ) = true -includes( (1..10], 1 ) = false -includes( [1..10), 10 ) = false -includes( [1..10], [4..6] ) = true -includes( [1..10], [1..5] ) = true -includes( (1..10], (1..5] ) = true -includes( [1..10], (1..10) ) = true -includes( [1..10), [5..10) ) = true -includes( [1..10], [1..10) ) = true -includes( [1..10], (1..10] ) = true -includes( [1..10], [1..10] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== during() - -A during B - -.Signatures -a. during(point, range) -b. during(range1 range2) - -.Evaluates to true if and only if -a. `(range.start < point and range.end > point) or (range.start = point and range.start included) or (range.end = point and range.end included)` -b. `(range2.start < range1.start or (range2.start = range1.start and (range2.start included or not(range1.start included)))) and (range2.end > range1.end or (range2.end = range1.end and (range2.end included or not(range1.end included))))` - -.Examples -[source,FEEL] ----- -during( 5, [1..10] ) = true -during( 12, [1..10] ) = false -during( 1, [1..10] ) = true -during( 10, [1..10] ) = true -during( 1, (1..10] ) = false -during( 10, [1..10) ) = false -during( [4..6], [1..10] ) = true -during( [1..5], [1..10] ) = true -during( (1..5], (1..10] ) = true -during( (1..10), [1..10] ) = true -during( [5..10), [1..10) ) = true -during( [1..10), [1..10] ) = true -during( (1..10], [1..10] ) = true -during( [1..10], [1..10] ) = true ----- - -// ---------------------------------------------------------------------------- - -=== starts() - -A starts B - -.Signatures -a. starts(point, range) -b. starts(range1, range2) - -.Evaluates to true if and only if -a. `range.start = point and range.start included` -b. `range1.start = range2.start and range1.start included = range2.start included and (range1.end < range2.end or (range1.end = range2.end and (not(range1.end included) or range2.end included)))` - -.Examples -[source,FEEL] ----- -starts( 1, [1..10] ) = true -starts( 1, (1..10] ) = false -starts( 2, [1..10] ) = false -starts( [1..5], [1..10] ) = true -starts( (1..5], (1..10] ) = true -starts( (1..5], [1..10] ) = false -starts( [1..5], (1..10] ) = false -starts( [1..10], [1..10] ) = true -starts( [1..10), [1..10] ) = true -starts( (1..10), (1..10) ) = true ----- - -// ---------------------------------------------------------------------------- - -=== started by() - -A started by B - -.Signatures -a. started by(range, point) -b. started by(range1, range2) - -.Evaluates to true if and only if -a. `range.start = point and range.start included` -b. `range1.start = range2.start and range1.start included = range2.start included and (range2.end < range1.end or (range2.end = range1.end and (not(range2.end included) or range1.end included)))` - -.Examples -[source,FEEL] ----- -started by( [1..10], 1 ) = true -started by( (1..10], 1 ) = false -started by( [1..10], 2 ) = false -started by( [1..10], [1..5] ) = true -started by( (1..10], (1..5] ) = true -started by( [1..10], (1..5] ) = false -started by( (1..10], [1..5] ) = false -started by( [1..10], [1..10] ) = true -started by( [1..10], [1..10) ) = true -started by( (1..10), (1..10) ) = true ----- - -// ---------------------------------------------------------------------------- - -=== coincides() - -A coincides B - -.Signatures -a. coincides(point1, point2) -b. coincides(range1, range2) - -.Evaluates to true if and only if -a. `point1 = point2` -b. `range1.start = range2.start and range1.start included = range2.start included and range1.end = range2.end and range1.end included = range2.end included` - -.Examples -[source,FEEL] ----- -coincides( 5, 5 ) = true -coincides( 3, 4 ) = false -coincides( [1..5], [1..5] ) = true -coincides( (1..5), [1..5] ) = false -coincides( [1..5], [2..6] ) = false ----- - -// ---------------------------------------------------------------------------- - -== Temporal functions - -Functions for general temporal operations. - -=== day of year( date ) - -Returns the Gregorian number of the day of the year - -.Parameters -* `date` of type `date` or `date and time` - -.Examples -[source,FEEL] ----- -day of year( date(2019, 9, 17) ) = 260 ----- - -// ---------------------------------------------------------------------------- - -=== day of year( date ) - -Returns the Gregorian day of the week, either of “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”, “Sunday” - -.Parameters -* `date` of type `date` or `date and time` - -.Examples -[source,FEEL] ----- -day of week( date(2019, 9, 17) ) = "Tuesday" ----- - -// ---------------------------------------------------------------------------- - -=== month of year( date ) - -Returns the Gregorian month, either of “January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December” - -.Parameters -* `date` of type `date` or `date and time` - -.Examples -[source,FEEL] ----- -month of year( date(2019, 9, 17) ) = "September" ----- - -// ---------------------------------------------------------------------------- - -=== month of year( date ) - -Returns the Gregorian week of the year accordingly to ISO 8601 - -.Parameters -* `date` of type `date` or `date and time` - -.Examples -[source,FEEL] ----- -week of year( date(2019, 9, 17) ) = 38 -week of year( date(2003, 12, 29) ) = 1 -week of year( date(2004, 1, 4) ) = 1 -week of year( date(2005, 1, 1) ) = 53 -week of year( date(2005, 1, 3) ) = 1 -week of year( date(2005, 1, 9) ) = 1 ----- - -// ---------------------------------------------------------------------------- - -== Sort function - -Function for sorting operations. - -=== sort(list, precedes) - -Returns a list of the same elements but ordered accordingly to the sorting function - -.Parameters -* `list` of type `list` -* `precedes` of type `function` - -.Examples -[source,FEEL] ----- -sort(list: [3,1,4,5,2], precedes: function(x,y) x < y) = [1,2,3,4,5] ----- - -// ---------------------------------------------------------------------------- - -== Context functions - -Function for context operations. - -=== get value(m, key) - -Returns the value from the context, for the specified entry key - -.Parameters -* `m` of type `context` -* `key` of type `string` - -.Examples -[source,FEEL] ----- -get value({key1 : "value1"}, "key1") = "value1" -get value({key1 : "value1"}, "unexistent-key") = null ----- - -// ---------------------------------------------------------------------------- - -=== get entries(m) - -Computes a list of key and value pair for the given context - -.Parameters -* `m` of type `context` - -.Examples -[source,FEEL] ----- -get entries({key1 : "value1", key2 : "value2"}) = [ { key : "key1", value : "value1" }, {key : "key2", value : "value2"} ] ----- - -// ---------------------------------------------------------------------------- \ No newline at end of file diff --git a/kie-dmn/kie-dmn-feel/pom.xml b/kie-dmn/kie-dmn-feel/pom.xml index 188edf4efb0..b2690d1b531 100644 --- a/kie-dmn/kie-dmn-feel/pom.xml +++ b/kie-dmn/kie-dmn-feel/pom.xml @@ -116,7 +116,7 @@ asciidoctorj test - + @@ -127,7 +127,7 @@ ${project.basedir}/../ - FEELbuiltinfunctions.adoc + ref-dmn-feel-builtin-functions.adoc false diff --git a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/documentation/ADocFEELExamplesTest.java b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/documentation/ADocFEELExamplesTest.java index 3406db087ee..594bd2493d3 100644 --- a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/documentation/ADocFEELExamplesTest.java +++ b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/documentation/ADocFEELExamplesTest.java @@ -26,9 +26,10 @@ import org.asciidoctor.Asciidoctor; import org.asciidoctor.OptionsBuilder; import org.asciidoctor.ast.Block; -import org.asciidoctor.ast.ContentNode; +import org.asciidoctor.ast.DescriptionList; +import org.asciidoctor.ast.DescriptionListEntry; import org.asciidoctor.ast.Document; -import org.asciidoctor.ast.Section; +import org.asciidoctor.ast.ListItem; import org.asciidoctor.ast.StructuralNode; import org.hamcrest.Matchers; import org.junit.Assert; @@ -56,7 +57,7 @@ public class ADocFEELExamplesTest { @Test public void test() throws URISyntaxException { Asciidoctor asciidoctor = Asciidoctor.Factory.create(); - URL resource = this.getClass().getResource("/FEELbuiltinfunctions.adoc"); + URL resource = this.getClass().getResource("/ref-dmn-feel-builtin-functions.adoc"); URI uri = resource.toURI(); LOG.debug("{}", uri); File src = new File(uri); @@ -70,23 +71,22 @@ private void processBlock(StructuralNode block) { for (int i = 0; i < blocks.size(); i++) { final StructuralNode currentBlock = blocks.get(i); if (currentBlock instanceof StructuralNode) { - if ("listing".equals(currentBlock.getContext())) { + if (currentBlock instanceof DescriptionList) { + DescriptionList descriptionList = (DescriptionList) currentBlock; + for (DescriptionListEntry dle : descriptionList.getItems()) { + ListItem description = dle.getDescription(); + processBlock(description); + } + } else if ("listing".equals(currentBlock.getContext())) { Block b = (Block) currentBlock; List lines = b.getLines(); LOG.trace("{}", lines); LOG.trace("{}", b.getAttributes()); - ContentNode parent = b.getParent(); - String sectionTitle = ""; - if (parent instanceof Section) { - Section section = (Section) parent; - sectionTitle = section.getTitle(); - } if (b.getAttribute("language", "unknown").equals("FEEL")) { - for (String l : lines) { - String titled = sectionTitle + ": " + l; - LOG.info("checking DOC {}", titled); - Object FEELResult = feel.evaluate(l); - Assert.assertThat(titled, FEELResult, Matchers.is(true)); + for (String line : lines) { + LOG.info("checking DOC {}", line); + Object FEELResult = feel.evaluate(line); + Assert.assertThat(line, FEELResult, Matchers.is(true)); } } else { LOG.trace("This block is not FEEL true predicate snippets: {}", b); diff --git a/kie-dmn/ref-dmn-feel-builtin-functions.adoc b/kie-dmn/ref-dmn-feel-builtin-functions.adoc new file mode 100644 index 00000000000..e73b0b6c375 --- /dev/null +++ b/kie-dmn/ref-dmn-feel-builtin-functions.adoc @@ -0,0 +1,2232 @@ +// If changing name, location, and structure of this document, align with Docs team + +[id='ref-dmn-feel-builtin-functions_{context}'] += Built-in functions in FEEL + +To promote interoperability with other platforms and systems, Friendly Enough Expression Language (FEEL) includes a library of built-in functions. The built-in FEEL functions are implemented in the Drools Decision Model and Notation (DMN) engine so that you can use the functions in your DMN decision services. + +The following sections describe each built-in FEEL function, listed in the format `__NAME__( __PARAMETERS__ )`. For more information about FEEL functions in DMN, see the OMG https://www.omg.org/spec/DMN[Decision Model and Notation specification]. + +== Conversion functions + +The following functions support conversion between values of different types. Some of these functions use specific string formats, such as the following examples: + +* `date string`: Follows the format defined in the https://www.w3.org/TR/xmlschema-2/#date[XML Schema Part 2: Datatypes] document, such as `2020-06-01` +* `time string`: Follows one of the following formats: +** Format defined in the https://www.w3.org/TR/xmlschema-2/#time[XML Schema Part 2: Datatypes] document, such as `23:59:00z` +** Format for a local time defined by ISO 8601 followed by `@` and an IANA Timezone, such as `00:01:00@Etc/UTC` +* `date time string`: Follows the format of a `date string` followed by `T` and a `time string`, such as `2012-12-25T11:00:00Z` +* `duration string`: Follows the format of `days and time duration` and `years and months duration` defined in the https://www.w3.org/TR/xpath-datamodel/#types[XQuery 1.0 and XPath 2.0 Data Model], such as `P1Y2M` + +// Empty break here to enable correct formatting of the first label that follows the bullets. (Stetson, 26 Aug 2020) + +date( from ) - _using date_:: ++ +-- +Converts `from` to a `date` value. + +.Parameters +[cols="30%,30%,40%", options="header"] +|=== +|Parameter +|Type +|Format + +|`from` +|`string` +|`date string` +|=== + +.Example +[source,FEEL] +---- +date( "2012-12-25" ) - date( "2012-12-24" ) = duration( "P1D" ) +---- +-- + +// ---------------------------------------------------------------------------- + +date( from ) - _using date and time_:: ++ +-- +Converts `from` to a `date` value and sets time components to null. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`from` +|`date and time` +|=== + +.Example +[source,FEEL] +---- +date(date and time( "2012-12-25T11:00:00Z" )) = date( "2012-12-25" ) +---- +-- + +// ---------------------------------------------------------------------------- + +date( year, month, day ):: ++ +-- +Produces a `date` from the specified year, month, and day values. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`year` +|`number` + +|`month` +|`number` + +|`day` +|`number` +|=== + +.Example +[source,FEEL] +---- +date( 2012, 12, 25 ) = date( "2012-12-25" ) +---- +-- + +// ---------------------------------------------------------------------------- + + +date and time( date, time ):: ++ +-- +Produces a `date and time` from the specified date and ignores any time components and the specified time. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`date` +|`date` or `date and time` + +|`time` +|`time` +|=== + +.Example +[source,FEEL] +---- +date and time ( "2012-12-24T23:59:00" ) = date and time(date( "2012-12-24" ), time( "23:59:00" )) +---- +-- + +// ---------------------------------------------------------------------------- + +date and time( from ):: ++ +-- +Produces a `date and time` from the specified string. + +.Parameters +[cols="30%,30%,40%", options="header"] +|=== +|Parameter +|Type +|Format + +|`from` +|`string` +|`date time string` +|=== + +.Example +[source,FEEL] +---- +date and time( "2012-12-24T23:59:00" ) + duration( "PT1M" ) = date and time( "2012-12-25T00:00:00" ) +---- +-- + +// ---------------------------------------------------------------------------- + +time( from ):: ++ +-- +Produces a `time` from the specified string. + +.Parameters +[cols="30%,30%,40%", options="header"] +|=== +|Parameter +|Type +|Format + +|`from` +|`string` +|`time string` +|=== + +.Example +[source,FEEL] +---- +time( "23:59:00z" ) + duration( "PT2M" ) = time( "00:01:00@Etc/UTC" ) +---- +-- + +// ---------------------------------------------------------------------------- + +time( from ):: ++ +-- +Produces a `time` from the specified parameter and ignores any date components. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`from` +|`time` or `date and time` +|=== + +.Example +[source,FEEL] +---- +time(date and time( "2012-12-25T11:00:00Z" )) = time( "11:00:00Z" ) +---- +-- + +// ---------------------------------------------------------------------------- + +time( hour, minute, second, offset? ):: ++ +-- +Produces a `time` from the specified hour, minute, and second component values. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`hour` +|`number` + +|`minute` +|`number` + +|`second` +|`number` + +|`offset` (Optional) +|`days and time duration` or null +|=== + +.Example +[source,FEEL] +---- +time( "23:59:00z" ) = time(23, 59, 0, duration( "PT0H" )) +---- +-- + +// ---------------------------------------------------------------------------- + +number( from, grouping separator, decimal separator ):: ++ +-- +Converts `from` to a `number` using the specified separators. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`from` +|`string` representing a valid number + +|`grouping separator` +|Space ( ), comma (`,`), period (`.`), or null + +|`decimal separator` +|Same types as `grouping separator`, but the values cannot match +|=== + +.Example +[source,FEEL] +---- +number( "1 000,0", " ", "," ) = number( "1,000.0", ",", "." ) +---- +-- + +// ---------------------------------------------------------------------------- + +string( from ):: ++ +-- +Provides a string representation of the specified parameter. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`from` +|Non-null value +|=== + +.Examples +[source,FEEL] +---- +string( 1.1 ) = "1.1" +string( null ) = null +---- +-- + +// ---------------------------------------------------------------------------- + +duration( from ):: ++ +-- +Converts `from` to a `days and time duration` value or `years and months duration` value. + +.Parameters +[cols="30%,30%,40%", options="header"] +|=== +|Parameter +|Type +|Format + +|`from` +|`string` +|`duration string` +|=== + +.Examples +[source,FEEL] +---- +date and time( "2012-12-24T23:59:00" ) - date and time( "2012-12-22T03:45:00" ) = duration( "P2DT20H14M" ) +duration( "P2Y2M" ) = duration( "P26M" ) +---- +-- + +// ---------------------------------------------------------------------------- + +years and months duration( from, to ):: ++ +-- +Calculates the `years and months duration` between the two specified parameters. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`from` +|`date` or `date and time` + +|`to` +|`date` or `date and time` +|=== + +.Example +[source,FEEL] +---- +years and months duration( date( "2011-12-22" ), date( "2013-08-24" ) ) = duration( "P1Y8M" ) +---- +-- + +// ---------------------------------------------------------------------------- + +== Boolean functions + +The following functions support Boolean operations. + +not( negand ):: ++ +-- +Performs the logical negation of the `negand` operand. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`negand` +|`boolean` +|=== + +.Examples +[source,FEEL] +---- +not( true ) = false +not( null ) = null +---- +-- + +// ---------------------------------------------------------------------------- + +== String functions + +The following functions support string operations. + +NOTE: In FEEL, Unicode characters are counted based on their code points. + +substring( string, start position, length? ):: ++ +-- +Returns the substring from the start position for the specified length. The first character is at position value `1`. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`start position` +|`number` + +|`length` (Optional) +|`number` +|=== + +.Examples +[source,FEEL] +---- +substring( "testing",3 ) = "sting" +substring( "testing",3,3 ) = "sti" +substring( "testing", -2, 1 ) = "n" +substring( "\U01F40Eab", 2 ) = "ab" +---- + +NOTE: In FEEL, the string literal `"\U01F40Eab"` is the `🐎ab` string (horse symbol followed by `a` and `b`). + +-- + +// ---------------------------------------------------------------------------- + +string length( string ):: ++ +-- +Calculates the length of the specified string. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` +|=== + +.Examples +[source,FEEL] +---- +string length( "tes" ) = 3 +string length( "\U01F40Eab" ) = 3 +---- +-- + +// ---------------------------------------------------------------------------- + +upper case( string ):: ++ +-- +Produces an uppercase version of the specified string. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` +|=== + +.Example +[source,FEEL] +---- +upper case( "aBc4" ) = "ABC4" +---- +-- + +// ---------------------------------------------------------------------------- + +lower case( string ):: ++ +-- +Produces a lowercase version of the specified string. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` +|=== + +.Example +[source,FEEL] +---- +lower case( "aBc4" ) = "abc4" +---- +-- + +// ---------------------------------------------------------------------------- + +substring before( string, match ):: ++ +-- +Calculates the substring before the match. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`match` +|`string` +|=== + +.Examples +[source,FEEL] +---- +substring before( "testing", "ing" ) = "test" +substring before( "testing", "xyz" ) = "" +---- +-- + +// ---------------------------------------------------------------------------- + +substring after( string, match ):: ++ +-- +Calculates the substring after the match. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`match` +|`string` +|=== + +.Examples +[source,FEEL] +---- +substring after( "testing", "test" ) = "ing" +substring after( "", "a" ) = "" +---- +-- + +// ---------------------------------------------------------------------------- + +replace( input, pattern, replacement, flags? ):: ++ +-- +Calculates the regular expression replacement. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`input` +|`string` + +|`pattern` +|`string` + +|`replacement` +|`string` + +|`flags` (Optional) +|`string` +|=== + +NOTE: This function uses regular expression parameters as defined in https://www.w3.org/TR/xquery-operators/#regex-syntax[XQuery 1.0 and XPath 2.0 Functions and Operators]. + +.Example +[source,FEEL] +---- +replace( "abcd", "(ab)|(a)", "[1=$1][2=$2]" ) = "[1=ab][2=]cd" +---- +-- + +// ---------------------------------------------------------------------------- + +contains( string, match ):: ++ +-- +Returns `true` if the string contains the match. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`match` +|`string` +|=== + +.Example +[source,FEEL] +---- +contains( "testing", "to" ) = false +---- +-- + +// ---------------------------------------------------------------------------- + +starts with( string, match ):: ++ +-- +Returns `true` if the string starts with the match + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`match` +|`string` +|=== + +.Example +[source,FEEL] +---- +starts with( "testing", "te" ) = true +---- +-- + +// ---------------------------------------------------------------------------- + +ends with( string, match ):: ++ +-- +Returns `true` if the string ends with the match. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`match` +|`string` +|=== + +.Example +[source,FEEL] +---- +ends with( "testing", "g" ) = true +---- +-- +// ---------------------------------------------------------------------------- + +matches( input, pattern, flags? ):: ++ +-- +Returns `true` if the input matches the regular expression. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`input` +|`string` + +|`pattern` +|`string` + +|`flags` (Optional) +|`string` +|=== + +NOTE: This function uses regular expression parameters as defined in https://www.w3.org/TR/xquery-operators/#regex-syntax[XQuery 1.0 and XPath 2.0 Functions and Operators]. + +.Example +[source,FEEL] +---- +matches( "teeesting", "^te*sting" ) = true +---- +-- +// ---------------------------------------------------------------------------- + +split( string, delimiter ):: ++ +-- +Returns a list of the original string and splits it at the delimiter regular expression pattern. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`string` +|`string` + +|`delimiter` +|`string` for a regular expression pattern +|=== + +NOTE: This function uses regular expression parameters as defined in https://www.w3.org/TR/xquery-operators/#regex-syntax[XQuery 1.0 and XPath 2.0 Functions and Operators]. + +.Examples +[source,FEEL] +---- +split( "John Doe", "\\s" ) = ["John", "Doe"] +split( "a;b;c;;", ";" ) = ["a","b","c","",""] +---- +-- +// ---------------------------------------------------------------------------- + +== List functions + +The following functions support list operations. + +NOTE: In FEEL, the index of the first element in a list is `1`. The index of the last element in a list can be identified as `-1`. + +list contains( list, element ):: ++ +-- +Returns `true` if the list contains the element. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`element` +|Any type, including null +|=== + +.Example +[source,FEEL] +---- +list contains( [1,2,3], 2 ) = true +---- +-- +// ---------------------------------------------------------------------------- + +count( list ):: ++ +-- +Counts the elements in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Examples +[source,FEEL] +---- +count( [1,2,3] ) = 3 +count( [] ) = 0 +count( [1,[2,3]] ) = 2 +---- +-- +// ---------------------------------------------------------------------------- + +min( list ):: ++ +-- +Returns the minimum comparable element in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Alternative signature +---- +min( e1, e2, ..., eN ) +---- + +.Examples +[source,FEEL] +---- +min( [1,2,3] ) = 1 +min( 1 ) = 1 +min( [1] ) = 1 +---- +-- +// ---------------------------------------------------------------------------- + +max( list ):: ++ +-- +Returns the maximum comparable element in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Alternative signature +---- +max( e1, e2, ..., eN ) +---- + +.Examples +[source,FEEL] +---- +max( 1,2,3 ) = 3 +max( [] ) = null +---- +-- +// ---------------------------------------------------------------------------- + +sum( list ):: ++ +-- +Returns the sum of the numbers in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +sum( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +sum( [1,2,3] ) = 6 +sum( 1,2,3 ) = 6 +sum( 1 ) = 1 +sum( [] ) = null +---- +-- +// ---------------------------------------------------------------------------- + +mean( list ):: ++ +-- +Calculates the average (arithmetic mean) of the elements in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +mean( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +mean( [1,2,3] ) = 2 +mean( 1,2,3 ) = 2 +mean( 1 ) = 1 +mean( [] ) = null +---- +-- +// ---------------------------------------------------------------------------- + +all( list ):: ++ +-- +Returns `true` if all elements in the list are true. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `boolean` elements +|=== + +.Alternative signature +---- +all( b1, b2, ..., bN ) +---- + +.Examples +[source,FEEL] +---- +all( [false,null,true] ) = false +all( true ) = true +all( [true] ) = true +all( [] ) = true +all( 0 ) = null +---- +-- +// ---------------------------------------------------------------------------- + +any( list ):: ++ +-- +Returns `true` if any element in the list is true. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `boolean` elements +|=== + +.Alternative signature +---- +any( b1, b2, ..., bN ) +---- + +.Examples +[source,FEEL] +---- +any( [false,null,true] ) = true +any( false ) = false +any( [] ) = false +any( 0 ) = null +---- +-- +// ---------------------------------------------------------------------------- + +sublist( list, start position, length? ):: ++ +-- +Returns the sublist from the start position, limited to the length elements. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`start position` +|`number` + +|`length` (Optional) +|`number` +|=== + +.Example +[source,FEEL] +---- +sublist( [4,5,6], 1, 2 ) = [4,5] +---- +-- +// ---------------------------------------------------------------------------- + +append( list, item ):: ++ +-- +Creates a list that is appended to the item or items. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`item` +|Any type +|=== + +.Example +[source,FEEL] +---- +append( [1], 2, 3 ) = [1,2,3] +---- +-- +// ---------------------------------------------------------------------------- + +concatenate( list ):: ++ +-- +Creates a list that is the result of the concatenated lists. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Example +[source,FEEL] +---- +concatenate( [1,2],[3] ) = [1,2,3] +---- +-- +// ---------------------------------------------------------------------------- + +insert before( list, position, newItem ):: ++ +-- +Creates a list with the `newItem` inserted at the specified position. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`position` +|`number` + +|`newItem` +|Any type +|=== + +.Example +[source,FEEL] +---- +insert before( [1,3],1,2 ) = [2,1,3] +---- +-- +// ---------------------------------------------------------------------------- + +remove( list, position ):: ++ +-- +Creates a list with the removed element excluded from the specified position. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`position` +|`number` +|=== + +.Example +[source,FEEL] +---- +remove( [1,2,3], 2 ) = [1,3] +---- +-- +// ---------------------------------------------------------------------------- + +reverse( list ):: ++ +-- +Returns a reversed list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Example +[source,FEEL] +---- +reverse( [1,2,3] ) = [3,2,1] +---- +-- +// ---------------------------------------------------------------------------- + +index of( list, match ):: ++ +-- +Returns indexes matching the element. + +.Parameters +* `list` of type `list` +* `match` of any type + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`match` +|Any type +|=== + +.Example +[source,FEEL] +---- +index of( [1,2,3,2],2 ) = [2,4] +---- +-- +// ---------------------------------------------------------------------------- + +union( list ):: ++ +-- +Returns a list of all the elements from multiple lists and excludes duplicates. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Example +[source,FEEL] +---- +union( [1,2],[2,3] ) = [1,2,3] +---- +-- +// ---------------------------------------------------------------------------- + +distinct values( list ):: ++ +-- +Returns a list of elements from a single list and excludes duplicates. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Example +[source,FEEL] +---- +distinct values( [1,2,3,2,1] ) = [1,2,3] +---- +-- +// ---------------------------------------------------------------------------- + +flatten( list ):: ++ +-- +Returns a flattened list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` +|=== + +.Example +[source,FEEL] +---- +flatten( [[1,2],[[3]], 4] ) = [1,2,3,4] +---- +-- +// ---------------------------------------------------------------------------- + +product( list ):: ++ +-- +Returns the product of the numbers in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +product( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +product( [2, 3, 4] ) = 24 +product( 2, 3, 4 ) = 24 +---- +-- +// ---------------------------------------------------------------------------- + +median( list ):: ++ +-- +Returns the median of the numbers in the list. If the number of elements is odd, the result is the middle element. If the number of elements is even, the result is the average of the two middle elements. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +median( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +median( 8, 2, 5, 3, 4 ) = 4 +median( [6, 1, 2, 3] ) = 2.5 +median( [ ] ) = null +---- +-- +// ---------------------------------------------------------------------------- + +stddev( list ):: ++ +-- +Returns the standard deviation of the numbers in the list. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +stddev( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +stddev( 2, 4, 7, 5 ) = 2.081665999466132735282297706979931 +stddev( [47] ) = null +stddev( 47 ) = null +stddev( [ ] ) = null +---- +-- +// ---------------------------------------------------------------------------- + +mode( list ):: ++ +-- +Returns the mode of the numbers in the list. If multiple elements are returned, the numbers are sorted in ascending order. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` of `number` elements +|=== + +.Alternative signature +---- +mode( n1, n2, ..., nN ) +---- + +.Examples +[source,FEEL] +---- +mode( 6, 3, 9, 6, 6 ) = [6] +mode( [6, 1, 9, 6, 1] ) = [1, 6] +mode( [ ] ) = [ ] +---- +-- +// ---------------------------------------------------------------------------- + +== Numeric functions + +The following functions support number operations. + +decimal( n, scale ):: ++ +-- +Returns a number with the specified scale. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` + +|`scale` +|`number` in the range `[−6111..6176]` +|=== + +.Examples +[source,FEEL] +---- +decimal( 1/3, 2 ) = .33 +decimal( 1.5, 0 ) = 2 +decimal( 2.5, 0 ) = 2 +---- +-- +// ---------------------------------------------------------------------------- + +floor( n ):: ++ +-- +Returns the greatest integer that is less than or equal to the specified number. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Examples +[source,FEEL] +---- +floor( 1.5 ) = 1 +floor( -1.5 ) = -2 +---- +-- +// ---------------------------------------------------------------------------- + +ceiling( n ):: ++ +-- +Returns the smallest integer that is greater than or equal to the specified number. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Examples +[source,FEEL] +---- +ceiling( 1.5 ) = 2 +ceiling( -1.5 ) = -1 +---- +-- +// ---------------------------------------------------------------------------- + +abs( n ):: ++ +-- +Returns the absolute value. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number`, `days and time duration`, or `years and months duration` +|=== + +.Examples +[source,FEEL] +---- +abs( 10 ) = 10 +abs( -10 ) = 10 +abs( @"PT5H" ) = @"PT5H" +abs( @"-PT5H" ) = @"PT5H" +---- +-- +// ---------------------------------------------------------------------------- + +modulo( dividend, divisor ):: ++ +-- +Returns the remainder of the division of the dividend by the divisor. If either the dividend or divisor is negative, the result is of the same sign as the divisor. + +NOTE: This function is also expressed as `modulo(dividend, divisor) = dividend - divisor*floor(dividen d/divisor)`. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`dividend` +|`number` + +|`divisor` +|`number` +|=== + +.Examples +[source,FEEL] +---- +modulo( 12, 5 ) = 2 +modulo( -12,5 )= 3 +modulo( 12,-5 )= -3 +modulo( -12,-5 )= -2 +modulo( 10.1, 4.5 )= 1.1 +modulo( -10.1, 4.5 )= 3.4 +modulo( 10.1, -4.5 )= -3.4 +modulo( -10.1, -4.5 )= -1.1 +---- +-- +// ---------------------------------------------------------------------------- + +sqrt( number ):: ++ +-- +Returns the square root of the specified number. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Example +[source,FEEL] +---- +sqrt( 16 ) = 4 +---- +-- +// ---------------------------------------------------------------------------- + +log( number ):: ++ +-- +Returns the logarithm of the specified number. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Example +[source,FEEL] +---- +decimal( log( 10 ), 2 ) = 2.30 +---- +-- +// ---------------------------------------------------------------------------- + +exp( number ):: ++ +-- +Returns Euler’s number `e` raised to the power of the specified number. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Example +[source,FEEL] +---- +decimal( exp( 5 ), 2 ) = 148.41 +---- +-- +// ---------------------------------------------------------------------------- + +odd( number ):: ++ +-- +Returns `true` if the specified number is odd. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Examples +[source,FEEL] +---- +odd( 5 ) = true +odd( 2 ) = false +---- +-- +// ---------------------------------------------------------------------------- + +even( number ):: ++ +-- +Returns `true` if the specified number is even. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`n` +|`number` +|=== + +.Examples +[source,FEEL] +---- +even( 5 ) = false +even ( 2 ) = true +---- +-- +// ---------------------------------------------------------------------------- + +== Date and time functions + +The following functions support date and time operations. + +is( value1, value2 ):: ++ +-- +Returns `true` if both values are the same element in the FEEL semantic domain. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`value1` +|Any type + +|`value2` +|Any type +|=== + +.Examples +[source,FEEL] +---- +is( date( "2012-12-25" ), time( "23:00:50" ) ) = false +is( date( "2012-12-25" ), date( "2012-12-25" ) ) = true +is( time( "23:00:50z" ), time( "23:00:50" ) ) = false +---- +-- +// ---------------------------------------------------------------------------- + +== Range functions + +The following functions support temporal ordering operations to establish relationships between single scalar values and ranges of such values. These functions are similar to the components in the Health Level Seven (HL7) International https://cql.hl7.org/08-a-cqlsyntax.html[Clinical Quality Language (CQL) 1.4 syntax]. + +before( ):: ++ +-- +Returns `true` when an element `A` is before an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `before( point1 point2 )` +b. `before( point range )` +c. `before( range point )` +d. `before( range1,range2 )` + + +.Requirements for evaluating to `true` +a. `point1 < point2` +b. `point < range.start or ( point = range.start and not(range.start included) )` +c. `range.end < point or ( range.end = point and not(range.end included) )` +d. `range1.end < range2.start or (( not(range1.end included) or not(range2.start included) ) and range1.end = range2.start )` + +.Examples +[source,FEEL] +---- +before( 1, 10 ) = true +before( 10, 1 ) = false +before( 1, [1..10] ) = false +before( 1, (1..10] ) = true +before( 1, [5..10] ) = true +before( [1..10], 10 ) = false +before( [1..10), 10 ) = true +before( [1..10], 15 ) = true +before( [1..10], [15..20] ) = true +before( [1..10], [10..20] ) = false +before( [1..10), [10..20] ) = true +before( [1..10], (10..20] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +after( ):: ++ +-- +Returns `true` when an element `A` is after an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `after( point1 point2 )` +b. `after( point range )` +c. `after( range, point )` +d. `after( range1 range2 )` + +.Requirements for evaluating to `true` +a. `point1 > point2` +b. `point > range.end or ( point = range.end and not(range.end included) )` +c. `range.start > point or ( range.start = point and not(range.start included) )` +d. `range1.start > range2.end or (( not(range1.start included) or not(range2.end included) ) and range1.start = range2.end )` + +.Examples +[source,FEEL] +---- +after( 10, 5 ) = true +after( 5, 10 ) = false +after( 12, [1..10] ) = true +after( 10, [1..10) ) = true +after( 10, [1..10] ) = false +after( [11..20], 12 ) = false +after( [11..20], 10 ) = true +after( (11..20], 11 ) = true +after( [11..20], 11 ) = false +after( [11..20], [1..10] ) = true +after( [1..10], [11..20] ) = false +after( [11..20], [1..11) ) = true +after( (11..20], [1..11] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +meets( ):: ++ +-- +Returns `true` when an element `A` meets an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `meets( range1, range2 )` + +.Requirements for evaluating to `true` +a. `range1.end included and range2.start included and range1.end = range2.start` + +.Examples +[source,FEEL] +---- +meets( [1..5], [5..10] ) = true +meets( [1..5), [5..10] ) = false +meets( [1..5], (5..10] ) = false +meets( [1..5], [6..10] ) = false +---- +-- +// ---------------------------------------------------------------------------- + +met by( ):: ++ +-- +Returns `true` when an element `A` is met by an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `met by( range1, range2 )` + +.Requirements for evaluating to `true` +a. `range1.start included and range2.end included and range1.start = range2.end` + +.Examples +[source,FEEL] +---- +met by( [5..10], [1..5] ) = true +met by( [5..10], [1..5) ) = false +met by( (5..10], [1..5] ) = false +met by( [6..10], [1..5] ) = false +---- +-- +// ---------------------------------------------------------------------------- + +overlaps( ):: ++ +-- +Returns `true` when an element `A` overlaps an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `overlaps( range1, range2 )` + +.Requirements for evaluating to `true` +a. `( range1.end > range2.start or (range1.end = range2.start and (range1.end included or range2.end included)) ) and ( range1.start < range2.end or (range1.start = range2.end and range1.start included and range2.end included) )` + +.Examples +[source,FEEL] +---- +overlaps( [1..5], [3..8] ) = true +overlaps( [3..8], [1..5] ) = true +overlaps( [1..8], [3..5] ) = true +overlaps( [3..5], [1..8] ) = true +overlaps( [1..5], [6..8] ) = false +overlaps( [6..8], [1..5] ) = false +overlaps( [1..5], [5..8] ) = true +overlaps( [1..5], (5..8] ) = false +overlaps( [1..5), [5..8] ) = false +overlaps( [1..5), (5..8] ) = false +overlaps( [5..8], [1..5] ) = true +overlaps( (5..8], [1..5] ) = false +overlaps( [5..8], [1..5) ) = false +overlaps( (5..8], [1..5) ) = false +---- +-- +// ---------------------------------------------------------------------------- + +overlaps before( ):: ++ +-- +Returns `true` when an element `A` overlaps before an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `overlaps before( range1 range2 )` + +.Requirements for evaluating to `true` +a. `( range1.start < range2.start or (range1.start = range2.start and range1.start included and range2.start included) ) and ( range1.end > range2.start or (range1.end = range2.start and range1.end included and range2.start included) ) and ( range1.end < range2.end or (range1.end = range2.end and (not(range1.end included) or range2.end included )) )` + +.Examples +[source,FEEL] +---- +overlaps before( [1..5], [3..8] ) = true +overlaps before( [1..5], [6..8] ) = false +overlaps before( [1..5], [5..8] ) = true +overlaps before( [1..5], (5..8] ) = false +overlaps before( [1..5), [5..8] ) = false +overlaps before( [1..5), (1..5] ) = true +overlaps before( [1..5], (1..5] ) = true +overlaps before( [1..5), [1..5] ) = false +overlaps before( [1..5], [1..5] ) = false +---- +-- +// ---------------------------------------------------------------------------- + +overlaps after( ):: ++ +-- +Returns `true` when an element `A` overlaps after an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `overlaps after( range1 range2 )` + +.Requirements for evaluating to `true` +a. `( range2.start < range1.start or (range2.start = range1.start and range2.start included and not( range1.start included)) ) and ( range2.end > range1.start or (range2.end = range1.start and range2.end included and range1.start included) ) and ( range2.end < range1.end or (range2.end = range1.end and (not(range2.end included) or range1.end included)) )` + +.Examples +[source,FEEL] +---- +overlaps after( [3..8], [1..5] )= true +overlaps after( [6..8], [1..5] )= false +overlaps after( [5..8], [1..5] )= true +overlaps after( (5..8], [1..5] )= false +overlaps after( [5..8], [1..5) )= false +overlaps after( (1..5], [1..5) )= true +overlaps after( (1..5], [1..5] )= true +overlaps after( [1..5], [1..5) )= false +overlaps after( [1..5], [1..5] )= false +overlaps after( (1..5), [1..5] )= false +overlaps after( (1..5], [1..6] )= false +overlaps after( (1..5], (1..5] )= false +overlaps after( (1..5], [2..5] )= false +---- +-- +// ---------------------------------------------------------------------------- + +finishes( ):: ++ +-- +Returns `true` when an element `A` finishes an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `finishes( point, range )` +b. `finishes( range1, range2 )` + +.Requirements for evaluating to `true` +a. `range.end included and range.end = point` +b. `range1.end included = range2.end included and range1.end = range2.end and ( range1.start > range2.start or (range1.start = range2.start and (not(range1.start included) or range2.start included)) )` + +.Examples +[source,FEEL] +---- +finishes( 10, [1..10] ) = true +finishes( 10, [1..10) ) = false +finishes( [5..10], [1..10] ) = true +finishes( [5..10), [1..10] ) = false +finishes( [5..10), [1..10) ) = true +finishes( [1..10], [1..10] ) = true +finishes( (1..10], [1..10] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +finished by( ):: ++ +-- +Returns `true` when an element `A` is finished by an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `finished by( range, point )` +b. `finished by( range1 range2 )` + +.Requirements for evaluating to `true` +a. `range.end included and range.end = point` +b. `range1.end included = range2.end included and range1.end = range2.end and ( range1.start < range2.start or (range1.start = range2.start and (range1.start included or not(range2.start included))) )` + +.Examples +[source,FEEL] +---- +finished by( [1..10], 10 ) = true +finished by( [1..10), 10 ) = false +finished by( [1..10], [5..10] ) = true +finished by( [1..10], [5..10) ) = false +finished by( [1..10), [5..10) ) = true +finished by( [1..10], [1..10] ) = true +finished by( [1..10], (1..10] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +includes( ):: ++ +-- +Returns `true` when an element `A` includes an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `includes( range, point )` +b. `includes( range1, range2 )` + +.Requirements for evaluating to `true` +a. `(range.start < point and range.end > point) or (range.start = point and range.start included) or (range.end = point and range.end included)` +b. `( range1.start < range2.start or (range1.start = range2.start and (range1.start included or not(range2.start included))) ) and ( range1.end > range2.end or (range1.end = range2.end and (range1.end included or not(range2.end included))) )` + +.Examples +[source,FEEL] +---- +includes( [1..10], 5 ) = true +includes( [1..10], 12 ) = false +includes( [1..10], 1 ) = true +includes( [1..10], 10 ) = true +includes( (1..10], 1 ) = false +includes( [1..10), 10 ) = false +includes( [1..10], [4..6] ) = true +includes( [1..10], [1..5] ) = true +includes( (1..10], (1..5] ) = true +includes( [1..10], (1..10) ) = true +includes( [1..10), [5..10) ) = true +includes( [1..10], [1..10) ) = true +includes( [1..10], (1..10] ) = true +includes( [1..10], [1..10] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +during( ):: ++ +-- +Returns `true` when an element `A` is during an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `during( point, range )` +b. `during( range1 range2 )` + +.Requirements for evaluating to `true` +a. `(range.start < point and range.end > point) or (range.start = point and range.start included) or (range.end = point and range.end included)` +b. `( range2.start < range1.start or (range2.start = range1.start and (range2.start included or not(range1.start included))) ) and ( range2.end > range1.end or (range2.end = range1.end and (range2.end included or not(range1.end included))) )` + +.Examples +[source,FEEL] +---- +during( 5, [1..10] ) = true +during( 12, [1..10] ) = false +during( 1, [1..10] ) = true +during( 10, [1..10] ) = true +during( 1, (1..10] ) = false +during( 10, [1..10) ) = false +during( [4..6], [1..10] ) = true +during( [1..5], [1..10] ) = true +during( (1..5], (1..10] ) = true +during( (1..10), [1..10] ) = true +during( [5..10), [1..10) ) = true +during( [1..10), [1..10] ) = true +during( (1..10], [1..10] ) = true +during( [1..10], [1..10] ) = true +---- +-- +// ---------------------------------------------------------------------------- + +starts( ):: ++ +-- +Returns `true` when an element `A` starts an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `starts( point, range )` +b. `starts( range1, range2 )` + +.Requirements for evaluating to `true` +a. `range.start = point and range.start included` +b. `range1.start = range2.start and range1.start included = range2.start included and ( range1.end < range2.end or (range1.end = range2.end and (not(range1.end included) or range2.end included)) )` + +.Examples +[source,FEEL] +---- +starts( 1, [1..10] ) = true +starts( 1, (1..10] ) = false +starts( 2, [1..10] ) = false +starts( [1..5], [1..10] ) = true +starts( (1..5], (1..10] ) = true +starts( (1..5], [1..10] ) = false +starts( [1..5], (1..10] ) = false +starts( [1..10], [1..10] ) = true +starts( [1..10), [1..10] ) = true +starts( (1..10), (1..10) ) = true +---- +-- +// ---------------------------------------------------------------------------- + +started by( ):: ++ +-- +Returns `true` when an element `A` is started by an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `started by( range, point )` +b. `started by( range1, range2 )` + +.Requirements for evaluating to `true` +a. `range.start = point and range.start included` +b. `range1.start = range2.start and range1.start included = range2.start included and ( range2.end < range1.end or (range2.end = range1.end and (not(range2.end included) or range1.end included)) )` + +.Examples +[source,FEEL] +---- +started by( [1..10], 1 ) = true +started by( (1..10], 1 ) = false +started by( [1..10], 2 ) = false +started by( [1..10], [1..5] ) = true +started by( (1..10], (1..5] ) = true +started by( [1..10], (1..5] ) = false +started by( (1..10], [1..5] ) = false +started by( [1..10], [1..10] ) = true +started by( [1..10], [1..10) ) = true +started by( (1..10), (1..10) ) = true +---- +-- +// ---------------------------------------------------------------------------- + +coincides( ):: ++ +-- +Returns `true` when an element `A` coincides with an element `B` and when the relevant requirements for evaluating to `true` are also met. + +.Signatures +a. `coincides( point1, point2 )` +b. `coincides( range1, range2 )` + +.Requirements for evaluating to `true` +a. `point1 = point2` +b. `range1.start = range2.start and range1.start included = range2.start included and range1.end = range2.end and range1.end included = range2.end included` + +.Examples +[source,FEEL] +---- +coincides( 5, 5 ) = true +coincides( 3, 4 ) = false +coincides( [1..5], [1..5] ) = true +coincides( (1..5), [1..5] ) = false +coincides( [1..5], [2..6] ) = false +---- +-- +// ---------------------------------------------------------------------------- + +== Temporal functions + +The following functions support general temporal operations. + +day of year( date ):: ++ +-- +Returns the Gregorian number of the day of the year. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`date` +|`date` or `date and time` +|=== + +.Example +[source,FEEL] +---- +day of year( date(2019, 9, 17) ) = 260 +---- +-- +// ---------------------------------------------------------------------------- + +day of week( date ):: ++ +-- +Returns the Gregorian day of the week: `"Monday"`, `"Tuesday"`, `"Wednesday"`, `"Thursday"`, `"Friday"`, `"Saturday"`, or `"Sunday"`. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`date` +|`date` or `date and time` +|=== + +.Example +[source,FEEL] +---- +day of week( date(2019, 9, 17) ) = "Tuesday" +---- +-- +// ---------------------------------------------------------------------------- + +month of year( date ):: ++ +-- +Returns the Gregorian month of the year: `"January"`, `"February"`, `"March"`, `"April"`, `"May"`, `"June"`, `"July"`, `"August"`, `"September"`, `"October"`, `"November"`, or `"December"`. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`date` +|`date` or `date and time` +|=== + +.Example +[source,FEEL] +---- +month of year( date(2019, 9, 17) ) = "September" +---- +-- +// ---------------------------------------------------------------------------- + +month of year( date ):: ++ +-- +Returns the Gregorian week of the year as defined by ISO 8601. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`date` +|`date` or `date and time` +|=== + +.Examples +[source,FEEL] +---- +week of year( date(2019, 9, 17) ) = 38 +week of year( date(2003, 12, 29) ) = 1 +week of year( date(2004, 1, 4) ) = 1 +week of year( date(2005, 1, 1) ) = 53 +week of year( date(2005, 1, 3) ) = 1 +week of year( date(2005, 1, 9) ) = 1 +---- +-- +// ---------------------------------------------------------------------------- + +== Sort functions + +The following functions support sorting operations. + +sort( list, precedes ):: ++ +-- +Returns a list of the same elements but ordered according to the sorting function. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`list` +|`list` + +|`precedes` +|`function` +|=== + +.Example +[source,FEEL] +---- +sort( list: [3,1,4,5,2], precedes: function(x,y) x < y ) = [1,2,3,4,5] +---- +-- +// ---------------------------------------------------------------------------- + +== Context functions + +The following functions support context operations. + +get value( m, key ):: ++ +-- +Returns the value from the context for the specified entry key. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`m` +|`context` + +|`key` +|`string` +|=== + +.Examples +[source,FEEL] +---- +get value( {key1 : "value1"}, "key1" ) = "value1" +get value( {key1 : "value1"}, "unexistent-key" ) = null +---- +-- +// ---------------------------------------------------------------------------- + +get entries( m ):: ++ +-- +Returns a list of key-value pairs for the specified context. + +.Parameters +[cols="30%,70%", options="header"] +|=== +|Parameter +|Type + +|`m` +|`context` +|=== + +.Example +[source,FEEL] +---- +get entries( {key1 : "value1", key2 : "value2"} ) = [ { key : "key1", value : "value1" }, {key : "key2", value : "value2"} ] +---- +-- +// ----------------------------------------------------------------------------