[[expressions]]
= Spring Expression Language (SpEL)

The Spring Expression Language ("`SpEL`" for short) is a powerful expression language that
supports querying and manipulating an object graph at runtime. The language syntax is
similar to Unified EL but offers additional features, most notably method invocation and
basic string templating functionality.

While there are several other Java expression languages available -- OGNL, MVEL, and JBoss
EL, to name a few -- the Spring Expression Language was created to provide the Spring
community with a single well supported expression language that can be used across all
the products in the Spring portfolio. Its language features are driven by the
requirements of the projects in the Spring portfolio, including tooling requirements
for code completion support within the https://spring.io/tools[Spring Tools for Eclipse].
That said, SpEL is based on a technology-agnostic API that lets other expression language
implementations be integrated, should the need arise.

While SpEL serves as the foundation for expression evaluation within the Spring
portfolio, it is not directly tied to Spring and can be used independently. To
be self contained, many of the examples in this chapter use SpEL as if it were an
independent expression language. This requires creating a few bootstrapping
infrastructure classes, such as the parser. Most Spring users need not deal with
this infrastructure and can, instead, author only expression strings for evaluation.
An example of this typical use is the integration of SpEL into creating XML or
annotation-based bean definitions, as shown in
<<expressions-beandef, Expression support for defining bean definitions>>.

This chapter covers the features of the expression language, its API, and its language
syntax. In several places, `Inventor` and `Society` classes are used as the target
objects for expression evaluation. These class declarations and the data used to
populate them are listed at the end of the chapter.

The expression language supports the following functionality:

* Literal expressions
* Boolean and relational operators
* Regular expressions
* Class expressions
* Accessing properties, arrays, lists, and maps
* Method invocation
* Relational operators
* Assignment
* Calling constructors
* Bean references
* Array construction
* Inline lists
* Inline maps
* Ternary operator
* Variables
* User-defined functions
* Collection projection
* Collection selection
* Templated expressions




[[expressions-evaluation]]
== Evaluation

This section introduces the simple use of SpEL interfaces and its expression language.
The complete language reference can be found in
<<expressions-language-ref, Language Reference>>.

The following code introduces the SpEL API to evaluate the literal string expression,
`Hello World`.

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("'Hello World'"); // <1>
	String message = (String) exp.getValue();
----
<1> The value of the message variable is `'Hello World'`.

