Accessing data model maps that use a non-string key (eg. gScopeCounts)

Managed by | Updated .

Normally you can access a map value (eg. rmcs counts) using something like response.resultPacket.rmcs["key"]

However this will only work if the key is a string type.

ie. if you look at the XML you will see the rmcs and gScopeCounts maps from the data model.

<rmcs>
<entry>
<string>B:Health professional publications</string>
<int>17</int>
</entry>
</rmcs>
<gScopeCounts>
<entry>
<int>1</int>
<int>76</int>
</entry>
</gScopeCounts>

For the gScopeCounts field you will see that the key and value are both integers.

This is due to how Freemarker wraps Java objects within the template.  See: http://fmpp.sourceforge.net/freemarker/app_faq.html#faq_question_14 for further information.

Example and workaround

The following freemarker macro is designed to return the gscope count given the gscope number.

The gscope counts are a map, but with an integer key.

The following code is what was written:

<#-- @begin Gscope facet item -->
<#---
Prints item containing a specified gscope facet and the corresponding count.
-->
<#macro gScopeFacetItem gParam facet="" category="">
<#if response?exists && response.facets?exists>
<#assign facetKey="f.${facet}|${gParam}"/>
<#assign gp=gParam?number>
<#if response.resultPacket.GScopeCounts[gp]?exists>
<input type="checkbox" name=${facetKey}" <#if question.inputParameterMap[facetKey]?exists> checked="checked"</#if> value="${category}"> ${category} (${response.resultPacket.GScopeCounts[gp?int]})
<#else>
<input type="checkbox" name="${facetKey}" disabled="disabled" value="${category}"> ${category} (0)
</#if>
</#if>
</#macro>
</#macro>

However when you use the square bracket notation eg response.resultPacket.GScopeCounts[gParam] freemarker automatically converts the key supplied to a string meaning the check will fail.

The above code generates an error.

Expected number, sequence, or string. response.resultPacket.GScopeCounts evaluated instead to freemarker.template.SimpleHash on line 88, column 14 in conf/nps/nps.ftl.

Other versions of the <#if> statement also fail:

<#if response.resultPacket.GScopeCounts[gp?int]?exists>
<#if response.resultPacket.GScopeCounts(gp)?exists>
<#if response.resultPacket.GScopeCounts(gp?int)?exists> 

The following is a workaround, but it's a bit messy:

<#-- @begin Gscope facet item -->
<#---
Prints item containing a specified gscope facet and the corresponding count.
-->
<#macro gScopeFacetItem gParam facet="" category="">
<#if response?exists && response.facets?exists>
<#assign facetKey="f.${facet}|${gParam}"/>
<#assign keys = response.resultPacket.GScopeCounts?keys>
<#assign vals = response.resultPacket.GScopeCounts?values>
<#if keys?seq_contains(gParam?number)>
<#list keys as key>
<#if key?number == gParam?number>
<input type="checkbox" name=${facetKey}" <#if question.inputParameterMap[facetKey]?exists> checked="checked"</#if> value="${category}"> ${category} (${vals[key_index]})
</#if>
</#list>
<#else>
<input type="checkbox" name="${facetKey}" disabled="disabled" value="${category}"> ${category} (0)
</#if>
</#if>
</#macro>
Was this artcle helpful?

Tags
Type: Keywords:
Features: Frontend > Modern UI Frontend > Freemarker Frontend > Hook scripts

Comments