All Downloads are FREE. Search and download functionalities are using the official Maven repository.

freemarker.core.InvalidReferenceException Maven / Gradle / Ivy

Go to download

Google App Engine compliant variation of FreeMarker. FreeMarker is a "template engine"; a generic tool to generate text output based on templates.

There is a newer version: 2.3.34
Show newest version
/*
 * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
 * 
 * Licensed 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.
 */

package freemarker.core;

import freemarker.template.TemplateException;

/**
 * A subclass of {@link TemplateException} that says that an FTL expression has evaluated to {@code null} or it refers
 * to something that doesn't exist. At least in FreeMarker 2.3.x these two cases aren't distinguished.
 */
public class InvalidReferenceException extends TemplateException {

    static final InvalidReferenceException FAST_INSTANCE = new InvalidReferenceException(
            "Invalid reference. Details are unavilable, as this should have been handled by an FTL construct. "
            + "If it wasn't, that's problably a bug in FreeMarker.",
            null);
    
    private static final String[] TIP = new String[] {
        "If the failing expression is known to be legally refer to something that's null or missing, either specify a "
        + "default value like myOptionalVar!myDefault, or use ",
        "<#if myOptionalVar??>", "when-present", "<#else>", "when-missing", "",
        ". (These only cover the last step of the expression; to cover the whole expression, "
        + "use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??"
    };

    private static final String TIP_NO_DOLAR =
            "Variable references must not start with \"$\", unless the \"$\" is really part of the variable name.";

    private static final String TIP_LAST_STEP_DOT =
            "It's the step after the last dot that caused this error, not those before it.";

    private static final String TIP_LAST_STEP_SQUARE_BRACKET =
            "It's the final [] step that caused this error, not those before it.";
    
    /**
     * Creates and invalid reference exception that contains no information about what was missing or null.
     * As such, try to avoid this constructor.
     */
    public InvalidReferenceException(Environment env) {
        super("Invalid reference: The expression has evaluated to null or refers to something that doesn't exist.",
                env);
    }

    /**
     * Creates and invalid reference exception that contains no programmatically extractable information about the
     * blamed expression. As such, try to avoid this constructor, unless need to raise this expression from outside
     * the FreeMarker core.
     */
    public InvalidReferenceException(String description, Environment env) {
        super(description, env);
    }

    /**
     * This is the recommended constructor, but it's only used internally, and has no backward compatibility guarantees.
     * 
     * @param expression The expression that evaluates to missing or null. The last step of the expression should be
     *     the failing one, like in {@code goodStep.failingStep.furtherStep} it should only contain
     *     {@code goodStep.failingStep}.
     */
    InvalidReferenceException(_ErrorDescriptionBuilder description, Environment env, Expression expression) {
        super(null, env, expression, description);
    }

    /**
     * Use this whenever possible, as it returns {@link #FAST_INSTANCE} instead of creating a new instance, when
     * appropriate.
     */
    static InvalidReferenceException getInstance(Expression blamed, Environment env) {
        if (env != null && env.getFastInvalidReferenceExceptions()) {
            return FAST_INSTANCE;
        } else {
            if (blamed != null) {
                final _ErrorDescriptionBuilder errDescBuilder
                        = new _ErrorDescriptionBuilder("The following has evaluated to null or missing:").blame(blamed);
                if (endsWithDollarVariable(blamed)) {
                    errDescBuilder.tips(new Object[] { TIP_NO_DOLAR, TIP });
                } else if (blamed instanceof Dot) {
                    final String rho = ((Dot) blamed).getRHO();
                    String nameFixTip = null;
                    if ("size".equals(rho)) {
                        nameFixTip = "To query the size of a collection or map use ?size, like myList?size";
                    } else if ("length".equals(rho)) {
                        nameFixTip = "To query the length of a string use ?length, like myString?size";
                    }
                    errDescBuilder.tips(
                            nameFixTip == null
                                    ? new Object[] { TIP_LAST_STEP_DOT, TIP }
                                    : new Object[] { TIP_LAST_STEP_DOT, nameFixTip, TIP });
                } else if (blamed instanceof DynamicKeyName) {
                    errDescBuilder.tips(new Object[] { TIP_LAST_STEP_SQUARE_BRACKET, TIP });
                } else {
                    errDescBuilder.tip(TIP);
                }
                return new InvalidReferenceException(errDescBuilder, env, blamed);
            } else {
                return new InvalidReferenceException(env);
            }
        }
    }

    private static boolean endsWithDollarVariable(Expression blame) {
        return blame instanceof Identifier && ((Identifier) blame).getName().startsWith("$")
                || blame instanceof Dot && ((Dot) blame).getRHO().startsWith("$");
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy