NIFI-218: Added isEmpty and replaceEmpty functions to doc

//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
Apache NiFi Expression Language Guide
=====================================
Apache NiFi Team <dev@nifi.incubator.apache.org>
:homepage: http://nifi.incubator.apache.org

[[overview]]
Overview
--------
All data in Apache NiFi is represented by an abstraction called a FlowFile.
A FlowFile is comprised of two major pieces: content and attributes.
The content portion of the FlowFile represents the data on which to operate.
For instance, if a file is picked up from a local file system using the
GetFile Processor, the contents of the file will become the contents of the
FlowFile.

The attributes portion of the FlowFile represents information about the data
itself, or metadata. Attributes are key-value pairs that represent what is
known about the data as well as information that is useful for routing and
processing the data appropriately.
Keeping with the example of a file that is picked up from
a local file system, the FlowFile would have an attribute called `filename` that
reflected the name of the file on the file system. Additionally, the FlowFile will
have a `path` attribute that reflects the directory on the file system that this
file lived in. The FlowFile will also have an attribute named `uuid`, which is a
unique identifier for this FlowFile.

However, placing these attributes on a FlowFile do not provide much benefit
if the user is unable to make use of them. The NiFi Expression Language provides
the ability to reference these attributes, compare them to other values,
and manipulate their values.

[[structure]]
Structure of a NiFi Expression
------------------------------

The NiFi Expression Language always begins with the start delimiter `${` and ends
with the end delimiter `}`. Between the start and end delimiters is the text of the
Expression itself. In its most basic form, the Expression can consist of just an
attribute name. For example, `${filename}` will return the value of the ``filename''
attribute.

In a slightly more complex example, we can instead return a manipulation of this value.
We can, for example, return an all upper-case version of the filename by calling the
`toUpper` function: `${filename:toUpper()}`. In this case, we reference the ``filename''
attribute and then manipulate this value by using the `toUpper` function. A function call
consists of 5 elements. First, there is a function call delimiter `:`. Second is the name
of the function - in this case, ``toUpper''. Next is an open parenthesis (`(`), followed
by the function arguments. The arguments necessary are dependent upon which function
is being called. In this example, we are using the `toUpper` function, which does not
have any arguments, so this element is omitted. Finally, the closing parenthesis (`)`)
indicates the end of the function call. There are many different functions that are supported
by the Expression Language to achieve many different goals. Some functions provide String (text)
manipulation, such as the `toUpper` function. Others, such as the `equals` and `matches` functions,
provide comparison functionality. Functions also exist for manipulating dates and times and
for performing mathematical operations. Each of these functions is described below, in the
<<functions> section, with an explanation of what the function does, the arguments that it
requires, and the type of information that it returns.

When we perform a function call on an attribute, as above, we refer to the attribute as the
_subject_ of the function, as the attribute is the entity on which the function is operating.
We can then chain together multiple function calls, where the return value of the first function
becomes the subject of the second function and its return value becomes the subject of the third
function and so on. Continuing with our example, we can chain together multiple functions by using
the expression `${filename:toUpper():equals('HELLO.TXT')}`. There is no limit to the number of
functions that can be chained together.

Any FlowFile attribute can be referenced using the Expression Language. However, if the attribute
name contains a ``special character,'' the attribute name must be escaped by quoting it. The following
characters are each considered ``special characters'':

- $ (dollar sign)
- | (pipe)
- { (open brace)
- } (close brace)
- ( (open parenthesis)
- ) (close parenthesis)
- [ (open bracket)
- ] (close bracket)
- , (comma)
- : (colon)
- ; (semicolon)
- / (forward slash)
- * (asterisk)
- ' (single quote)
-  (space)
- \t (tab)
- \r (carriage return)
- \n (new-line)

Additionally, a number is considered a ``special character'' if it is the first character of the attribute name.
If any of these special characters is present in an attribute is quoted by using either single or double quotes.
The Expression Language allows single quotes and double quotes to be used interchangeably. For example, the following
can be used to escape an attribute named ``my attribute'': `${"my attribute"}` or `${'my attribute'}`.

In this example, the value to be returned is the value of the "my attribute" value, if it exists. If that attribute
does not exist, the Expression Language will then look for a System Environment Variable named "my attribute." If
unable to find this, it will look for a JVM System Property named "my attribute." Finally, if none of these exists,
the Expression Language will return a `null` value.

There also exist some functions that expect to have no subject. These functions are invoked simply
by calling the function at the beginning of the Expression, such as `${hostname()}`. These functions
can then be changed together, as well. For example, `${hostname():toUpper()}`. Attempting to
evaluate the function with subject will result in an error. In the <<functions>>
section below, these functions will clearly indicate in their descriptions that they do not
require a subject.

Often times, we will need to compare the values of two different attributes to each other.
We are able to accomplish this by using embedded Expressions. We can, for example, check if
the ``filename'' attribute is the same as the ``uuid'' attribute: `${filename:equals( ${uuid} )}`.
Notice here, also, that we have a space between the opening parenthesis for the `equals` method and
the embedded Expression. This is not necessary and does not affect how the Expression is evaluated
in any way. Rather, it is intended to make the Expression easier to read. White space is ignored by
the Expression Language between delimiters. Therefore, we can use the Expression
`${     filename   : equals(${    uuid})  }` or `${filename:equals(${uuid})}` and both Expressions
mean the same thing. We cannot, however, use `${file name:equals(${uuid})}`, because this results
in `file` and `name` being interpreted as different tokens, rather than a single token, `filename`.

[[usage]]
== Expression Language in the Application

The Expression Language is used heavily throughout the NiFi application for configuring Processor
properties. Not all Processor properties support the Expression Language, however. Whether or not
a Property supports the Expression Language is determined by the developer of the Processor when
the Processor is written. However, the application strives to clearly illustrate for each Property
whether or not the Expression Language is supported.

In the application, when configuring a Processor property, the User Interface provides an Information
icon (
image:iconInfo.png["Info"]
) next to the name of the Property. Hovering over this icon with the mouse will provide a tooltip that
provides helpful information about the Property. This information includes a description of the Property,
the default value (if any), historically configured values (if any), and whether or not this Property
supports the expression language.

[[editor]]
=== Expression Language Editor

When configuring the value of a Processor property, the NiFi User Interface provides help with the
Expression Language using the Expression Language editor. Once an Expression is begin by typing `${`,
the editor begins to highlight parentheses and braces so that the user is easily able to tell which
opening parenthesis or brace matches which closing parenthesis or brace.

The editor also supplies context-sensitive help by providing a list of all functions that can be used
at the current cursor position. To activate this feature, press Ctrl+Space on the keyboard. The user
is also able to type part of a function name and then press Ctrl+Space to see all functions that can
be used that start with the same prefix. For example, if we type into the editor `${filename:to`
and then press Ctrl+Space, we are provided a pop-up that lists six different functions: `toDate`,
`toLower`, `toNumber`, `toRadix`, `toString`, and `toUpper`. We can then continue typing to narrow
which functions are shown, or we can select one of the functions from the list by double-clicking
it with the mouse or using the arrow keys to highlight the desired function and pressing Enter.

[[functions]]
== Functions

Functions provide a convenient way to manipulate and compare values of attributes. The Expression Language
provides many different functions to meet the needs of a automated dataflow. Each function takes
zero or more arguments and returns a single value. These functions can then be chained together to create
powerful Expressions to evaluate conditions and manipulate values. See <<structure>> for more information
on how to call and chain functions together.

[[types]]
=== Data Types

Each argument to a function and each value returned from a function has a specific data type. The Expression
Language supports four different data types:

- *String*: A String is a sequence of characters that can consist of numbers, letters, white space, and
	special characters.
- *Number*: A Number is an integer comprised of one or more digits (`0` through `9`). The Expression Language
	does not provide support for fractional numbers. Dates and times are represented in the
	Expression Language as Numbers, representing the number of milliseconds since midnight GMT on January 1, 1970.
- *Boolean*: A Boolean is one of either `true` or `false`.

All attributes are considered to be of type String.

The Expression Language is generally able to automatically coerce a value of one data type to the appropriate
data type for a function. However, functions do exist to manually coerce a value into a specific data type.
See the <<type_cast>> section for more information.

[[boolean]]
== Boolean Logic

One of the most powerful features of the Expression Language is the ability to compare an attribute value against
some other value. This is used often, for example, to configure how a Processor should route data. The following
functions are used for performing boolean logic, such as comparing two values.
Each of these functions returns a value of type Boolean.

[.function]
=== isNull
*Description*: [.description]#The `isNull` function returns `true` if the subject is null, `false` otherwise. This is typically used to determine
if an attribute exists.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Boolean#

*Examples*:	`${filename:isNull()}` returns `true` if the "filename" attribute does not exist.
	It returns `true` if the attribute exists.

[.function]
=== notNull
*Description*: [.description]#The `notNull` function returns the opposite value of the `isNull` function. That is, it will return `true` if the
subject exists and `false` otherwise.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Boolean#

*Examples*: `${filename:notNull()}` returns `true` if the "filename" attribute exists. It returns "false" if the attribute
	does not exist.

[.function]
=== isEmpty
*Description*: [.description]#The `isEmpty` function returns `true` if the Subject is null or contains only white-space
	(new line, carriage return, space, tab), `false` otherwise.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#Boolean#

*Examples*: `${filename:isEmpty()}` returns `true` if the "filename" attribute does not exist or contains only
	white space.

[.function]
=== equals

[.description]
*Description*: [.description]#The `equals` function is very widely used and determines if its subject is equal to another String value.
	Note that the `equals` function performs a direct comparison of two String values. Take care not to confuse this
	function with the <<matches>> function, which evaluates its subject against a Regular Expression.#

[.subject]
*Subject Type*: [.subject]#Any#

[.arguments]
*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to compare the Subject to. Must be same type as the Subject.#

[.returnType]
*Return Type*: [.returnType]#Boolean#

