There are 4 scalar types:
- Boolean
- Number
- String
- Date-like (subtypes: date (no time part), time or date-time)
For each scalar type is a
TemplateTypeModel
interface, where Type
is
the name of the type. These interfaces define only one method:
type
getAsType();
. This returns the
value of the variable with the Java type (boolean
,
Number
, String
and
Date
respectively).
For historical reasons the interface for string scalars is
called TemplateScalarModel
, not
TemplateStringModel
. (It's because in early
FreeMarker strings were the only kind of scalars.)
A trivial implementation of these interfaces are available in
freemarker.template
package with
SimpleType
class name.
However, there is no SimpleBooleanModel
; to
represent the boolean values you can use the
TemplateBooleanModel.TRUE
and
TemplateBooleanModel.FALSE
singletons.
For historical reasons the class for string scalars is called
SimpleScalar
, not
SimpleString
.
Scalars are immutable within FTL. When you set the value of a
variable in a template, then you replace the
TemplateTypeModel
instance with another instance, and don't change the value stored in
the original instance.
Difficulties with the "date-like" types
There is a complication around date-like types, because Java
API usually does not differentiate
java.util.Date
-s that store only the date part
(April 4, 2003), only the time part (10:19:18 PM), or both (April 4,
2003 10:19:18 PM). To display the value as text correctly (or to do
certain other operations), FreeMarker must know what parts of the
java.util.Date
stores meaningful information, and
what parts are unused (usually 0-ed out). Unfortunately, this
information is usually only available when the value comes from a
database, because most databases have separate date, time and
date-time (aka. timestap) types, and java.sql
has
3 corresponding java.util.Date
subclasses for
them.
TemplateDateModel
interface has two
methods: java.util.Date getAsDate()
and
int getDateType()
. A typical implementation of
this interface, stores a java.util.Date
object,
plus an integer that tells the subtype. The value of this integer
must be a constant from the TemplateDateModel
interface: DATE
, TIME
,
DATETIME
and UNKNOWN
.
About UNKNOWN
: java.lang
and java.util
classes are usually converted
automatically into TemplateModel
implementations
be the ObjectWrapper
(see object wrapping
earlier). If the object wrapper has to wrap a
java.util.Date
, that is not an instance of a
java.sql
date class, it can't decide what the
subtype is, so it uses UNKNOWN
. Later, if the
template has to use this variable, and the subtype is needed for the
operation, it will stop with error. To prevent this, for the
problematic variables the template author must specify the subtype
explicitly using the date
,
time
or datetime
built-ins (like lastUpdated?datetime
).
Note that if you use string
built-in with format
parameter, as foo?string["MM/dd/yyyy"]
, then
FreeMarker doesn't need to know the subtype.