⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 astreference.java

📁 velocity官方工具包 包括各种JAR包 示例 文档等
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.apache.velocity.runtime.parser.node;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;

import org.apache.velocity.app.event.EventHandlerUtil;
import org.apache.velocity.context.Context;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.runtime.parser.ParserVisitor;
import org.apache.velocity.runtime.parser.Token;
import org.apache.velocity.util.introspection.Info;
import org.apache.velocity.util.introspection.VelPropertySet;

/**
 * This class is responsible for handling the references in
 * VTL ($foo).
 *
 * Please look at the Parser.jjt file which is
 * what controls the generation of this class.
 *
 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
 * @author <a href="mailto:Christoph.Reck@dlr.de">Christoph Reck</a>
 * @author <a href="mailto:kjohnson@transparent.com>Kent Johnson</a>
 * @version $Id: ASTReference.java 471381 2006-11-05 08:56:58Z wglass $
*/
public class ASTReference extends SimpleNode
{
    /* Reference types */
    private static final int NORMAL_REFERENCE = 1;
    private static final int FORMAL_REFERENCE = 2;
    private static final int QUIET_REFERENCE = 3;
    private static final int RUNT = 4;

    private int referenceType;
    private String nullString;
    private String rootString;
    private boolean escaped = false;
    private boolean computableReference = true;
    private boolean logOnNull = true;
    private String escPrefix = "";
    private String morePrefix = "";
    private String identifier = "";

    private String literal = null;

    private int numChildren = 0;

    protected Info uberInfo;

    /**
     * @param id
     */
    public ASTReference(int id)
    {
        super(id);
    }