[.examples]
*Examples*:
We can check if the filename of a FlowFile is "hello.txt" by using the expression `${filename:equals('hello.txt')}`,
or we could check if the value of the attribute `hello` is equal to the value of the `filename` attribute:
`${hello:equals( ${filename} )}`.

[.function]
=== equalsIgnoreCase
*Description*: [.description]#Similar to the `equals` function, the `equalsIgnoreCase` function compares its subject against a String value but returns
`true` if the two values differ only by case (upper case vs. lower case).#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${filename:equalsIgnoreCase('hello.txt')}` will evaluate to `true` if filename is equal to "hello.txt"
	or "HELLO.TXT" or "HeLLo.TxT".

[.function]
=== gt
*Description*: [.description]#The `gt` function is used for numeric comparison and returns `true` if the subject is Greater Than
	its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:gt( 1024 )}` will return `true` if the size of the FlowFile's content is more than 1 kilobyte
	(1024 bytes). Otherwise, it will return `false`.

[.function]
=== ge
*Description*: [.description]#The `ge` function is used for numeric comparison and returns `true` if the subject is Greater Than
	Or Equal To its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:ge( 1024 )}` will return `true` if the size of the FlowFile's content is at least (
	is greater than or equal to) 1 kilobyte (1024 bytes). Otherwise, it will return `false`.

[.function]
=== lt
*Description*: [.description]#The `lt` function is used for numeric comparison and returns `true` if the subject is Less Than
	its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:lt( 1048576 )}` will return `true` if the size of the FlowFile's content is less than
	1 megabyte (1048576 bytes). Otherwise, it will return `false`.

[.function]
=== le
*Description*: [.description]#The `le` function is used for numeric comparison and returns `true` if the subject is Less Than
	Or Equal To its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:le( 1048576 )}` will return `true` if the size of the FlowFile's content is at most
	(less than or equal to) 1 megabyte (1048576 bytes). Otherwise, it will return `false`.

[.function]
=== and
*Description*: [.description]#The `and` function takes as a single argument a Boolean value and returns `true` if both the Subject
	and the argument are `true`. If either the subject or the argument is `false` or cannot be coerced into a Boolean,
	the function returns `false`. Typically, this is used with an embedded Expression as the argument.#

*Subject Type*: [.subject]#Boolean#

*Arguments*:

	- [.argName]#_condition_# : [.argDesc]#The right-hand-side of the 'and' Expression#

*Return Type*: [.returnType]#Boolean#

*Examples*: We can check if the filename is both all lower-case and has at least 5 characters by using the Expression
-----------------------------------------------
${filename:toLower():equals( ${filename} ):and(
	${filename:length():ge(5)}
)}
-----------------------------------------------

[.function]
=== or

*Description*: [.description]#The `or` function takes as a single argument a Boolean value and returns `true` if either the Subject
	or the argument is `true`. If both the subject and the argument are `false`, the function returns `false`. If
	either the Subject or the argument cannot be coerced into a Boolean value, this function will return `false`.#

*Subject Type*: [.subject]#Boolean#

*Arguments*:

	- [.argName]#_condition_# : [.argDesc]#The right-hand-side of the 'and' Expression#

*Return Type*: [.returnType]#Boolean#

*Examples*: The following example will return `true` if either the filename has exactly 5 characters or if
	the filename is all lower-case.
----------------------------------------------
${filename:toLower():equals( ${filename} ):or(
	${filename:length():equals(5)}
)}
----------------------------------------------

[.function]
=== not

[.description]
*Description*: [.description]#The `not` function returns the negation of the Boolean value of the subject.#

[.subject]
*Subject Type*: [.subject]#Boolean#

[.arguments]
*Arguments*: No arguments

[.returnType]
*Return Type*: [.returnType]#Boolean#

[.examples]
*Examples*: We can invert the value of another function by using the `not` function, as
	`${filename:equals('hello.txt'):not()}`. This will return `true` if the filename is NOT equal to
	"hello.txt" and will return `false` if the filename is "hello.txt."

[[strings]]
== String Manipulation

Each of the following functions manipulates a String in some way.

[.function]
=== toUpper

*Description*: [.description]#This function converts the Subject into an all upper-case String. Said another way, it
	replaces any lowercase letter with the uppercase equivalent.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute is "abc123.txt", then the Expression `${filename:toUpper()}`
	will return "ABC123.TXT"

[.function]
=== toLower

*Description*: [.description]#This function converts the Subject into an all lower-case String. Said another way,
	it replaces any uppercase letter with the lowercase equivalent.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute is "ABC123.TXT", then the Expression `${filename:toLower()}`
	will return "abc123.txt"

[.function]
=== trim

*Description*: [.description]#The `trim` function will remove any leading or trailing white space from its subject.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the attribute `attr` has the value "     1 2 3     ", then the Expression `${attr:trim()}` will
	return the value "1 2 3".

[.function]
=== urlEncode

*Description*: [.description]#Returns a URL-friendly version of the Subject. This is useful, for instance, when using an
	attribute value to indicate the URL of a website.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: We can URL-Encode an attribute named "url" by using the Expression `${url:urlEncode()}`. If
	the value of the "url" attribute is "https://nifi.incubator.apache.org/some value with spaces", this
	Expression will then return "https://nifi.incubator.apache.org/some%20value%20with%20spaces".

[.function]
=== urlDecode

*Description*: [.description]#Converts a URL-friendly version of the Subject into a human-readable form.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If we have a URL-Encoded attribute named "url" with the value
	"https://nifi.incubator.apache.org/some%20value%20with%20spaces", then the Expression
	`${url:urlDecode()}` will return "https://nifi.incubator.apache.org/some value with spaces".

[.function]
=== substring

*Description*:
[.description]#Returns a portion of the Subject, given a _starting index_ and an optional _ending index_.
	If the _ending index_ is not supplied, it will return the portion of the Subject starting at the given
	'start index' and ending at the end of the Subject value.#

[.description]#The _starting index_ and _ending index_ are zero-based. That is, the first character is referenced by using
	the value `0`, not `1`.#

[.description]#If either the _starting index_ is or the _ending index_ is not a number, this function call will result
	in an error.#

[.description]#If the _starting index_ is larger than the _ending index_, this function call will result in an error.#

[.description]#If the _starting index_ or the _ending index_ is greater than the length of the Subject or has a value
	less than 0, this function call will result in an error.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_starting index_# : [.argDesc]#The 0-based index of the first character to capture (inclusive)#
	- [.argName]#_ending index_# : [.argDesc]#The 0-based index of the last character to capture (exclusive)#

*Return Type*: [.returnType]#String#

*Examples*:

If we have an attribute named "filename" with the value "a brand new filename.txt",
then the following Expressions will result in the following values:

.Substring Examples
|================================================================
| Expression | Value
| `${filename:substring(0,1)}` | `a`
| `${filename:substring(2)}` | `brand new filename.txt`
| `${filename:substring(12)}` | `filename.txt`
| `${filename:substring( ${filename:length():minus(2)} )}` | `xt`
|================================================================

[.function]
=== substringBefore

*Description*: [.description]#Returns a portion of the Subject, starting with the first character of the Subject
	and ending with the character immediately before the first occurrence of the argument. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringBefore Examples
|======================================================================
| Expression | Value
| `${filename:substringBefore('.')}` | `a brand new filename`
| `${filename:substringBefore(' ')}` | `a`
| `${filename:substringBefore(' n')}` | `a brand`
| `${filename:sbustringBefore('missing')}` | `a brand new filename.txt`
|======================================================================

[.function]
=== substringBeforeLast

*Description*: [.description]#Returns a portion of the Subject, starting with the first character of the Subject
	and ending with the character immediately before the last occurrence of the argument. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String3

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringBeforeLast Examples
|==========================================================================
| Expression | Value
| `${filename:substringBeforeLast('.')}` | `a brand new filename`
| `${filename:substringBeforeLast(' ')}` | `a brand new`
| `${filename:substringBeforeLast(' n')}` | `a brand`
| `${filename:substringBeforeLast('missing')}` | `a brand new filename.txt`
|==========================================================================

[.function]
=== substringAfter

*Description*: [.description]#Returns a portion of the Subject, starting with the character immediately after
	the first occurrence of the argument and extending to the end of the Subject. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringAfter Examples
|======================================================================
| Expression | Value
| `${filename:substringAfter('.')}` | `txt`
| `${filename:substringAfter(' ')}` | `brand new filename.txt`
| `${filename:substringAfter(' n')}` | `ew filename.txt`
| `${filename:substringAfter('missing')}` | `a brand new filename.txt`
|======================================================================

[.function]
=== substringAfterLast

*Description*: [.description]#Returns a portion of the Subject, starting with the character immediately after
	the last occurrence of the argument and extending to the end of the Subject. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringAfterLast Examples
|=========================================================================
| Expression | Value
| `${filename:substringAfterLast('.')}` | `txt`
| `${filename:substringAfterLast(' ')}` | `filename.txt`
| `${filename:substringAfterLast(' n')}` | `ew filename.txt`
| `${filename:substringAfterLast('missing')}` | `a brand new filename.txt`
|=========================================================================

[.function]
=== append

