As you have seen, the data-model is basically a tree. This tree can be arbitrarily complicated and deep, for example:
(root) | +- animals | | | +- mouse | | | | | +- size = "small" | | | | | +- price = 50 | | | +- elephant | | | | | +- size = "large" | | | | | +- price = 5000 | | | +- python | | | +- size = "medium" | | | +- price = 4999 | +- message = "It is a test" | +- misc | +- foo = "Something"
The variables that act like directories (the root,
        animals, mouse,
        elephant, python,
        misc) are called hashes. Hashes store other variables (the so
        called sub
        variables) by a lookup name (e.g., "animals",
        "mouse" or "price").
The variables that store a single value
        (size, price,
        message and foo) are called
        scalars.
When you want to
        use a subvariable in a template, you specify its path from the root,
        and separate the steps with dots. To access the
        price of a mouse, you start from
        the root and go into animals, and then go into
        mouse then go into price. So you
        write animals.mouse.price.
Another important kind of variables are sequences. They store subvariables like hashes,
        but here subvariables doesn't have a name, they are just items in a
        list. For example, in this data-model, animals and
        misc.fruits are sequences:
(root) | +- animals | | | +- (1st) | | | | | +- name = "mouse" | | | | | +- size = "small" | | | | | +- price = 50 | | | +- (2nd) | | | | | +- name = "elephant" | | | | | +- size = "large" | | | | | +- price = 5000 | | | +- (3rd) | | | +- name = "python" | | | +- size = "medium" | | | +- price = 4999 | +- misc | +- fruits | +- (1st) = "orange" | +- (2nd) = "banana"
To access a subvariable of a sequence you use a numerical index
        in square brackets. Indexes start from 0 (it's a programmer tradition
        to start with 0), thus the index of the 1st item is 0, the index of
        the 2nd item is 1, and so on. So to get the name of the first animal
        you write animals[0].name. To get the second item
        in misc.fruits (the string
        "banana") you write
        misc.fruits[1]. (In practice, you usually just walk
        through sequences in order, not caring about the index, but that will
        be shown later.)
Scalars can be further divided into these categories:
- 
            
String: Text, that is, an arbitrary sequence of characters such as ''m'', ''o'', ''u'', ''s'', ''e'' above. For example the
name-s andsize-s are strings above. - 
            
Number: It's a numerical value, like the
price-s above. The string"50"and the number50are two totally different things in FreeMarker. The former is just a sequence of two characters (which happens to be readable as a number for humans), while the latter is a numerical value that you can use in arithmetical calculations. - 
            
Date-like: Either a date-time (stores a date with time of the day), or a date (no time of day), or a time (time of day, no date).
 - 
            
Boolean: A true/false (yes/no, on/off, etc.) thing. Like animals could have a
protectedsubvariable, which store if the animal is protected or not. 
Summary:
- 
            
The data-model can be visualized as a tree.
 - 
            
Scalars store a single value. The value can be a string or a number or a date-time/date/time or a boolean.
 - 
            
Hashes are containers that store other variables and associate them with a unique lookup name.
 - 
            
Sequences are containers that store other variables in an ordered sequence. The stored variables can be retrieved via their numerical index, starting from 0.
 
There are other, more advanced value types that we don't cover here, such as methods and directives.
