public boolean render()

in velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java [193:290]


    public boolean render(InternalContextAdapter context, Writer writer,
                          Node node, Renderable body)
        throws IOException
    {
        int callArgNum = node.jjtGetNumChildren();

        // if this macro was invoked by a call directive, we might have a body AST here.
        Object oldBodyRef = context.remove(bodyReference);
        if (body != null)
        {
            context.put(bodyReference, body);
            callArgNum--;  // Remove the body AST from the arg count
        }

        // is everything copacetic?
        checkArgumentCount(node, callArgNum);
        checkDepth(context);

        // put macro arg values and save the returned old/new value pairs
        Object[] values = handleArgValues(context, node, callArgNum);
        try
        {
            // render the velocity macro
            context.pushCurrentMacroName(macroName);
            nodeTree.render(context, writer);
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            String msg = "VelocimacroProxy.render() : exception VM = #" + macroName + "()";
            log.error(msg, e);
            throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace());
        }
        finally
        {
            // if MacroOverflowException was thrown then it already empties the stack
            // for everything else - e.g. other exceptions - we clean up after ourself
            if (context.getCurrentMacroCallDepth() > 0)
                context.popCurrentMacroName();

            // clean up after the args and bodyRef
            // but only if they weren't overridden inside
            Object current = context.get(bodyReference);
            if (current == body)
            {
                if (oldBodyRef != null)
                {
                    context.put(bodyReference, oldBodyRef);
                }
                else
                {
                    context.remove(bodyReference);
                }
            }

            for (int i = 1; i < macroArgs.size(); i++)
            {
                MacroArg macroArg = macroArgs.get(i);
                current = context.get(macroArg.name);
                Object given = values[(i-1) * 2 + 1];
                Object old = values[(i-1) * 2];
                if (current == given || current == null && given == NULL_VALUE_MARKER)
                {
                    if (old == null)
                    {
                        context.remove(macroArg.name);
                    }
                    else if (old == NULL_VALUE_MARKER)
                    {
                        context.put(macroArg.name, null);
                    }
                    else
                    {
                        context.put(macroArg.name, old);
                    }
                }

                if (enableBCmode)
                {
                    /* allow for nested calls */
                    Deque<String> literalsStack = (Deque<String>)context.get(literalArgArray[i]);
                    if (literalsStack != null) /* shouldn't be null */
                    {
                        literalsStack.removeFirst();
                        if (literalsStack.size() == 0)
                        {
                            context.remove(literalArgArray[i]);
                        }
                    }
                }
            }
        }
            
        return true;
    }