*Description*: [.description]#The `append` function returns the result of appending the argument to the value of
	the Subject. If the Subject is null, returns the argument itself.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to append to the end of the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:append('.gz')}` will return "a brand new filename.txt.gz".

[.function]
=== prepend

*Description*: [.description]#The `prepend` function returns the result of prepending the argument to the value of
	the Subject. If the subject is null, returns the argument itself.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to prepend to the beginning of the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "filename.txt", then the Expression
	`${filename:prepend('a brand new ')}` will return "a brand new filename.txt".

[.function]
=== replace

*Description*: [.description]#Replaces occurrences of one String within the Subject with another String.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Search String_# : [.argDesc]#The String to find within the Subject#
	- [.argName]#_Replacement_# : [.argDesc]#The value to replace _Search String_ with#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.Replace Examples
|===================================================================
| Expression | Value
| `${filename:replace('.', '_')}` | `a brand new filename_txt`
| `${filename:replace(' ', '.')}` | `a.brand.new.filename.txt`
| `${filename:replace('XYZ', 'ZZZ')}` | `a brand new filename.txt`
| `${filename:replace('filename', 'book')}` | `a brand new book.txt`
|===================================================================

[.function]
=== replaceAll

*Description*: [.description]#The `replaceAll` function takes two String arguments: a Regular Expression (NiFi uses the Java Pattern
	syntax), and a replacement string. The return value is the result of substituting the replacement string for
	all patterns within the Subject that match the Regular Expression.#

*Subject Type*: [.subject]#String#

*Arguments*:

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#he Regular Expression (in Java syntax) to match in the Subject#
	- [.argName]#_Replacement_# : [.argDesc]#The value to use for replacing matches in the Subject. If the _regular expression_
		argument uses Capturing Groups, back references are allowed in the _replacement_.#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.replaceAll Examples
|=======================================================================================
| Expression | Value
| `${filename:replaceAll('\..*', '')}` | `a brand new filename`
| `${filename:replaceAll('a brand (new)', '$1')}` | `new filename.txt`
| `${filename:replaceAll('XYZ', 'ZZZ')}` | `a brand new filename.txt`
| `${filename:replaceAll('brand (new)', 'somewhat $1')}` | `a somewhat new filename.txt`
|=======================================================================================

[.function]
=== replaceNull

*Description*: [.description]#The `replaceNull` function returns the argument if the Subject is null. Otherwise,
	returns the Subject.#

*Subject Type*: [.subject]#Any#

*Arguments*:

	- [.argName]#_Replacement_# : [.argDesc]#The value to return if the Subject is null.#

*Return Type*: [.returnType]#Type of Subject if Subject is not null; else, type of Argument#

*Examples*: If the attribute "filename" has the value "a brand new filename.txt" and the attribute
	"hello" does not exist, then the Expression `${filename:replaceNull('abc')}` will return
	"a brand new filename.txt", while `${hello:replaceNull('abc')}` will return "abc".

[.function]
=== replaceEmpty

*Description*: [.description]#The `replaceEmpty` function returns the argument if the Subject is null or
	if the Subject consists only of white space (new line, carriage return, tab, space). Otherwise,
	returns the Subject.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Replacement_# : [.argDesc]#The value to return if the Subject is null or empty.#

*Return Type*: [.returnType]#String#

*Examples*: If the attribute "filename" has the value "a brand new filename.txt" and the attribute
	"hello" has the value "  ", then the Expression `${filename:replaceEmpty('abc')}` will return
	"a brand new filename.txt", while `${hello:replaceEmpty('abc')}` will return "abc".

[.function]
=== length

*Description*: [.description]#Returns the length of the Subject#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: If the attribute "filename" has a value of "a brand new filename.txt" and the attribute
	"hello" does not exist, then the Expression `${filename:length()}` will return 24. `${hello:length()}`
	will return 0.

[[searching]]
== Searching

Each of the following functions is used to search its subject for some value.

[.function]
=== startsWith

*Description*: [.description]#Returns `true` if the Subject starts with the String provided as the argument,
	`false` otherwise.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:startsWith('a brand')}` will return `true`. `${filename:startsWith('A BRAND')}` will
	return `false`. `${filename:toUpper():startsWith('A BRAND')}` returns `true`.

[.function]
=== endsWith

*Description*: [.description]#Returns `true` if the Subject ends with the String provided as the argument,
	`false` otherwise.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:endsWith('txt')}` will return `true`. `${filename:endsWith('TXT')}` will
	return `false`. `${filename:toUpper():endsWith('TXT')}` returns `true`.

[.function]
=== contains

*Description*: [.description]#Returns `true` if the Subject contains the value of the argument anywhere in the value.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:contains('new')}` will return `true`. `${filename:contains('NEW')}` will
	return `false`. `${filename:toUpper():contains('NEW')}` returns `true`.

[.function]
=== find

*Description*: [.description]#Returns `true` if the Subject contains any sequence of characters that matches the
	Regular Expression provided by the argument.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#The Regular Expression (in the Java Pattern syntax) to match against the Subject#

*Return Type*: [.returnType]#Boolean#

*Examples*:

If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.find Examples
|=======================================================================================
| Expression | Value
| `${filename:find('a [Bb]rand [Nn]ew')}` | `true`
| `${filename:find('Brand.*')}` | `false`
| `${filename:find('brand')}` | `true`
|=======================================================================================

[.function]
=== matches

*Description*: [.description]#Returns `true` if the Subject exactly matches the Regular Expression provided by the argument.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#The Regular Expression (in the Java Pattern syntax) to match against the Subject#

*Return Type*: [.returnType]#Boolean#

*Examples*:

If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.matches Examples
|=======================================================================================
| Expression | Value
| `${filename:matches('a.*txt')}` | `true`
| `${filename:matches('brand')}` | `false`
| `${filename:matches('.+brand.+')}` | `true`
|=======================================================================================

[.function]
=== indexOf

*Description*: [.description]#Returns the index of the first character in the Subject that matches the String value provided
	as an argument. If the argument is found multiple times within the Subject, the value returned is the
	starting index of the *first* occurrence.
	If the argument cannot be found in the Subject, returns `-1`. The index is zero-based. This means that if
	the search string is found at the beginning of the Subject, the value returned will be `0`, not `1`.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for in the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.indexOf Examples
|===============================================
| Expression | Value
| `${filename:indexOf('a.*txt')}` | `-1`
| `${filename:indexOf('.')}` | `20`
| `${filename:indexOf('a')}` | `0`
| `${filename:indexOf(' ')}` | `1`
|===============================================

[.function]
=== lastIndexOf

*Description*: [.description]#Returns the index of the first character in the Subject that matches the String value provided
	as an argument. If the argument is found multiple times within the Subject, the value returned is the
	starting index of the *last* occurrence.
	If the argument cannot be found in the Subject, returns `-1`. The index is zero-based. This means that if
	the search string is found at the beginning of the Subject, the value returned will be `0`, not `1`.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for in the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.lastIndexOf Examples
|=======================================================================================
| Expression | Value
| `${filename:lastIndexOf('a.*txt')}` | `-1`
| `${filename:lastIndexOf('.')}` | `20`
| `${filename:lastIndexOf('a')}` | `17`
| `${filename:lastIndexOf(' ')}` | `11`
|=======================================================================================

[[numbers]]
== Mathematical Operations and Numeric Manipulation

[.function]
=== plus

*Description*: [.description]#Adds a numeric value to the Subject. If either the argument or the Subject cannot be
	coerced into a Number, returns `null`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to add to the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:plus(1000)}`
	will return the value `1100`.

[.function]
=== minus

*Description*: [.description]#Subtracts a numeric value from the Subject.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to subtract from the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:minus(100)}`
	will return the value `0`.

[.function]
=== multiply

*Description*: [.description]#Multiplies a numeric value by the Subject and returns the product.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to multiple the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:multiply(1024)}`
	will return the value `102400`.

[.function]
=== divide

*Description*: [.description]#Divides a numeric value by the Subject and returns the result, rounded down to the nearest integer.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to add divide the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:divide(12)}`
	will return the value `8`.

[.function]
=== mod