[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("'Hello World'") // <1>
	val message = exp.value as String
----
<1> The value of the message variable is `'Hello World'`.


The SpEL classes and interfaces you are most likely to use are located in the
`org.springframework.expression` package and its sub-packages, such as `spel.support`.

The `ExpressionParser` interface is responsible for parsing an expression string. In
the preceding example, the expression string is a string literal denoted by the surrounding single
quotation marks. The `Expression` interface is responsible for evaluating the previously defined
expression string. Two exceptions that can be thrown, `ParseException` and
`EvaluationException`, when calling `parser.parseExpression` and `exp.getValue`,
respectively.

SpEL supports a wide range of features, such as calling methods, accessing properties,
and calling constructors.

In the following example of method invocation, we call the `concat` method on the string literal:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("'Hello World'.concat('!')"); // <1>
	String message = (String) exp.getValue();
----
<1> The value of `message` is now 'Hello World!'.

[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("'Hello World'.concat('!')") // <1>
	val message = exp.value as String
----
<1> The value of `message` is now 'Hello World!'.

The following example of calling a JavaBean property calls the `String` property `Bytes`:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();

	// invokes 'getBytes()'
	Expression exp = parser.parseExpression("'Hello World'.bytes"); // <1>
	byte[] bytes = (byte[]) exp.getValue();
----
<1> This line converts the literal to a byte array.

[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()

	// invokes 'getBytes()'
	val exp = parser.parseExpression("'Hello World'.bytes") // <1>
	val bytes = exp.value as ByteArray
----
<1> This line converts the literal to a byte array.

SpEL also supports nested properties by using the standard dot notation (such as
`prop1.prop2.prop3`) and also the corresponding setting of property values.
Public fields may also be accessed.

The following example shows how to use dot notation to get the length of a literal:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();

	// invokes 'getBytes().length'
	Expression exp = parser.parseExpression("'Hello World'.bytes.length"); // <1>
	int length = (Integer) exp.getValue();
----
<1> `'Hello World'.bytes.length` gives the length of the literal.

[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()

	// invokes 'getBytes().length'
	val exp = parser.parseExpression("'Hello World'.bytes.length") // <1>
	val length = exp.value as Int
----
<1> `'Hello World'.bytes.length` gives the length of the literal.

The String's constructor can be called instead of using a string literal, as the following
example shows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); // <1>
	String message = exp.getValue(String.class);
----
<1> Construct a new `String` from the literal and make it be upper case.

[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("new String('hello world').toUpperCase()")  // <1>
	val message = exp.getValue(String::class.java)
----
<1> Construct a new `String` from the literal and make it be upper case.


Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`.
Using this method removes the need to cast the value of the expression to the desired
result type. An `EvaluationException` is thrown if the value cannot be cast to the
type `T` or converted by using the registered type converter.

The more common usage of SpEL is to provide an expression string that is evaluated
against a specific object instance (called the root object). The following example shows
how to retrieve the `name` property from an instance of the `Inventor` class or
create a boolean condition:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// Create and set a calendar
	GregorianCalendar c = new GregorianCalendar();
	c.set(1856, 7, 9);

	// The constructor arguments are name, birthday, and nationality.
	Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");

	ExpressionParser parser = new SpelExpressionParser();

	Expression exp = parser.parseExpression("name"); // Parse name as an expression
	String name = (String) exp.getValue(tesla);
	// name == "Nikola Tesla"

	exp = parser.parseExpression("name == 'Nikola Tesla'");
	boolean result = exp.getValue(tesla, Boolean.class);
	// result == true
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// Create and set a calendar
	val c = GregorianCalendar()
	c.set(1856, 7, 9)

	// The constructor arguments are name, birthday, and nationality.
	val tesla = Inventor("Nikola Tesla", c.time, "Serbian")

	val parser = SpelExpressionParser()

	var exp = parser.parseExpression("name") // Parse name as an expression
	val name = exp.getValue(tesla) as String
	// name == "Nikola Tesla"

	exp = parser.parseExpression("name == 'Nikola Tesla'")
	val result = exp.getValue(tesla, Boolean::class.java)
	// result == true
----




[[expressions-evaluation-context]]
=== Understanding `EvaluationContext`

The `EvaluationContext` interface is used when evaluating an expression to resolve
properties, methods, or fields and to help perform type conversion. Spring provides two
implementations.

* `SimpleEvaluationContext`: Exposes a subset of essential SpEL language features and
configuration options, for categories of expressions that do not require the full extent
of the SpEL language syntax and should be meaningfully restricted. Examples include but
are not limited to data binding expressions and property-based filters.

* `StandardEvaluationContext`: Exposes the full set of SpEL language features and
configuration options. You can use it to specify a default root object and to configure
every available evaluation-related strategy.

`SimpleEvaluationContext` is designed to support only a subset of the SpEL language syntax.
It excludes Java type references, constructors, and bean references. It also requires
you to explicitly choose the level of support for properties and methods in expressions.
By default, the `create()` static factory method enables only read access to properties.
You can also obtain a builder to configure the exact level of support needed, targeting
one or some combination of the following:

* Custom `PropertyAccessor` only (no reflection)
* Data binding properties for read-only access
* Data binding properties for read and write


[[expressions-type-conversion]]
==== Type Conversion

By default, SpEL uses the conversion service available in Spring core
(`org.springframework.core.convert.ConversionService`). This conversion service comes
with many built-in converters for common conversions but is also fully extensible so that
you can add custom conversions between types. Additionally, it is
generics-aware. This means that, when you work with generic types in
expressions, SpEL attempts conversions to maintain type correctness for any objects
it encounters.

What does this mean in practice? Suppose assignment, using `setValue()`, is being used
to set a `List` property. The type of the property is actually `List<Boolean>`. SpEL
recognizes that the elements of the list need to be converted to `Boolean` before
being placed in it. The following example shows how to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	class Simple {
		public List<Boolean> booleanList = new ArrayList<>();
	}

	Simple simple = new Simple();
	simple.booleanList.add(true);

	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

	// "false" is passed in here as a String. SpEL and the conversion service
	// will recognize that it needs to be a Boolean and convert it accordingly.
	parser.parseExpression("booleanList[0]").setValue(context, simple, "false");

	// b is false
	Boolean b = simple.booleanList.get(0);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class Simple {
		var booleanList: MutableList<Boolean> = ArrayList()
	}

	val simple = Simple()
	simple.booleanList.add(true)

	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()

	// "false" is passed in here as a String. SpEL and the conversion service
	// will recognize that it needs to be a Boolean and convert it accordingly.
	parser.parseExpression("booleanList[0]").setValue(context, simple, "false")

	// b is false
	val b = simple.booleanList[0]
----


[[expressions-parser-configuration]]
=== Parser Configuration

It is possible to configure the SpEL expression parser by using a parser configuration
object (`org.springframework.expression.spel.SpelParserConfiguration`). The configuration
object controls the behavior of some of the expression components. For example, if you
index into an array or collection and the element at the specified index is `null`, SpEL
can automatically create the element. This is useful when using expressions made up of a
chain of property references. If you index into an array or list and specify an index
that is beyond the end of the current size of the array or list, SpEL can automatically
grow the array or list to accommodate that index. In order to add an element at the
specified index, SpEL will try to create the element using the element type's default
constructor before setting the specified value. If the element type does not have a
default constructor, `null` will be added to the array or list. If there is no built-in
or custom converter that knows how to set the value, `null` will remain in the array or
list at the specified index. The following example demonstrates how to automatically grow
the list:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	class Demo {
		public List<String> list;
	}

	// Turn on:
	// - auto null reference initialization
	// - auto collection growing
	SpelParserConfiguration config = new SpelParserConfiguration(true, true);

	ExpressionParser parser = new SpelExpressionParser(config);

	Expression expression = parser.parseExpression("list[3]");

	Demo demo = new Demo();

	Object o = expression.getValue(demo);

	// demo.list will now be a real collection of 4 entries
	// Each entry is a new empty String
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class Demo {
		var list: List<String>? = null
	}

	// Turn on:
	// - auto null reference initialization
	// - auto collection growing
	val config = SpelParserConfiguration(true, true)

	val parser = SpelExpressionParser(config)

	val expression = parser.parseExpression("list[3]")

	val demo = Demo()

	val o = expression.getValue(demo)

	// demo.list will now be a real collection of 4 entries
	// Each entry is a new empty String
----



[[expressions-spel-compilation]]
=== SpEL Compilation

Spring Framework 4.1 includes a basic expression compiler. Expressions are usually
interpreted, which provides a lot of dynamic flexibility during evaluation but
does not provide optimum performance. For occasional expression usage,
this is fine, but, when used by other components such as Spring Integration,
performance can be very important, and there is no real need for the dynamism.

The SpEL compiler is intended to address this need. During evaluation, the compiler
generates a Java class that embodies the expression behavior at runtime and uses that
class to achieve much faster expression evaluation. Due to the lack of typing around
expressions, the compiler uses information gathered during the interpreted evaluations
of an expression when performing compilation. For example, it does not know the type
of a property reference purely from the expression, but during the first interpreted
evaluation, it finds out what it is. Of course, basing compilation on such derived
information can cause trouble later if the types of the various expression elements
change over time. For this reason, compilation is best suited to expressions whose
type information is not going to change on repeated evaluations.

Consider the following basic expression:

----
someArray[0].someProperty.someOtherProperty < 0.1
----

Because the preceding expression involves array access, some property de-referencing,
and numeric operations, the performance gain can be very noticeable. In an example
micro benchmark run of 50000 iterations, it took 75ms to evaluate by using the
interpreter and only 3ms using the compiled version of the expression.


[[expressions-compiler-configuration]]
==== Compiler Configuration

The compiler is not turned on by default, but you can turn it on in either of two
different ways. You can turn it on by using the parser configuration process
(<<expressions-parser-configuration, discussed earlier>>) or by using a Spring property
when SpEL usage is embedded inside another component. This section discusses both of
these options.

The compiler can operate in one of three modes, which are captured in the
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows:

* `OFF` (default): The compiler is switched off.
* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This
is typically after the first interpreted evaluation. If the compiled expression fails
(typically due to a type changing, as described earlier), the caller of the expression
evaluation receives an exception.
* `MIXED`: In mixed mode, the expressions silently switch between interpreted and compiled
mode over time. After some number of interpreted runs, they switch to compiled
form and, if something goes wrong with the compiled form (such as a type changing, as
described earlier), the expression automatically switches back to interpreted form
again. Sometime later, it may generate another compiled form and switch to it. Basically,
the exception that the user gets in `IMMEDIATE` mode is instead handled internally.

`IMMEDIATE` mode exists because `MIXED` mode could cause issues for expressions that
have side effects. If a compiled expression blows up after partially succeeding, it
may have already done something that has affected the state of the system. If this
has happened, the caller may not want it to silently re-run in interpreted mode,
since part of the expression may be running twice.

After selecting a mode, use the `SpelParserConfiguration` to configure the parser. The
following example shows how to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
			this.getClass().getClassLoader());

	SpelExpressionParser parser = new SpelExpressionParser(config);

	Expression expr = parser.parseExpression("payload");

	MyMessage message = new MyMessage();

	Object payload = expr.getValue(message);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val config = SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
			this.javaClass.classLoader)

	val parser = SpelExpressionParser(config)

	val expr = parser.parseExpression("payload")

	val message = MyMessage()

	val payload = expr.getValue(message)
----

When you specify the compiler mode, you can also specify a classloader (passing null is allowed).
Compiled expressions are defined in a child classloader created under any that is supplied.
It is important to ensure that, if a classloader is specified, it can see all the types involved in
the expression evaluation process. If you do not specify a classloader, a default classloader is used
(typically the context classloader for the thread that is running during expression evaluation).

The second way to configure the compiler is for use when SpEL is embedded inside some
other component and it may not be possible to configure it through a configuration
object. In these cases, it is possible to set the `spring.expression.compiler.mode`
property via a JVM system property (or via the
<<appendix.adoc#appendix-spring-properties,`SpringProperties`>> mechanism) to one of the
`SpelCompilerMode` enum values (`off`, `immediate`, or `mixed`).


[[expressions-compiler-limitations]]
==== Compiler Limitations

Since Spring Framework 4.1, the basic compilation framework is in place. However, the framework
does not yet support compiling every kind of expression. The initial focus has been on the
common expressions that are likely to be used in performance-critical contexts. The following
kinds of expression cannot be compiled at the moment:

* Expressions involving assignment
* Expressions relying on the conversion service
* Expressions using custom resolvers or accessors
* Expressions using selection or projection

More types of expressions will be compilable in the future.




[[expressions-beandef]]
== Expressions in Bean Definitions

You can use SpEL expressions with XML-based or annotation-based configuration metadata for
defining `BeanDefinition` instances. In both cases, the syntax to define the expression is of the
form `#{ <expression string> }`.



[[expressions-beandef-xml-based]]
=== XML Configuration

A property or constructor argument value can be set by using expressions, as the following
example shows:

[source,xml,indent=0,subs="verbatim"]
----
	<bean id="numberGuess" class="org.spring.samples.NumberGuess">
		<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>

		<!-- other properties -->
	</bean>
----

All beans in the application context are available as predefined variables with their
common bean name. This includes standard context beans such as `environment` (of type
`org.springframework.core.env.Environment`) as well as `systemProperties` and
`systemEnvironment` (of type `Map<String, Object>`) for access to the runtime environment.

The following example shows access to the `systemProperties` bean as a SpEL variable:

[source,xml,indent=0,subs="verbatim"]
----
	<bean id="taxCalculator" class="org.spring.samples.TaxCalculator">
		<property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>

		<!-- other properties -->
	</bean>
----

Note that you do not have to prefix the predefined variable with the `#` symbol here.

You can also refer to other bean properties by name, as the following example shows:

[source,xml,indent=0,subs="verbatim"]
----
	<bean id="numberGuess" class="org.spring.samples.NumberGuess">
		<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>

		<!-- other properties -->
	</bean>

	<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
		<property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>

		<!-- other properties -->
	</bean>
----



[[expressions-beandef-annotation-based]]
=== Annotation Configuration

To specify a default value, you can place the `@Value` annotation on fields, methods,
and method or constructor parameters.

The following example sets the default value of a field:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
		public class FieldValueTestBean {

			@Value("#{ systemProperties['user.region'] }")
			private String defaultLocale;

			public void setDefaultLocale(String defaultLocale) {
				this.defaultLocale = defaultLocale;
			}

			public String getDefaultLocale() {
				return this.defaultLocale;
			}
		}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class FieldValueTestBean {

		@Value("#{ systemProperties['user.region'] }")
		var defaultLocale: String? = null
	}
----

The following example shows the equivalent but on a property setter method:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	public class PropertyValueTestBean {

		private String defaultLocale;

		@Value("#{ systemProperties['user.region'] }")
		public void setDefaultLocale(String defaultLocale) {
			this.defaultLocale = defaultLocale;
		}

		public String getDefaultLocale() {
			return this.defaultLocale;
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class PropertyValueTestBean {

		@Value("#{ systemProperties['user.region'] }")
		var defaultLocale: String? = null
	}
----

Autowired methods and constructors can also use the `@Value` annotation, as the following
examples show:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	public class SimpleMovieLister {

		private MovieFinder movieFinder;
		private String defaultLocale;

		@Autowired
		public void configure(MovieFinder movieFinder,
				@Value("#{ systemProperties['user.region'] }") String defaultLocale) {
			this.movieFinder = movieFinder;
			this.defaultLocale = defaultLocale;
		}

		// ...
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class SimpleMovieLister {

		private lateinit var movieFinder: MovieFinder
		private lateinit var defaultLocale: String

		@Autowired
		fun configure(movieFinder: MovieFinder,
					@Value("#{ systemProperties['user.region'] }") defaultLocale: String) {
			this.movieFinder = movieFinder
			this.defaultLocale = defaultLocale
		}

		// ...
	}
----

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	public class MovieRecommender {

		private String defaultLocale;

		private CustomerPreferenceDao customerPreferenceDao;

		public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
				@Value("#{systemProperties['user.country']}") String defaultLocale) {
			this.customerPreferenceDao = customerPreferenceDao;
			this.defaultLocale = defaultLocale;
		}

		// ...
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class MovieRecommender(private val customerPreferenceDao: CustomerPreferenceDao,
				@Value("#{systemProperties['user.country']}") private val defaultLocale: String) {
		// ...	
	}
----




[[expressions-language-ref]]
== Language Reference

This section describes how the Spring Expression Language works. It covers the following
topics:

* <<expressions-ref-literal>>
* <<expressions-properties-arrays>>
* <<expressions-inline-lists>>
* <<expressions-inline-maps>>
* <<expressions-array-construction>>
* <<expressions-methods>>
* <<expressions-operators>>
* <<expressions-types>>
* <<expressions-constructors>>
* <<expressions-ref-variables>>
* <<expressions-ref-functions>>
* <<expressions-bean-references>>
* <<expressions-operator-ternary>>
* <<expressions-operator-elvis>>
* <<expressions-operator-safe-navigation>>



[[expressions-ref-literal]]
=== Literal Expressions

SpEL supports the following types of literal expressions.

- strings
- numeric values: integer (`int` or `long`), hexadecimal (`int` or `long`), real (`float`
  or `double`)
- boolean values: `true` or `false`
- null

Strings can delimited by single quotation marks (`'`) or double quotation marks (`"`). To
include a single quotation mark within a string literal enclosed in single quotation
marks, use two adjacent single quotation mark characters. Similarly, to include a double
quotation mark within a string literal enclosed in double quotation marks, use two
adjacent double quotation mark characters.

Numbers support the use of the negative sign, exponential notation, and decimal points.
By default, real numbers are parsed by using `Double.parseDouble()`.

The following listing shows simple usage of literals. Typically, they are not used in
isolation like this but, rather, as part of a more complex expression -- for example,
using a literal on one side of a logical comparison operator or as an argument to a
method.

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();

	// evaluates to "Hello World"
	String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();

	// evaluates to "Tony's Pizza"
	String pizzaParlor = (String) parser.parseExpression("'Tony''s Pizza'").getValue();

	double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();

	// evaluates to 2147483647
	int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();

	boolean trueValue = (Boolean) parser.parseExpression("true").getValue();

	Object nullValue = parser.parseExpression("null").getValue();
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()

	// evaluates to "Hello World"
	val helloWorld = parser.parseExpression("'Hello World'").value as String

	// evaluates to "Tony's Pizza"
	val pizzaParlor = parser.parseExpression("'Tony''s Pizza'").value as String

	val avogadrosNumber = parser.parseExpression("6.0221415E+23").value as Double

	// evaluates to 2147483647
	val maxValue = parser.parseExpression("0x7FFFFFFF").value as Int

	val trueValue = parser.parseExpression("true").value as Boolean

	val nullValue = parser.parseExpression("null").value
----



[[expressions-properties-arrays]]
=== Properties, Arrays, Lists, Maps, and Indexers

Navigating with property references is easy. To do so, use a period to indicate a nested
property value. The instances of the `Inventor` class, `pupin` and `tesla`, were
populated with data listed in the <<expressions-example-classes, Classes used in the
examples>> section. To navigate "down" the object graph and get Tesla's year of birth and
Pupin's city of birth, we use the following expressions:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// evaluates to 1856
	int year = (Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);

	String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// evaluates to 1856
	val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int

	val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
----

[NOTE]
====
Case insensitivity is allowed for the first letter of property names. Thus, the
expressions in the above example may be written as `Birthdate.Year + 1900` and
`PlaceOfBirth.City`, respectively. In addition, properties may optionally be accessed via
method invocations -- for example, `getPlaceOfBirth().getCity()` instead of
`placeOfBirth.city`.
====

The contents of arrays and lists are obtained by using square bracket notation, as the
following example shows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

	// Inventions Array

	// evaluates to "Induction motor"
	String invention = parser.parseExpression("inventions[3]").getValue(
			context, tesla, String.class);

	// Members List

	// evaluates to "Nikola Tesla"
	String name = parser.parseExpression("members[0].name").getValue(
			context, ieee, String.class);

	// List and Array navigation
	// evaluates to "Wireless communication"
	String invention = parser.parseExpression("members[0].inventions[6]").getValue(
			context, ieee, String.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()

	// Inventions Array

	// evaluates to "Induction motor"
	val invention = parser.parseExpression("inventions[3]").getValue(
			context, tesla, String::class.java)

	// Members List

	// evaluates to "Nikola Tesla"
	val name = parser.parseExpression("members[0].name").getValue(
			context, ieee, String::class.java)

	// List and Array navigation
	// evaluates to "Wireless communication"
	val invention = parser.parseExpression("members[0].inventions[6]").getValue(
			context, ieee, String::class.java)
----

The contents of maps are obtained by specifying the literal key value within the
brackets. In the following example, because keys for the `officers` map are strings, we can specify
string literals:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// Officer's Dictionary

	Inventor pupin = parser.parseExpression("officers['president']").getValue(
			societyContext, Inventor.class);

	// evaluates to "Idvor"
	String city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
			societyContext, String.class);

	// setting values
	parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
			societyContext, "Croatia");
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// Officer's Dictionary

	val pupin = parser.parseExpression("officers['president']").getValue(
			societyContext, Inventor::class.java)

	// evaluates to "Idvor"
	val city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
			societyContext, String::class.java)

	// setting values
	parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
			societyContext, "Croatia")
----



[[expressions-inline-lists]]
=== Inline Lists

You can directly express lists in an expression by using `{}` notation.

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// evaluates to a Java list containing the four numbers
	List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);

	List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// evaluates to a Java list containing the four numbers
	val numbers = parser.parseExpression("{1,2,3,4}").getValue(context) as List<*>

	val listOfLists = parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context) as List<*>
----

`{}` by itself means an empty list. For performance reasons, if the list is itself
entirely composed of fixed literals, a constant list is created to represent the
expression (rather than building a new list on each evaluation).



[[expressions-inline-maps]]
=== Inline Maps

You can also directly express maps in an expression by using `{key:value}` notation. The
following example shows how to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// evaluates to a Java map containing the two entries
	Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);

	Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
.Kotlin
----
	// evaluates to a Java map containing the two entries
	val inventorInfo = parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context) as Map<*, *>

	val mapOfMaps = parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context) as Map<*, *>	
