package com.hubspot.jinjava.lib.filter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.math.NumberUtils;
import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.doc.annotations.JinjavaParam;
import com.hubspot.jinjava.doc.annotations.JinjavaSnippet;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.util.ForLoop;
import com.hubspot.jinjava.util.ObjectIterator;
@JinjavaDoc(
value = "A filter that groups up items within a sequence",
params = {
@JinjavaParam(value = "value", desc = "The sequence or dict that the filter is applied to"),
@JinjavaParam(value = "linecount", type = "number", desc = "Number of items to include in the batch", defaultValue = "0"),
@JinjavaParam(value = "fill_with", desc = "Value used to fill up missing items")
},
snippets = {
@JinjavaSnippet(
code = "{% set items=[1, 2, 3, 4, 5] %}\n\n" +
"<table>\n" +
"{% for row in items|batch(3, ' ') %}\n" +
" <tr>\n" +
" {%- for column in row %}\n" +
" <td>{{ column }}</td>\n" +
" {%- endfor %}\n" +
" </tr>\n" +
"{% endfor %}\n" +
"</table>",
output = "<table>\n" +
" <tr>\n" +
" <td>1</td>\n" +
" <td>2</td>\n" +
" <td>3</td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td>4</td>\n" +
" <td>5</td>\n" +
" <td> </td>\n" +
" </tr>\n" +
"</table>")
})
public class BatchFilter implements Filter {
@Override
public String getName() {
return "batch";
}
@Override
public Object filter(Object var, JinjavaInterpreter interpreter, String... args) {
if (var == null || args.length == 0) {
return Collections.emptyList();
}
int lineCount = NumberUtils.toInt(args[0], 0);
if (lineCount == 0) {
return Collections.emptyList();
}
Object fillWith = args.length > 1 ? args[1] : null;
ForLoop loop = ObjectIterator.getLoop(var);
List<List<Object>> result = new ArrayList<>();
List<Object> currentRow = null;
while (loop.hasNext()) {
Object item = loop.next();
if (currentRow == null) {
currentRow = new ArrayList<>();
result.add(currentRow);
}
currentRow.add(item);
if (currentRow.size() == lineCount) {
currentRow = null;
}
}
if (currentRow != null) {
while (currentRow.size() < lineCount) {
currentRow.add(fillWith);
}
}
return result;
}
}