如何在 Freemarker 中创建要循环访问的子数据列表

How to create lists of subdata to loop through in Freemarker

提问人:Stephane Grenier 提问时间:3/7/2023 更新时间:3/8/2023 访问量:44

问:

我正在寻找一种方法,根据数据项列表中的 dataType (int) 使用 Freemarker 生成按报告分组。

例如,我有:

data.datatype = 1 where data has id = 1
data.datatype = 1 where data has id = 4
data.datatype = 1 where data has id = 7
data.datatype = 3 where data has id = 2
data.datatype = 3 where data has id = 3
data.datatype = 4 where data has id = 5
... and so on

该序列按数据类型排序,但同时我需要将数据项保持在各自的顺序(辅助排序顺序)中。

我也使用函数等宏。理想情况下,我很想拥有<#macro rendertable filteredDatatypelist datatype>

过去,我确实调用了一个宏来根据当前数据类型呈现页眉、页脚和行,但我试图摆脱它,并有一个宏来呈现每个数据类型的子列表上的整个表。

也就是说,向宏发送数据类型的数据项列表。例如,在上面的数据中,我会调用宏 3 次,一次用于数据类型 1、3 和 4。rendertable

我考虑尝试使用创建一个子列表,但这似乎是每种数据类型的 O(n) 的性能问题。不理想,但即便如此,我也不确定它究竟是如何工作的。另请注意,我不知道有多少种数据类型或它们的值可能是什么。我也看了一下,但我不知道不同的数据类型是什么。我考虑过先创建一个唯一数据类型的列表,但我也不知道如何做到这一点。换句话说,我什至不确定如何做这样的事情filterseq_index_ofseq_last_index_of

<#assign dataForDataType = dataList?filter(data.datatype = 1)>
<#list dataForDataType as x>$<@renderTable x 1></#list>

除了在上面的情况下,我对数据类型进行了硬编码,并且它仅适用于一种硬编码的数据类型。即使它是 O(n),我想我也可以接受它,但问题是我不知道如何为数据类型列表做到这一点。关于如何实现这一目标的任何帮助将不胜感激。

Java 模板 freemarker

评论


答:

0赞 Stephane Grenier 3/8/2023 #1

我最终做的是创建一个类,该类扩展了接口,该接口将接受数据列表,然后返回数据类型列表。然后,我遍历了数据类型,然后使用另一个函数通过另一个TemplateMethodModelEx获取了特定数据类型的数据项列表。TemplateMethodModelEx

大致如下:

<#assign datatypes = getDistinctDataTypes(dataList)/>
<#list datatypes as datatype>
    Datatype: ${datatype.id}
    <#list getDataForDatatype(dataList, datatype) as data>
        ${data.whatever}
     </#list>
</#list>

然后我有像这个例子这样的类:

public class GetDistinctDataTypes implements TemplateMethodModelEx {
    @Override
    public Object exec(List arguments) throws TemplateModelException
    {
        // Testing code is omitted for brevity and everything is assumed to just work and be correct.
        DefaultListAdapter defaultListAdapter = ((DefaultListAdapter)arguments.get(0));
        List<Data> dataList = (List<Data>)defaultListAdapter.getWrappedObject();
        // Do what I need and return list of datatypes
        return getDistinctDataTypesListFromDataList(dataList);
    }
}

然后,我还将该方法添加到配置中,以便可以使用它。您可以在 freemarker 文件中执行此操作,但我发现在 Java 代码中更好。

CONFIGURATION.setSharedVariable("getDistinctDataTypes", new GetDistinctDataTypes());

您可以在以下 Freemarker 文档页面上找到有关方法指令的更多详细信息。