----

`{:}` by itself means an empty map. For performance reasons, if the map is itself
composed of fixed literals or other nested constant structures (lists or maps), a
constant map is created to represent the expression (rather than building a new map on
each evaluation). Quoting of the map keys is optional (unless the key contains a period
(`.`)). The examples above do not use quoted keys.



[[expressions-array-construction]]
=== Array Construction

You can build arrays by using the familiar Java syntax, optionally supplying an initializer
to have the array populated at construction time. The following example shows how to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);

	// Array with initializer
	int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);

	// Multi dimensional array
	int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val numbers1 = parser.parseExpression("new int[4]").getValue(context) as IntArray

	// Array with initializer
	val numbers2 = parser.parseExpression("new int[]{1,2,3}").getValue(context) as IntArray

	// Multi dimensional array
	val numbers3 = parser.parseExpression("new int[4][5]").getValue(context) as Array<IntArray>
----

You cannot currently supply an initializer when you construct a multi-dimensional array.



[[expressions-methods]]
=== Methods

You can invoke methods by using typical Java programming syntax. You can also invoke methods
on literals. Variable arguments are also supported. The following examples show how to
invoke methods:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// string literal, evaluates to "bc"
	String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);

	// evaluates to true
	boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
			societyContext, Boolean.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// string literal, evaluates to "bc"
	val bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String::class.java)

	// evaluates to true
	val isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
			societyContext, Boolean::class.java)
