Package org.springframework.binding.expression.el

Source Code of org.springframework.binding.expression.el.ELExpressionParser$ParserELContext

/*
* Copyright 2004-2012 the original author or authors.
*
* 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 org.springframework.binding.expression.el;

import java.util.HashMap;
import java.util.Map;

import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.FunctionMapper;
import javax.el.ValueExpression;
import javax.el.VariableMapper;

import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.convert.service.DefaultConversionService;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.NullParserContext;
import org.springframework.util.Assert;

/**
* The expression parser that parses EL expressions.
*
* @author Keith Donald
* @author Jeremy Grelle
*/
public class ELExpressionParser implements ExpressionParser {

  private ExpressionFactory expressionFactory;

  private Map<Class<?>, ELContextFactory> contextFactories = new HashMap<Class<?>, ELContextFactory>();

  private ConversionService conversionService = new DefaultConversionService();

  /**
   * Creates a new EL expression parser for standalone usage.
   */
  public ELExpressionParser(ExpressionFactory expressionFactory) {
    init(expressionFactory);
  }

  /**
   * The conversion service to use to perform type conversions as needed by the Unified EL system. If not specified,
   * the default is an instance of {@link DefaultConversionService}.
   */
  public ConversionService getConversionService() {
    return conversionService;
  }

  /**
   * Sets the conversion service to use to perform type conversions as needed by the Unified EL system.
   * @param conversionService the conversion service to use
   */
  public void setConversionService(ConversionService conversionService) {
    Assert.notNull(conversionService, "The conversion service is required");
    this.conversionService = conversionService;
  }

  /**
   * Register the ELContextFactory for expressions that evaluate the given class of context object.
   * @param contextType the expression context class
   * @param contextFactory the context factory to use for expressions that evaluate those types of contexts
   */
  public void putContextFactory(Class<?> contextType, ELContextFactory contextFactory) {
    Assert.notNull(contextFactory, "The EL context factory cannot be null");
    contextFactories.put(contextType, contextFactory);
  }

  public Expression parseExpression(String expressionString, ParserContext context) throws ParserException {
    Assert.notNull(expressionString, "The expression string to parse is required");
    if (context == null) {
      context = NullParserContext.INSTANCE;
    }
    if (context.isTemplate()) {
      return parseExpressionInternal(expressionString, context, true);
    } else {
      assertNotDelimited(expressionString);
      assertHasText(expressionString);
      return parseExpressionInternal("#{" + expressionString + "}", context, false);
    }
  }

  private Expression parseExpressionInternal(String expressionString, ParserContext context, boolean template)
      throws ParserException {
    Assert.notNull(expressionString, "The expression string to parse is required");
    try {
      ValueExpression expression = parseValueExpression(expressionString, context);
      ELContextFactory contextFactory = getContextFactory(context.getEvaluationContextType(), expressionString);
      return new ELExpression(contextFactory, expression);
    } catch (ELException e) {
      throw new ParserException(expressionString, e);
    }
  }

  private ValueExpression parseValueExpression(String expressionString, ParserContext context) throws ELException {
    ParserELContext elContext = new ParserELContext();
    elContext.mapVariables(context.getExpressionVariables(), expressionFactory);
    ValueExpression expression = expressionFactory.createValueExpression(elContext, expressionString, Object.class);
    return new BindingValueExpression(expression, getExpectedType(context), conversionService, context.isTemplate());
  }

  private Class<?> getExpectedType(ParserContext context) {
    Class<?> expectedType = context.getExpectedEvaluationResultType();
    return expectedType != null ? expectedType : Object.class;
  }

  private ELContextFactory getContextFactory(Class<?> expressionTargetType, String expressionString) {
    if (contextFactories.containsKey(expressionTargetType)) {
      return contextFactories.get(expressionTargetType);
    } else {
      return contextFactories.get(Object.class);
    }
  }

  private void init(ExpressionFactory expressionFactory) {
    this.expressionFactory = expressionFactory;
    DefaultElContextFactory contextFactory = new DefaultElContextFactory();
    putContextFactory(null, contextFactory);
    putContextFactory(Object.class, contextFactory);
  }

  private void assertNotDelimited(String expressionString) {
    if ((expressionString.startsWith("#{") && expressionString.endsWith("}"))
        || (expressionString.startsWith("${") && expressionString.endsWith("}"))) {
      throw new ParserException(expressionString, "This expression '" + expressionString
          + "' being parsed is expected be an 'eval' EL expression string. "
          + "Do not attempt to enclose such expression strings in #{} or ${} delimiters. "
          + "If you need to parse a template that mixes literal text with evaluatable blocks, "
          + "set the 'template' parser context attribute to true.", null);
    }
  }

  private void assertHasText(String expressionString) {
    if (expressionString.length() == 0) {
      throw new ParserException(expressionString, "The EL eval expression to parse must have text", null);
    }
  }

  private class ParserELContext extends ELContext {
    private VariableMapper variableMapper;

    public ELResolver getELResolver() {
      return null;
    }

    public FunctionMapper getFunctionMapper() {
      return null;
    }

    public VariableMapper getVariableMapper() {
      return variableMapper;
    }

    public void mapVariables(ExpressionVariable[] variables, ExpressionFactory expressionFactory) {
      if (variables != null && variables.length > 0) {
        variableMapper = new VariableMapperImpl();
        for (ExpressionVariable var : variables) {
          ParserContext context = var.getParserContext() != null ? var.getParserContext()
              : NullParserContext.INSTANCE;
          ValueExpression expr;
          if (context.isTemplate()) {
            expr = parseValueExpression(var.getValueExpression(), context);
          } else {
            assertNotDelimited(var.getValueExpression());
            assertHasText(var.getValueExpression());
            expr = parseValueExpression("#{" + var.getValueExpression() + "}", context);
          }
          variableMapper.setVariable(var.getName(), expr);
        }
      }
    }
  }

  private static class VariableMapperImpl extends VariableMapper {
    private Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>();

    public ValueExpression resolveVariable(String name) {
      return variables.get(name);
    }

    public ValueExpression setVariable(String name, ValueExpression value) {
      return variables.put(name, value);
    }

    public String toString() {
      return variables.toString();
    }
  }

}
TOP

Related Classes of org.springframework.binding.expression.el.ELExpressionParser$ParserELContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.