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/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.