----


[[expressions-operators]]
=== Operators

The Spring Expression Language supports the following kinds of operators:

* <<expressions-operators-relational>>
* <<expressions-operators-logical>>
* <<expressions-operators-mathematical>>
* <<expressions-assignment>>


[[expressions-operators-relational]]
==== Relational Operators

The relational operators (equal, not equal, less than, less than or equal, greater than,
and greater than or equal) are supported by using standard operator notation.
These operators work on `Number` types as well as types implementing `Comparable`.
The following listing shows a few examples of operators:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// evaluates to true
	boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);

	// evaluates to false
	boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);

	// evaluates to true
	boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);

	// uses CustomValue:::compareTo
	boolean trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// evaluates to true
	val trueValue = parser.parseExpression("2 == 2").getValue(Boolean::class.java)

	// evaluates to false
	val falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean::class.java)

	// evaluates to true
	val trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean::class.java)

	// uses CustomValue:::compareTo
	val trueValue = parser.parseExpression("new CustomValue(1) < new CustomValue(2)").getValue(Boolean::class.java);
----

[NOTE]
====
Greater-than and less-than comparisons against `null` follow a simple rule: `null` is treated as
nothing (that is NOT as zero). As a consequence, any other value is always greater
than `null` (`X > null` is always `true`) and no other value is ever less than nothing
(`X < null` is always `false`).

