The following table shows you how to use some of the built-in string operations using a string variable called
tester, the value of which is sent to "hello world " (with
three trailing blank spaces).
Note
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
contains('world') expressions returns either
true or false. These boolean values are
replaced with a string using the string ('string1','string2')
function.
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.
The casing of user input may be inconsistent, even within a word (WiNE). Instead of
adding all possible variations to the component definition, use an FTL operation like
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.
In the following example, airline flight numbers (represented by the
flight.value variable) of UA1234 and UA
1234 would both be transformed to 1234.
The following table lists the built-in
number operations and shows how they output the value set for the
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 ?string.
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.
You can use arrays to create mock data for testing, or for defining data structures
that persist beyond user sessions. You can save an array in a custom component, in a flow or
global variable. Here are arrays for person and colors
variables,
respectively.
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:
Jump, Marcelo
Normal, Frank
Power, Geoff
Right, Grant
Note: Unless you save the sorted array in a variable using System.SetVariable, the data remains sorted for a single request only.
Note: ?seq_contains returns a boolean value. This value
is then replaced by a string using the ?string('…','…')
expression.
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 🔗
You can use array operations to return the results from the intent and entity
processing. For example:
${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 the nlpresult
variable.
${skill.system.nlpresult.value.intentMatches.summary[n].intent}
returns the name of the intent that has a confidence ranking of
n, where 0 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.
For these two expressions, 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:
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.
Note
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:
The output described in this code is not sorted (that is, no sort_by operation is used).
Built-In FreeMarker Date Operations 🔗
The following expression derives the current date using the FreeMarker special
variable reference, .now and the built-in date operator.
${.now?date}
The following table lists some of the built-in date operations that you can use to define properties and manipulate entity values.
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 datetime operator enables FreeMarker to tell if the variable holds a date that contains both date and time information. Similarly, you can use the date or time operators to indicate if the date value contains only the date or only the time, but using datetime?string avoids errors.
Prints the date derived from the entity in a custom format.
Example: Extracting Dates from User Input 🔗
The following examples are from a skill that manages appointments. When a user asks
it, Can you arrange a meeting with Mr. Higgs a day later than tomorrow?, the bot uses a
complex entity, 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
"Today is: ${.now}"
Today is: 1/18/18 8:31 AM
"Date found is: ${theDate.value.date}"
Date found is: Jan 19, 2018
"A day later is ${(theDate.value.date?long + 86400000)?number_to_date}"
A day later is Jan 20, 2018
Example: Setting a Default Date (When No Date Value Is Set) 🔗
If the user message doesn’t include any date information, your skill can prompt
users for the date, or provide a default date. To provide the current date, you can use the
following expression:
${.now?datetime?string.long}
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:
nextRangeStart - index number of
the entity's allowable value list that will be navigated to when
tapping the Show More button.
updatedEntities - list of
composite bag items that were updated based on the last user
message.
needShowMoreButton - Boolean
property that can be used in as an expression
for the visible property to conditionally
render the Show More button to navigate
to the next set of entity values.
outOfOrderMatches - list of bag
items that were populated with a value based on the last user
message when the user was prompted for another bag item.
rangeStartVar - name of the variable that holds
the current range start of the entity values.
validationErrors - for the current bag item,
list of error messages caused by an invalid value provided in
the last user message.
allMatches - list of bag items that
got a new or updated values based on the last user message.
resolvingField - name of current
bag item the user is prompted for.
userInput - the last user
message.
skippedItems - list of bag items
where the maximum number of prompts for a value is
exceeded.
disambiguationValues - list of
allowed entity values that have matches in the last user
message.
enumValues - list of entity
allowed values for the current bag item.
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.
(
${iResult.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.)
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:
channelConversation - the channel conversation object, which has the following properties:
botId
channelType - When running in the tester, this will return test. If you want to get the name of the channel that is being simulated in the tester, use system.channelType instead.
channelName
channelCategory - Returns the type of channel. For DA as Agent
channels, this returns botAsAgent.
groupConversation - Returns true if the conversation is a group chat.
userId - Returns the user ID. For DA as Agent channels, this will
return the engagement ID.
sessionId - Returns the session ID. For DA as Agent channels, this
will return the engagement ID.
sessionExpiryDuration
messagePayload - the actual message sent by the user. The properties you can access depend on the type of message:
Text message: the text property returning the actual message entered by the user
Postback message: the properties of the postback object, typically
action and
variables when using the Common
Response component. For example, when the user taps a
button that sets the variable
pizzaSize, this value can be retrieved
using following
expression:${system.message.messagePayload.variables.pizzaSize}
Location message: the location property, which holds a location object with following properties:
title
url
latitude
longitude
stateCount - the number of states executed to process the last user message.
platformVersion - the current runtime platform version.
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.
Note
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.