The following code does not work because Freemarker seems to cast the value of the expression inside [] to String and then to use it as a key, which is not what is actually
The accepted answer isn't the simplest solution since 2.3.22. While myMap[key]
still assumes a string key (see FAQ entry why), now one can use myMap?api.get(key)
as a workaround. It needs some configuring though:
?api
is disallowed by default, so you need to set the api_builtin_enabled
(Configuration.setAPIBuiltinEnabled(boolean)
) setting to true
.object_wrapper
(Configuration.setObjectWrapper(ObjectWrapper)
) used needs to support this feature (exposing the API). If you don't set the object_wrapper
anywhere, then just increasing the incompatible_improvements
setting (the Configuration
constructor parameter, or Configuration.setIncompatibleImprovements(Version)
) to 2.3.22 solves this. If you set the object_wrapper
(i.e., you overwrite the default), and it's a DefaultObjectWrapper
instance, then note that DefaultObjectWrapper
has its own incompatibleImprovements
property that has to be set to 2.3.22. If you are using pure BeansWrapper
(not recommended!) then you have to do nothing, as it always supports this feature.To paraphrase Freemarker Documentation FAQ on this,
You can't use non-string keys in the myMap[key] expression. You can use methods!
So, you could create a bean that provides a way for you to get to your Java EnumMap, (i.e). Then just instantiate this bean with your mapp, and put the bean in your Model.
class EnumMap
{
HashMap<MyEnum, String> map = new HashMap<MyEnum, String>();
public String getValue(MyEnum e)
{
return map.get(e);
}
..constructor, generics, getters, setters left out.
}
I'm a little bit confused about what general goal your trying to accomplish. If you just need to list out the values of the enum (or perhaps a display value for each one). There is a much easier way to do it.
One way I've seen this problem solved is by putting a display value on the Enum instances.
i.e
enum MyEnum
{ FOO("Foo"),
BAR_EXAMPLE("Bar Example");
private String displayValue;
MyEnum(String displayValue)
{
this.displayValue = displayValue;
}
public String getDisplay()
{
return displayValue;
}
}
This allows you to put the Enum itself into your configuration, and iterate over all instances.
SimpleHash globalModel = new SimpleHash();
TemplateHashModel enumModels = BeansWrapper.getDefaultInstance().getEnumModels();
TemplateHashModel myEnumModel = (TemplateHashModel) enumModels.get("your.fully.qualified.enum.MyEnum");
globalModel.put("MyEnum", myEnumModel);
freemarkerConfiguration.setAllSharedVariables(globalModel);
Then you can iterate over the enum,
<#list MyEnum?values as item>
${item.display}
</#list>