*Description*: [.description]#Performs a modular division of the Subject by the argument. That is, this function will divide
	the Subject by the value of the argument and return not the quotient but rather the remainder.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to divide the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:mod(12)}`
	will return the value `4`.

[.function]
=== toRadix

*Description*: [.description]#Converts the Subject from a Base 10 number to a different Radix (or number base). An optional
	second argument can be used to indicate the minimum number of characters to be used. If the converted value
	has fewer than this number of characters, the number will be padded with leading zeroes.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Desired Base_# : [.argDesc]#A Number between 2 and 36 (inclusive)#
	- [.argName]#_Padding_# : [.argDesc]#Optional argument that specifies the minimum number of characters in the converted output#

*Return Type*: [.returnType]#String#

*Examples*: If the "fileSize" attributes has a value of 1024, then the following Expressions will yield
	the following results:

.toRadix Examples
|=======================================================================================
| Expression | Value
| `${fileSize:toRadix(10)}` | `1024`
| `${fileSize:toRadix(10, 1)}` | `1024`
| `${fileSize:toRadix(10, 8)}` | `00001024`
| `${fileSize:toRadix(16)}` | `400`
| `${fileSize:toRadix(16, 8)}` | `00000400`
| `${fileSize:toRadix(2)}` | `10000000000`
| `${fileSize:toRadix(2, 16)}` | `0000010000000000`
|=======================================================================================

[[dates]]
== Date Manipulation

[[format]]
[.function]
=== format

*Description*: [.description]#Formats a number as a date/time according to the format specified by the argument. The argument
	must be a String that is a valid Java SimpleDateFormat format. The Subject is expected to be a Number that
	represents the number of milliseconds since Midnight GMT January 1, 1970.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_format_# : [.argDesc]#The format to use in the Java SimpleDateFormat syntax#

*Return Type*: [.returnType]#String#

*Examples*: If the attribute "time" has the value "1420058163264", then the following Expressions will yield
	the following results:

.format Examples
|============================================================================
| Expression | Value
| `${time:format("yyyy/MM/dd HH:mm:ss.SSS'Z'")}` | `2014/12/31 15:36:03.264Z`
| `${time:format("yyyy/MM/dd")}` | `2014/12/31`
| `${time:format("HH:mm:ss.SSS'Z'")}` | `15:36:03.264Z`
| `${time:format("2014")}` | `2014`
|============================================================================

[.function]
=== toDate

*Description*: [.description]#Converts a String into a Number, based on the format specified by the argument. The argument
	must be a String that is a valid Java SimpleDateFormat syntax. The Subject is expected to be a String
	that is formatted according the argument. The return value is the numbr of milliseconds since
	Midnight GMT January 1, 1979.#

*Subject Type*: [.subject]#String#

*Arguments*:

		- [.argName]#_format_# : [.argDesc]#The current format to use when parsing the Subject, in the Java SimpleDateFormat syntax.#

*Return Type*: [.returnType]#Number#

*Examples*: If the attribute "year" has the value "2014" and the attribute "time" has the value "2014/12/31 15:36:03.264Z",
	then the Expression `${year:toDate('yyyy')}` will return the number of milliseconds between Midnight GMT on January 1, 1970
	and Midnight GMT on January 1, 2014. The Expression `${time:toDate("yyyy/MM/dd HH:mm:ss.SSS'Z'")}` will result in the
	number of milliseconds between Midnight GMT on January 1, 1970 and 15:36:03.264 GMT on December 31, 2014.

	Often, this function is used in conjunction with the <<format>> function to change the format of a date/time. For example,
	if the attribute "date" has the value "12-24-2014" and we want to change the format to "2014/12/24", we can do so by
	chaining together the two functions: `${date:toDate('MM-dd-yyyy'):format('yyyy/MM/dd')}`.

[.function]
=== now

*Description*: [.description]#The `now` function returns the current date and time as the number of milliseconds since Midnight GMT on
	January 1, 1970.#

*Subject Type*: [.subject]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: We can format the current date and time by using the `now` function in conjunction with the <<format>> function:
	`${now():format('yyyy/MM/dd HH:mm:ss')}`.

[[type_cast]]
== Type Coercion

[.function]
=== toString

*Description*: [.description]#Coerces the Subject into a String#

*Subject Type*: [.subject]#Any type#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: The Expression `${fileSize:toNumber():toString()}` converts the value of "fileSize" attribute to a number and
	back to a String.

[.function]
=== toNumber

*Description*: [.description]#Coerces the Subject into a Number#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: The Expression `${fileSize:toNumber()}` converts the String attribute value of "fileSize" to a number.

[[subjectless]]
== Subjectless Functions

While the majority of functions in the Expression Language are called by using the syntax
`${attributeName:function()}`, there exist a few functions that are not expected to have subjects.
In this case, the attribute name is not present. For example, the IP address of the machine can
be obtained by using the Expression `${ip()}`. All of the functions in this section are to be called
without a subject. Attempting to call a subjectless function and provide it a subject will result in
an error when validating the function.

[.function]
=== ip

*Description*: [.description]#Returns the IP address of the machine.#

*Subject Type*: [.subjectless]#No subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: The IP address of the machine can be obtained by using the Expresison `${ip()}`.

[.function]
=== hostname

*Description*: [.description]#Returns the Hostname of the machine. An optional argument of type Boolean can be provided
	to specify whether or not the Fully Qualified Domain Name should be used. If `false`, or not specified,
	the hostname will not be fully qualified. If the argument is `true` but the fully qualified hostname
	cannot be resolved, the simple hostname will be returned.#

*Subject Type*: [.subjectless]#No subject#

*Arguments*:

	- [.argName]#_Fully Qualified_# : [.argDesc]#Optional parameter that specifies whether or not the hostname should be
		fully qualified. If not specified, defaults to false.#

*Return Type*: [.returnType]#String#

*Examples*: The fully qualified hostname of the machine can be obtained by using the Expression `${hostname(true)}`,
	while the simple hostname can be obtained by using either `${hostname(false)}` or simply `${hostname()}`.

[.function]
=== UUID

*Description*: [.description]#Returns a randomly generated UUID.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: ${UUID()} returns a value similar to de305d54-75b4-431b-adb2-eb6b9e546013

[.function]
=== nextInt

*Description*: [.description]#Returns a one-up value (starting at 0) and increasing over the lifetime of the running instance of NiFi.
	This value is not persisted across restarts and is not guaranteed to be unique across a cluster.
	This value is considered "one-up" in that if called multiple times across the NiFi instance, the values will be sequential.
	However, this counter is shared across all NiFi components, so calling this function multiple times from one Processor will
	not guarantee sequential values within the context of a particular Processor.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: If the previous value returned by `nextInt` was `5`, the Expression `${nextInt():divide(2)}` obtains the next available
	integer (6) and divides the result by 2, returning a value of `3`.

[[multi]]
== Evaluating Multiple Attributes

When it becomes necessary to evaluate the same conditions against multiple attributes, this can be accomplished by means of the
`and` and `or` functions. However, this quickly becomes tedious, error-prone, and difficult to maintain. For this reason, NiFi
provides several functions for evaluating the same conditions against groups of attributes at the same time.

[.function]
=== anyAttribute

*Description*: [.description]#Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are the names of attributes to which the remainder of the Expression is to be applied. If any of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Attribute Names_# : [.argDesc]#One or more attribute names to evaluate#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyAttribute Examples
|=======================================================================
| Expression | Value
| `${anyAttribute("abc", "xyz"):contains("bye")}` | `true`
| `${anyAttribute("filename","xyz"):toUpper():contains("e")}` | `false`
|=======================================================================

[.function]
=== allAttributes

*Description*: [.description]#Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are the names of attributes to which the remainder of the Expression is to be applied. If all of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Attribute Names_# : [.argDesc]#One or more attribute names to evaluate#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.allAttributes Example
|=============================================================================
| Expression | Value
| `${allAttributes("abc", "xyz"):contains("world")}` | `true`
| `${allAttributes("abc", "filename","xyz"):toUpper():contains("e")}` | `false`
|=============================================================================

[.function]
=== anyMatchingAttribute

*Description*: [.description]# Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are Regular Expressions to match against attribute names. Any attribute whose name matches one of the supplied
	Regular Expressions will be evaluated against the rest of the Expression. If any of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#One or more Regular Expressions (in the Java Pattern syntax) to evaluate against attribute names#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyMatchingAttribute Example
|==============================================================
| Expression | Value
| `${anyMatchingAttribute("[ax].*"):contains('bye')}` | `true`
| `${anyMatchingAttribute(".*"):isNull()}` | `false`
|==============================================================

[.function]
=== allMatchingAttributes

*Description*: [.description]# Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are Regular Expressions to match against attribute names. Any attribute whose name matches one of the supplied
	Regular Expressions will be evaluated against the rest of the Expression. If all of the attributes specified,
	when evaluated against the rest of the Expression, return a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

	- [.argName]#_Regex_# : [.argDesc]#One or more Regular Expressions (in the Java Pattern syntax) to evaluate against attribute names#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyMatchingAttributes Examples
|==============================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):contains("world")}` | `true`
| `${allMatchingAttributes(".*"):isNull()}` | `false`
| `${allMatchingAttributes("f.*"):count()}` | `1`
|==============================================================

[.function]
=== anyDelineatedValue

*Description*: [.description]#Splits a String apart according to a delimiter that is provided, and then evaluates each of the values against
	the rest of the Expression. If the Expression, when evaluated against any of the individual values, returns `true`, this
	function returns `true`. Otherwise, the function returns `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Delineated Value_# : [.argDesc]#The value that is delineated. This is generally an embedded Expression,
		though it does not have to be.#
	- [.argName]#_Delimiter_# : [.argDesc]#The value to use to split apart the _delineatedValue_ argument.#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "number_list" attribute contains the value "1,2,3,4,5", and the "word_list" attribute contains the value "the,and,or,not",
	consider the following examples:

.anyDelineatedValue Examples
|===============================================================================
| Expression | Value
| `${anyDelineatedValue("${number_list}", ","):contains("5")}` | `true`
| `${anyDelineatedValue("this that and", ","):equals("${word_list}")}` | `false`
|===============================================================================

[.function]
=== allDelineatedValues

*Description*: [.description]#Splits a String apart according to a delimiter that is provided, and then evaluates each of the values against
	the rest of the Expression. If the Expression, when evaluated against all of the individual values, returns `true` in each
	case, then this function returns `true`. Otherwise, the function returns `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Delineated Value_# : [.argDesc]#The value that is delineated. This is generally
		an embedded Expression, though it does not have to be.#

	- [.argName]#_Delimiter_# : [.argDesc]#The value to use to split apart the _delineatedValue_ argument.#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "number_list" attribute contains the value "1,2,3,4,5", and the "word_list" attribute contains the value "those,known,or,not",
	consider the following examples:

.allDelineatedValues Examples
|===============================================================================
| Expression | Value
| `${allDelineatedValues("${word_list}", ","):contains("o")}` | `true`
| `${allDelineatedValues("${number_list}", ","):count()}` | `4`
| `${allDelineatedValues("${number_list}", ","):matches("[0-9]+")}` | `true`
| `${allDelineatedValues("${word_list}", ","):matches('e')}` | `false`
|===============================================================================

[.function]
=== join

*Description*: [.description]#Aggregate function that concatenates multiple values with the specified delimiter. This function
	may be used only in conjunction with the `allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`
	functions.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Delimiter_# : [.argDesc]#The String delimiter to use when joining values#

*Return Type*: [.returnType]#String#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.join Examples
|=======================================================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):substringBefore(" "):join("-")}` | `hello-good`
| `${allAttributes("abc", "xyz"):join(" now")}` | `hello world nowgood bye world now`
|=======================================================================================

[.function]
=== count

*Description*: [.description]#Aggregate function that counts the number of non-null, non-false values returned by the
	`allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`. This function
	may be used only in conjunction with the `allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`
	functions.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "number_list" contains "1,2,3,4,5" consider the following examples:

.count Examples
|===========================================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):substringBefore(" "):count()}` | `2`
| `${allAttributes("abc", "xyz"):contains("world"):count()}` | `1`
| `${allDelineatedValues(${number_list}, ","):count()}` | `5`
| `${allAttributes("abc", "non-existent-attr", "xyz"):count()}` | `2`
| `${allMatchingAttributes(".*"):length():gt(10):count()}` | `2`
|===========================================================================

//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
Apache NiFi Expression Language Guide
=====================================
Apache NiFi Team <dev@nifi.incubator.apache.org>
:homepage: http://nifi.incubator.apache.org

[[overview]]
Overview
--------
All data in Apache NiFi is represented by an abstraction called a FlowFile.
A FlowFile is comprised of two major pieces: content and attributes.
The content portion of the FlowFile represents the data on which to operate.
For instance, if a file is picked up from a local file system using the
GetFile Processor, the contents of the file will become the contents of the
FlowFile.