If you prefer numeric comparisons instead, avoid number-based `null` comparisons
in favor of comparisons against zero (for example, `X > 0` or `X < 0`).
====

In addition to the standard relational operators, SpEL supports the `instanceof` and regular
expression-based `matches` operator. The following listing shows examples of both:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// evaluates to false
	boolean falseValue = parser.parseExpression(
			"'xyz' instanceof T(Integer)").getValue(Boolean.class);

	// evaluates to true
	boolean trueValue = parser.parseExpression(
			"'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);

	// evaluates to false
	boolean falseValue = parser.parseExpression(
			"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// evaluates to false
	val falseValue = parser.parseExpression(
			"'xyz' instanceof T(Integer)").getValue(Boolean::class.java)

	// evaluates to true
	val trueValue = parser.parseExpression(
			"'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean::class.java)

	// evaluates to false
	val falseValue = parser.parseExpression(
			"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean::class.java)
----

CAUTION: Be careful with primitive types, as they are immediately boxed up to their
wrapper types. For example, `1 instanceof T(int)` evaluates to `false`, while
`1 instanceof T(Integer)` evaluates to `true`, as expected.

Each symbolic operator can also be specified as a purely alphabetic equivalent. This
avoids problems where the symbols used have special meaning for the document type in
which the expression is embedded (such as in an XML document). The textual equivalents are:

* `lt` (`<`)
* `gt` (`>`)
* `le` (`\<=`)
* `ge` (`>=`)
* `eq` (`==`)
* `ne` (`!=`)
* `div` (`/`)
* `mod` (`%`)
* `not` (`!`).

All of the textual operators are case-insensitive.


[[expressions-operators-logical]]
==== Logical Operators

SpEL supports the following logical operators:

* `and` (`&&`)
* `or` (`||`)
* `not` (`!`)

The following example shows how to use the logical operators:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// -- AND --

	// evaluates to false
	boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);

	// evaluates to true
	String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
	boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

	// -- OR --

	// evaluates to true
	boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);

	// evaluates to true
	String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
	boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

	// -- NOT --

	// evaluates to false
	boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);

	// -- AND and NOT --
	String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
	boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// -- AND --

	// evaluates to false
	val falseValue = parser.parseExpression("true and false").getValue(Boolean::class.java)

	// evaluates to true
	val expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')"
	val trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)

	// -- OR --

	// evaluates to true
	val trueValue = parser.parseExpression("true or false").getValue(Boolean::class.java)

	// evaluates to true
	val expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')"
	val trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)

	// -- NOT --

	// evaluates to false
	val falseValue = parser.parseExpression("!true").getValue(Boolean::class.java)

	// -- AND and NOT --
	val expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')"
	val falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)
----


[[expressions-operators-mathematical]]
==== Mathematical Operators

