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

io.gravitee.el.spel.CachedExpression Maven / Gradle / Ivy

/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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 io.gravitee.el.spel;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.expression.Expression;
import org.springframework.expression.common.CompositeStringExpression;
import org.springframework.expression.spel.SpelNode;
import org.springframework.expression.spel.ast.CompoundExpression;
import org.springframework.expression.spel.ast.PropertyOrFieldReference;
import org.springframework.expression.spel.ast.VariableReference;
import org.springframework.expression.spel.standard.SpelExpression;

/**
 * Allows to cache a given {@link Expression} for later reuse.
 * It also gives access to the list of variables accessed by the {@link Expression}.
 *
 * @author Jeoffrey HAEYAERT (jeoffrey.haeyaert at graviteesource.com)
 * @author GraviteeSource Team
 */
public class CachedExpression {

    private final Expression expression;
    private Set variables;

    public CachedExpression(final Expression expression) {
        this.expression = expression;
        computeVariables(expression);
    }

    private void computeVariables(Expression expression) {
        if (expression instanceof SpelExpression) {
            // Ex: "{#request.headers['X-Gravitee-Endpoint']}"
            computeVariables(((SpelExpression) expression).getAST());
        } else if (expression instanceof CompositeStringExpression) {
            // Ex: "Header X-Gravitee-Endpoint: {#request.headers['X-Gravitee-Endpoint'][0]}"
            computeVariables((CompositeStringExpression) expression);
        }
        // Could be a LiteralExpression we don't really care, ex: "Hello Gravitee".
    }

    private void computeVariables(CompositeStringExpression expression) {
        // Ex: "Header X-Gravitee-Endpoint: {#request.headers['X-Gravitee-Endpoint'][0]}"
        for (Expression e : expression.getExpressions()) {
            computeVariables(e);
        }
    }

    private void computeVariables(CompoundExpression expression) {
        // Ex: "{#value.content.val1}"
        for (int i = 0; i < expression.getChildCount(); i++) {
            final SpelNode node = expression.getChild(i);
            if (node instanceof VariableReference) {
                i++;
                StringBuilder variableName = new StringBuilder(getVariableName((VariableReference) node));
                SpelNode attrNode;
                while (i < expression.getChildCount() && ((attrNode = expression.getChild(i)) instanceof PropertyOrFieldReference)) {
                    // Iterate over all children, ex: value -> content -> val1
                    variableName.append(".").append(((PropertyOrFieldReference) attrNode).getName());
                    i++;
                }

                i--;

                addVariable(variableName.toString());
            } else {
                // Could be a method, ex: {#value.content()}.
                computeVariables(node);
            }
        }
    }

    private void computeVariables(SpelNode spelNode) {
        if (spelNode instanceof CompoundExpression) {
            // Ex: "{#value.content.val1}"
            computeVariables((CompoundExpression) spelNode);
        } else if (spelNode instanceof VariableReference && spelNode.getChildCount() == 0) {
            // Ex: "{#value}
            addVariable(getVariableName((VariableReference) spelNode));
        } else {
            // Iterate and process all child nodes.
            for (int i = 0; i < spelNode.getChildCount(); i++) {
                computeVariables(spelNode.getChild(i));
            }
        }
    }

    private String getVariableName(VariableReference variableReference) {
        return variableReference.toStringAST().replace("#", "");
    }

    private void addVariable(String name) {
        if (variables == null) {
            variables = new HashSet<>();
        }
        variables.add(name);
    }

    public Expression getExpression() {
        return expression;
    }

    public Set getVariables() {
        if (variables == null) {
            return Collections.emptySet();
        }
        return variables;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy