package com.hubspot.jinjava.lib.filter; import java.math.BigDecimal; import java.util.Map; import java.util.Objects; 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 = "Returns the sum of a sequence of numbers plus the value of parameter ‘start’ (which defaults to 0). When the sequence is empty it returns start.", params = { @JinjavaParam(value = "value", type = "iterable", desc = "Selects the sequence or dict to sum values from"), @JinjavaParam(value = "attribute", desc = "Specify an optional attribute of dict to sum"), @JinjavaParam(value = "start", type = "number", defaultValue = "0", desc = "Sets a value to return, if there is nothing in the variable to sum") }, snippets = { @JinjavaSnippet( code = "{% set sum_this = [1, 2, 3, 4, 5] %}\n" + "{{ sum_this|sum }}\n"), @JinjavaSnippet( desc = "Sum up only certain attributes", code = "Total: {{ items|sum(attribute='price') }}") }) public class SumFilter implements AdvancedFilter { @Override public String getName() { return "sum"; } @Override public Object filter(Object var, JinjavaInterpreter interpreter, Object[] args, Map<String, Object> kwargs) { ForLoop loop = ObjectIterator.getLoop(var); BigDecimal sum = BigDecimal.ZERO; String attr = kwargs.containsKey("attribute") ? kwargs.get("attribute").toString() : null; if (args.length > 0) { try { sum = sum.add(new BigDecimal(args[0].toString())); } catch (NumberFormatException e) { } } while (loop.hasNext()) { Object val = loop.next(); if (val == null) { continue; } BigDecimal addend = BigDecimal.ZERO; if (attr != null) { val = interpreter.resolveProperty(val, attr); } try { if (Number.class.isAssignableFrom(val.getClass())) { addend = new BigDecimal(((Number) val).doubleValue()); } else { addend = new BigDecimal(Objects.toString(val, "0")); } } catch (NumberFormatException e) { } sum = sum.add(addend); } return sum; } }