You can use the addition operator (`+`) on both numbers and strings. You can use the
subtraction (`-`), multiplication (`*`), and division (`/`) operators only on numbers.
You can also use the modulus (`%`) and exponential power (`^`) operators on numbers.
Standard operator precedence is enforced. The following example shows the mathematical
operators in use:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// Addition
	int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2

	String testString = parser.parseExpression(
			"'test' + ' ' + 'string'").getValue(String.class);  // 'test string'

	// Subtraction
	int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4

	double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000

	// Multiplication
	int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6

	double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0

	// Division
	int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2

	double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0

	// Modulus
	int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3

	int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1

	// Operator precedence
	int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// Addition
	val two = parser.parseExpression("1 + 1").getValue(Int::class.java)  // 2

	val testString = parser.parseExpression(
			"'test' + ' ' + 'string'").getValue(String::class.java)  // 'test string'

	// Subtraction
	val four = parser.parseExpression("1 - -3").getValue(Int::class.java)  // 4

	val d = parser.parseExpression("1000.00 - 1e4").getValue(Double::class.java)  // -9000

	// Multiplication
	val six = parser.parseExpression("-2 * -3").getValue(Int::class.java)  // 6

	val twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double::class.java)  // 24.0

	// Division
	val minusTwo = parser.parseExpression("6 / -3").getValue(Int::class.java)  // -2

	val one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double::class.java)  // 1.0

	// Modulus
	val three = parser.parseExpression("7 % 4").getValue(Int::class.java)  // 3

	val one = parser.parseExpression("8 / 5 % 2").getValue(Int::class.java)  // 1

	// Operator precedence
	val minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Int::class.java)  // -21	
----


[[expressions-assignment]]
==== The Assignment Operator