    /**
     * @param p
     * @param id
     */
    public ASTReference(Parser p, int id)
    {
        super(p, id);
    }

    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.ParserVisitor, java.lang.Object)
     */
    public Object jjtAccept(ParserVisitor visitor, Object data)
    {
        return visitor.visit(this, data);
    }

    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
     */
    public Object init(InternalContextAdapter context, Object data)
    throws TemplateInitException
    {
        /*
         *  init our children
         */

        super.init(context, data);

        /*
         *  the only thing we can do in init() is getRoot()
         *  as that is template based, not context based,
         *  so it's thread- and context-safe
         */

        rootString = getRoot();

        numChildren = jjtGetNumChildren();

        /*
         * and if appropriate...
         */

        if (numChildren > 0 )
        {
            identifier = jjtGetChild(numChildren - 1).getFirstToken().image;
        }

        /*
         * make an uberinfo - saves new's later on
         */

        uberInfo = new Info(context.getCurrentTemplateName(),
                getLine(),getColumn());

        /*
         * track whether we log invalid references
         */
        logOnNull =
            rsvc.getBoolean(RuntimeConstants.RUNTIME_LOG_REFERENCE_LOG_INVALID, true);

        return data;
    }

    /**
     *  Returns the 'root string', the reference key
     * @return the root string.
     */
     public String getRootString()
     {
        return rootString;
     }

    /**
     *   gets an Object that 'is' the value of the reference
     *
     *   @param o   unused Object parameter
     *   @param context context used to generate value
     * @return The execution result.
     * @throws MethodInvocationException
     */
    public Object execute(Object o, InternalContextAdapter context)
        throws MethodInvocationException
    {

        if (referenceType == RUNT)
            return null;

        /*
         *  get the root object from the context
         */

        Object result = getVariableValue(context, rootString);

        if (result == null)
        {
            return EventHandlerUtil.invalidGetMethod(rsvc, context, 
                    "$" + rootString, null, null, uberInfo);
        }

        /*
         * Iteratively work 'down' (it's flat...) the reference
         * to get the value, but check to make sure that
         * every result along the path is valid. For example:
         *
         * $hashtable.Customer.Name
         *
         * The $hashtable may be valid, but there is no key
         * 'Customer' in the hashtable so we want to stop
         * when we find a null value and return the null
         * so the error gets logged.
         */

        try
        {
            Object previousResult = result; 
            int failedChild = -1;
            for (int i = 0; i < numChildren; i++)
            {
                previousResult = result;
                result = jjtGetChild(i).execute(result,context);
                if (result == null)
                {
                    failedChild = i;
                    break;
                }
            }

            if (result == null)
            {
                if (failedChild == -1)
                {
                    result = EventHandlerUtil.invalidGetMethod(rsvc, context, 
                            "$" + rootString, previousResult, null, uberInfo);                    
                }
                else
                {
                    StringBuffer name = new StringBuffer("$").append(rootString);
                    for (int i = 0; i <= failedChild; i++)
                    {
                        Node node = jjtGetChild(i);
                        if (node instanceof ASTMethod)
                        {
                            name.append(".").append(((ASTMethod) node).getMethodName()).append("()");
                        }
                        else
                        {
                            name.append(".").append(node.getFirstToken().image);
                        }
                    }
                    
                    if (jjtGetChild(failedChild) instanceof ASTMethod)
                    {
                        String methodName = ((ASTMethod) jjtGetChild(failedChild)).getMethodName();
                        result = EventHandlerUtil.invalidMethod(rsvc, context, 
                                name.toString(), previousResult, methodName, uberInfo);                                                                
                    }
                    else
                    {
                        String property = jjtGetChild(failedChild).getFirstToken().image;
                        result = EventHandlerUtil.invalidGetMethod(rsvc, context, 
                                name.toString(), previousResult, property, uberInfo);                        
                    }
                }
                
            }
            
            return result;
        }
        catch(MethodInvocationException mie)
        {
            /*
             *  someone tossed their cookies
             */

            log.error("Method " + mie.getMethodName()
                        + " threw exception for reference $"
                        + rootString
                        + " in template " + context.getCurrentTemplateName()
                        + " at " +  " [" + this.getLine() + ","
                        + this.getColumn() + "]");

            mie.setReferenceName(rootString);
            throw mie;
        }
    }

    /**
     *  gets the value of the reference and outputs it to the
     *  writer.
     *
     *  @param context  context of data to use in getting value
     *  @param writer   writer to render to
     * @return True if rendering was successful.
     * @throws IOException
     * @throws MethodInvocationException
     */
    public boolean render(InternalContextAdapter context, Writer writer)
        throws IOException, MethodInvocationException
    {

        if (referenceType == RUNT)
        {
            if (context.getAllowRendering())
            {
                writer.write(rootString);
            }

            return true;
        }

        Object value = execute(null, context);

        /*
         *  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)
        {
            if (value == null)
            {
                if (context.getAllowRendering())
                {
                    writer.write(escPrefix);
                    writer.write("\\");
                    writer.write(nullString);
                }
            }
            else
            {
                if (context.getAllowRendering())
                {
                    writer.write(escPrefix);
                    writer.write(nullString);
                }
            }

            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)
        {
            toString = value.toString();
        }


        /*
         *  if value is null...
         */

        if ( value == null || toString == null)
        {
            /*
             *  write prefix twice, because it's schmoo, so the \ don't escape each other...
             */

            if (context.getAllowRendering())
            {
                writer.write(escPrefix);
                writer.write(escPrefix);
                writer.write(morePrefix);
                writer.write(nullString);
            }

            if (logOnNull && referenceType != QUIET_REFERENCE && log.isInfoEnabled())
            {
                log.info("Null reference [template '"
                         + context.getCurrentTemplateName() + "', line "
                         + this.getLine() + ", column " + this.getColumn()
                         + "] : " + this.literal() + " cannot be resolved.");
            }
            return true;
        }
        else
        {
            /*
             *  non-null processing
             */

            if (context.getAllowRendering())
            {
                writer.write(escPrefix);
                writer.write(morePrefix);
                writer.write(toString);
            }

            return true;
        }
    }

    /**
     *   Computes boolean value of this reference
     *   Returns the actual value of reference return type
     *   boolean, and 'true' if value is not null
     *
     *   @param context context to compute value with
     * @return True if evaluation was ok.
     * @throws MethodInvocationException

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -