package com.hubspot.jinjava.lib.filter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; 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.InterpretException; import com.hubspot.jinjava.interpret.JinjavaInterpreter; import com.hubspot.jinjava.lib.exptest.ExpTest; import com.hubspot.jinjava.util.ForLoop; import com.hubspot.jinjava.util.ObjectIterator; @JinjavaDoc( value = "Filters a sequence of objects by applying a test to an attribute of an object and only selecting the ones with the test succeeding.", params = { @JinjavaParam(value = "sequence", type = "sequence", desc = "Sequence to test"), @JinjavaParam(value = "attr", desc = "Attribute to test for and select items that contain it"), @JinjavaParam(value = "exp_test", type = "name of expression test", defaultValue = "truthy", desc = "Specify which expression test to run for making the selection") }, snippets = { @JinjavaSnippet( desc = "This loop would select any post containing content.post_list_summary_featured_image", code = "{% for content in contents|selectattr('post_list_summary_featured_image') %}\n" + " <div class=\"post-item\">Post in listing markup</div>\n" + "{% endfor %}") }) public class SelectAttrFilter implements Filter { @Override public String getName() { return "selectattr"; } @Override public Object filter(Object var, JinjavaInterpreter interpreter, String... args) { List<Object> result = new ArrayList<>(); if (args.length == 0) { throw new InterpretException(getName() + " filter requires an attr to filter on", interpreter.getLineNumber()); } String[] expArgs = new String[]{}; String attr = args[0]; ExpTest expTest = interpreter.getContext().getExpTest("truthy"); if (args.length > 1) { expTest = interpreter.getContext().getExpTest(args[1]); if (expTest == null) { throw new InterpretException("No expression test defined with name '" + args[1] + "'", interpreter.getLineNumber()); } if (args.length > 2) { expArgs = Arrays.copyOfRange(args, 2, args.length); } } ForLoop loop = ObjectIterator.getLoop(var); while (loop.hasNext()) { Object val = loop.next(); Object attrVal = interpreter.resolveProperty(val, attr); if (expTest.evaluate(attrVal, interpreter, (Object[]) expArgs)) { result.add(val); } } return result; } }