The attributes portion of the FlowFile represents information about the data
itself, or metadata. Attributes are key-value pairs that represent what is
known about the data as well as information that is useful for routing and
processing the data appropriately.
Keeping with the example of a file that is picked up from
a local file system, the FlowFile would have an attribute called `filename` that
reflected the name of the file on the file system. Additionally, the FlowFile will
have a `path` attribute that reflects the directory on the file system that this
file lived in. The FlowFile will also have an attribute named `uuid`, which is a
unique identifier for this FlowFile.

However, placing these attributes on a FlowFile do not provide much benefit
if the user is unable to make use of them. The NiFi Expression Language provides
the ability to reference these attributes, compare them to other values,
and manipulate their values.

[[structure]]
Structure of a NiFi Expression
------------------------------

The NiFi Expression Language always begins with the start delimiter `${` and ends
with the end delimiter `}`. Between the start and end delimiters is the text of the
Expression itself. In its most basic form, the Expression can consist of just an
attribute name. For example, `${filename}` will return the value of the ``filename''
attribute.

In a slightly more complex example, we can instead return a manipulation of this value.
We can, for example, return an all upper-case version of the filename by calling the
`toUpper` function: `${filename:toUpper()}`. In this case, we reference the ``filename''
attribute and then manipulate this value by using the `toUpper` function. A function call
consists of 5 elements. First, there is a function call delimiter `:`. Second is the name
of the function - in this case, ``toUpper''. Next is an open parenthesis (`(`), followed
by the function arguments. The arguments necessary are dependent upon which function
is being called. In this example, we are using the `toUpper` function, which does not
have any arguments, so this element is omitted. Finally, the closing parenthesis (`)`)
indicates the end of the function call. There are many different functions that are supported
by the Expression Language to achieve many different goals. Some functions provide String (text)
manipulation, such as the `toUpper` function. Others, such as the `equals` and `matches` functions,
provide comparison functionality. Functions also exist for manipulating dates and times and
for performing mathematical operations. Each of these functions is described below, in the
<<functions> section, with an explanation of what the function does, the arguments that it
requires, and the type of information that it returns.

When we perform a function call on an attribute, as above, we refer to the attribute as the
_subject_ of the function, as the attribute is the entity on which the function is operating.
We can then chain together multiple function calls, where the return value of the first function
becomes the subject of the second function and its return value becomes the subject of the third
function and so on. Continuing with our example, we can chain together multiple functions by using
the expression `${filename:toUpper():equals('HELLO.TXT')}`. There is no limit to the number of
functions that can be chained together.

Any FlowFile attribute can be referenced using the Expression Language. However, if the attribute
name contains a ``special character,'' the attribute name must be escaped by quoting it. The following
characters are each considered ``special characters'':

- $ (dollar sign)
- | (pipe)
- { (open brace)
- } (close brace)
- ( (open parenthesis)
- ) (close parenthesis)
- [ (open bracket)
- ] (close bracket)
- , (comma)
- : (colon)
- ; (semicolon)
- / (forward slash)
- * (asterisk)
- ' (single quote)
-  (space)
- \t (tab)
- \r (carriage return)
- \n (new-line)

Additionally, a number is considered a ``special character'' if it is the first character of the attribute name.
If any of these special characters is present in an attribute is quoted by using either single or double quotes.
The Expression Language allows single quotes and double quotes to be used interchangeably. For example, the following
can be used to escape an attribute named ``my attribute'': `${"my attribute"}` or `${'my attribute'}`.

In this example, the value to be returned is the value of the "my attribute" value, if it exists. If that attribute
does not exist, the Expression Language will then look for a System Environment Variable named "my attribute." If
unable to find this, it will look for a JVM System Property named "my attribute." Finally, if none of these exists,
the Expression Language will return a `null` value.

There also exist some functions that expect to have no subject. These functions are invoked simply
by calling the function at the beginning of the Expression, such as `${hostname()}`. These functions
can then be changed together, as well. For example, `${hostname():toUpper()}`. Attempting to
evaluate the function with subject will result in an error. In the <<functions>>
section below, these functions will clearly indicate in their descriptions that they do not
require a subject.

Often times, we will need to compare the values of two different attributes to each other.
We are able to accomplish this by using embedded Expressions. We can, for example, check if
the ``filename'' attribute is the same as the ``uuid'' attribute: `${filename:equals( ${uuid} )}`.
Notice here, also, that we have a space between the opening parenthesis for the `equals` method and
the embedded Expression. This is not necessary and does not affect how the Expression is evaluated
in any way. Rather, it is intended to make the Expression easier to read. White space is ignored by
the Expression Language between delimiters. Therefore, we can use the Expression
`${     filename   : equals(${    uuid})  }` or `${filename:equals(${uuid})}` and both Expressions
mean the same thing. We cannot, however, use `${file name:equals(${uuid})}`, because this results
in `file` and `name` being interpreted as different tokens, rather than a single token, `filename`.

[[usage]]
== Expression Language in the Application

The Expression Language is used heavily throughout the NiFi application for configuring Processor
properties. Not all Processor properties support the Expression Language, however. Whether or not
a Property supports the Expression Language is determined by the developer of the Processor when
the Processor is written. However, the application strives to clearly illustrate for each Property
whether or not the Expression Language is supported.

In the application, when configuring a Processor property, the User Interface provides an Information
icon (
image:iconInfo.png["Info"]
) next to the name of the Property. Hovering over this icon with the mouse will provide a tooltip that
provides helpful information about the Property. This information includes a description of the Property,
the default value (if any), historically configured values (if any), and whether or not this Property
supports the expression language.

[[editor]]
=== Expression Language Editor

When configuring the value of a Processor property, the NiFi User Interface provides help with the
Expression Language using the Expression Language editor. Once an Expression is begin by typing `${`,
the editor begins to highlight parentheses and braces so that the user is easily able to tell which
opening parenthesis or brace matches which closing parenthesis or brace.

The editor also supplies context-sensitive help by providing a list of all functions that can be used
at the current cursor position. To activate this feature, press Ctrl+Space on the keyboard. The user
is also able to type part of a function name and then press Ctrl+Space to see all functions that can
be used that start with the same prefix. For example, if we type into the editor `${filename:to`
and then press Ctrl+Space, we are provided a pop-up that lists six different functions: `toDate`,
`toLower`, `toNumber`, `toRadix`, `toString`, and `toUpper`. We can then continue typing to narrow
which functions are shown, or we can select one of the functions from the list by double-clicking
it with the mouse or using the arrow keys to highlight the desired function and pressing Enter.

[[functions]]
== Functions

Functions provide a convenient way to manipulate and compare values of attributes. The Expression Language
provides many different functions to meet the needs of a automated dataflow. Each function takes
zero or more arguments and returns a single value. These functions can then be chained together to create
powerful Expressions to evaluate conditions and manipulate values. See <<structure>> for more information
on how to call and chain functions together.

[[types]]
=== Data Types

Each argument to a function and each value returned from a function has a specific data type. The Expression
Language supports four different data types:

- *String*: A String is a sequence of characters that can consist of numbers, letters, white space, and
	special characters.
- *Number*: A Number is an integer comprised of one or more digits (`0` through `9`). The Expression Language
	does not provide support for fractional numbers. Dates and times are represented in the
	Expression Language as Numbers, representing the number of milliseconds since midnight GMT on January 1, 1970.
- *Boolean*: A Boolean is one of either `true` or `false`.

All attributes are considered to be of type String.

The Expression Language is generally able to automatically coerce a value of one data type to the appropriate
data type for a function. However, functions do exist to manually coerce a value into a specific data type.
See the <<type_cast>> section for more information.

[[boolean]]
== Boolean Logic

One of the most powerful features of the Expression Language is the ability to compare an attribute value against
some other value. This is used often, for example, to configure how a Processor should route data. The following
functions are used for performing boolean logic, such as comparing two values.
Each of these functions returns a value of type Boolean.

[.function]
=== isNull
*Description*: [.description]#The `isNull` function returns `true` if the subject is null, `false` otherwise. This is typically used to determine
if an attribute exists.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Boolean#

*Examples*:	`${filename:isNull()}` returns `true` if the "filename" attribute does not exist.
	It returns `true` if the attribute exists.

[.function]
=== notNull
*Description*: [.description]#The `notNull` function returns the opposite value of the `isNull` function. That is, it will return `true` if the
subject exists and `false` otherwise.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Boolean#

*Examples*: `${filename:notNull()}` returns `true` if the "filename" attribute exists. It returns "false" if the attribute
	does not exist.

[.function]
=== equals

[.description]
*Description*: [.description]#The `equals` function is very widely used and determines if its subject is equal to another String value.
	Note that the `equals` function performs a direct comparison of two String values. Take care not to confuse this
	function with the <<matches>> function, which evaluates its subject against a Regular Expression.#

[.subject]
*Subject Type*: [.subject]#Any#

[.arguments]
*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to compare the Subject to. Must be same type as the Subject.#

[.returnType]
*Return Type*: [.returnType]#Boolean#

[.examples]
*Examples*:
We can check if the filename of a FlowFile is "hello.txt" by using the expression `${filename:equals('hello.txt')}`,
or we could check if the value of the attribute `hello` is equal to the value of the `filename` attribute:
`${hello:equals( ${filename} )}`.

[.function]
=== equalsIgnoreCase
*Description*: [.description]#Similar to the `equals` function, the `equalsIgnoreCase` function compares its subject against a String value but returns
`true` if the two values differ only by case (upper case vs. lower case).#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${filename:equalsIgnoreCase('hello.txt')}` will evaluate to `true` if filename is equal to "hello.txt"
	or "HELLO.TXT" or "HeLLo.TxT".

