D Apache FreeMarker Reference
Built-In String FreeMarker Operations
tester
, the value of which is sent to "hello world "
(with
three trailing blank spaces).
The following expression allows the bot to output either the
tester
value, or,
no string found
if no value has been set for the
variable.${tester.value!'no string found'}
Built-In Operation | Usage | Output |
---|---|---|
capitalize |
${tester.value?capitalize} |
Hello World |
last_index_of |
${tester.value?last_index_of('orld')} |
7 |
left_pad |
${tester.value?left_pad(3,'_')} |
___hello world |
length |
${tester.value?length} |
14 |
lower_case |
${tester.value?lower_case} |
hello world |
upper_case |
${tester.value?upper_case} |
HELLO WORLD |
replace |
${tester.value?replace('world',
'friends')} |
hello friends |
remove_beginning |
${tester.value?remove_beginning('hello')} |
world |
trim |
${tester.value?trim} |
hello world (the trailing three spaces are
removed)
|
ensure_starts_with |
${tester.value?ensure_starts_with('brave new
')} |
brave new hello world |
ensure_ends_with |
${tester.value?ensure_ends_with(' my
friend')}$ |
hello world my friend |
contains |
${tester.value?contains('world')?string ('You said world',
'You did not say world')} |
You said world The
|
ends_with |
${tester.value?ends_with('world')?string ('Ends with
world', 'Doesn't end with world')} |
Ends with world |
starts_with |
${tester.value?starts_with('world')?string ('Starts with
world', 'Doesn't start with world')} |
Doesn't start with world |
matches (regular expression returns true or
false)
|
${tester.value?matches('^([^0-9]*)$')} |
The regular expression returns true or
false depending on whether the value contains a number (in which
case the boolean value is returned as false ). The
tester value returns true .
|
matches (regular expression returns a
string)
|
${tester.value?matches('^([^0-9]*)$')?} |
Same as above, but this time, true is returned as
a string. The matches('regular expression') function returns
true or false as boolean types. To print
true or false in a
System.Output component, use ?string to perform
a to-string conversion.
Note: You can’t use regular expression to return a group of values; use them to return a single matching value (or no match). |
Example: Transforming Case with the Switch Component
Imagine a case where different states get called depending on the user input (wine
or beer), which is stored in the choice
variable.
upper_case
to make the casing
uniform:${choice.value?upper_case}
Example: Concatenating FTL Expressions
You can also concatenate FTL operations into a single expression.
flight.value
variable) of UA1234
and UA
1234
would both be transformed to 1234
.
${flight.value?trim?lower_case?remove_beginning('ua ')?remove_beginning('ua')}"
Built-In FreeMarker Number Operations
negativeValue
(-2.5) and positiveValue
(0.5175)
variables:
Operation | Example | Output |
---|---|---|
abs |
${negativeValue.value?abs} |
2.5
The operator turns the negative numeric value into a positive value. |
string (used with a numerical value)
|
${negativeValue.value?abs?string.percent} |
250%
The operator first changes the negative value to a positive. Then it converts it into percent, implicitly multiplying the value by 100. |
string (with the decimal format
value and various currencies)
Tip: Check out Charbase for other currency symbols. |
${positiveValue.value?string['###.##']} |
0.51 |
${positiveValue.value?string['###.##%']} |
51%
The operator adds adding a percentage character after multiplying the value by 100. |
|
${positiveValue.value?string['##.###\u00A4']} |
0.51 $ | |
${positiveValue.value?string['##.###\u20AC']} |
0.51 € | |
${positiveValue.value?string['##.###\u00A3']} |
0.51 £ | |
round |
${negativeValue.value?round} |
-2
The operator rounds to the nearest whole number. If the number ends with .5, then it rounds upwards. |
${positiveValue.value?round} |
1
The operator rounds to the nearest whole number. If the number ends with .5, then it rounds upwards. |
|
floor |
${positiveValue.value?floor} |
0
The operator rounds downwards. |
ceiling |
${positiveValue.value?ceiling} |
1
The operator rounds upwards. |
lower_abc |
${negativeValue.value?abs?round?lower_abc} |
c
The operator turns the negative value into a positive, then rounds it to 3. It returns c, the third letter of the alphabet. |
upper_abc |
${negativeValue.value?abs?round?upper_abc} |
C
The operator turns the negative value into a positive, then rounds it to 3. It returns C, the third letter of the alphabet. |
is_infinite |
${positiveValue.value?is_infinite?string} |
false
The operator returns false, because a float value is not infinite according to IEEE 754 (Standard for Floating-Point Arithmetic). Note: The returned value would be a boolean
without |
Built-In FreeMarker Array Operations
Array (or sequence) operations enable your bot to, among other things, determine the size of an array, sort arrays, or find content within an array.
person
and colors
variables,
respectively.[
{
"firstName" : "Frank",
"lastName" : "Normal"
},
{
"firstName" : "Grant",
"lastName" : "Right"
},
{
"firstName" : "Geoff",
"lastName" : "Power"
},
{
"firstName" : "Marcelo",
"lastName" : "Jump"
}
]
[
"yellow", "blue", "red", "black", "white", "green"
]
These
arrays are used to illustrate the array operations in the following table and in Example: Iterating Arrays.
Operator | Example | Output |
---|---|---|
size |
${person.value?size?number} |
4 —The size (four members) of the person array
|
array index | ${person.value[1].firstName} |
Grant —It’s the value of the second firstName property in the person array.
|
${person.value[1].firstName !'unknown'} |
Same as the above, but in this case, the bot outputs unknown if the second firstName property has no value.
|
|
first |
${person.value?first.firstName} |
Frank —The first entry of the person array. This operation doesn’t use the array index.
|
last |
${person.value?last.firstName} |
Marcelo —The final lastName value in the person array.
|
sort_by |
${person.value?sort_by('lastName') [0].firstName} |
Marcelo This operator sorts the
person array by the lastName property in ascending order. It then prints the value of the corresponding firstName property for final entry in the person array:
Note: Unless you save the sorted array in a variable using |
${person.value?sort_by('lastName')?reverse[0].firstName} |
Grant —the values are sorted in descending order:
|
|
seq_index_of |
${colors.value?seq_index_of('red')} |
2 —The index value for red in the colors array.
|
seq_last_index_of |
${colors.value?seq_last_index_of('red')} |
2 —The last index value for red in the
|
join |
${colors.value?join(',')} |
Returns the colors array as a comma-separated string: yellow, blue, red, black, white, green |
seq_contains |
${colors.value?seq_contains('red')?string('Yes', 'No') |
Returns Yes because the array contains red.
Note: |
sort |
${colors.value?sort?join(',')} |
Returns the colors array as a comma-separated string in ascending order: black, blue, green, red, white, yellow |
reverse |
${colors.value?sort?reverse?join(',')} |
Returns the colors array as a comma-separated string in descending order: yellow, blue, red, black, white, green |
Returning Intents and Scores
-
${skill.system.nlpresult.value.entityMatches[‘name of entity’]}
returns an array of entities found in a user string that’s passed to the Intent Engine stored in thenlpresult
variable. -
${skill.system.nlpresult.value.intentMatches.summary[n].intent}
returns the name of the intent that has a confidence ranking ofn
, where0
represents the top-ranked intent,1
represents the second ranked intent, etc. ${skill.system.nlpresult.value.intentMatches.summary[n].score}
returns the confidence score for the given intent.
n
is the index of the item you want to
look up. For example, the expression to return the top-resolved intent name would
be:${skill.system.nlpresult.value.intentMatches.summary[0].intent}
For the top intent's score, the expression would
be:${skill.system.nlpresult.value.intentMatches.summary[0].score}
You can use these expressions for intents that scored above the confidence
threshold, but you can also use them to return intents whose score falls below the
confidence threshold. These expressions are not dependent on the confidence threshold
value that's configured in the Skill's Settings page, so you can
use them to return the candidate intents and their scores even when no intent could be
resolved and an unresolvedIntent
action has been triggered. In this
case, you can, for example, use these expressions to return the top three intents and
their sub-confidence threshold scores.
If you need to refer to the intent that a user has selected after being asked to disambiguate, you can use
${system.intent.name}
.
(${skill.system.nlpresult.value.intentMatches.summary[0].intent}
always returns the intent with the top score, which might not be the intent that the
user selects when disambiguating.
Example: Iterating Arrays
Arrays determine the number of entities in the user input.
The following snippet from a Common Response component's Metadata property shows
how to determine the size of the array held in the person
variable and then
iterate over its elements so that the skill outputs something like:
responseItems:
- type: "text"
text: "${person?index+1}. ${person.firstName} ${person.lastName}"
name: "Sorry"
separateBubbles: true
iteratorVariable: "person"
The output described in this code is not sorted (that is, no
sort_by
operation is used).
Built-In FreeMarker Date Operations
.now
and the built-in date
operator.
${.now?date}
Operation(s) | Example | Output |
---|---|---|
date |
${.now?date} |
The current date |
time |
${.now?time} |
The time of day, like 5:46:09 PM |
datetime |
${.now?datetime} |
Prints current date and time, like Jan 17, 2018 5:36:13 PM. |
long and number_to_date |
${(.now?long + 86400000)?number_to_date } |
Adds 24 hours to the current date. If the call is made on January 17, 2018, FreeMarker outputs January 18, 2018. |
string (with formatting styles)
|
${.now?string.full} |
Converts the current date to string formatted as Wednesday, January 17, 2018 6:35:12 PM UTC. |
${.now?string.long} |
Converts date to string with the following formatted output: January 17, 20186:36:47 PM UTC. | |
${.now?string.short} |
Converts date to string with the following formatted output: 1/17/18 6:37 PM | |
${.now?string.medium} |
Converts date to string with the following formatted output: Jan 17, 2018 6:38:35. | |
${.now?string.iso} |
Prints the date in the ISO 8601 standard like 2018-01-17T18:54:01.129Z. |
|
string (with specified output formats)
|
${.now?string['dd.MM.yyyy, HH:mm']} |
Prints the current date in a custom format, like 17.01.2018, 18:58. |
${.now?string['yyyy']} |
2018 |
|
datetime (with string and formatting style)
|
${date_variable?datetime?string.short} |
Converts the date to a string formatted as 1/17/18 6:37 PM.
The |
Converting the entity value to a string using
|
${dateVar.value.date?long?number_to_date?date?string.short} |
Converts the date from the entity extraction to a string formatted as 11/17/18.
The date operator tells FreeMarker that the variable only holds a date, not time information. Using this format avoids errors. |
${dateVar.value.date?long?number_to_date?string.medium} |
Converts the date that’s derived from entity extraction to a string formatted as Jan 17, 2018.
Note: All other formats like |
|
${dateVar.value.date?long?number_to_date?string['dd.MM.yyyy']} |
Prints the date in custom format. For example: 17.01.2018, 18:58. | |
${dateVar.value.date?long?number_to_date?string['yyyy']} |
Prints the date derived from the entity in a custom format. |
Example: Extracting Dates from User Input
DATE
, to extract tomorrow from the request. It outputs
the requested date using ${(theDate.value.date?long +
86400000)?number_to_date}
to add 24 hours (or 86,400,000 milliseconds) to
"tomorrow".
Text with Expression | Output |
---|---|
|
|
|
|
|
|
FreeMarker-Accessible System Variables
Oracle Digital Assistant has a set of system variables through which you can retrieve useful information in your dialog flows through FreeMarker expressions.
In their simplest forms, these expressions take the following form:
${system.variableName}
Some variables can hold objects with nested properties that can be accessed using dot notation after the variable name in the following form.
${system.variableName.propertyName}
In addition, the nested property values can also be objects with nested properties.
Here are the system variables that are available through FreeMarker expressions.
Variable | Description |
---|---|
system.actualState |
Name of the state the user has navigated to by tapping an older "out-of-order" button. If the postback payload contains a system.state property, the dialog engine will navigate to this state and sets this variable to the name of that state. See also Configure the Dialog Flow for Unexpected Actions.
|
system.authorizedUsers |
A list of all of the users that have been authorized for a given group chat. |
system.channelType |
The type of channel of the current user session. Allowable values:
facebook , androidsdk ,
iossdk , websdk ,
slack , twilio ,
msteams , cortana ,
webhook , and test .
If the session is running in the tester, the value corresponds to the channel type being simulated. |
system.entityToResolve |
Object representing the current composite bag item to resolve in the Common
Response component when the variable property of the component is
referring to a composite bag entity.The object has the following
properties:
See The system.entityToResolve Variable for examples of how to use |
system.errorAction |
Error message text of an unexpected error thrown during execution of the state. |
system.errorState |
Name of the state that has thrown an unexpected error during execution. |
system.expectedState |
When user scrolls up the message history, and taps on an older "out-of-order" button this variable is populated with the name of the state that was expected to be executed, but never got executed because the user decided to tap on this "out-of-order" button. See also Configure the Dialog Flow for Unexpected Actions. |
system.intent.name |
Use to refer to the intent that a user has selected after
being asked to disambiguate.
(
always returns the intent with the top score, which might not be the
intent that the user selects when disambiguating.) |
system.invalidUserInput |
Boolean value set to true when the user input cannot be matched to the requested variable type.
|
system.message |
Last message received by Oracle Digital Assistant. This variable has the following properties:
|
system.requestedState |
If a users enters a conversation at a state that requires authorization and the user is not in the list of users stored in system.authorizedUsers , the dialog engine stores the state it intended to execute in this variable.
|
system.selectedCardIndex |
This variable holds the index of the selected card when using the facility to optimize card rendering for text-only channels like Twilio. This optimization allows the user to select a card in a two step process: first a list of cards is presented, then the user can enter the number of the cards he wants to select. The corresponding index number of this card is stored in this variable. |
The system variables in the above table are the only ones that you can use in FreeMarker expressions. Other system variables are not public and their use is subject to change, which means your skills can't rely on them.
For example, the system.routingFromSkill
,
system.routingToSkill
,
system.routingFromIntent
, and
system.routingToIntent
variables are only available for
specific digital assistant settings. See System Variables for Digital Assistants.