Velocity Question : Maps

Hi,

I’m trying to create a map and, according to the Velocity Users Guide from Apache, I should be able to do something like

#set( $fruit.shapes = {“Apple” : “round”, “Pear” : “conical”})
$fruit.shapes.get(“Apple”)
$fruit.shapes.Apple

but this throws the following error

Problem assembling output for item: 4-101-2352 with template: cuSnExternalLinkDesc exception: Lexical error: org.apache.velocity.runtime.parser.TokenMgrError: Lexical error at line 9, column 31. Encountered: “{” (123), after : “” see log for stack trace

Does anyone know how to create a map like this in Rhythmyx?

Thanks,
Nick.

[QUOTE=NickK;3708]Hi,
Does anyone know how to create a map like this in Rhythmyx?
[/QUOTE]

Certainly… Dave Benua knows how to create everything…

I get the same error with the first line of your code. Changing the syntax changes the errors, but doesn’t make them go away.

As far as that goes, I’m getting a lexical error with a template snippet that says only

#field("body")##
Problem assembling output for item: 4-101-1039 with template: SnNavFooter exception: Lexical error: org.apache.velocity.runtime.parser.TokenMgrError: Lexical error at line 1, column 17. Encountered:  after : "" see log for stack trace

Nick,

This turns out not to be such a simple question. Velocity only deals with “properties” and “methods”, it never creates objects directly.

Fortunately for us, JEXL (or at least our implementation of the backing store) does create objects when you create a compound reference.

In the bindings:

$fruit.shapes.Apple = "xxx"

will create $fruit as a Map and $fruit.shapes as a property of that Map that contains another Map. It also creates an entry in the shapes map for “Apple” Once you’ve done this, you can use Velocity #set commands:


#set($fruit.shapes.Apple =  "round")
#set($fruit.shapes.Pear = "conical")

However, $fruit.weight (for example) is a simple property, so

#set($fruit.weight.Apple = 10)

will return an error.

The best policy seems to be to do as much as you can in JEXL and use Velocity for formatting, not computations.

Dave

PS: this is a really bad example, I would declare the variables as $fruit.Apple.shape, $fruit.Pear.shape, etc.

Because I needed to create a Map in a macro in rx_assembly.vm, and didn’t feel like adding bindings to every page template we have in our system, for every variable I want to contain a Map, I poked around and discovered that this…

#set($foobar = $rx.string.stringToMap("foo=bar"))##

…does the trick instead. You can then add the real entries to the Map stored in $foobar like this…

#set($foobar.query = "SELECT rx:sys_contentid, rx:sys_contentstartdate FROM rx:cmsNews WHERE jcr:path LIKE '//Sites/Internal%' ORDER BY rx:displaytitle ")##
#set($foobar.template = "cmsSnDsAll")##

…and that can be passed into a calls to #slot, #initslot, etc. It works, as long as there is no content finder out there that expects a parameter called foo.

Andrew.