[.function]
=== gt
*Description*: [.description]#The `gt` function is used for numeric comparison and returns `true` if the subject is Greater Than
	its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:gt( 1024 )}` will return `true` if the size of the FlowFile's content is more than 1 kilobyte
	(1024 bytes). Otherwise, it will return `false`.

[.function]
=== ge
*Description*: [.description]#The `ge` function is used for numeric comparison and returns `true` if the subject is Greater Than
	Or Equal To its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:ge( 1024 )}` will return `true` if the size of the FlowFile's content is at least (
	is greater than or equal to) 1 kilobyte (1024 bytes). Otherwise, it will return `false`.

[.function]
=== lt
*Description*: [.description]#The `lt` function is used for numeric comparison and returns `true` if the subject is Less Than
	its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:lt( 1048576 )}` will return `true` if the size of the FlowFile's content is less than
	1 megabyte (1048576 bytes). Otherwise, it will return `false`.

[.function]
=== le
*Description*: [.description]#The `le` function is used for numeric comparison and returns `true` if the subject is Less Than
	Or Equal To its argument. If either the subject or the argument cannot be coerced into a Number,
	this function returns `false`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The number to compare the Subject to.#

*Return Type*: [.returnType]#Boolean#

*Examples*: `${fileSize:le( 1048576 )}` will return `true` if the size of the FlowFile's content is at most
	(less than or equal to) 1 megabyte (1048576 bytes). Otherwise, it will return `false`.

[.function]
=== and
*Description*: [.description]#The `and` function takes as a single argument a Boolean value and returns `true` if both the Subject
	and the argument are `true`. If either the subject or the argument is `false` or cannot be coerced into a Boolean,
	the function returns `false`. Typically, this is used with an embedded Expression as the argument.#

*Subject Type*: [.subject]#Boolean#

*Arguments*:

	- [.argName]#_condition_# : [.argDesc]#The right-hand-side of the 'and' Expression#

*Return Type*: [.returnType]#Boolean#

*Examples*: We can check if the filename is both all lower-case and has at least 5 characters by using the Expression
-----------------------------------------------
${filename:toLower():equals( ${filename} ):and(
	${filename:length():ge(5)}
)}
-----------------------------------------------

[.function]
=== or

*Description*: [.description]#The `or` function takes as a single argument a Boolean value and returns `true` if either the Subject
	or the argument is `true`. If both the subject and the argument are `false`, the function returns `false`. If
	either the Subject or the argument cannot be coerced into a Boolean value, this function will return `false`.#

*Subject Type*: [.subject]#Boolean#

*Arguments*:

	- [.argName]#_condition_# : [.argDesc]#The right-hand-side of the 'and' Expression#

*Return Type*: [.returnType]#Boolean#

*Examples*: The following example will return `true` if either the filename has exactly 5 characters or if
	the filename is all lower-case.
----------------------------------------------
${filename:toLower():equals( ${filename} ):or(
	${filename:length():equals(5)}
)}
----------------------------------------------

[.function]
=== not

[.description]
*Description*: [.description]#The `not` function returns the negation of the Boolean value of the subject.#

[.subject]
*Subject Type*: [.subject]#Boolean#

[.arguments]
*Arguments*: No arguments

[.returnType]
*Return Type*: [.returnType]#Boolean#

[.examples]
*Examples*: We can invert the value of another function by using the `not` function, as
	`${filename:equals('hello.txt'):not()}`. This will return `true` if the filename is NOT equal to
	"hello.txt" and will return `false` if the filename is "hello.txt."

[[strings]]
== String Manipulation

Each of the following functions manipulates a String in some way.

[.function]
=== toUpper

*Description*: [.description]#This function converts the Subject into an all upper-case String. Said another way, it
	replaces any lowercase letter with the uppercase equivalent.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute is "abc123.txt", then the Expression `${filename:toUpper()}`
	will return "ABC123.TXT"

[.function]
=== toLower

*Description*: [.description]#This function converts the Subject into an all lower-case String. Said another way,
	it replaces any uppercase letter with the lowercase equivalent.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute is "ABC123.TXT", then the Expression `${filename:toLower()}`
	will return "abc123.txt"

[.function]
=== trim

*Description*: [.description]#The `trim` function will remove any leading or trailing white space from its subject.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If the attribute `attr` has the value "     1 2 3     ", then the Expression `${attr:trim()}` will
	return the value "1 2 3".

[.function]
=== urlEncode

*Description*: [.description]#Returns a URL-friendly version of the Subject. This is useful, for instance, when using an
	attribute value to indicate the URL of a website.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: We can URL-Encode an attribute named "url" by using the Expression `${url:urlEncode()}`. If
	the value of the "url" attribute is "https://nifi.incubator.apache.org/some value with spaces", this
	Expression will then return "https://nifi.incubator.apache.org/some%20value%20with%20spaces".

[.function]
=== urlDecode

*Description*: [.description]#Converts a URL-friendly version of the Subject into a human-readable form.#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: If we have a URL-Encoded attribute named "url" with the value
	"https://nifi.incubator.apache.org/some%20value%20with%20spaces", then the Expression
	`${url:urlDecode()}` will return "https://nifi.incubator.apache.org/some value with spaces".

[.function]
=== substring

*Description*:
[.description]#Returns a portion of the Subject, given a _starting index_ and an optional _ending index_.
	If the _ending index_ is not supplied, it will return the portion of the Subject starting at the given
	'start index' and ending at the end of the Subject value.#

[.description]#The _starting index_ and _ending index_ are zero-based. That is, the first character is referenced by using
	the value `0`, not `1`.#

[.description]#If either the _starting index_ is or the _ending index_ is not a number, this function call will result
	in an error.#

[.description]#If the _starting index_ is larger than the _ending index_, this function call will result in an error.#

[.description]#If the _starting index_ or the _ending index_ is greater than the length of the Subject or has a value
	less than 0, this function call will result in an error.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_starting index_# : [.argDesc]#The 0-based index of the first character to capture (inclusive)#
	- [.argName]#_ending index_# : [.argDesc]#The 0-based index of the last character to capture (exclusive)#

*Return Type*: [.returnType]#String#

*Examples*:

If we have an attribute named "filename" with the value "a brand new filename.txt",
then the following Expressions will result in the following values:

.Substring Examples
|================================================================
| Expression | Value
| `${filename:substring(0,1)}` | `a`
| `${filename:substring(2)}` | `brand new filename.txt`
| `${filename:substring(12)}` | `filename.txt`
| `${filename:substring( ${filename:length():minus(2)} )}` | `xt`
|================================================================

[.function]
=== substringBefore

*Description*: [.description]#Returns a portion of the Subject, starting with the first character of the Subject
	and ending with the character immediately before the first occurrence of the argument. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringBefore Examples
|======================================================================
| Expression | Value
| `${filename:substringBefore('.')}` | `a brand new filename`
| `${filename:substringBefore(' ')}` | `a`
| `${filename:substringBefore(' n')}` | `a brand`
| `${filename:sbustringBefore('missing')}` | `a brand new filename.txt`
|======================================================================

[.function]
=== substringBeforeLast

*Description*: [.description]#Returns a portion of the Subject, starting with the first character of the Subject
	and ending with the character immediately before the last occurrence of the argument. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String3

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringBeforeLast Examples
|==========================================================================
| Expression | Value
| `${filename:substringBeforeLast('.')}` | `a brand new filename`
| `${filename:substringBeforeLast(' ')}` | `a brand new`
| `${filename:substringBeforeLast(' n')}` | `a brand`
| `${filename:substringBeforeLast('missing')}` | `a brand new filename.txt`
|==========================================================================

[.function]
=== substringAfter

*Description*: [.description]#Returns a portion of the Subject, starting with the character immediately after
	the first occurrence of the argument and extending to the end of the Subject. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringAfter Examples
|======================================================================
| Expression | Value
| `${filename:substringAfter('.')}` | `txt`
| `${filename:substringAfter(' ')}` | `brand new filename.txt`
| `${filename:substringAfter(' n')}` | `ew filename.txt`
| `${filename:substringAfter('missing')}` | `a brand new filename.txt`
|======================================================================

[.function]
=== substringAfterLast

*Description*: [.description]#Returns a portion of the Subject, starting with the character immediately after
	the last occurrence of the argument and extending to the end of the Subject. If
	the argument is not present in the Subject, the entire Subject will be returned.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to search for in the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt",
	then the following Expressions will result in the following values:

.SubstringAfterLast Examples
|=========================================================================
| Expression | Value
| `${filename:substringAfterLast('.')}` | `txt`
| `${filename:substringAfterLast(' ')}` | `filename.txt`
| `${filename:substringAfterLast(' n')}` | `ew filename.txt`
| `${filename:substringAfterLast('missing')}` | `a brand new filename.txt`
|=========================================================================

[.function]
=== append

*Description*: [.description]#The `append` function returns the result of appending the argument to the value of
	the Subject. If the Subject is null, returns the argument itself.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to append to the end of the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:append('.gz')}` will return "a brand new filename.txt.gz".

[.function]
=== prepend

*Description*: [.description]#The `prepend` function returns the result of prepending the argument to the value of
	the Subject. If the subject is null, returns the argument itself.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The String to prepend to the beginning of the Subject#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "filename.txt", then the Expression
	`${filename:prepend('a brand new ')}` will return "a brand new filename.txt".

[.function]
=== replace

*Description*: [.description]#Replaces occurrences of one String within the Subject with another String.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Search String_# : [.argDesc]#The String to find within the Subject#
	- [.argName]#_Replacement_# : [.argDesc]#The value to replace _Search String_ with#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.Replace Examples
|===================================================================
| Expression | Value
| `${filename:replace('.', '_')}` | `a brand new filename_txt`
| `${filename:replace(' ', '.')}` | `a.brand.new.filename.txt`
| `${filename:replace('XYZ', 'ZZZ')}` | `a brand new filename.txt`
| `${filename:replace('filename', 'book')}` | `a brand new book.txt`
|===================================================================

[.function]
=== replaceAll

*Description*: [.description]#The `replaceAll` function takes two String arguments: a Regular Expression (NiFi uses the Java Pattern
	syntax), and a replacement string. The return value is the result of substituting the replacement string for
	all patterns within the Subject that match the Regular Expression.#

*Subject Type*: [.subject]#String#

*Arguments*:

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#he Regular Expression (in Java syntax) to match in the Subject#
	- [.argName]#_Replacement_# : [.argDesc]#The value to use for replacing matches in the Subject. If the _regular expression_
		argument uses Capturing Groups, back references are allowed in the _replacement_.#

*Return Type*: [.returnType]#String#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.replaceAll Examples
|=======================================================================================
| Expression | Value
| `${filename:replaceAll('\..*', '')}` | `a brand new filename`
| `${filename:replaceAll('a brand (new)', '$1')}` | `new filename.txt`
| `${filename:replaceAll('XYZ', 'ZZZ')}` | `a brand new filename.txt`
| `${filename:replaceAll('brand (new)', 'somewhat $1')}` | `a somewhat new filename.txt`
|=======================================================================================

[.function]
=== replaceNull

*Description*: [.description]#The `replaceNull` function returns the argument if the Subject is null. Otherwise,
	returns the Subject.#

*Subject Type*: [.subject]#Any#

*Arguments*:

	- [.argName]#_Replacement_# : [.argDesc]#The value to return if the Subject is null.#

*Return Type*: [.returnType]#Type of Subject if Subject is not null; else, type of Argument#

*Examples*: If the attribute "filename" has the value "a brand new filename.txt" and the attribute
	"hello" does not exist, then the Expression `${filename:replaceNull('abc')}` will return
	"a brand new filename.txt", while `${hello:replaceNull('abc')}` will return "abc".

[.function]
=== length

*Description*: [.description]#Returns the length of the Subject#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: If the attribute "filename" has a value of "a brand new filename.txt" and the attribute
	"hello" does not exist, then the Expression `${filename:length()}` will return 24. `${hello:length()}`
	will return 0.

[[searching]]
== Searching

Each of the following functions is used to search its subject for some value.

[.function]
=== startsWith

*Description*: [.description]#Returns `true` if the Subject starts with the String provided as the argument,
	`false` otherwise.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:startsWith('a brand')}` will return `true`. `${filename:startsWith('A BRAND')}` will
	return `false`. `${filename:toUpper():startsWith('A BRAND')}` returns `true`.

[.function]
=== endsWith

*Description*: [.description]#Returns `true` if the Subject ends with the String provided as the argument,
	`false` otherwise.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:endsWith('txt')}` will return `true`. `${filename:endsWith('TXT')}` will
	return `false`. `${filename:toUpper():endsWith('TXT')}` returns `true`.

[.function]
=== contains

*Description*: [.description]#Returns `true` if the Subject contains the value of the argument anywhere in the value.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for#

*Return Type*: [.returnType]#Boolean#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the Expression
	`${filename:contains('new')}` will return `true`. `${filename:contains('NEW')}` will
	return `false`. `${filename:toUpper():contains('NEW')}` returns `true`.

[.function]
=== find

*Description*: [.description]#Returns `true` if the Subject contains any sequence of characters that matches the
	Regular Expression provided by the argument.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#The Regular Expression (in the Java Pattern syntax) to match against the Subject#

*Return Type*: [.returnType]#Boolean#

*Examples*:

If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.find Examples
|=======================================================================================
| Expression | Value
| `${filename:find('a [Bb]rand [Nn]ew')}` | `true`
| `${filename:find('Brand.*')}` | `false`
| `${filename:find('brand')}` | `true`
|=======================================================================================

[.function]
=== matches

*Description*: [.description]#Returns `true` if the Subject exactly matches the Regular Expression provided by the argument.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#The Regular Expression (in the Java Pattern syntax) to match against the Subject#

*Return Type*: [.returnType]#Boolean#

*Examples*:

If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.matches Examples
|=======================================================================================
| Expression | Value
| `${filename:matches('a.*txt')}` | `true`
| `${filename:matches('brand')}` | `false`
| `${filename:matches('.+brand.+')}` | `true`
|=======================================================================================

[.function]
=== indexOf

*Description*: [.description]#Returns the index of the first character in the Subject that matches the String value provided
	as an argument. If the argument is found multiple times within the Subject, the value returned is the
	starting index of the *first* occurrence.
	If the argument cannot be found in the Subject, returns `-1`. The index is zero-based. This means that if
	the search string is found at the beginning of the Subject, the value returned will be `0`, not `1`.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for in the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.indexOf Examples
|===============================================
| Expression | Value
| `${filename:indexOf('a.*txt')}` | `-1`
| `${filename:indexOf('.')}` | `20`
| `${filename:indexOf('a')}` | `0`
| `${filename:indexOf(' ')}` | `1`
|===============================================

[.function]
=== lastIndexOf

*Description*: [.description]#Returns the index of the first character in the Subject that matches the String value provided
	as an argument. If the argument is found multiple times within the Subject, the value returned is the
	starting index of the *last* occurrence.
	If the argument cannot be found in the Subject, returns `-1`. The index is zero-based. This means that if
	the search string is found at the beginning of the Subject, the value returned will be `0`, not `1`.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_value_# : [.argDesc]#The value to search for in the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "filename" attribute has the value "a brand new filename.txt", then the following
Expressions will provide the following results:

.lastIndexOf Examples
|=======================================================================================
| Expression | Value
| `${filename:lastIndexOf('a.*txt')}` | `-1`
| `${filename:lastIndexOf('.')}` | `20`
| `${filename:lastIndexOf('a')}` | `17`
| `${filename:lastIndexOf(' ')}` | `11`
|=======================================================================================

[[numbers]]
== Mathematical Operations and Numeric Manipulation

[.function]
=== plus

*Description*: [.description]#Adds a numeric value to the Subject. If either the argument or the Subject cannot be
	coerced into a Number, returns `null`.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to add to the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:plus(1000)}`
	will return the value `1100`.

[.function]
=== minus

*Description*: [.description]#Subtracts a numeric value from the Subject.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to subtract from the Subject#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:minus(100)}`
	will return the value `0`.

[.function]
=== multiply

*Description*: [.description]#Multiplies a numeric value by the Subject and returns the product.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to multiple the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:multiply(1024)}`
	will return the value `102400`.

[.function]
=== divide

*Description*: [.description]#Divides a numeric value by the Subject and returns the result, rounded down to the nearest integer.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to add divide the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:divide(12)}`
	will return the value `8`.

[.function]
=== mod

*Description*: [.description]#Performs a modular division of the Subject by the argument. That is, this function will divide
	the Subject by the value of the argument and return not the quotient but rather the remainder.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Operand_# : [.argDesc]#The value to divide the Subject by#

*Return Type*: [.returnType]#Number#

*Examples*: If the "fileSize" attribute has a value of 100, then the Expression `${fileSize:mod(12)}`
	will return the value `4`.

[.function]
=== toRadix

*Description*: [.description]#Converts the Subject from a Base 10 number to a different Radix (or number base). An optional
	second argument can be used to indicate the minimum number of characters to be used. If the converted value
	has fewer than this number of characters, the number will be padded with leading zeroes.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_Desired Base_# : [.argDesc]#A Number between 2 and 36 (inclusive)#
	- [.argName]#_Padding_# : [.argDesc]#Optional argument that specifies the minimum number of characters in the converted output#

*Return Type*: [.returnType]#String#

*Examples*: If the "fileSize" attributes has a value of 1024, then the following Expressions will yield
	the following results:

.toRadix Examples
|=======================================================================================
| Expression | Value
| `${fileSize:toRadix(10)}` | `1024`
| `${fileSize:toRadix(10, 1)}` | `1024`
| `${fileSize:toRadix(10, 8)}` | `00001024`
| `${fileSize:toRadix(16)}` | `400`
| `${fileSize:toRadix(16, 8)}` | `00000400`
| `${fileSize:toRadix(2)}` | `10000000000`
| `${fileSize:toRadix(2, 16)}` | `0000010000000000`
|=======================================================================================

[[dates]]
== Date Manipulation

[[format]]
[.function]
=== format

*Description*: [.description]#Formats a number as a date/time according to the format specified by the argument. The argument
	must be a String that is a valid Java SimpleDateFormat format. The Subject is expected to be a Number that
	represents the number of milliseconds since Midnight GMT January 1, 1970.#

*Subject Type*: [.subject]#Number#

*Arguments*:

	- [.argName]#_format_# : [.argDesc]#The format to use in the Java SimpleDateFormat syntax#

*Return Type*: [.returnType]#String#

*Examples*: If the attribute "time" has the value "1420058163264", then the following Expressions will yield
	the following results:

.format Examples
|============================================================================
| Expression | Value
| `${time:format("yyyy/MM/dd HH:mm:ss.SSS'Z'")}` | `2014/12/31 15:36:03.264Z`
| `${time:format("yyyy/MM/dd")}` | `2014/12/31`
| `${time:format("HH:mm:ss.SSS'Z'")}` | `15:36:03.264Z`
| `${time:format("2014")}` | `2014`
|============================================================================

[.function]
=== toDate

*Description*: [.description]#Converts a String into a Number, based on the format specified by the argument. The argument
	must be a String that is a valid Java SimpleDateFormat syntax. The Subject is expected to be a String
	that is formatted according the argument. The return value is the numbr of milliseconds since
	Midnight GMT January 1, 1979.#

*Subject Type*: [.subject]#String#

*Arguments*:

		- [.argName]#_format_# : [.argDesc]#The current format to use when parsing the Subject, in the Java SimpleDateFormat syntax.#

*Return Type*: [.returnType]#Number#

*Examples*: If the attribute "year" has the value "2014" and the attribute "time" has the value "2014/12/31 15:36:03.264Z",
	then the Expression `${year:toDate('yyyy')}` will return the number of milliseconds between Midnight GMT on January 1, 1970
	and Midnight GMT on January 1, 2014. The Expression `${time:toDate("yyyy/MM/dd HH:mm:ss.SSS'Z'")}` will result in the
	number of milliseconds between Midnight GMT on January 1, 1970 and 15:36:03.264 GMT on December 31, 2014.

	Often, this function is used in conjunction with the <<format>> function to change the format of a date/time. For example,
	if the attribute "date" has the value "12-24-2014" and we want to change the format to "2014/12/24", we can do so by
	chaining together the two functions: `${date:toDate('MM-dd-yyyy'):format('yyyy/MM/dd')}`.

[.function]
=== now

*Description*: [.description]#The `now` function returns the current date and time as the number of milliseconds since Midnight GMT on
	January 1, 1970.#

*Subject Type*: [.subject]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: We can format the current date and time by using the `now` function in conjunction with the <<format>> function:
	`${now():format('yyyy/MM/dd HH:mm:ss')}`.

[[type_cast]]
== Type Coercion

[.function]
=== toString

*Description*: [.description]#Coerces the Subject into a String#

*Subject Type*: [.subject]#Any type#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: The Expression `${fileSize:toNumber():toString()}` converts the value of "fileSize" attribute to a number and
	back to a String.

[.function]
=== toNumber

*Description*: [.description]#Coerces the Subject into a Number#

*Subject Type*: [.subject]#String#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: The Expression `${fileSize:toNumber()}` converts the String attribute value of "fileSize" to a number.

[[subjectless]]
== Subjectless Functions

While the majority of functions in the Expression Language are called by using the syntax
`${attributeName:function()}`, there exist a few functions that are not expected to have subjects.
In this case, the attribute name is not present. For example, the IP address of the machine can
be obtained by using the Expression `${ip()}`. All of the functions in this section are to be called
without a subject. Attempting to call a subjectless function and provide it a subject will result in
an error when validating the function.

[.function]
=== ip

*Description*: [.description]#Returns the IP address of the machine.#

*Subject Type*: [.subjectless]#No subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: The IP address of the machine can be obtained by using the Expresison `${ip()}`.

[.function]
=== hostname

*Description*: [.description]#Returns the Hostname of the machine. An optional argument of type Boolean can be provided
	to specify whether or not the Fully Qualified Domain Name should be used. If `false`, or not specified,
	the hostname will not be fully qualified. If the argument is `true` but the fully qualified hostname
	cannot be resolved, the simple hostname will be returned.#

*Subject Type*: [.subjectless]#No subject#

*Arguments*:

	- [.argName]#_Fully Qualified_# : [.argDesc]#Optional parameter that specifies whether or not the hostname should be
		fully qualified. If not specified, defaults to false.#

*Return Type*: [.returnType]#String#

*Examples*: The fully qualified hostname of the machine can be obtained by using the Expression `${hostname(true)}`,
	while the simple hostname can be obtained by using either `${hostname(false)}` or simply `${hostname()}`.

[.function]
=== UUID

*Description*: [.description]#Returns a randomly generated UUID.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#String#

*Examples*: ${UUID()} returns a value similar to de305d54-75b4-431b-adb2-eb6b9e546013

[.function]
=== nextInt

*Description*: [.description]#Returns a one-up value (starting at 0) and increasing over the lifetime of the running instance of NiFi.
	This value is not persisted across restarts and is not guaranteed to be unique across a cluster.
	This value is considered "one-up" in that if called multiple times across the NiFi instance, the values will be sequential.
	However, this counter is shared across all NiFi components, so calling this function multiple times from one Processor will
	not guarantee sequential values within the context of a particular Processor.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: If the previous value returned by `nextInt` was `5`, the Expression `${nextInt():divide(2)}` obtains the next available
	integer (6) and divides the result by 2, returning a value of `3`.

[[multi]]
== Evaluating Multiple Attributes

When it becomes necessary to evaluate the same conditions against multiple attributes, this can be accomplished by means of the
`and` and `or` functions. However, this quickly becomes tedious, error-prone, and difficult to maintain. For this reason, NiFi
provides several functions for evaluating the same conditions against groups of attributes at the same time.

[.function]
=== anyAttribute

*Description*: [.description]#Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are the names of attributes to which the remainder of the Expression is to be applied. If any of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Attribute Names_# : [.argDesc]#One or more attribute names to evaluate#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyAttribute Examples
|=======================================================================
| Expression | Value
| `${anyAttribute("abc", "xyz"):contains("bye")}` | `true`
| `${anyAttribute("filename","xyz"):toUpper():contains("e")}` | `false`
|=======================================================================

[.function]
=== allAttributes

*Description*: [.description]#Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are the names of attributes to which the remainder of the Expression is to be applied. If all of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Attribute Names_# : [.argDesc]#One or more attribute names to evaluate#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.allAttributes Example
|=============================================================================
| Expression | Value
| `${allAttributes("abc", "xyz"):contains("world")}` | `true`
| `${allAttributes("abc", "filename","xyz"):toUpper():contains("e")}` | `false`
|=============================================================================

[.function]
=== anyMatchingAttribute

*Description*: [.description]# Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are Regular Expressions to match against attribute names. Any attribute whose name matches one of the supplied
	Regular Expressions will be evaluated against the rest of the Expression. If any of the attributes specified,
	when evaluated against the rest of the Expression, returns a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Regex_# : [.argDesc]#One or more Regular Expressions (in the Java Pattern syntax) to evaluate against attribute names#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyMatchingAttribute Example
|==============================================================
| Expression | Value
| `${anyMatchingAttribute("[ax].*"):contains('bye')}` | `true`
| `${anyMatchingAttribute(".*"):isNull()}` | `false`
|==============================================================

[.function]
=== allMatchingAttributes

*Description*: [.description]# Checks to see if any of the given attributes, match the given condition. This function has no subject and takes one or more
	arguments that are Regular Expressions to match against attribute names. Any attribute whose name matches one of the supplied
	Regular Expressions will be evaluated against the rest of the Expression. If all of the attributes specified,
	when evaluated against the rest of the Expression, return a value of `true`, then this function will return `true`. Otherwise, this function
	will return `false`.#

*Subject Type*: [.subjectless]#No Subject#

	- [.argName]#_Regex_# : [.argDesc]#One or more Regular Expressions (in the Java Pattern syntax) to evaluate against attribute names#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.anyMatchingAttributes Examples
|==============================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):contains("world")}` | `true`
| `${allMatchingAttributes(".*"):isNull()}` | `false`
| `${allMatchingAttributes("f.*"):count()}` | `1`
|==============================================================

[.function]
=== anyDelineatedValue

*Description*: [.description]#Splits a String apart according to a delimiter that is provided, and then evaluates each of the values against
	the rest of the Expression. If the Expression, when evaluated against any of the individual values, returns `true`, this
	function returns `true`. Otherwise, the function returns `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Delineated Value_# : [.argDesc]#The value that is delineated. This is generally an embedded Expression,
		though it does not have to be.#
	- [.argName]#_Delimiter_# : [.argDesc]#The value to use to split apart the _delineatedValue_ argument.#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "number_list" attribute contains the value "1,2,3,4,5", and the "word_list" attribute contains the value "the,and,or,not",
	consider the following examples:

.anyDelineatedValue Examples
|===============================================================================
| Expression | Value
| `${anyDelineatedValue("${number_list}", ","):contains("5")}` | `true`
| `${anyDelineatedValue("this that and", ","):equals("${word_list}")}` | `false`
|===============================================================================

[.function]
=== allDelineatedValues

*Description*: [.description]#Splits a String apart according to a delimiter that is provided, and then evaluates each of the values against
	the rest of the Expression. If the Expression, when evaluated against all of the individual values, returns `true` in each
	case, then this function returns `true`. Otherwise, the function returns `false`.#

*Subject Type*: [.subjectless]#No Subject#

*Arguments*:

	- [.argName]#_Delineated Value_# : [.argDesc]#The value that is delineated. This is generally
		an embedded Expression, though it does not have to be.#

	- [.argName]#_Delimiter_# : [.argDesc]#The value to use to split apart the _delineatedValue_ argument.#

*Return Type*: [.returnType]#Boolean#

*Examples*: Given that the "number_list" attribute contains the value "1,2,3,4,5", and the "word_list" attribute contains the value "those,known,or,not",
	consider the following examples:

.allDelineatedValues Examples
|===============================================================================
| Expression | Value
| `${allDelineatedValues("${word_list}", ","):contains("o")}` | `true`
| `${allDelineatedValues("${number_list}", ","):count()}` | `4`
| `${allDelineatedValues("${number_list}", ","):matches("[0-9]+")}` | `true`
| `${allDelineatedValues("${word_list}", ","):matches('e')}` | `false`
|===============================================================================

[.function]
=== join

*Description*: [.description]#Aggregate function that concatenates multiple values with the specified delimiter. This function
	may be used only in conjunction with the `allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`
	functions.#

*Subject Type*: [.subject]#String#

*Arguments*:

	- [.argName]#_Delimiter_# : [.argDesc]#The String delimiter to use when joining values#

*Return Type*: [.returnType]#String#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "filename" contains "file.txt" consider the following examples:

.join Examples
|=======================================================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):substringBefore(" "):join("-")}` | `hello-good`
| `${allAttributes("abc", "xyz"):join(" now")}` | `hello world nowgood bye world now`
|=======================================================================================

[.function]
=== count

*Description*: [.description]#Aggregate function that counts the number of non-null, non-false values returned by the
	`allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`. This function
	may be used only in conjunction with the `allAttributes`, `allMatchingAttributes`, and `allDelineatedValues`
	functions.#

*Subject Type*: [.subject]#Any#

*Arguments*: No arguments

*Return Type*: [.returnType]#Number#

*Examples*: Given that the "abc" attribute contains the value "hello world", "xyz" contains "good bye world",
	and "number_list" contains "1,2,3,4,5" consider the following examples:

.count Examples
|===========================================================================
| Expression | Value
| `${allMatchingAttributes("[ax].*"):substringBefore(" "):count()}` | `2`
| `${allAttributes("abc", "xyz"):contains("world"):count()}` | `1`
| `${allDelineatedValues(${number_list}, ","):count()}` | `5`
| `${allAttributes("abc", "non-existent-attr", "xyz"):count()}` | `2`
| `${allMatchingAttributes(".*"):length():gt(10):count()}` | `2`
|===========================================================================