Package org.apache.el.lang

Source Code of org.apache.el.lang.ExpressionBuilder

/*
* 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.
*/

package org.apache.el.lang;

import java.io.StringReader;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.el.ELContext;
import javax.el.ELException;
import javax.el.FunctionMapper;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.el.VariableMapper;

import org.apache.el.MethodExpressionImpl;
import org.apache.el.MethodExpressionLiteral;
import org.apache.el.ValueExpressionImpl;
import org.apache.el.parser.AstCompositeExpression;
import org.apache.el.parser.AstDeferredExpression;
import org.apache.el.parser.AstDynamicExpression;
import org.apache.el.parser.AstFunction;
import org.apache.el.parser.AstIdentifier;
import org.apache.el.parser.AstLiteralExpression;
import org.apache.el.parser.AstValue;
import org.apache.el.parser.ELParser;
import org.apache.el.parser.Node;
import org.apache.el.parser.NodeVisitor;
import org.apache.el.parser.ParseException;
import org.apache.el.util.ConcurrentCache;
import org.apache.el.util.MessageFactory;

/**
* @author Jacob Hookom [jacob@hookom.net]
* @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: markt $
*/
public final class ExpressionBuilder implements NodeVisitor {

  private static final ConcurrentCache cache = new ConcurrentCache(5000);

  private FunctionMapper fnMapper;

  private VariableMapper varMapper;

  private String expression;

  /**
   *
   */
  public ExpressionBuilder(String expression, ELContext ctx)
      throws ELException {
    this.expression = expression;

    FunctionMapper ctxFn = ctx.getFunctionMapper();
    VariableMapper ctxVar = ctx.getVariableMapper();

    if (ctxFn != null) {
      this.fnMapper = new FunctionMapperFactory(ctxFn);
    }
    if (ctxVar != null) {
      this.varMapper = new VariableMapperFactory(ctxVar);
    }
  }

  public final static Node createNode(String expr) throws ELException {
    Node n = createNodeInternal(expr);
    return n;
  }

  private final static Node createNodeInternal(String expr)
      throws ELException {
    if (expr == null) {
      throw new ELException(MessageFactory.get("error.null"));
    }

    Node n = (Node) cache.get(expr);
    if (n == null) {
      try {
        n = (new ELParser(new StringReader(expr)))
            .CompositeExpression();

        // validate composite expression
        if (n instanceof AstCompositeExpression) {
          int numChildren = n.jjtGetNumChildren();
          if (numChildren == 1) {
            n = n.jjtGetChild(0);
          } else {
            Class type = null;
            Node child = null;
            for (int i = 0; i < numChildren; i++) {
              child = n.jjtGetChild(i);
              if (child instanceof AstLiteralExpression)
                continue;
              if (type == null)
                type = child.getClass();
              else {
                if (!type.equals(child.getClass())) {
                  throw new ELException(MessageFactory.get(
                      "error.mixed", expr));
                }
              }
            }
          }
        }
        if (n instanceof AstDeferredExpression
            || n instanceof AstDynamicExpression) {
          n = n.jjtGetChild(0);
        }
        cache.put(expr, n);
      } catch (ParseException pe) {
        throw new ELException("Error Parsing: " + expr, pe);
      }
    }
    return n;
  }

  private void prepare(Node node) throws ELException {
        try {
            node.accept(this);
        } catch (Exception e) {
            throw (ELException) e;
        }
    if (this.fnMapper instanceof FunctionMapperFactory) {
      this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create();
    }
    if (this.varMapper instanceof VariableMapperFactory) {
      this.varMapper = ((VariableMapperFactory) this.varMapper).create();
    }
  }

  private Node build() throws ELException {
    Node n = createNodeInternal(this.expression);
    this.prepare(n);
    if (n instanceof AstDeferredExpression
        || n instanceof AstDynamicExpression) {
      n = n.jjtGetChild(0);
    }
    return n;
  }

  /*
   * (non-Javadoc)
   *
   * @see com.sun.el.parser.NodeVisitor#visit(com.sun.el.parser.Node)
   */
  public void visit(Node node) throws ELException {
    if (node instanceof AstFunction) {

      AstFunction funcNode = (AstFunction) node;

      if (this.fnMapper == null) {
        throw new ELException(MessageFactory.get("error.fnMapper.null"));
      }
      Method m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode
          .getLocalName());
      if (m == null) {
        throw new ELException(MessageFactory.get(
            "error.fnMapper.method", funcNode.getOutputName()));
      }
      int pcnt = m.getParameterTypes().length;
      if (node.jjtGetNumChildren() != pcnt) {
        throw new ELException(MessageFactory.get(
            "error.fnMapper.paramcount", funcNode.getOutputName(),
            "" + pcnt, "" + node.jjtGetNumChildren()));
      }
    } else if (node instanceof AstIdentifier && this.varMapper != null) {
      String variable = ((AstIdentifier) node).getImage();

      // simply capture it
      this.varMapper.resolveVariable(variable);
    }
  }

  public ValueExpression createValueExpression(Class expectedType)
      throws ELException {
    Node n = this.build();
    return new ValueExpressionImpl(this.expression, n, this.fnMapper,
        this.varMapper, expectedType);
  }

  public MethodExpression createMethodExpression(Class expectedReturnType,
      Class[] expectedParamTypes) throws ELException {
    Node n = this.build();
    if (n instanceof AstValue || n instanceof AstIdentifier) {
      return new MethodExpressionImpl(expression, n, this.fnMapper,
          this.varMapper, expectedReturnType, expectedParamTypes);
    } else if (n instanceof AstLiteralExpression) {
      return new MethodExpressionLiteral(expression, expectedReturnType,
          expectedParamTypes);
    } else {
      throw new ELException("Not a Valid Method Expression: "
          + expression);
    }
  }
}
TOP

Related Classes of org.apache.el.lang.ExpressionBuilder

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.