package com.hubspot.jinjava.lib.fn; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.hubspot.jinjava.el.ext.AbstractCallableMethod; import com.hubspot.jinjava.interpret.Context; import com.hubspot.jinjava.interpret.JinjavaInterpreter; import com.hubspot.jinjava.interpret.JinjavaInterpreter.InterpreterScopeClosable; import com.hubspot.jinjava.tree.Node; /** * Function definition parsed from a jinjava template, stored in global macros registry in interpreter context. * * @author jstehler * */ public class MacroFunction extends AbstractCallableMethod { private final List<Node> content; private final boolean catchKwargs; private final boolean catchVarargs; private final boolean caller; private final Context localContextScope; public MacroFunction(List<Node> content, String name, LinkedHashMap<String, Object> argNamesWithDefaults, boolean catchKwargs, boolean catchVarargs, boolean caller, Context localContextScope) { super(name, argNamesWithDefaults); this.content = content; this.catchKwargs = catchKwargs; this.catchVarargs = catchVarargs; this.caller = caller; this.localContextScope = localContextScope; } @Override public Object doEvaluate(Map<String, Object> argMap, Map<String, Object> kwargMap, List<Object> varArgs) { JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent(); try (InterpreterScopeClosable c = interpreter.enterScope()) { for (Map.Entry<String, Object> scopeEntry : localContextScope.getScope().entrySet()) { if (scopeEntry.getValue() instanceof MacroFunction) { interpreter.getContext().addGlobalMacro((MacroFunction) scopeEntry.getValue()); } else { interpreter.getContext().put(scopeEntry.getKey(), scopeEntry.getValue()); } } // named parameters for (Map.Entry<String, Object> argEntry : argMap.entrySet()) { interpreter.getContext().put(argEntry.getKey(), argEntry.getValue()); } // parameter map interpreter.getContext().put("kwargs", argMap); // varargs list interpreter.getContext().put("varargs", varArgs); StringBuilder result = new StringBuilder(); for (Node node : content) { result.append(node.render(interpreter)); } return result.toString(); } } public boolean isCatchKwargs() { return catchKwargs; } public boolean isCatchVarargs() { return catchVarargs; } public boolean isCaller() { return caller; } }