In DMN, all decision logic is represented as boxed expressions. Clause 7.2 introduced the concept of the boxed expression and defined two simple kinds: boxed literal expressions and boxed invocations. Clause 8 defined decision tables, a very important kind of boxed expression. This section completes the graphical notation for decision logic, by defining other kinds of boxed expressions.
The expressions 'in the boxes' are FEEL expressions. FEEL stands for Friendly Enough Expression Language and it has the following features:
Side-effect freeSimple data model with numbers, dates, strings, lists, and contextsSimple syntax designed for a wide audienceThree-valued logic (true, false, null)This section also completely specifies the syntax and semantics of FEEL. The syntax is specified as a grammar (10.3.1). The subset of the syntax intended to be rendered graphically as a boxed expression is also specified as a meta-model (10.5).
FEEL has two roles in DMN:
As a textual notation in the boxes of boxed expressions such as decision tables.As a slightly larger language to represent the logic of expressions and DRGs for the main purpose of composing the semantics in a simple and uniform way. Notation
This section builds on the generic notation for decision logic and boxed expressions defined in clause 7.2.
We define a graphical notation for decision logic called boxed expressions. This notation serves to decompose the decision logic model into small pieces that can be associated with DRG artifacts. The DRG plus the boxed expressions form a complete, mostly graphical language that completely specifies Decision Models.
A boxed expression is either:
a decision tablea boxed FEEL expressiona boxed invocationa boxed contexta boxed lista relationa boxed functiona boxed conditionala boxed filter, ora boxed iteratorBoxed expressions are defined recursively, i.e., boxed expressions can contain other boxed expressions. The top-level boxed expression corresponds to the decision logic of a single DRG artifact. This boxed expression SHALL have a name box that contains the name of the DRG artifact. The name box may be attached in a single box on top, as shown in Figure 10‑1:
[_Toc87278840 .anchor]#Figure 10‑1: Boxed expression
Alternatively, the name box and expression box can be separated by white space and connected on the left side with a line, as shown in Figure 10‑2:
[_Toc87278841 .anchor]#Figure 10‑2: Boxed expression with separated name and expression boxes
Graphical tools are expected to support appropriate graphical links, for example, clicking on a decision shape opens a decision table.
Color is suggested, but does not influence the meaning. In section 10:
Green is used for names of parameters, names of context entries, keywords in boxed conditionals and boxed iterators, and brackets in boxed filters.Embedded decision tables are colored as in section 8.
The executable decision tables defined here use the same notation as the decision tables defined in Clause 8. Their execution semantics is defined in clause 10.3.2.10.
A boxed FEEL expression is any FEEL expression e, as defined by the FEEL grammar (clause 10.3.1), in a table cell, as shown in Figure 10‑3:
[_Toc87278842 .anchor]#Figure 10‑3: Boxed FEEL expression
The meaning of a boxed expression containing e is FEEL(*e, *s), where s is the scope. The scope includes the context derived from the containing DRD as described in 10.4, and any boxed contexts containing e.
It is usually good practice to make e relatively simple, and compose small boxed expressions into larger boxed expressions.
The syntax for boxed invocation is described in clause 7.2.3. This syntax may be used to invoke any function (e.g., business knowledge model, FEEL built-in function, boxed function definition).
The box labeled 'invoked business knowledge model' can be any boxed expression whose value is a function, as shown in Figure 10‑4 :
|
||
|
||
|
|
|
|
|
|
|
||
|
|
[_Toc87278843 .anchor]#Figure 10‑4: Boxed invocation
The boxed syntax maps to the textual syntax defined by grammar rules 38, 39, 40, 41. Boxed invocation uses named parameters. Positional invocation can be achieved using a boxed expression containing a textual positional invocation.
The boxed syntax requires at least one parameter. A parameterless function must be invoked using the textual syntax, e.g., as shown in Figure 10‑5.
[_Toc87278844 .anchor]#Figure 10‑5: Parameterless function
Formally, the meaning of a boxed invocation is given by the semantics of the equivalent textual invocation, e.g., function-valued expression(parameter1: binding expression1, parameter2: binding expression2, …).
A boxed context is a collection of n (name, value) pairs with an optional result value. The names SHALL be distinct within a context. Each pair is called a context entry. Context entries may be separated by whitespace and connected with a line on the left (top). The intent is that all the entries of a context should be easily identified by looking down the left edge of a vertical context or across the top edge of a horizontal context. Cells SHALL be arranged in one of the following ways (see Figure 10‑6, Figure 10‑7):
|
|
|
|
|
|
|
[_Toc87278845 .anchor]#Figure 10‑6: Vertical context
|
|
|
|
|
|
|
|
[_Toc87278846 .anchor]#Figure 10‑7: Horizontal context
The context entries in a context are often used to decompose a complex expression into simpler expressions, each with a name. These context entries may be thought of as intermediate results. For example, contexts without a final Result box are useful for representing case data (see Figure 10‑8).
|
|||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
|
|
|
|
||
|
|
[_Toc87278847 .anchor]#Figure 10‑8: Use of context entries
Contexts with a final result box are useful for representing calculations (see Figure 10‑9).
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
[_Toc87278848 .anchor]#Figure 10‑9: Use of final result box
When decision tables are (non-result) context entries, the output cell can be used to name the entry, thus saving space. Any format decision table can be used in a vertical context. A jagged right edge is allowed. Whitespace between context entries may be helpful. See Figure 10‑10.
|
|
||
|
|||
|
|
||
|
[_Toc87278849 .anchor]#Figure 10‑10: Vertical context with decision table entry
The names SHALL be legal FEEL names. The values and optional result are boxed expressions.
Boxed contexts may have a decision table as the result, and use the named context entries to compute the inputs, and give them names. For example (see Figure 10‑11):
|
||||||
|
|
|||||
|
|
|||||
|
|
|||||
|
|
|
|
|
||
|
|
|
|
|
||
|
|
|
||||
|
|
|
||||
|
|
|
|
|||
|
|
|
||||
|
|
|
||||
|
|
|
|
|
||
|
|
|
||||
|
|
|
||||
|
|
|
|
|||
|
|
|
||||
|
|
|
[_Toc87278850 .anchor]#Figure 10‑11: Use of boxed expressions with a decision table
Formally, the meaning of a boxed context is \{ “Name 1”: Value 1, “Name 2”: Value 2, …, “Name n”: Value n } if no Result is specified. Otherwise, the meaning is \{ “Name 1”: Value 1, “Name 2”: Value 2, …, “Name n”: Value n, “result”: Result }.result. Recall that the bold face indicates elements in the FEEL Semantic Domain. The scope includes the context derived from the containing DRG as described in 10.4.
Boxed context entries for contexts that do not have a result box are accessible outside the context (as QNs), subject to the scope rules defined in clause 10.3.2.11. Boxed context entries for contexts that have a result box are not accessible outside the context.
A boxed list is a list of n items. Cells SHALL be arranged in one of the following ways (see Figure 10‑12, Figure 10‑13):
[_Toc87278851 .anchor]#Figure 10‑12: Vertical list
[_Toc87278852 .anchor]#Figure 10‑13: Horizontal list
Line styles are normative. The items are boxed expressions. Formally, the meaning of a boxed list is just the meaning of the list, i.e., [ Item 1, Item 2, …, Item n ]. The scope includes the context derived from the containing DRG as described in 10.4.
A vertical list of homogeneous horizontal contexts (with no result cells) can be displayed with the names appearing just once at the top of the list, like a relational table, as shown in Figure 10‑14:
Name 1 |
Name 2 |
|
Value 1a |
Value 2a |
|
Value 1b |
Value 2b |
|
Value 1m |
Value 2m |
|
-
+ [_Toc87278853 .anchor]#*Figure 10‑14: Relation
A Boxed Function Definition is the notation for parameterized boxed expressions.
The boxed expression associated with a Business Knowledge Model SHALL be a boxed function definition or a decision table whose input expressions are assumed to be the parameter names.
A boxed function has 3 cells:
1. Kind, containing the initial letter of one of the following:
FEELPMMLJava The Kind box can be omitted for FEEL functions, including decision tables.
Parameters: 0 or more comma-separated names, in parenthesesBody: a boxed expression
The 3 cells SHALL be arranged as shown in Figure 10‑15:
|
|
|
[_Toc87278854 .anchor]#Figure 10‑15: Boxed function definition
For FEEL functions, denoted by Kind FEEL or by omission of Kind, the Body SHALL be a FEEL expression that references the parameters. For externally defined functions denoted by Kind Java, the Body SHALL be a context as described in 10.3.2.13.3 and the form of the mapping information SHALL be the java form. For externally defined functions denoted by Kind PMML, the Body SHALL be a context as described in 10.3.2.13.3 and the form of the mapping information SHALL be the pmml form.
Formally, the meaning of a boxed function is just the meaning of the function, i.e., FEEL(funcion(Parameter1, Parameter2, …) Body) if the Kind is FEEL, and FEEL(funcion(Parameter1, Parameter2, …) external Body) otherwise. The scope includes the context derived from the containing DRG as described in 10.4.
Boxed conditional offers a visual representation of an if statement using three rows. The first one is labelled “if”; the second one is labelled “then” and the last one is labelled “else”. In the right part, another FEEL expression is expected. The expression in the “if” part MUST resolve to a boolean.
[_Toc87278855 .anchor]#Figure 10‑16: Boxed conditional
[_Toc87278856 .anchor]#Figure 10‑17: Use of conditional expression with decision table and invocation
Boxed filter offers a visual representation of collection filtering. The top part is an expression that is the collection to be filtered. The bottom part, between the square brackets, holds the filter expression. The expression in the top part MUST resolve to a collection. The expression in the bottom part MUST resolve to a Boolean.
[_Toc87278857 .anchor]#Figure 10‑18: Filter expression
Color is suggested but it is considered a good practice to have a different color for the square brackets, so the filtering expression is easier to see.
[_Toc87278858 .anchor]#Figure 10‑19: Use of filter expression with a list expression
Boxed iterator offers a visual representation of an iterator statement. There are three flavors to it: for loop and quantified expression some and every.
For the for loop, the three rows are labelled “for”, “in” and “return”. The right part of the “for” displays the iterator variable name. The second row holds an expression representing the collection that will be iterated over. The expression in the in row MUST resolve to a collection. The last row contains the expression that will process each element of the collection.
[_Toc87278859 .anchor]#Figure 10‑20: For expression
[_Toc87278860 .anchor]#Figure 10‑21: Use of for expression that returns a context
Every and some expression have a similar structure. The only difference between the two is the caption on the first line which is “every” or “some”. The second line is labelled “in” and the last one “satisfies”. The right part of the first line is the iterator variable name. The expression defined in the second row is the collection that will be tested. The expression in the in row MUST resolve to a collection. The last line is an expression that will be evaluated on each item. The expression defined in the satisfies MUST resolve to a boolean.
[_Toc87278861 .anchor]#Figure 10‑22: Every expression
[_Toc87278862 .anchor]#Figure 10‑23: Use of every with a list expression
[_Toc87278863 .anchor]#Figure 10‑24: Some expression
[_Toc87278864 .anchor]#Figure 10‑25: Use of some with a relation and a decision table
A subset of FEEL, defined in the next section, serves as the notation "in the boxes" of boxed expressions. A FEEL object is a number, a string, a date, a time, a duration, a function, a context, or a list of FEEL objects (including nested lists).
Note: A JSON object is a number, a string, a context (JSON calls them maps) or a list of JSON objects. So, FEEL is an extension of JSON in this regard. In addition, FEEL provides friendlier syntax for literal values, and does not require context keys to be quoted.
Here we give a "feel" for the language by starting with some simple examples.
Ranges and lists of ranges appear in decision table input entry, input value, and output value cells. In the examples in Table 39, this portion of the syntax is shown underlined. Strings, dates, times, and durations also may be compared, using typographical literals defined in section 7.2.2.1.
FEEL Expression | Value |
---|---|
5 in (⇐5 ) |
true |
5 in ( (5..10] ) |
false |
5 in ( 5..10] ) |
true |
5 in (4, 5, 6) |
true |
5 in (<5, >5) |
false |
2012-12-31 in ( (2012-12-25..2013-02-14) ) |
true |
FEEL numbers and calculations are exemplified in Table 40.
FEEL Expression | Value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Clause 9 introduced a subset of FEEL sufficient to support decision tables for Conformance Level 2 (see clause 2). The full DMN friendly-enough expression language (FEEL) required for Conformance Level 3 is specified here. FEEL is a simple language with inspiration drawn from Java, JavaScript, XPath, SQL, PMML, Lisp, and many others.
The syntax is defined using grammar rules that show how complex expressions are composed of simpler expressions. Likewise, the semantic rules show how the meaning of a complex expression is composed from the meaning of constituent simper expressions.
DMN completely defines the meaning of FEEL expressions that do not invoke externally-defined functions. There are no implementation-defined semantics. FEEL expressions (that do not invoke externally-defined functions) have no side- effects and have the same interpretation in every conformant implementation. Externally-defined functions SHOULD be deterministic and side-effect free.
FEEL syntax is defined as grammar here and equivalently as a UML Class diagram in the meta-model (10.5)
The grammar rules use the ISO EBNF notation. Each rule defines a non-terminal symbol S in terms of some other symbols S1, S2, … The following table summarizes the EBNF notation.
_ Example _ | _ Meaning _ |
---|---|
|
|
|
S2_ __ |
|
|
|
|
|
|
|
|
|
|
We extend the ISO notation with character ranges for brevity, as follows:
A character range has the following EBNF syntax:
character range = "[", low character, "-", high character, "]" ;
low character = unicode character ;
high character = unicode character ;
unicode character = simple character | code point ;
code point = "\u", 4 * hexadecimal digit | "\U", 6 * hexadecimal digit;
hexadecimal digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |
"a" | "A" | "b" | "B" | "c" | "C" | "d" | "D" | "e" | "E" | "f" | "F" ;
A simple character is a single Unicode character, e.g. a, 1, $, etc. Alternatively, a character may be specified by its hexadecimal code point value, prefixed with \u.
Every Unicode character has a numeric code point value. The low character in a range must have numeric value less than the numeric value of the high character.
For example, hexadecimal digit can be described more succinctly using character ranges as follows:
hexadecimal digit = [0-9] | [a-i | [A-F] ;
Note that the character range that includes all Unicode characters is [\u0-\u10FFFF].
The complete FEEL grammar is specified below. Grammar rules are numbered, and in some cases alternatives are lettered, for later reference. Boxed expression syntax (rule 53) is used to give execution semantics to boxed expressions.
1. expression =
boxed expression |textual expression ;2. textual expression =
for expression | if expression | quantified expression |disjunction |conjunction |comparison |arithmetic expression |instance of |path expression | filter expression | function invocation |literal | simple positive unary test | name | "(" , expression , ")" ;3. textual expressions = textual expression , \{ "," , textual expression } ;
4. arithmetic expression =
addition | subtraction |multiplication | division |exponentiation |arithmetic negation ;5. simple expression = arithmetic expression | simple value ;
6. simple expressions = simple expression , \{ "," , simple expression } ;
7. simple positive unary test =
( "<" | "⇐" | ">" | ">=" ) , endpoint |interval ;8. interval = ( open interval start | closed interval start ) , endpoint , ".." , endpoint , ( open interval end | closed interval end ) ;
9. open interval start = "(" | "]" ;
10. closed interval start = "[" ;
11. open interval end = ")" | "[" ;
12. closed interval end = "]" ;
13. positive unary test = expression ;
14. positive unary tests = positive unary test , \{ "," , positive unary test } ;
15. unary tests =
positive unary tests |"not", " (", positive unary tests, ")" |"-"16. endpoint = expression ;
17. simple value = qualified name | simple literal ;
18. qualified name = name , \{ "." , name } ;
19. addition = expression , "+" , expression ;
20. subtraction = expression , "-" , expression ;
21. multiplication = expression , "*" , expression ;
22. division = expression , "/" , expression ;
23. exponentiation = expression, "**", expression ;
24. arithmetic negation = "-" , expression ;
25. name = name start , \{ name part | additional name symbols } ;
26. name start = name start char, \{ name part char } ;
27. name part = name part char , \{ name part char } ;
28. name start char = "?" | [A-Z] | "_" | [a-z] | [\uC0-\uD6] | [\uD8-\uF6] | [\uF8-\u2FF] | [\u370-\u37D] | [\u37F-\u1FFF] | [\u200C-\u200D] | [\u2070-\u21 8F] | [\u2C00-\u2FEF] | [\u3001 -\uD7FF] | [\uF900-\uFDCF] | [\uFDF0-\uFFFD] | [\u10000-\uEFFFF] ;
29. name part char = name start char | digit | \uB7 | [\u0300-\u036F] | [\u203F-\u2040] ;
30. additional name symbols = "." | "/" | "-" | "’" | "+" | "*" ;
31. literal = simple literal | "null" ;
32. simple literal = numeric literal | string literal | boolean literal | date time literal ;
33. string literal = """, \{ character – (""" | vertical space) | string escape sequence}, """ ;
34. boolean literal = "true" | "false" ;
35. numeric literal = [ "-" ] , ( digits , [ ".", digits ] | "." , digits ) ;
36. digit = [0-9] ;
37. digits = digit , {digit} ;
38. function invocation = expression , parameters ;
39. parameters = "(" , ( named parameters | positional parameters ) , ")" ;
40. named parameters = parameter name , ":" , expression , \{ "," , parameter name , ":" , expression } ;
41. parameter name = name ;
42. positional parameters = [ expression , \{ "," , expression } ] ;
43. path expression = expression , "." , name ;
44. for expression = "for" , name , "in" , iteration context \{ "," , name , "in" , iteration context } , "return" , expression ;
45. if expression = "if" , expression , "then" , expression , "else" expression ;
46. quantified expression = ("some" | "every") , name , "in" , expression , \{ "," , name , "in" , expression } , "satisfies" ,
expression ;
47. disjunction = expression , "or" , expression ;
48. conjunction = expression , "and" , expression ;
49. comparison =
expression , ( "=" | "!=" | "<" | "⇐" | ">" | ">=" ) , expression |expression , "between" , expression , "and" , expression |expression , "in" , positive unary test |expression , "in" , " (", positive unary tests, ")" ;50. filter expression = expression , "[" , expression , "]" ;
51. instance of = expression , "instance" , "of" , type ;
52. type =
qualified name |
"range" "<" type ">" |
"list" "<" type ">" |
"context" "<" name ":" type \{ "," name ":" type } ">" | "function" "<" [ type \{ ", " type } ] ">" "→" type
;
53. boxed expression = list | function definition | context ;
54. list = "[" , [ expression , \{ "," , expression } ] , "]" ;
55. function definition = "function" , "(" , [ formal parameter \{ "," , formal parameter } ] , ")" , [ "external" ] , expression ;
56. formal parameter = parameter name [":" type ] ;
57. context = "\{" , [context entry , \{ "," , context entry } ] , "}" ;
58. context entry = key , ":" , expression ;
59. key = name | string literal ;
60. date time literal = at literal | function invocation;
61. white space = vertical space | \u0009 | \u0020 | \u0085 | \u00A0 | \u1 680 | \u1 80E | [\u2000-\u200B] | \u2028 | \u2029 | \u202F | \u205F | \u3000 | \uFEFF ;
62. vertical space = [\u000A-\u000D]
63. iteration context = expression, [ “..”, expression ];
64. string escape sequence = "\'" | "\"" | "\\" | "\n" | "\r" | "\t" | code point;
65. at literal = “@”, string literal
Additional syntax rules:
Operator precedence is given by the order of the alternatives in grammar rules 1, 2 and 4, in order from lowest to highest. E.g., (boxed) invocation has higher precedence than multiplication, multiplication has higher precedence than addition, and addition has higher precedence than comparison. Addition and subtraction have equal precedence, and like all FEEL infix binary operators, are left associative.Java-style comments can be used, i.e. '//' to end of line and /* … */.In rule 62, the only permitted functions are the builtins date, time, date and time, and duration.The string in rule 65 must follow the date string, time string, date and time string or duration string syntax, as detailed in section 10.3.4.1. Literals, data types, built-in functions
FEEL supports literal syntax for numbers, strings, booleans, date, time, date and time, duration, and null. (See grammar rules, clause 10.3.1.2). Literals can be mapped directly to values in the FEEL semantic domain (clause 10.3.2.1).
FEEL supports the following datatypes:
NumberStringBooleandays and time durationyears and months durationdatetimedate and timelistrangecontextfunctionTokens, Names and White space
A FEEL expression consists of a sequence of tokens, possibly separated with white space (grammar rule 63). A token is a sequence of Unicode characters, either:
A literal terminal symbol in any grammar rule other than grammar rule 30. Literal terminal symbols are enclosed in double quotes in the grammar rules, e.g., “and”, “+”, “=”, orA sequence conforming to grammar rule 28, 29, 35, or 37For backward compatibility reasons, “list”, “context” and “range” from grammar rule 52 are not considered literal terminal symbols.
White space (except inside strings) acts as token separators. Most grammar rules act on tokens, and thus ignore white space (which is not a token).
A name (grammar rule 27) is defined as a sequence of tokens. I.e. the name IncomeTaxesAmount is defined as the list of tokens [ Income, Taxes, Amount ]. The name Income+Expenses is defined as the list of tokens [ Income, + , Expenses ]. A consequence of this is that a name like Phone Number with one space in between the tokens is the same as Phone Number with several spaces in between the tokens.
A name start (grammar rule 26) SHALL NOT be a literal terminal symbol.
A name part (grammar rule 27) MAY be a literal terminal symbol.
A context is a map of key-value pairs called context entries, and is written using curly braces to delimit the context, commas to separate the entries, and a colon to separate key and value (grammar rule 57). The key can be a string or a name. The value is an expression.
A list is written using square brackets to delimit the list, and commas to separate the list items (grammar rule 54).
Contexts and lists can reference other contexts and lists, giving rise to a directed acyclic graph. Naming is path based. The qualified name (QN) of a context entry is of the form N1.N2 … Nn where N1 is the name of an in-scope context.
Nested lists encountered in the interpretation of N1.N2 … Nn are preserved. E.g.,
\{b: [1]}}, \{a: \{b: [2.1, 2.2]}}, \{a: \{b: [3]}}, \{a: \{b: [4, 5]}}].a.b =[1]}, \{b: [2.1,2.2]}, \{b: [3]}, \{b: [4, 5]}].b =[[1], [2.1, 2.2], [3], [4, 5]]
Nested lists can be flattened using the flatten() built-in function (10.3.4).
FEEL expressions reference InformationItems by their qualified name (QN), in which name parts are separated by a period. For example, variables containing components are referenced as [varName].[componentName]. Imported elements such as InformationItems and ItemDefinitions are referenced by namespace-qualified name, in which the first name part is the name specified by the Import element importing the element. For example, an imported variable containing components is referenced as [import name].[varName].[componentName].
Because names are a sequence of tokens, and some of those tokens can be FEEL operators and keywords, context is required to resolve ambiguity. For example, the following could be names or other expressions:
a-ba – bwhat if?Profit and lossAmbiguity is resolved using the scope. Name tokens are matched from left to right against the names in-scope, and the longest match is preferred. In the case where the longest match is not desired, parenthesis or other punctuation (that is not allowed in a name) can be used to disambiguate a FEEL expression. For example, to subtract b from a if a-b is the name of an in-scope context entry, one could write (a)-(b). Notice that it does not help to write a - b, using space to separate the tokens, because the space is not part of the token sequence and thus not part of the name.
FEEL semantics is specified by mapping syntax -fragments to values in the FEEL semantic domain. Literals (clause 10.3.1.3) can be mapped directly. Expressions composed of literals are mapped to values in the semantic domain using simple logical and arithmetic operations on the mapped literal values. In general, the semantics of any FEEL expression are composed from the semantics of its sub-expressions.
The FEEL semantic domain D consists of an infinite number of typed values. The types are organized into a lattice called L.
The types include:
simple datatypes such as number, boolean, string, date, time, and durationconstructed datatypes such as functions, lists, and contextsthe Null type, which includes only the null valuethe special type Any, which includes all values in DA function is a lambda expression with lexical closure or is externally defined by Java or PMML. A list is an ordered collection of domain elements, and a context is a partially ordered collection of (string, value) pairs called context entries.
We use italics to denote syntactic elements and boldface to denote semantic elements. For example, FEEL([1+ 1, 2+2]*) is [2, 4]*
Note that we use bold [] to denote a list in the FEEL semantic domain, and bold numbers 2, 4 to denote those decimal values in the FEEL semantic domain.
The semantics of equality are specified in the semantic mappings in clause 10.3.2.15. In general, the values to be compared must be of the same kind, for example, both numbers, to obtain a non-null result.
Identity simply compares whether two objects in the semantic domain are the same object. We denote the test for identity using infix is, and its negation using infix is not. For example, FEEL( "1" = 1) is null. Note that is never results in null.
Every FEEL expression e in scope s can be mapped to an element e in the FEEL semantic domain. This mapping defines the meaning of e in s. The mapping may be written e is FEEL(e,s). Two FEEL expressions e1 and e2 are equivalent in scope s if and only if FEEL(e1,s) is FEEL(e2,s). When s is understood from context (or not important), we may abbreviate the equivalence as e1 is e2.
FEEL datatypes are described in the following sub-sections. The meaning of the datatypes includes:
A mapping from a literal form (which in some cases is a string) to a value in the semantic domain.A precise definition of the set of semantic domain values belonging to the datatype, and the operations on them. Each datatype describes a (possibly infinite) set of values. The sets for the datatypes defined below are disjoint. We use italics to indicate a literal and boldface to indicate a value in the semantic domain.
FEEL Numbers are based on IEEE 754-2008 Decimal128 format, with 34 decimal digits of precision and rounding toward the nearest neighbor with ties favoring the even neighbor. Numbers are a restriction of the XML Schema type precisionDecimal, and are equivalent to Java BigDecimal with MathContext DECIMAL 128.
Grammar rule 35 defines literal numbers. Literals consist of base 10 digits and an optional decimal point. –INF, +INF, and NaN literals are not supported. There is no distinction between -0 and 0. The number(from, grouping separator, decimal separator) built-in function supports a richer literal format. E.g., FEEL(number("1. 000.000,01 ", ". ", ",")) = 1000000.01.
FEEL does not support a literal scientific notation. E.g., 1 .2e3 is not valid FEEL syntax. Use 1.2*10**3 instead.
A FEEL number is represented in the semantic domain as a pair of integers (p,s) such that p is a signed 34 digit integer carrying the precision information, and s is the scale, in the range [−611 1..6176]. Each such pair represents the number p/10s. To indicate the numeric value, we write value(p,s). E.g. value(100,2) = 1. If precision is not of concern, we may write the value as simply 1. Note that many different pairs have the same value. For example, value(1,0) = value(10,1) = value(100,2).
There is no value for notANumber, positiveInfinity, or negativeInfinity. Use null instead.
Grammar rule 33 defines literal strings as a double-quoted sequence of Unicode characters (see [.underline#https://unicode.org/glossary/#character),] e.g., "abc". The supported Unicode character range is [\u0-\u10FFFF]. The string literals are described by rule 33. The corresponding Unicode code points are used to encode a string literal.
The Boolean literals are given by grammar rule 34. The values in the semantic domain are true and false.
Times in FEEL can be expressed using either a time literal (see grammar rule 65) or the time() built-in function (See 10.3.4.1). We use boldface time literals to represent values in the semantic domain.
A time in the semantic domain is a value of the XML Schema time datatype. It can be represented by a sequence of numbers for the hour, minute, second, and an optional time offset from Universal Coordinated Time (UTC). If a time offset is specified, including time offset = 00:00, the time value has a UTC form and is comparable to all time values that have UTC forms. If no time offset is specified, the time is interpreted as a local time of day at some location, whose relationship to UTC time is dependent on time zone rules for that location, and may vary from day to day. A local time of day value is only sometimes comparable to UTC time values, as described in XML Schema Part 2 Datatypes.
A time t can also be represented as the number of seconds since midnight. We write this as valuet(t). E.g., valuet(01:01:01) = 3661.
The valuet function is one-to-one, but its range is restricted to [0..86400]. So, it has an inverse function valuet -1(x) that returns: the corresponding time value for x, if x is in [0..86400]; and valuet -1(y), where y = x – floor(x/86400) * 86400, if x is not in [0..86400].
Note: That is, valuet -1(x) is always actually applied to x modulo 86400. For example, valuet -1(3600) will return the time of day that is “01:00:00”, valuet -1(90000) will also return “T01 :00:00”, and valuet -1(-3600) will return the time of day that is “23 :00:00”, treating -3600 seconds as one hour before midnight.
Dates in FEEL can be expressed using either a date literal (see grammar rule 65) or the date() built-in function (See 10.3.4.1). A date in the semantic domain is a sequence of numbers for the year, month, day of the month. The year must be in the range [-999,999,999. .999,999,999]. We use boldface date literals to represent values in the semantic domain.
Where necessary, including the valuedt function (see 10.3.2.3.6), a date value is considered to be equivalent to a date time value in which the time of day is UTC midnight (00:00:00).
Date and time in FEEL can be expressed using either a date time literal (see grammar rule 65) or the date and time() built-in function (See 10.3.2.3.6). We use boldface date and time literals to represent values in the semantic domain.
A date and time in the semantic domain is a sequence of numbers for the year, month, day, hour, minute, second, and optional time offset from Universal Coordinated Time (UTC). The year must be in the range [-999,999,999..999,999,999]. If there is an associated time offset, including 00:00, the date-time value has a UTC form and is comparable to all other date-time values that have UTC forms. If there is no associated time offset, the time is taken to be a local time of day at some location, according to the time zone rules for that location. When the time zone is specified, e.g., using the IANA tz form (see 10.3.4.1), the date-time value may be converted to a UTC form using the time zone rules for that location, if applicable.
Note: projecting timezone rules into the future may only be safe for near-term date-time values.
A date and time d that has a UTC form can be represented as a number of seconds since a reference date and time (called the epoch). We write valuedt(d) to represent the number of seconds between d and the epoch. The valuedt function is one- to-one and so it has an inverse function valuedt -1. E.g., valuedt-1(valuedt(d)) = d. valuedt -1 returns null rather than a date with a year outside the legal range.
Days and time durations in FEEL can be expressed using either a duration literal (see grammar rule 65) or the duration() built-in function (See 10.3.4.1). We use boldface days and time duration literals to represent values in the semantic domain. The literal format of the characters within the quotes of the string literal is defined by the lexical space of the XPath Data Model dayTimeDuration datatype. A days and time duration in the semantic domain is a sequence of numbers for the days, hours, minutes, and seconds of duration, normalized such that the sum of these numbers is minimized. For example, FEEL(duraion("P0DT25H")) = P1DT1H.
The value of a days and time duration can be expressed as a number of seconds. E.g., valuedtd(P1DT1H) = 90000. The valuedtd function is one-to-one and so it has an inverse function valuedtd -1. E.g., valuedtd -1(90000) = P1DT1H.
Years and months durations in FEEL can be expressed using either a duration literal (see grammar rule 65) or the duration() built-in function (See 10.3.4.1). We use boldface years and month duration literals to represent values in the semantic domain. The literal format of the characters within the quotes of the string literal is defined by the lexical space of the XPath Data Model yearMonthDuration datatype. A years and months duration in the semantic domain is a pair of numbers for the years and months of duration, normalized such that the sum of these numbers is minimized. For example, FEEL(duraion("P0Y13M")) = P1Y1M.
The value of a years and months duration can be expressed as a number of months. E.g., valueymd(P1Y1M) = 13. The valueymd function is one-to-one and so it has an inverse function valueymd -1. E.g., valueymd -1(13) = P1Y1M.
FEEL, like SQL and PMML, uses of ternary logic for truth values. This makes and and or complete functions from *D* x D → *D*. Ternary logic is used in Predictive Modeling Markup Language to model missing data values.
Lists are immutable and may be nested. The first element of a list L can be accessed using L[1] and the last element can be accessed using L[-1]. The nth element from the beginning can be accessed using L[n], and the nth element from the end can be accessed using L[-n].
If FEEL(L) = L is a list in the FEEL semantic domain, the first element is FEEL(L[1]) = L[1]. If L does not contain n items, then L[n] is null.
L can be filtered with a Boolean expression in square brackets. The expression in square brackets can reference a list element using the name item, unless the list element is a context that contains the key "item". If the list element is a context, then its context entries may be referenced within the filter expression without the 'item.' prefix. For example:
[1, 2, 3, 4][item > 2] = [3, 4]
[ \{x:1, y:2}, \{x:2, y:3} ][x=1] = [\{x:1, y:2}]
The filter expression is evaluated for each item in list, and a list containing only items where the filter expression is true is returned. E.g:
[ \{x:1, y:2}, \{x:null, y:3} ][x < 2] = [\{x:1, y:2}]
The expression to be filtered is subject to implicit conversions (10.3.2.9.4) before the entire expression is evaluated.
For convenience, a selection using the "." operator with a list of contexts on its left hand side returns a list of selections, i.e. FEEL(e.f, c) = [ FEEL(f, c'), FEEL(f, c"), … ] where FEEL(e) = [ e', e", … ] and c' is c augmented with the context entries of e', c" is c augmented with the context entries of e", etc. For example,
[ \{x:1, y:2}, \{x:2, y:3} ].y = [2,3]
A FEEL context is a partially ordered collection of (key, expression) pairs called context entries. In the syntax, keys can be either names or strings. Keys are mapped to strings in the semantic domain. These strings are distinct within a context. A context in the domain is denoted using bold FEEL syntax with string keys, e.g. \{ "key1" : expr1, "key2" : expr2, … }.
The syntax for selecting the value of the entry named key1 from context-valued expression m is m.key1.
If key1 is not a legal name or for whatever reason one wishes to treat the key as a string, the following syntax is allowed: get value(m, "key1 "). Selecting a value by key from context m in the semantic domain is denoted as m.key1 or get value(m, "key1")
To retrieve a list of key,value pairs from a context m, the following built-in function may be used: get entries(m). For example, the following is true:
get entries(\{key1: "value1 "})[key= "key1 "].value = "value1"
An expression in a context entry may not reference the key of the same context entry, but may reference keys (as QNs) from previous context entries in the same context, as well as other values (as QNs) in scope.
These references SHALL be acyclic and form a partial order. The expressions in a context SHALL be evaluated consistent with this partial order.
FEEL supports a compact syntax for a range of values, useful in decision table test cells and elsewhere. Ranges can be syntactically represented either:
as a comparison operator and a single endpoint (grammar rule 7.a.)or a pair of endpoints and endpoint inclusivity flags that indicate whether one or both endpoints are included in the range (grammar rule 7.b.); on this case, endpoints must be of equivalent types (see section 10.3.2.9.1for the definition of type equivalence) and the endpoints must be ordered such that range start ⇐ range end.Endpoints can be either a literal or a qualified name of the following types: number, string, date, time, date and time, or duration. The following are examples of valid ranges:
< 10>= date(“2019-03-31”)>= @”2019-03-31”⇐ duration(“PT01H”)⇐ @”PT01H”[ 5 .. 10 ]( birthday .. @”2019-01-01” ) Ranges are mapped into the semantic domain as a typed instance of the range type. If the syntax with a single endpoint and an operator is used, then the other endpoint is undefined (represented by a null value) and the inclusivity flag is set to false. E.g.:
[_Toc87278972 .anchor]#Table 42: Examples of range properties values
_ range _ | _ start included _ | _ start _ | _ end _ | _ end included _ |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The FEEL function literal is given by grammar rule 55. Functions can also be specified in DMN via Function Definitions (see 6.3.9). The constructed type (T1, . . . , Tn) → U contains the function values that take arguments of types T1, . . . , Tn and yield results of type U, regardless of the way the function syntax (e.g., FEEL literal or DMN Function Definition). In the case of exactly one argument type T → U is a shorthand for (T ) → U.
Every FEEL expression executed in a certain context has a value in D, and every value has a type. The FEEL types are organized as a lattice (see Figure 10‑26), with upper type Any and lower type Null. The lattice determines the conformance of the different types to each other. For example, because comparison is defined only between values with conforming types, you cannot compare a number with a boolean or a string.
We define type(*e)* as the type of the domain element FEEL(*e, *c), where e is an expression defined by grammar rule 1. Literals for numbers, strings, booleans, null, date, time, date and time and duration literals are mapped to the corresponding node in lattice L. Complex expression such as list, contexts and functions are mapped to the corresponding parameterized nodes in lattice L. . For example, see Table 43.
_ _e __ | _ type(*_e)* __ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A type expression e defined by grammar rule 54 is mapped to the nodes in the lattice L by function type(*e)* as follows: primitive data type names are mapped to the node with the same name (e.g. string is mapped the string node)
Any is mapped to the node Any*Null is mapped to the node *Null*list< T> is mapped to the *list node with the parameter type(*T)context(k1:T1, …, kn:Tn> where n≥1 is mapped to the *context node with parameters k1: type(*T1), …, kn: *type(*Tn)function< T1, … Tn> → T is mapped to the *function node with signature type(*T1), …, *type(*Tn)* → *type(*T)Type names defined in the itemDefinitions section are mapped similarly to the context types (see rule above).If none of the above rules can be applied (e.g. type name does not exist in the decision model) the type expression is semantically incorrect.We define two relations between types:
Equivalence (T ≡ S): Types T and S are interchangeable in all contexts.Conformance (T <:S): An instance of type T can be substituted at each place where an instance of type S is expected.Type Equivalence
The equivalence relationship (≡) between types is defined as follows:
Primitive datatypes are equivalent to themselves, e.g., string ≡ string.Two list types list< T> and list<S> are equivalent iff T is equivalent to S. For example, the types of [“a”, “b”] and [“c”] are equivalent.Two context types context<k1: T1, …, kn: Tn> and context<l1: S 1, …, lm: Sm> are equivalent iff n = m and for every ki :Ti there is a unique lj :Sj such that ki = lj and Ti ≡ Sj for i = 1, n. Context types are the types defined via ItemDefinitions or the types associated to FEEL context literals such as \{ “name”: “John”, “age”: 25}.Two function types (T1, …, Tn) →U and (S1, …, Sm) →V are equivalent iff n = m, Ti ≡ Sj for i = 1, n and U ≡ V.Two range types range< T> and range<S> are equivalent iff T is equivalent to S. For example, the types of [1..10] and [30..40] are equivalent.Type equivalence is transitive: if type1 is equivalent to type2, and type2 is equivalent to type3, then type1 is equivalent to type3.
The conformance relation (<:) is defined as follows:
Conformance includes equivalence. If T ≡ S then T <: SFor every type T, Null <: T <: Any, where Null is the lower type in the lattice and Any the upper type in the lattice.The list type list< T> conforms to list<S> iff T conforms to S.The context type context<k1: T1, …, kn: Tn> conforms to context<l1: S 1, …, lm: Sm> iff n ≥ m and for every li : Si there is a unique kj:Tj such that li = kj and Tj <: Si for i = 1, mThe function type (T1, …, Tn) →U conforms to type (S1, …, Sm) →V iff n = m, Si <: Ti for i = 1, n and U <: V. The FEEL functions follow the “contravariant function argument type” and “covariant function return type” principles to provide type safety.The range type range< T> conforms to range< S> iff T conforms to S. Type conformance is transitive: if type1 conforms to type2, and type2 conforms to type3 , then type1 conforms to type3.
[_Toc87278865 .anchor]#Figure 10‑26: FEEL lattice type
Let us consider the following ItemDefinitions:
<itemDefinition name="Employee1"> <itemComponent name="id">
<typeRef>number</typeRef> </itemComponent>
<itemComponent name="name"> <typeRef>string</typeRef> </itemComponent>
</itemDefinition>
<itemDefinition name="Employee2"> <itemComponent name="name">
<typeRef>string</typeRef> </itemComponent>
<itemComponent name="id">
<typeRef>number</typeRef>
</itemComponent> </itemDefinition>
<itemDefinition name="Employee3"> <itemComponent name="id">
<typeRef>number</typeRef> </itemComponent>
<itemComponent name="name"> <typeRef>string</typeRef> </itemComponent>
<itemComponent name="age">
<typeRef>number</typeRef> </itemComponent>
</itemDefinition>
<itemDefinition isCollection=”true” name="Employee3List">
<itemComponent name="id">
<typeRef>number</typeRef> </itemComponent>
<itemComponent name="name"> <typeRef>string</typeRef> </itemComponent>
<itemComponent name="age">
<typeRef>number</typeRef> </itemComponent>
</itemDefinition>
and the decisions Decision1 , Decision2, Decision3 and Decision4 with corresponding typeRefs Employee1 , Employee2,
Employee3 and Employee3List.
Table 44 provides examples for equivalence to and conforms to relations.
_ type1 _ | _ type2 _ | _ equivalent to _ | _ conforms to _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The type of a FEEL expression e is determined from the value e = FEEL(e, s) in the semantic domain, where s is a set of variable bindings (see 10.3.2.11and 10.3.2.12). When an expression appears in a certain context it must be compatible with a type expected in that context, called the target type. After the type of the expression is deduced, an implicit conversion from the type of the expression to the target type can be performed sometimes. If an implicit conversion is mandatory but it cannot be performed the result is null.
There are several possible type conversions:
-
to singleton list:
When the type of the expression is T and the target type is List<T> the expression is converted to a singleton list. -
from singleton list:
When the type of the expression is List<T>, the value of the expression is a singleton list and the target type is T, the expression is converted by unwraping the first element. -
conforms to:
When the type of the expression is T1, the target type is T2, and T1 conforms to T2 the value of expression remains unchanged. Otherwise the result is null.
There are several kinds of contexts in which implicit conversions may occur:
-
Filter context (10.3.2.5) in which a filter expression is present. The expression to be filtered is subject to implicit conversion to singleton list.
-
Invocation context (Table 63) in which an argument is bound to a formal parameter of a function. The arguments are subject to implicit conversion from singleton list.
-
Binding contexts in which the value of an expression is bound to a variable with associated type information (e.g. binding actual parameters to formal parameters in an invocation, or binding the result of a decision’s logic to the decision’s output variable). The expression is subject to conforms to conversion.
======= Examples
The table below contains several examples for singleton list conversions.
_ Expression _ | _ Conversion _ | _ Result _ |
---|---|---|
|
|
|
|
|
|
In the example below, before binding variable decision_003 to value "123" the conversion to the target type (number) fails, hence the variable is bound to null.
<decision name="decision_003" id="_decision_003"> <variable name="decision_003" typeRef="number"/> <literalExpression>
<text>””123”</text>
</literalExpression>
</decision>
The normative notation for decision tables is specified in Clause 8. Each input expression SHALL be a textual expression (grammar rule 2). Each list of input values SHALL be an instance of unary tests (grammar rule 15). The value that is tested is the value of the input expression of the containing InputClause. Each list of output values SHALL be an instance of unary tests (grammar rule 15). The value that is tested is the value of a selected output entry of the containing OutputClause. Each input entry SHALL be an instance of unary tests (grammar rule 15). Rule annotations are ignored in the execution semantics.
The decision table components are shown in Figure 8‑5: Rules as rows – schematic layout, and also correspond to the metamodel in clause 8.3 For convenience, Figure 8‑5 is reproduced here.
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The semantics of a decision table is specified by first composing its literal expressions and unary tests into Boolean expressions that are mapped to the semantic domain, and composed into rule matches then rule hits. Finally, some of the decision table output expressions are mapped to the semantic domain and comprise the result of the decision table interpretation. Decision table components are detailed in Table 46.
_ Component name ( means optional)* _ | _ Description _ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Unary tests (grammar rule 15) are used to represent both input values and input entries. An input expression e is said to satisfy an input entry t (with optional input values v), depending on the syntax of t, as follows:
grammar rule 1 5.a: FEEL(e in (t))=truegrammar rule 1 5.b: FEEL(e in (t))=falsegrammar rule 1 5.c when v is not provided: e != nullgrammar rule 1 5.c when v is provided: FEEL(e in (v))=trueA rule with input entries t1,t2,…,tN is said to match the input expression list [e1,e2,…,eN] (with optional input values list [v1,v2, …vN]) if ei satisfies ti (with optional input values vi) for all i in 1 ..N.
A rule is hit if it is matched and the hit policy indicates that the matched rule’s output value should be included in the decision table result. Each hit results in one output value (multiple outputs are collected into a single context value). Therefore, multiple hits require aggregation.
The hit policy is specified using the initial letter of one of the following boldface policy names.
Single hit policies:
Unique – only a single rule can be matched.Any – multiple rules can match, but they all have the same output,Priority – multiple rules can match, with different outputs. The output that comes first in the supplied output values list is returned,First – return the first match in rule order,Multiple hit policies:
Collect – return a list of the outputs in arbitrary order,Rule order – return a list of outputs in rule order,Output order – return a list of outputs in the order of the output values list The Collect policy may optionally specify an aggregation, as follows:
C+ – return the sum of the outputsC# – return the count of the outputsC< – return the minimum-valued output C> – return the maximum-valued outputThe aggregation is defined using the following built-in functions specified in clause 10.3.4.4: sum, count, minimum, maximum. To reduce complexity, decision tables with compound outputs do not support aggregation and support only the following hit policies: Unique, Any, Priority, First, Collect without operator, and Rule order.
A decision table may have no rule hit for a set of input values. In this case, the result is given by the default output value, or null if no default output value is specified. A complete decision table SHALL NOT specify a default output value.
The semantics of a decision table invocation DTI are as follows:
1. Every rule in the rule list is matched with the input expression list. Matching is unordered.
2. If no rules match,
if a default output value d is specified, DTI=FEEL(d)else DTI=null.3. Else let m be the sublist of rules that match the input expression list. If the hit policy is "First" or "Rule order", order m by rule number.
Let o be a list of output expressions, where the expression at index i is the output expression from rule m[i]. The output expression of a rule in a single output decision table is simply the rule’s output entry. The output expression of a multiple output decision table is a context with entries composed from the output names and the rule’s corresponding output entries. If the hit policy is "Output order", the decision table SHALL be single output and o is ordered consistent with the order of the output values. Rule annotations are ignored for purposes of determining the expression value of a decision table.If a multiple hit policy is specified, DTI=FEEL(aggregation(o)), where aggregation is one of the built-in functions sum, count, minimum as specified in clause 10.3.4.4.else DTI=FEEL(o[1]).Scope and context stack
A FEEL expression e is always evaluated in a well-defined set of name bindings that are used to resolve QNs in e. This set of name bindings is called the scope of e. Scope is modeled as a list of contexts. A scope s contains the contexts with entries that are in scope for e. The last context in s is the built-in context. Next to last in s is the global context. The first context in s is the context immediately containing e (if any). Next are enclosing contexts of e (if any).
The QN of e is the QN of the first context in s appended with .N, where N is the name of entry in the first context of s containing e. QNs in e are resolved by looking through the contexts in s from first to last.
If e denotes the value of a context entry of context m, then m is the local context for e, and m is the first element of s. Otherwise, e has no local context and the first element of s is the global context, or in some cases explained later, the first element of s is a special context.
All of the entries of m are in-scope for e, but the depends on graph SHALL be acyclic. This provides a simple solution to the problem of the confusing definition above: if m is the result of evaluating the context expression m that contains e, how can we know it in order to evaluate e? Simply evaluate the context entries in depends on order.
The global context is a context created before the evaluation of e and contains names and values for the variables defined outside expression e that are accessible in e. For example, when e is the body of a decision D, the global context contains entries for the information requirements and knowledge requirements of D (i.e., names and logic of the business knowledge models, decisions and decision services required by D).
Some FEEL expressions are interpreted in a special context that is pushed on the front of s. For example, a filter expression is repeatedly executed with special first context containing the name 'item' bound to successive list elements. A function is executed with a special first context containing argument name→value mappings.
Qualified names (QNs) in FEEL expressions are interpreted relative to s. The meaning of a FEEL expression e in scope s is denoted as FEEL(*e, *s). We can also say that e evaluates to e in scope s, or e = FEEL(*e, *s). Note that e and s are elements of the FEEL domain. s is a list of contexts.
A FEEL expression e denotes a value e in the semantic domain. Some kinds of values can be passed between FEEL and external Java methods, between FEEL and external PMML models, and between FEEL and XML, as summarized in Table 47. An empty cell means that no mapping is defined.
_ _FEEL value __ | _ _Java __ | _ _XML __ | _ _PMML __ |
---|---|---|---|
|
|
|
decimal, PROB-NUMBER, |
|
|
||
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sometimes we do not want to evaluate a FEEL expression e, we just want to know the type of e*. Note that if e has QNs, then a context may be needed for type inference. We write *type(*e)* as the type of the domain element FEEL(*e, *c).
FEEL functions can be:
sum (see clause 10.3.4.4), oruser-defined, e.g.,
function(age) age < 21, orexternally defined, e.g.,
function(angle) external \{
java: \{
class: “java.lang.Math ”,
method signature: “cos(double)”
}} Built-in Functions
The built-in functions are described in detail in section 10.3.4. In particular, function signatures and parameter domains are specified. Some functions have more than one signature.
Built-in functions are invoked using the same syntax as other functions (grammar rule 40). The actual parameters must conform to the parameter domains in at least one signature before or after applying implicit conversions, or the result of the invocation is null.
User-defined functions (grammar rule 55) have the form
function(X1, … Xn) body
The terms X1, … Xn are formal parameters. Each formal parameter has the form ni or ni :_ti_, where the ni are the parameter names and ti are their types. If the type isn’t specified, Any is assumed. The meaning of FEEL(function(X1, … Xn) body, s) is an element in the FEEL semantic domain that we denote as function(argument list: [*X1, … Xn], body:* body*, scope: s)* (shortened to f below). FEEL functions are lexical closures, i.e., the body is an expression that references the formal parameters and any other names in scope s.
User-defined functions are invoked using the same syntax as other functions (grammar rule 38). The meaning of an invocation f(n1:e1,…,nn:en) in scope s is FEEL(f, s) applied to arguments n1:FEEL(e1, s)… ,nn:FEEL(en, s). This can also be written as f(n1:e1… ,*n*n:*e*n).
The arguments n1:e1… ,*n*n:*e*n conform to the argument list [*X1, … Xn]* if type(ei) conforms to ti before or after applying implicit conversions or ti is not specified in Xi, for all i in 1. .n. The result of applying f to the interpreted arguments n1:e1… ,*n*n:*e*n is determined as follows. If f is not a function, or if the arguments do not conform to the argument list, the result of the invocation is null. Otherwise, let c be a context with entries n1:e1… ,*n*n:*e*n. The result of the invocation is FEEL(body, s’*), where *s' = insert before(s, 1, c) (see 10.3.4.4).
Invocable elements (Business Knowledge Models or Decision Services) are invoked using the same syntax as other functions (grammar rule 38). An Invocable is equivalent to a FEEL function whose parameters are the invocable’s inputs (see 10.4)
FEEL externally-defined functions have the following form
function (X1, … Xn) external mapping-information
Mapping-information is a context that SHALL have one of the following forms:
\{
java: \{class: class-name, method signature: method-signature}
}
or
\{
pmml: \{document: IRI, model: model-name}
}
The meaning of an externally defined function is an element in the semantic domain that we denote as function(argument list: [*X1, … Xn], external: mapping-information)*.
The java form of the mapping information indicates that the external function is to be accessed as a method on a Java class. The class-name SHALL be the string name of a Java class on the classpath. Classpath configuration is implementation-defined. The method-signature SHALL be a string consisting of the name of a public static method in the named class, followed by an argument list containing only Java argument type names. The argument type information SHOULD be used to resolve overloaded methods and MAY be used to detect out-of-domain errors before runtime.
The pmml form of the mapping information indicates that the external function is to be accessed as a PMML model. The IRI SHALL be the resource identifier for a PMML document. The model-name is optional. If the model-name is specified, it SHALL be the name of a model in the document to which the IRI refers. If no model-name is specified, the external function SHALL be the first model in the document.
When an externally-defined function is invoked, actual argument values and result value are converted when possible using the type mapping table for Java or PMML (see Table 47). When a conversion is not possible, null is substituted. If a result cannot be obtained, e.g. an exception is thrown, the result of the invocation is null. If the externally-defined function is of type PMML, and PMML invocation results in a single predictor output, the result of the externally-defined function is the single predictor output’s value.
Passing parameter values to the external method or model requires knowing the expected parameter types. For Java, this information is obtained using reflection. For PMML, this information is obtained from the mining schema and data dictionary elements associated with independent variables of the selected model.
Note that DMN does not completely define the semantics of a Decision Model that uses externally-defined functions. Externally-defined functions SHOULD have no side-effects and be deterministic.
To name a function, define it as a context entry. For example:
\{
isPositive : function(x) x > 0,
isNotNegative : function(x) isPositive(x+ 1), result: isNotNegative(0)
}
The for loop expression iterates over lists of elements or ranges of numbers. The general syntax is:
for i1 in ic1 [, i2 in ic2 [, …]] return e
where:
ic1, ic2, …, icn are iteration contextsi1, i2, …, in are variables bound to each element in the iteration contexte is the return expressionAn iteration context may either be an expression that returns a list of elements, or two expressions that return integers connected by “..”. Examples of valid iteration contexts are:
[ 1, 2, 3]a list1..1050..40x..x+10A for loop expression will iterate over each element in the iteration context, binding the element to the corresponding variable in and evaluating the expression e in that scope.
When the iteration context is a range of numbers, the for loop expression will iterate over the range incrementing or decrementing the value of in by 1, depending if the range is ascendant (when the resulting integer from the first expression is lower than the second) or descendant (when the resulting integer from the first expression is higher than the second).
The result of the for loop expression is a list containing the result of the evaluation of the expression e for each individual iteration in order.
The expression e may also reference an implicitly defined variable called “partial” that is a list containing all the results of the previous iterations of the expression. The variable “partial” is immutable. E.g.: to calculate the factorial list of numbers, from 0 to N, where N is a non-negative integer, one may write:
for i in 0..N return if i = 0 then 1 else i * partial[-1]
When multiple iteration contexts are defined in the same for loop expression, the resulting iteration is a cross-product of the elements of the iteration contexts. The iteration order is from the inner iteration context to the outer iteration context.
E.g., the result of the following for loop expression is:
for i in [i1,i2], j in [j1j2] return e *= [ r1, r2, r3, r4 ]*
Where:
r1 = FEEL( e, \{ i: i1, j: j1, partial:[], … } )
r2 = FEEL( e, \{ i: i1, j: j2, partial:[r1], … )
r3 = FEEL( e, \{ i: i2, j: j1, partial:[r1,r2], … } )
r4 = FEEL( e, \{ i: i2, j: j2, partial:[r1,r2,r3], … } )
The meaning of each substantive grammar rule is given below by mapping the syntax to a value in the semantic domain. The value may depend on certain input values, themselves having been mapped to the semantic domain. The input values may have to obey additional constraints. The input domain(s) may be a subset of the semantic domain. Inputs outside of their domain result in a null value, unless the implicit conversion from singleton list (10.3.2.9.4) can be applied.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Mapped to Domain _ |
---|---|---|
|
|
|
|
|
|
See 10.3.2.7.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Mapped to Domain _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49.a |
|
|
49.a |
|
|
49.a |
|
|
49.a |
|
|
Notice that we use bold syntax to denote contexts, lists, conjunctions, disjunctions, conditional expressions, true, false, and null in the FEEL domain.
The meaning of the conjunction a and b and the disjunction a or b is defined by ternary logic. Because these are total functions, the input can be true, false, or otherwise (meaning any element of D other than true or false).
A conditional if a then b else c is equal to b if a is true, and equal to c otherwise.
s' is the scope s with a special first context containing keys n1, n2, etc. bound to the first element of the Cartesian product of FEEL(e1*) x* FEEL(e2*) x …, s"* is s with a special first context containing keys bound to the second element of the Cartesian product, etc. When the Cartesian product is empty, the some … satisfies quantifier returns false and the every … satisfies quantifier returns true.
_ a _ | _ b _ | _ a and b _ | _ a or b _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Negation is accomplished using the built-in function not. The ternary logic is as shown in Table 51.
_ a _ | _ not(a) _ |
---|---|
|
|
|
|
|
|
Equality and inequality map to several kind- and datatype-specific tests, as shown in Table 52, Table 53 and Table 54. By definition, FEEL(e1 != e2) is FEEL(not(e 1= e2)). The other comparison operators are defined only for the datatypes listed in Table 54. Note that Table 54 defines only ‘<’; ‘>’ is similar to ‘<’ and is omitted for brevity; e1⇐e2 is defined as e1< e2 or e1= e2.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Input Domain _ | _ Result _ |
---|---|---|---|
|
|
|
|
|
|
|
|
_ kind/datatype _ | _ _e1 = e2 __ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ datatype _ | _ _e1 < e2 __ |
---|---|
number |
|
string |
|
|
|
|
|
|
|
|
|
|
|
+ FEEL supports additional syntactic sugar for comparison. Note that Grammar Rules (clause 10.3.1.2) are used in decision table condition cells. These decision table syntaxes are defined in *Table _55_*.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Equivalent FEEL Syntax _ | _ applicability _ |
---|---|---|---|
49.b |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
49.c |
|
|
|
Addition and subtraction are defined in Table 56 and Table 57. Note that if input values are not of the listed types, the result is null.
_ Grammar Rule _ | FEEL | _ Input Domain and Result _ |
---|---|---|
|
e1 + e2 |
|
|
e1 – e2 |
|
duration string – a string value in the lexical space of the xs:dayTimeDuration or xs:yearMonthDuration datatypes specified by the XQuery 1.0 and XPath 2.0 Data Model. [_Toc87279002 .anchor]#Table 72: Semantics of conversion functions
_ type(e1) _ | _ type(e2) _ | _ _e1 + e2, e1 – e2 __ | _ result type _ |
---|---|---|---|
|
|
|
|
value(p,s) = value(p1,s1) +/- value(p2,s2) + ε |
|||
s ≤ max(s1,s2) |
|||
s is maximized subject to the limitation that p has 34 digits or less |
|||
ε is a possible rounding error. |
|||
|
|
|
|
|
|||
|
|||
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Multiplication and division are defined in Table 58 and Table 59. Note that if input values are not of the listed types, the result is null.
_ Grammar Rule _ | FEEL | _ Input Domain and Result _ |
---|---|---|
|
e1 * e2 |
|
|
e1 / e2 |
|
_ type(e1) _ | _ type(e2) _ | e1 * e2 | e1 / e2 | _ result type _ |
---|---|---|---|---|
|
|
|
value(p,s) = value(p1,s1) / value(p2,s2) + εs ≤ s1-s2s is maximized subject to the limitation that p has 34 digits or less |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ Grammar Rule _ | _ FEEL Syntax _ | _ Input Domain _ | _ Result _ |
---|---|---|---|
|
e1 ** e2 |
|
|
value(p,s)= value(e1)value(e2) + εp is limited to 34 digitsε is rounding error
Type-checking is defined in Table 61. Note that type is not mapped to the domain, and null is the only value in the Null type (see 10.3.2.1).
Before evaluating the instance of operator both operands are mapped to the type lattice L (see 10.3.2.9).
_ Grammar Rule _ | _ FEEL Syntax _ | _ Mapped to Domain _ | _ Examples _ |
---|---|---|---|
|
|
|
|
Negative numbers are defined in Table 62.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Equivalent FEEL Syntax _ |
---|---|---|
|
|
|
Invocation is defined in Table 63. An invocation can use positional arguments or named arguments. If positional, all arguments must be supplied. If named, unsupplied arguments are bound to null. Note that e can be a user-defined function, a user-defined external function, or a built-in function. The arguments are subject to implicit conversions (10.3.2.9.4). If the argument types before or after conversion do not conform to the corresponding parameter types, the result of the invocation is null.
_ Grammar Rule _ | _ FEEL _ | _ Mapped to Domain _ | _ Applicability _ | |||
---|---|---|---|---|---|---|
|
39, |
42 |
|
|
|
|
|
39, |
40, |
41 |
|
|
|
Properties are defined in Table 64 and Table 65. If type(*e)* is date and time, time, or duration, and name is a property name, then the meaning is given by Table 65 and Table 66. For example, FEEL(date and time("2012-03-07Z").year) = 2012.
_ Grammar Rule _ | _ FEEL _ | _ Mapped to Domain _ | _ Applicability _ |
---|---|---|---|
|
|
|
|
|
|
|
|
_ type(_e) __ | _ _e . name __ | _ name = _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ name _ | _ _type(name) __ | _ description _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_ name _ | _ type(name) _ | _ description _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Lists are defined in Table 68.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Mapped to Domain (scope s) _ | _ Applicability _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Contexts are defined in Table 69.
_ Grammar Rule _ | _ FEEL Syntax _ | _ Mapped to Domain (scope s) _ |
---|---|---|
|
|
|
|
||
|
subset of the entries of this result context. If ci contains |
|
|
|
|
FEEL supports XML Data in the FEEL context by mapping XML Data into the FEEL Semantic Domain. Let XE(e, p) be a function mapping an XML element e and a parent FEEL context p to a FEEL context , as defined in the following tables. XE makes use of another mapping function, XV(v), that maps an XML value v to the FEEL semantic domain.
XML namespace semantics are not supported by the mappings. For example, given the namespace prefix declarations xmlns:p1= "http://example.org/foobar" and xmlns:p2= "http://example. org/foobar", the tags p1:myElement and p2:myElement are the same element using XML namespace semantics but are different using XML without namespace semantics.
Table 70, e is the name of an XML element, a is the name of one of its attributes, c is a child element, and v is a value. The parent context p is initially empty.
_ XML _ | _ context entry in p _ | _ Remark _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
<c1>v1</c1>
|
|
|
|
|
|
An entry in the context entry in p column such as "e" : null indicates a context entry with string key "e" and value null. The context entries are contained by context p that corresponds to the containing XML element, or to the XML document itself.
The mapping does not replace namespace prefixes with the namespace IRIs. FEEL requires only that keys within a context be distinct, and the namespace prefixes are sufficient.
If an XML document was parsed with a schema, then some atomic values may have a datatype other than string. Table 71defines how a typed XML value v is mapped to FEEL.
_ Type of _v __ | _ FEEL Semantic Domain _ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The following schema and instance are equivalent to the following FEEL:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org/http://www.example.org]"
ta rgetNa mespace=" http://www.example.org/http://www.example.org]"
elementFormDefault="qualified">
<xsd:element name="Context">
<xsd :complexType> <xsd:sequence>
<xsd:element name="Employee">
<xsd:complexType> <xsd:sequence>
<xsd :element na me="sala ry" type="xsd :deci ma l"/>
</xsd :seq uence> </xsd :complexType> </xsd:element>
<xsd:element name="Customer" maxOccurs="unbounded">
<xsd:complexType> <xsd:sequence>
<xsd :element na me="loya lty_level" type="xsd :stri ng"/>
<xsd :element na me="credit_li mit" type="xsd :decima l"/>
</xsd :seq uence>
</xsd :complexType>
</xsd:element>
</xsd:sequence> </xsd :complexType> </xsd:element>
</xsd:schema>
<Context xmlns:tns="http://www.example.org/http://www.example.org]"
xmlns="http://www.example.org/http://www.example.org]">
<tns:Employee>
<tns:salary>13000</tns:salary>
</tns:Employee>
<Customer>
<loyalty_level>gold</loyalty_level>
<credit_limit>10000</credit_limit>
</Customer>
<Customer>
<loyalty_level>gold</loyalty_level>
<credit_limit>20000</credit_limit>
</Customer> <Customer> <loya lty_level>si lver</loya lty_level>
<credit_limit>5000</credit_limit>
</Customer>
</Context>
_ Context _ | ||
---|---|---|
|
|
|
|
|
|
|
10000 |
|
|
20000 |
|
|
5000 |
When a decision model is evaluated, its input data described by an item definition such as an XML Schema element (clause 7.3.2) is bound to case data mapped to the FEEL domain. The case data can be in various formats, such as XML. We can notate case data as an equivalent boxed context, as above. Decision logic can reference entries in the context using expressions such as Context.tns$Employee.tns$salary, which has a value of 13000.
To promote interoperability, FEEL includes a library of built-in functions. The syntax and semantics of the built-ins are required for a conformant FEEL implementation.
In all of the tables in this section, a superscript refers to an additional domain constraint stated in the corresponding footnote to the table. Whenever a parameter is outside its domain, the result of the built-in is null.
FEEL supports many conversions between values of different types. Of particular importance is the conversion from strings to dates, times, and durations. There is no literal representation for date, time, or duration. Also, formatted numbers such as 1,000.00 must be converted from a string by specifying the grouping separator and the decimal separator.
Built-ins are summarized in Table 72. The first column shows the name and parameters. A question mark (?) denotes an optional parameter. The second column specifies the domain for the parameters. The parameter domain is specified as one of:
a type, e.g., number, stringany – any element from the semantic domain, including nullnot null – any element from the semantic domain, excluding nulldate string – a string value in the lexical space of the date datatype specified by XML Schema Part 2 Datatypes time string – eithera string value in the lexical space of the time datatype specified by XML Schema Part 2 Datatypes; or
a string value that is the extended form of a local time representation as specified by ISO 8601, followed by the character "@", followed by a string value that is a time zone identifier in the IANA Time Zones Database (http://www.iana.org/time-zones)http://www.iana.org/time-zones)]
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. grouping SHALL be one of space (' '), comma (','), period ('.'), or null.
decimal SHALL be one of period, comma, or null, but SHALL NOT be the same as the grouping separator unless both are null.
from SHALL conform to grammar rule 37, after removing all occurrences of the grouping separator, if any, and after changing the decimal separator, if present, to a period.
Table 73 defines Boolean functions.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
Table 74 defines string functions.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(a)", "[1=$1][2=$2]") = "[1=ab][2=]cd"_ __ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start position must be a non-zero integer (0 scale number) in the range [-L..L], where L is the length of the string. length must be in the range [1 ..E], where E is L – start position + 1 if start position is positive, and –start position otherwise.pattern, replacement, and flags SHALL conform to the syntax and constraints specified in clause 7.6 of XQuery 1.0 and XPath 2.0 Functions and Operators. Note that where XPath specifies an error result, FEEL specifies a null result.
Table 75 defines list functions.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
all([false,null,true]) = false |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
position must be a non-zero integer (0 scale number) in the range [-L..L], where L is the length of the listlength must be in the range [1 ..E], where E is L – start position + 1 if start position is positive, and –start position otherwise.
Table 76 defines numeric functions.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
|
|
|
floor(1.5) = 1 |
|
|
|
ceiling(1.5) = 2 |
|
|
|
round up(5.5, 0) = 6 _ |
|
|
|
round down(5.5, 0) = 5 _ |
|
|
|
round half up(5.5, 0) = 6 _ |
|
|
|
round half down (5.5, 0) = 5 _ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
even( 5 ) = false |
1. Scale is in the range [−6111 ..6176]
Table 77 defines date and time functions.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
The following set of functions establish relationships between single scalar values and ranges of such values. All functions in this list take two arguments and return True if the relationship between the argument holds, or False otherwise.
The specification of these functions is heavily inspired by the equivalent functions in the HL7 CQL (Clinical Quality Language) standard version 1.4.
The following table intuitively depicts the relationships defined by the functions in this chapter, but the full semantics of the functions are listed in
Table 78.
_ Name(parameters) _ | _ Evaluates to true if and only if (for each signature, respectively) _ | _ Example _ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(range1.start < range2.start or (range1.start = range2.start and range1.start included and not(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 ))) |
|
(a) overlaps after(range1, range2) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The following set of functions provide common support utilities when dealing with date or date and time values; listed in Table 1.
_ Name(parameters) _ | _ Parameter Domain _ | _ Description _ | _ Example _ | |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
month of year( date ) |
|
|
|
|
week of year( date ) |
|
|
|
Sort a list using an ordering function. For example,
sort(list: [3,1,4,5,2], precedes: function(x,y) x < y) = [1,2,3,4,5]
_ Parameter name (* means optional) _ | _ Domain _ |
---|---|
|
|
|
|
Table 81 defines Context functions
_ Name(parameters) _ | _ Parameter domain _ | _ Description _ | _ Example _ |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The following set of functions provide support utilities for several miscellaneous use-cases. For example, when a decision depends on the current date, like deciding the support SLA over the weekends, additional charges for weekend delivery, etc.
It is important to note that the functions in this section are intended to be side-effect-free, but they are not deterministic and not idempotent from the perspective of an external observer.
Vendors are encouraged to guide end-users in ensuring deterministic behavior of the DMN model during testing, for example, through specific configuration.
Users are encouraged to isolate decision logic that uses these functions in specific DRG elements, such as Decisions. This encapsulation enables them to be overridden with synthetic values that remain constant across executions of the DMN model’s test cases.
Name(parameters) | Parameter domain | Description |
---|---|---|
now() |
(none) |
returns current date and time |
today() |
(none) |
returns current date |
FEEL gives execution semantics to decision services defined in decision models where FEEL is the expression language. A decision service is semantically equivalent to a FEEL function whose parameters are the decision service inputs, and whose logic is a context assembled from the decision service’s decisions and knowledge requirements.
Decision service implementations SHALL return a result as described above, and MAY return additional information such as intermediate results, log records, debugging information, error messages, rule annotations, etc. The format of any additional information is left unspecified.
Every FEEL expression in a decision model has execution semantics. LiteralExpression (FEEL text) semantics is defined in 10.3. Boxed expressions described in 10.2.2 can be mapped to FEEL text and thus also have execution semantics.
Recall that a DecisionService is defined by four lists: inputData, inputDecisions, outputDecisions, and encapsulatedDecisions. The lists are not independent and thus not all required to be specified, e.g., each required decision (direct and indirect) of the outputDecisions must be an encapsulatedDecision, an inputDecision, or required by an inputDecision. For simplicity in the following, we assume that all four lists are correctly and completely specified.
A DecisionService is given execution semantics by mapping it to a FEEL function F. Let S be a DecisionService with input data id1, id2, …, input decisions di1, di2, …, encapsulated decisions de1, de2, …, and output decisions do1, do2, …. Each input data idi has a qualified name nidi. Each decision di has a qualified name ndi and a decision logic expression ed. The decisions may have knowledge requirements. In particular the decisions may require BusinessKnowledgeModels bkm1, bkm2, … and DecisionServices s1, s2, …. BusinessKnowledgeModels have qualified names nbkmi and encapsulatedLogic fbkmi. DecisionServices have qualified names nsi and equivalent logic fsi, where the equivalent logic is defined recursively, binding si to S.
The syntax for FEEL function F is funcion(nid1, nid2, …, ndi1, ndi2, … ) C.result, where C is the context \{
ns1 : fs1, ns2 : fs2, …,
nbkm1 : fbkm1, nbkm2 : fbkm2, …,
nde1 : ede1, nde2 : ede2, …,
result: \{ ndo1 : edo1, ndo2 : edo2, . ..}
such that si, bkmi, dei and doi are partially ordered by requirements (e.g., the context entry for a required decision comes before a decision that requires it).
The qualified name of an element named E (decision, input data, decision service, or BKM) that is defined in the same decision model as S is simply E. Otherwise, the qualified name is I.E, where I is the name of the import element that refers to the model where E is defined.
The execution semantics of S is FEEL(F): a function that when invoked with values from the FEEL semantic domain bound to the parameters representing input data and input decisions, returns:
In the case of a single output decision(s), the single decision’s output value.In the case of multiple output decisions, a context consisting of all the output decisions' output values.XML elements SHALL map to the FEEL semantic domain as specified in section 10.3.3. Otherwise, details of the syntax of input/output data values and mapping to/from FEEL are undefined.
[_Toc87278866 .anchor]#Figure 10‑27: Expression class diagram
The class Expression is extended to support the four new kinds of boxed expressions introduced by FEEL, namely: Context, FunctionDefinition, Relation and List.
Boxed expressions are Expressions that have a standard diagrammatic representation (see clauses 7.2.1 and 10.2.1). FEEL contexts, function definitions, relations and lists SHOULD be modeled as Context, FunctionDefinition, Relation and List elements, respectively, and represented as a boxed expression whenever possible; that is, when they are top-level expressions, since an instance of LiteralExpression cannot contain another Expression element.
A Context is composed of any number of contextEntrys, which are instances of ContextEntry.
A Context element is represented diagrammatically as a boxed context (clause 10.2.1.4). A FEEL context (grammar rule 57 and clause 10.3.2.6) SHOULD be modeled as a Context element whenever possible.
Context inherits all the attributes and model associations from Expression. Table 83 presents the additional attributes and model associations of the Context element.
_ Attribute _ | _ Description _ |
---|---|
|
|
The class ContextEntry is used to model FEEL context entries when a context is modeled as a Context element. ContextEntry is a specialization of DMNElement, from which it inherits the optional id, description, and label attributes.
An instance of ContextEntry is composed of an optional variable, which is an InformationItem element whose name is the key in the context entry, and of a value, which is the instance of Expression that models the expression in the context entry.
Table 84 presents the attributes and model associations of the ContextEntry element.
_ Attribute _ | _ Description _ |
---|---|
|
|
|
|
A FunctionDefinition has formalParameters and a body. A FunctionDefinition element is represented diagrammatically as a boxed function, as described in clause. A FEEL function definition (grammar rule 55 and clause 10.3.2.15) SHOULD be modeled as a FunctionDefinition element whenever possible.
FunctionDefinition inherits all the attributes and model associations from Expression. Table 85 presents the additional attributes and model associations of the Function Definition element.
_ Attribute _ | _ Description _ |
---|---|
|
|
|
|
|
Java |
PMML } __ |
|
A List is simply a list of element, which are instances of Expressions. A List element is represented diagrammatically as a boxed list, as described in clause 10.2.1.5. A FEEL list (grammar rule 54 and clause 10.3.2.15) SHOULD be modeled as a List element whenever possible.
List inherits all the attributes and model associations from Expression. Table 86 presents the additional attributes and model associations of the List element.
_ Attribute _ | _ Description _ |
---|---|
|
|
A Relation is convenient shorthand for a list of similar contexts. A Relation has a column instead of repeated ContextEntrys, and a List is used for every row, with one of the List’s expression for each column value.
Relation inherits all the attributes and model associations from Expression. Table 87 presents the additional attributes and model associations of the Relation element.
_ Attribute _ | _ Description _ |
---|---|
|
|
|
|
A Conditional is a visual way to express an if statement.
Conditional inherits all the attributes and model associations from Expression. Table 88 presents the additional attributes and model associations of the Conditional element.
_ Attribute _ | _ Description _ |
---|
if: ChildExpression | This attribute holds the expression that is evaluate by the conditional expression. |
---|---|
then: ChildExpression |
This attribute holds the expression that will be evaluated when the condition in the if statement evaluates to true. |
else: ChildExpression |
This attribute holds the expression that will be evaluated when the condition in the if statement evaluates to false. |
A ChildExpression is used to hold an expression inside a node. Table 89 presents the attributes of a ChildExpression.
_ Attribute _ | _ Description _ |
---|---|
id: ID[0..1] |
Optional identifier for this element. SHALL be unique within its containing Definitions element. |
value: Expression |
The instance of Expression that is the expression in this ChildExpression |
A Filter is a visual way to express list filtering.
Filter inherits all the attributes and model associations from Expression. Table XX presents the additional attributes and model associations of the Filter element.
_ Attribute _ | _ Description _ |
---|---|
in: ChildExpression |
This attribute holds the expression that is evaluate as the collection to be filtered. |
match: ChildExpression |
This attribute holds the expression that is used to filter the collection. |
An Iterator is the abstract class for all boxed iteration.
Iterator inherits all the attributes and model associations from Expression. Table 91 presents the additional attributes and model associations of the Iterator element.
_ Attribute _ | _ Description _ |
---|---|
iteratorVariable: String |
This attribute holds name of the iterator variable that will be populated at each iteration. |
in: TypedChildExpression |
This attribute holds the expression that is evaluated as the collection to be processed. |
A For is a representation of a loop.
For inherits all the attributes and model associations from Iterator. Table 92 presents the additional attributes and model associations of the For element.
_ Attribute _ | _ Description _ |
---|---|
return: ChildExpression |
This attribute holds the expression that is evaluated to create the new collection that will be returned. |
A Quantified is an abstraction of an expression that is evaluated on each item of a collection.
Quantified inherits all the attributes and model associations from Iterator. Table XX presents the additional attributes and model associations of Quantified.
_ Attribute _ | _ Description _ |
---|---|
satisfies: ChildExpression |
This attribute holds the expression that is evaluated to determine if the current item satisfies a condition. |
Every is an expression where all “satisfies” needs to be true for it to return true.
Every inherits all the attributes and model associations of Quantified.
A good way to get a quick overview of FEEL is by example.
FEEL expressions may reference other FEEL expressions by name. Named expressions are contained in a context. Expressions are evaluated in a scope, which is a list of contexts in which to resolve names. The result of the evaluation is an element in the FEEL semantic domain.
Figure 10‑28 shows the boxed context used for the examples. Such a context could arise in several ways. It could be part of the decision logic for a single, complex decision. Or, it could be a context that is equivalent to part of a DRG as defined in clause 10.4, where applicant, requested product, and credit history are input data instances, monthly income and monthly outgoings are the results of other decisions linked through information requirements, and PMT is a business knowledge model.
_ applicant _ | _ age _ | 51 | ||||
---|---|---|---|---|---|---|
|
"M" |
|||||
|
false |
|||||
|
|
10000 |
||||
|
2500 |
|||||
|
3000 |
|||||
|
|
"STANDARD LOAN" |
||||
|
0.25 |
|||||
|
36 |
|||||
|
100000.00 |
|||||
|
applicant.monthly.income |
|||||
|
applicant.monthly.repayments, applicant.monthly.expenses |
|||||
|
record date |
|
weight |
|||
date("2008-03-12") |
"home mortgage" |
100 |
||||
date("2011-04-01") |
"foreclosure warning" |
150 |
||||
|
(rate, term, amount) |
|||||
(amount rate/12) / (1 - (1 + rate/12)*-term) |
[_Toc87278867 .anchor]#Figure 10‑28: Example context
Notice that there are 6 top-level context entries, represented by the six rows of the table. The value of the context entry named 'applicant' is itself a context, and the value of the context entry named 'monthly' is itself a context. The value of the context entry named 'monthly outgoings' is a list, the value of the context entry named 'credit history' is a relation, i.e. a list of two contexts, one context per row. The value of the context entry named 'PMT' is a function with parameters 'rate', 'term', and 'amount'.
The following examples use the above context. Each example has a pair of equivalent FEEL expressions separated by a horizontal line. Both expressions denote the same element in the semantic domain. The second expression, the ‘answer’, is a literal value.
[.underline]#monthly income * 12
#120000
The context defines monthly income as applicant.monthly.income, which is also defined in the context as 10,000. Twelve times the monthly income is 120,000.
[.underline]#if applicant.maritalStatus in (“M”, “S”) then “valid” else “not valid”
#“valid”
The in test determines if the left-hand side expression satisfies the list of values or ranges on the right-hand side. If satisfied, the if expression returns the value of the then expression. Otherwise, the value of the else expression is returned.
[.underline]#sum (monthly outgoings)
#5500
Monthly outgoings is computed in the context as the list [applicant.monthly.repayments, applicant.monthly.expenses], or [2500, 3000]. The square brackets are not required to be written in the boxed context.
The PMT function defined in the context computes the monthly payments for a given interest rate, number of months, and loan amount.
PMT (requested product . rate,
requested product . term,
[.underline]#requested product . amount)___
#3975.982590125552338278440100112431
A function is invoked textually using a parenthesized argument list after the function name. The arguments are defined in the context, and are 0.25, 36, and 100,000, respectively.
sum (credit history[record date > date (“2011-01-01”)].weight
150__
This is a complex "one-liner" that will be useful to expand into constituent sub-expressions:
built-in: sumo path expression ending in .weight
filter: [record date > date("2011-01-01 ")]
An expression in square brackets following a list expression filters the list. Credit history is defined in the context as a relation, that is, a list of similar contexts. Only the last item in the relation satisfies the filter. The first item is too old. The path expression ending in .weight selects the value of the weight entry from the context or list of contexts satisfied by the filter. The weight of the last item in the credit history is 150. This is the only item that satisfies the filter, so the sum is 150 as well.