public boolean render()

in velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java [466:635]


    public boolean render(InternalContextAdapter context, Writer writer) throws IOException,
            MethodInvocationException
    {
        try
        {
            rsvc.getLogContext().pushLogContext(this, uberInfo);

            if (referenceType == RUNT)
            {
                writer.write(literal);
                return true;
            }

            Object value = null;
            if (escaped && strictEscape)
            {
              /*
               * If we are in strict mode and the variable is escaped, then don't bother to
               * retrieve the value since we won't use it. And if the var is not defined
               * it will throw an exception.  Set value to TRUE to fall through below with
               * simply printing $foo, and not \$foo
               */
              value = Boolean.TRUE;
            }
            else
            {
              value = execute(null, context);
            }

            String localNullString = null;

            /*
             * if this reference is escaped (\$foo) then we want to do one of two things: 1) if this is
             * a reference in the context, then we want to print $foo 2) if not, then \$foo (its
             * considered schmoo, not VTL)
             */

            if (escaped)
            {
                localNullString = getNullString(context);

                if (value == null)
                {
                    writer.write(escPrefix);
                    writer.write("\\");
                    writer.write(localNullString);
                }
                else
                {
                    writer.write(escPrefix);
                    writer.write(localNullString);
                }
                return true;
            }

            /*
             * the normal processing
             *
             * if we have an event cartridge, get a new value object
             */

            value = EventHandlerUtil.referenceInsert(rsvc, context, literal, value);

            String toString = null;
            if (value != null)
            {
                if (value instanceof Renderable)
                {
                    Renderable renderable = (Renderable)value;
                    try
                    {
                        writer.write(escPrefix);
                        writer.write(morePrefix);
                        if (renderable.render(context,writer))
                        {
                          return true;
                        }
                    }
                    catch(RuntimeException e)
                    {
                        // We commonly get here when an error occurs within a block reference.
                        // We want to log where the reference is at so that a developer can easily
                        // know where the offending call is located.  This can be seen
                        // as another element of the error stack we report to log.
                        log.error("Exception rendering "
                            + ((renderable instanceof Reference)? "block ":"Renderable ")
                            + rootString + " at " + StringUtils.formatFileString(this));
                        throw e;
                    }
                }

                toString = DuckType.asString(value);
            }

            if (value == null || toString == null)
            {
                if (strictRef)
                {
                    if (referenceType != QUIET_REFERENCE)
                    {
                      log.error("Prepend the reference with '$!' e.g., $!{}" +
                                " if you want Velocity to ignore the reference when it evaluates to null",
                                literal().substring(1));
                      if (value == null)
                      {
                        throw new VelocityException("Reference " + literal()
                            + " evaluated to null when attempting to render at "
                            + StringUtils.formatFileString(this)
                        , null, rsvc.getLogContext().getStackTrace());
                      }
                      else  // toString == null
                      {
                        // This will probably rarely happen, but when it does we want to
                        // inform the user that toString == null so they don't pull there
                        // hair out wondering why Velocity thinks the value is null.
                        throw new VelocityException("Reference " + literal()
                            + " evaluated to object " + value.getClass().getName()
                            + " whose toString() method returned null at "
                            + StringUtils.formatFileString(this)
                            , null, rsvc.getLogContext().getStackTrace());
                      }
                    }
                    return true;
                }

                /*
                 * write prefix twice, because it's schmoo, so the \ don't escape each
                 * other...
                 */
                localNullString = getNullString(context);
                if (!strictEscape)
                {
                    // If in strict escape mode then we only print escape once.
                    // Yea, I know.. brittle stuff
                    writer.write(escPrefix);
                }
                writer.write(escPrefix);
                writer.write(morePrefix);
                writer.write(localNullString);

                if (logOnNull && referenceType != QUIET_REFERENCE)
                {
                    log.debug("Null reference [template '{}', line {}, column {}]: {} cannot be resolved.",
                              getTemplateName(), this.getLine(), this.getColumn(), this.literal());
                }
            }
            else
            {
                /*
                 * non-null processing
                 */
                writer.write(escPrefix);
                writer.write(morePrefix);
                if (writer instanceof Filter)
                {
                    ((Filter)writer).writeReference(toString);
                }
                else
                {
                    writer.write(toString);
                }

            }
            return true;
        }
        finally
        {
            rsvc.getLogContext().popLogContext();
        }
    }