map?get(nonStringKey) for FM 2.3.x?
Daniel Dekany <[email protected]>
| Newsgroups | gmane.comp.web.freemarker.devel |
|---|---|
| Message-ID | <[email protected]> |
FTL has this annoying problem that it has no type that corresponds to Java's Map. It has a type called hash, but it was introduced for variable hierarchies (like `user.name`), so the keys are limited to stings. For some reason TemplateMapModel wasn't introduced, instead, the bundled wrappers wrap Map-s as hashes, which of course doesn't work for non-string keys. Except, if you call the Map.get method directly from the template, but since FTL doesn't use separate name-spaces for plain sub-variables and methods, if Map methods are exposed, they mix with the actual string keys, which is a mess, so by default Map methods are hidden. Luckily, with BeansWrapper, you can just do `someMap(nonStringKey)`, but sadly, BeansWrapper is not used by default for wrapping Map-s, they are wrapped into a SimpleHash instead. So the user asks how to get an item from this map with a non-String key, and we don't have a simple answer. You need to use BeansWrapper instead of the default... oh, but wait, switching wrapper might breaks your application, and depending on the framework there's possibly no way to set the object wrapper at all. How to fix this situation: - Ultimately, add TemplateMapModel, and a new recommended ObjectWrapper that uses it too. Unfortunately, this is not an option for existing applications and frameworks, unless they willing to review their templates. - SimpleHash should implement TemplateMethodModelEx, so `someMap(nonStringKey)` works for SimpleHash-wrapped templates too. My problem with this is that calling a map like a method is quite confusing for most programmers. You look at the template, and believe that "someMap" is primarily a function. But it's a Map. Also adding TemplateMethodModelEx to SimpleHash can break existing applications with a small chance. - Add `get` as built-in, which will utilize its knowledge of the bundled wrappers to get to the Map behind. No mater how "someMap" was wrapped, if there's a Map behind, `someMap?get(key)` just works. If the wrapper is not recognized, nor AdapterTemplateModel is implemented, it can still call TemplateHashModel.get(String) and give an error for a non-String key. -- Best regards, Daniel Dekany ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/