Hash Model

Hash models are probably the most common model you'll use in FreeMarker. Like TemplateScalarModel, TemplateHashModel defines only one method:

public TemplateModel get(java.lang.String key)
                  throws TemplateModelException;
        

FreeMarker uses this method to return a value for a given key name. This method is similar to the get() method in the Java  2 java.util.Map interface, with the restriction that the keys are always Strings.

If the specified key does not exist in the hash, the results are implementation dependant. Some people may throw a TemplateModelException, others might return null, still others might return a default value. All are considered to be valid in FreeMarker.

Similarly, if the get() method is passed a null value, which can happen when a hash is indexed by another FreeMarker variable, the results are undefined. The implementing class may be expected to throw a TemplateModelException, or otherwise gracefully deal with the null value.

Hash models are powerful because humans tend to recognise things in terms of names rather than numbers. Hash models can return other models. A hash model can contain other hash models, and so on (as we saw in the introduction).

Key Names

Key names should not include any dots (".") as part of the name. This is because FreeMarker uses the dot character to determine when a key name is complete, and to then traverse into the next TemplateModel. If you're tempted to use a dot in your key name, try a different separator instead, or make sure you always use the Dynamic Key Name operator (the [] operator).

Finally, key names beginning with an underscore ("_") should be avoided. These may be used as special keys by future versions of FreeMarker.

Getting started quickly

To quickly roll your own hash model, you can use either the freemarker.template.SimpleHash class, or you can wrap an arbitrary implementation of java.util.Map interface using the freemarker.ext.beans.RootMapModel. Also, many other FreeMarker facilities residing in the freemarker.ext.* packages create various hash models: you can wrap JDOM nodes, servlet context, HTTP session, and HTTP request attributes and HTTP request parameters into hashes. You can even wrap arbitrary Java objects into a hash and access their JavaBeans-style properties and methods through the hash interface.

Extended Functionality for Hashes

The 2.0rc2 release introduced a subinterface of TemplateHashModel, called TemplateHashModelEx. This interface defines 3 extra methods: size(), keys() and values(). If a model implements this interface, certain built-ins are available:

  • You can write myHash?size to get the number of key/value pairs in the hash.
  • You can write myHash?keys or myHash?values to get a sequence containing the keys or the values respectively of the key/value pairs contained in the hash.

Note that the default implementation, SimpleHash already implements the TemplateHashModelEx interface, and thus, the above keys will work. Note that this is what is behind the removal of the class freemarker.template.utility.ExtendedHash, since its existence is now superfluous, as SimpleHash contains all of the additional functionality that ExtendedHash used to contain.