To set a property, use the assignment operator (`=`). This is typically done within a
call to `setValue` but can also be done inside a call to `getValue`. The following
listing shows both ways to use the assignment operator:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Inventor inventor = new Inventor();
	EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();

	parser.parseExpression("name").setValue(context, inventor, "Aleksandar Seovic");

	// alternatively
	String aleks = parser.parseExpression(
			"name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val inventor = Inventor()
	val context = SimpleEvaluationContext.forReadWriteDataBinding().build()

	parser.parseExpression("name").setValue(context, inventor, "Aleksandar Seovic")

	// alternatively
	val aleks = parser.parseExpression(
			"name = 'Aleksandar Seovic'").getValue(context, inventor, String::class.java)
----


[[expressions-types]]
=== Types

You can use the special `T` operator to specify an instance of `java.lang.Class` (the
type). Static methods are invoked by using this operator as well. The
`StandardEvaluationContext` uses a `TypeLocator` to find types, and the
`StandardTypeLocator` (which can be replaced) is built with an understanding of the
`java.lang` package. This means that `T()` references to types within the `java.lang`
package do not need to be fully qualified, but all other type references must be. The
following example shows how to use the `T` operator:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);

	Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);

	boolean trueValue = parser.parseExpression(
			"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
			.getValue(Boolean.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class::class.java)

	val stringClass = parser.parseExpression("T(String)").getValue(Class::class.java)

	val trueValue = parser.parseExpression(
			"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
			.getValue(Boolean::class.java)
----



[[expressions-constructors]]
=== Constructors

You can invoke constructors by using the `new` operator. You should use the fully
qualified class name for all types except those located in the `java.lang` package
(`Integer`, `Float`, `String`, and so on). The following example shows how to use the
`new` operator to invoke constructors:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Inventor einstein = p.parseExpression(
			"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
			.getValue(Inventor.class);

	// create new Inventor instance within the add() method of List
	p.parseExpression(
			"Members.add(new org.spring.samples.spel.inventor.Inventor(
				'Albert Einstein', 'German'))").getValue(societyContext);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val einstein = p.parseExpression(
			"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
			.getValue(Inventor::class.java)

	// create new Inventor instance within the add() method of List
	p.parseExpression(
			"Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
			.getValue(societyContext)
----



[[expressions-ref-variables]]
=== Variables

You can reference variables in the expression by using the `#variableName` syntax. Variables
are set by using the `setVariable` method on `EvaluationContext` implementations.

[NOTE]
====
Valid variable names must be composed of one or more of the following supported
characters.

* letters: `A` to `Z` and `a` to `z`
* digits: `0` to `9`
* underscore: `_`
* dollar sign: `$`
====

The following example shows how to use variables.

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Inventor tesla = new Inventor("Nikola Tesla", "Serbian");

	EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
	context.setVariable("newName", "Mike Tesla");

	parser.parseExpression("name = #newName").getValue(context, tesla);
	System.out.println(tesla.getName())  // "Mike Tesla"
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val tesla = Inventor("Nikola Tesla", "Serbian")

	val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
	context.setVariable("newName", "Mike Tesla")

	parser.parseExpression("name = #newName").getValue(context, tesla)
	println(tesla.name)  // "Mike Tesla"
----


[[expressions-this-root]]
==== The `#this` and `#root` Variables

The `#this` variable is always defined and refers to the current evaluation object
(against which unqualified references are resolved). The `#root` variable is always
defined and refers to the root context object. Although `#this` may vary as components of
an expression are evaluated, `#root` always refers to the root. The following examples
show how to use the `#this` and `#root` variables:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// create an array of integers
	List<Integer> primes = new ArrayList<>();
	primes.addAll(Arrays.asList(2,3,5,7,11,13,17));

	// create parser and set variable 'primes' as the array of integers
	ExpressionParser parser = new SpelExpressionParser();
	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
	context.setVariable("primes", primes);

	// all prime numbers > 10 from the list (using selection ?{...})
	// evaluates to [11, 13, 17]
	List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
			"#primes.?[#this>10]").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// create an array of integers
	val primes = ArrayList<Int>()
	primes.addAll(listOf(2, 3, 5, 7, 11, 13, 17))

	// create parser and set variable 'primes' as the array of integers
	val parser = SpelExpressionParser()
	val context = SimpleEvaluationContext.forReadOnlyDataAccess()
	context.setVariable("primes", primes)

	// all prime numbers > 10 from the list (using selection ?{...})
	// evaluates to [11, 13, 17]
	val primesGreaterThanTen = parser.parseExpression(
			"#primes.?[#this>10]").getValue(context) as List<Int>
----



[[expressions-ref-functions]]
=== Functions

You can extend SpEL by registering user-defined functions that can be called within the
expression string. The function is registered through the `EvaluationContext`. The
following example shows how to register a user-defined function:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Method method = ...;

	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
	context.setVariable("myFunction", method);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val method: Method = ...

	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
	context.setVariable("myFunction", method)
----

For example, consider the following utility method that reverses a string:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	public abstract class StringUtils {

		public static String reverseString(String input) {
			StringBuilder backwards = new StringBuilder(input.length());
			for (int i = 0; i < input.length(); i++) {
				backwards.append(input.charAt(input.length() - 1 - i));
			}
			return backwards.toString();
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	fun reverseString(input: String): String {
		val backwards = StringBuilder(input.length)
		for (i in 0 until input.length) {
			backwards.append(input[input.length - 1 - i])
		}
		return backwards.toString()
	}
----

You can then register and use the preceding method, as the following example shows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();

	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
	context.setVariable("reverseString",
			StringUtils.class.getDeclaredMethod("reverseString", String.class));

	String helloWorldReversed = parser.parseExpression(
			"#reverseString('hello')").getValue(context, String.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()

	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
	context.setVariable("reverseString", ::reverseString::javaMethod)

	val helloWorldReversed = parser.parseExpression(
			"#reverseString('hello')").getValue(context, String::class.java)
----



[[expressions-bean-references]]
=== Bean References

If the evaluation context has been configured with a bean resolver, you can
look up beans from an expression by using the `@` symbol. The following example shows how
to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	StandardEvaluationContext context = new StandardEvaluationContext();
	context.setBeanResolver(new MyBeanResolver());

	// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
	Object bean = parser.parseExpression("@something").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val context = StandardEvaluationContext()
	context.setBeanResolver(MyBeanResolver())

	// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
	val bean = parser.parseExpression("@something").getValue(context)
----

To access a factory bean itself, you should instead prefix the bean name with an `&` symbol.
The following example shows how to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	StandardEvaluationContext context = new StandardEvaluationContext();
	context.setBeanResolver(new MyBeanResolver());

	// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
	Object bean = parser.parseExpression("&foo").getValue(context);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val context = StandardEvaluationContext()
	context.setBeanResolver(MyBeanResolver())

	// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
	val bean = parser.parseExpression("&foo").getValue(context)
----


[[expressions-operator-ternary]]
=== Ternary Operator (If-Then-Else)

You can use the ternary operator for performing if-then-else conditional logic inside
the expression. The following listing shows a minimal example:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	String falseString = parser.parseExpression(
			"false ? 'trueExp' : 'falseExp'").getValue(String.class);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val falseString = parser.parseExpression(
			"false ? 'trueExp' : 'falseExp'").getValue(String::class.java)
----

In this case, the boolean `false` results in returning the string value `'falseExp'`. A more
realistic example follows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	parser.parseExpression("name").setValue(societyContext, "IEEE");
	societyContext.setVariable("queryName", "Nikola Tesla");

	expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
			"+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";

	String queryResultString = parser.parseExpression(expression)
			.getValue(societyContext, String.class);
	// queryResultString = "Nikola Tesla is a member of the IEEE Society"
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	parser.parseExpression("name").setValue(societyContext, "IEEE")
	societyContext.setVariable("queryName", "Nikola Tesla")

	expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'"

	val queryResultString = parser.parseExpression(expression)
			.getValue(societyContext, String::class.java)
	// queryResultString = "Nikola Tesla is a member of the IEEE Society"
----

See the next section on the Elvis operator for an even shorter syntax for the
ternary operator.



[[expressions-operator-elvis]]
=== The Elvis Operator

The Elvis operator is a shortening of the ternary operator syntax and is used in the
https://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language.
With the ternary operator syntax, you usually have to repeat a variable twice, as the
following example shows:

[source,groovy,indent=0,subs="verbatim,quotes"]
----
	String name = "Elvis Presley";
	String displayName = (name != null ? name : "Unknown");
----

Instead, you can use the Elvis operator (named for the resemblance to Elvis' hair style).
The following example shows how to use the Elvis operator:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();

	String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
	System.out.println(name);  // 'Unknown'
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()

	val name = parser.parseExpression("name?:'Unknown'").getValue(Inventor(), String::class.java)
	println(name)  // 'Unknown'
----

The following listing shows a more complex example:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

	Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
	String name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
	System.out.println(name);  // Nikola Tesla

	tesla.setName(null);
	name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String.class);
	System.out.println(name);  // Elvis Presley
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()

	val tesla = Inventor("Nikola Tesla", "Serbian")
	var name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
	println(name)  // Nikola Tesla

	tesla.setName(null)
	name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
	println(name)  // Elvis Presley
----

[NOTE]
=====
You can use the Elvis operator to apply default values in expressions. The following
example shows how to use the Elvis operator in a `@Value` expression:

[source,java,indent=0,subs="verbatim,quotes"]
----
	@Value("#{systemProperties['pop3.port'] ?: 25}")
----

This will inject a system property `pop3.port` if it is defined or 25 if not.
=====


[[expressions-operator-safe-navigation]]
=== Safe Navigation Operator

The safe navigation operator is used to avoid a `NullPointerException` and comes from
the https://www.groovy-lang.org/operators.html#_safe_navigation_operator[Groovy]
language. Typically, when you have a reference to an object, you might need to verify that
it is not null before accessing methods or properties of the object. To avoid this, the
safe navigation operator returns null instead of throwing an exception. The following
example shows how to use the safe navigation operator:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	ExpressionParser parser = new SpelExpressionParser();
	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

	Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
	tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));

	String city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
	System.out.println(city);  // Smiljan

	tesla.setPlaceOfBirth(null);
	city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
	System.out.println(city);  // null - does not throw NullPointerException!!!
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val parser = SpelExpressionParser()
	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()

	val tesla = Inventor("Nikola Tesla", "Serbian")
	tesla.setPlaceOfBirth(PlaceOfBirth("Smiljan"))

	var city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
	println(city)  // Smiljan

	tesla.setPlaceOfBirth(null)
	city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
	println(city)  // null - does not throw NullPointerException!!!
----



[[expressions-collection-selection]]
=== Collection Selection

Selection is a powerful expression language feature that lets you transform a
source collection into another collection by selecting from its entries.

Selection uses a syntax of `.?[selectionExpression]`. It filters the collection and
returns a new collection that contains a subset of the original elements. For example,
selection lets us easily get a list of Serbian inventors, as the following example shows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	List<Inventor> list = (List<Inventor>) parser.parseExpression(
			"members.?[nationality == 'Serbian']").getValue(societyContext);
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val list = parser.parseExpression(
			"members.?[nationality == 'Serbian']").getValue(societyContext) as List<Inventor>
----

Selection is supported for arrays and anything that implements `java.lang.Iterable` or
`java.util.Map`. For a list or array, the selection criteria is evaluated against each
individual element. Against a map, the selection criteria is evaluated against each map
entry (objects of the Java type `Map.Entry`). Each map entry has its `key` and `value`
accessible as properties for use in the selection.

The following expression returns a new map that consists of those elements of the
original map where the entry's value is less than 27:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	Map newMap = parser.parseExpression("map.?[value<27]").getValue();
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val newMap = parser.parseExpression("map.?[value<27]").getValue()
----

In addition to returning all the selected elements, you can retrieve only the first or
the last element. To obtain the first element matching the selection, the syntax is
`.^[selectionExpression]`. To obtain the last matching selection, the syntax is
`.$[selectionExpression]`.



[[expressions-collection-projection]]
=== Collection Projection

Projection lets a collection drive the evaluation of a sub-expression, and the result is
a new collection. The syntax for projection is `.![projectionExpression]`. For example,
suppose we have a list of inventors but want the list of cities where they were born.
Effectively, we want to evaluate 'placeOfBirth.city' for every entry in the inventor
list. The following example uses projection to do so:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	// returns ['Smiljan', 'Idvor' ]
	List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]");
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	// returns ['Smiljan', 'Idvor' ]
	val placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]") as List<*>
----

Projection is supported for arrays and anything that implements `java.lang.Iterable` or
`java.util.Map`. When using a map to drive projection, the projection expression is
evaluated against each entry in the map (represented as a Java `Map.Entry`). The result
of a projection across a map is a list that consists of the evaluation of the projection
expression against each map entry.



[[expressions-templating]]
=== Expression templating

Expression templates allow mixing literal text with one or more evaluation blocks.
Each evaluation block is delimited with prefix and suffix characters that you can
define. A common choice is to use `#{ }` as the delimiters, as the following example
shows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	String randomPhrase = parser.parseExpression(
			"random number is #{T(java.lang.Math).random()}",
			new TemplateParserContext()).getValue(String.class);

	// evaluates to "random number is 0.7038186818312008"
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	val randomPhrase = parser.parseExpression(
			"random number is #{T(java.lang.Math).random()}",
			TemplateParserContext()).getValue(String::class.java)

	// evaluates to "random number is 0.7038186818312008"
----

The string is evaluated by concatenating the literal text `'random number is '` with the
result of evaluating the expression inside the `#{ }` delimiter (in this case, the result
of calling that `random()` method). The second argument to the `parseExpression()` method
is of the type `ParserContext`. The `ParserContext` interface is used to influence how
the expression is parsed in order to support the expression templating functionality.
The definition of `TemplateParserContext` follows:

[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
	public class TemplateParserContext implements ParserContext {

		public String getExpressionPrefix() {
			return "#{";
		}

		public String getExpressionSuffix() {
			return "}";
		}

		public boolean isTemplate() {
			return true;
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
	class TemplateParserContext : ParserContext {

		override fun getExpressionPrefix(): String {
			return "#{"
		}

		override fun getExpressionSuffix(): String {
			return "}"
		}

		override fun isTemplate(): Boolean {
			return true
		}
	}
----


[[expressions-example-classes]]
== Classes Used in the Examples

This section lists the classes used in the examples throughout this chapter.

[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
.Inventor.Java
----
	package org.spring.samples.spel.inventor;

	import java.util.Date;
	import java.util.GregorianCalendar;

	public class Inventor {

		private String name;
		private String nationality;
		private String[] inventions;
		private Date birthdate;
		private PlaceOfBirth placeOfBirth;

		public Inventor(String name, String nationality) {
			GregorianCalendar c= new GregorianCalendar();
			this.name = name;
			this.nationality = nationality;
			this.birthdate = c.getTime();
		}

		public Inventor(String name, Date birthdate, String nationality) {
			this.name = name;
			this.nationality = nationality;
			this.birthdate = birthdate;
		}

		public Inventor() {
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getNationality() {
			return nationality;
		}

		public void setNationality(String nationality) {
			this.nationality = nationality;
		}

		public Date getBirthdate() {
			return birthdate;
		}

		public void setBirthdate(Date birthdate) {
			this.birthdate = birthdate;
		}

		public PlaceOfBirth getPlaceOfBirth() {
			return placeOfBirth;
		}

		public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
			this.placeOfBirth = placeOfBirth;
		}

		public void setInventions(String[] inventions) {
			this.inventions = inventions;
		}

		public String[] getInventions() {
			return inventions;
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
.Inventor.kt
----
	package org.spring.samples.spel.inventor

	class Inventor(
		var name: String,
		var nationality: String,
		var inventions: Array<String>? = null,
		var birthdate: Date =  GregorianCalendar().time,
		var placeOfBirth: PlaceOfBirth? = null)
----

[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
.PlaceOfBirth.java
----
	package org.spring.samples.spel.inventor;

	public class PlaceOfBirth {

		private String city;
		private String country;

		public PlaceOfBirth(String city) {
			this.city=city;
		}

		public PlaceOfBirth(String city, String country) {
			this(city);
			this.country = country;
		}

		public String getCity() {
			return city;
		}

		public void setCity(String s) {
			this.city = s;
		}

		public String getCountry() {
			return country;
		}

		public void setCountry(String country) {
			this.country = country;
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
.PlaceOfBirth.kt
----
	package org.spring.samples.spel.inventor

	class PlaceOfBirth(var city: String, var country: String? = null) {
----

[source,java,indent=0,subs="verbatim,quotes",role="primary",chomp="-packages"]
.Society.java
----
	package org.spring.samples.spel.inventor;

	import java.util.*;

	public class Society {

		private String name;

		public static String Advisors = "advisors";
		public static String President = "president";

		private List<Inventor> members = new ArrayList<>();
		private Map officers = new HashMap();

		public List getMembers() {
			return members;
		}

		public Map getOfficers() {
			return officers;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public boolean isMember(String name) {
			for (Inventor inventor : members) {
				if (inventor.getName().equals(name)) {
					return true;
				}
			}
			return false;
		}
	}
----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary",chomp="-packages"]
.Society.kt
----
	package org.spring.samples.spel.inventor

	import java.util.*

	class Society {

		val Advisors = "advisors"
		val President = "president"

		var name: String? = null

		val members = ArrayList<Inventor>()
		val officers = mapOf<Any, Any>()

		fun isMember(name: String): Boolean {
			for (inventor in members) {
				if (inventor.name == name) {
					return true
				}
			}
			return false
		}
	}
----
