A primary feature of JDBL is its support for an expression language (EL). This language is an extension of the JSP EL as defined in the J2EE standard. The JDBL-EL is a superset of JSP-EL, making it simple for people to learn and use our EL. This is an important design consideration, given that people are most likely to use both ELs at the same time (e.g. when developing a web-based application).
Employing a real expression language makes it easy for developers to use
simple and intuitive syntax such as ${name}
to
access a variable, while at the same time allowing for the flexibility and
power that comes with a fully-blown expression language.
The JDBL-EL can be used both within the SQL body to prepare it for execution (such as passing variables, etc.), as well as within the result expressions, to build the result object.
The expression language has been designed to give you access to the full power of JDBC. It is meant to help you exploit JDBC to its fullest by eliminating some of the tedium, rather then completely isolate you from the advanced JDBC features.
JDBL evaluates variable refrences by looking up their value in the following scopes:
Properties of variables are accessed using the .
operator, and can be
nested arbitrarily.
Similar to JSP-EL, JDBL-EL unifies the treatment of the .
and []
operators. Thus, A.B
is equivalent to A["B"]
. For example, the
expressions person.name
is equivalent to person["name"]
.
Evaluating A[B]
proceeds according to the following rules:
A
or B
is null
, return null
A
is a Map
, return A.get(B)
A
is a List
or array, coerce B
to int
,
and return A.get(B)
or Array.get(B)
respectively.
If B
can not be coerced, an exception is thrown.
If get()
throws an IndexOutOfBoundsException
,
null
is returned. Any other exception is propagated up.A
is a JavaBeans object, coerce B
to String
and return the value of the get()
call.
Exceptions are propagated up the stack.In the spirit of allowing you full access to the JDBC features, the JDBL-EL defines a set of implicit objects:
statement
: the JDBC Statement
object used to execute the SQLresultSet
: the JDBC ResultSet
object obtained as a result of
executing the SQL. Please note that this object is defined
only for SELECT
statements or potentially for
stored-procedure calls.
Please note that you should execise caution when using these objects.
Modifying the state of the statement
and/or of the resultSet
behind JDBL's back can lead to unexpected results.
The JDBL-EL recongnizes the following literals:
null
true
and false
"
is escaped as \"
,
'
is escaped as \'
, and
\
is escaped as \\
The JDBL-EL provides the following operators:
.
, []
, @
{}
, :=
, new
, as
+
, -
(binary), *
, mul
,
/
, div
, %
, mod
, -
(unary)&&
, and
, ||
, or
, !
, not
, empty
==
, eq
, !=
, ne
, <
, lt
>
, gt
, <=
, le
, >=
, ge
A ? B : C
. Evaluate B
if A
is true
, else evaluate C
Please note that JDBL-EL works typically within an XML file. As a result, any
operators that contain <
or &
must be escaped as
<
or &
respectively, making their use awkward
at best. For this reason, most operators have a textual synonim:
Operator | Synonim | Operation |
---|---|---|
* | mul | Multiplication |
/ | div | Division |
% | mod | Reminder |
&& | and | Logical AND |
|| | or | Logical OR |
! | not | Logical NOT |
== | eq | Equality |
!= | ne | Non-equality |
< | lt | Less then |
> | gt | Greater then |
<= | le | Less then or equal |
>= | ge | Greater then or equal |
The precedence of the operators, highest to lowest, is as follows:
Priority | Operators | Operation | Associativity |
---|---|---|---|
1 | @ |
result set column access | left |
[] |
array index/property access | ||
() |
method call | ||
. |
member access | ||
2 | + - |
unary plus, minus | right |
! not |
logical NOT | ||
empty |
test for emptiness | ||
new |
object creation | ||
3 | * mul |
multiplication | left |
/ div |
division | ||
% mod |
remainder | ||
4 | + - |
addition, substraction | left |
5 | < lt <= le |
less than, less than or equal to | left |
> gt >= ge |
greater than, greater than or equal to | ||
6 | == eq |
equal to | left |
!= ne |
not equal to | ||
7 | && and |
logical AND | left |
8 | || or |
logical OR | left |
9 | as |
type transformer | right |
10 | ? : |
conditional | right |
11 | := |
mapping | right |
The following is the list of reserved words for JDBL-EL:
and | eq | gt | true | div | array | as | instanceof |
or | ne | le | false | mod | list | empty |
|
not | lt | ge | null | mul | map | new |
|
Please note that some of them are not currently used, but they are reserved for future improvements.
JDBL-EL is compatible with JSP-EL in terms of function definition and invocation.
As a result, you can share your taglib
directives for defining functions.
For example, suppose you have a /text
function library, and want to invoke
a function called trim()
in an expression:
<taglib prefix="t" uri="/text" /> ... ${t:trim(myarg)}
To define your own functions, you need to create a public static
method
in a public
class. As an example, lets define the trim()
function
used above.
First, you need to create the function in a Java class:
package com.mycorp.package; public class TextUtil { public static String trim(String str) { str.trim(); } }
Next you need to create a signature in a TLD. In our case, we will create
a text.tld
file with the following declaration:
<function> <name>trim</name> <function-class> com.mycorp.package </function-class> <function-signature> java.lang.String trim(java.lang.String) </function-signature> </function>
Expression | Result |
---|---|
1 > 2/3 |
true |
'100' == 100 |
true |
empty name |
true if name is null |
@name |
The value of resultSet.getObject("name") |
@3 |
The value of resultSet.getObject(3) |
person.name |
The name property from the object person |
@salary as int |
The value of the column salary read via resultSet.getInt("salary") |
@salary lt 0 ? -@salary : @salary |
The absolute value of salary column |
new Person(@name, @salary) |
A new instance of Person with values from resultSet |
new Person(name := @name, salary := @salary) |
A new instance of Person , with the properties name and salary
initialized with values from the columns @name and @salary |
{n:new Person(@name, @salary)} |
An new instance of Person from the n th row of resultSet |
{?:new Person(@name, @salary)} |
An new instance of Person if there is a row in resultSet , or null otherwise |
{*:new Person(@name, @salary)} |
An array or list of Person objects, one for each row in resultSet |
{*: @name := @salary} |
A java.util.Map of salaries indexed by names |
{*: @name := @salary} as SortedMap |
A java.util.SortedMap of salaries indexed by names |