Package tcg.common.util

Source Code of tcg.common.util.ExpressionParser

package tcg.common.util;

import java.util.ArrayList;
import org.codehaus.janino.ExpressionEvaluator;

public class ExpressionParser
{
  private String    expression_ = "";
  private Class<?>  returnType_ = int.class;
 
  private ExpressionEvaluator   evaluator_ = null;
 
  //list of variables
  private ArrayList<String>   varNames_ = new ArrayList<String>();
  private ArrayList<Class<?>>  varTypes_ = new ArrayList<Class<?>>();
  private ArrayList<Object>   varValues_ = new ArrayList<Object>();
 
  //Once the expression is parsed, if it contains invalid expression this flag
  //will be set to false. This will prevent more attempt of parsing.
  private boolean    isValidExpression_ = true;
 
  /**
   * Default constructor.
   * The preferred ctor is the one with parameters: expression string and return type
   */
  public ExpressionParser()
  {
    //default constructor
  }
 
  /**
   * Preferred constructor. Provide the expression string and the return type
   * @param expression  - the expression string
   * @param type      - the return type
   */
  public ExpressionParser(String expression, Class<?> type)
  {
    if (expression != null)
    {
      this.expression_ = expression;
    }
    if (type != null)
    {
      this.returnType_ = type;
    }
  }
 
  /**
   * Set expression. If one uses the default ctor, he must call this right after.
   * Note: The preferred way is to use ctor with the parameters.
   *
   * @param expression  - the expression string
   * @param type      - the return type
   */
  public void setExpression(String expression, Class<?> type)
  {
    if (expression == null)
    {
      return;
    }
   
    if (type == null)
    {
      return;
    }   

    //reset the class just in case
    this.reset();
    //copy to local variable
    this.expression_ = expression;
    this.returnType_ = type;
  }
 
  /**
   * Reset the expression parser.
   */
  protected void reset()
  {
    expression_ = "";
    evaluator_ = null;
    varNames_.clear();
    varTypes_.clear();
    varValues_.clear();
    //always default to valid (true), otherwise the parser will never get initialized
    isValidExpression_ = true;
  }
 
  /**
   * Get current expression
   * @return  - the current expression
   */
  public String getExpression()
  {
    return expression_;
  }
 
  /**
   * Check if the expression is valid.
   * @return - true if the expression is valid, false otherwise.
   *           if the expression is not parsed (ie. not initialized), it will always return true.
   *           if the expression is never set, then it will return false
   */
  public boolean isValid()
  {
    //if expression is never set, always return as not valid
    if (expression_.isEmpty())
    {
      return false;
    }
    return isValidExpression_;
  };

  /**
   * Check if the expression has been successfully parsed.
   * @return - true if the expression has been successfully parsed, false otherwise
   */
  public boolean isInitialized()
  {
    return (evaluator_ != null);
  }

  /**
   * Evaluate the expression.
   * <br>
   * If the expression is not yet parsed, it will be parsed. If the operation (both the parsing,
   * if it is not yet done, and the evaluation) fails, the return value is null.
   * The caller is responsible for converting the result into the correct type.
   *
   * @return  the result of the expression if successful, null otherwise.
   * @throws   Exception   when the evaluation fails, exception is thrown.
   */
  public Object evaluate() throws Exception
  {
    //if expression is never set, return null
    if (evaluator_ == null && expression_.isEmpty())
    {
      //not set yet
      return null;
    }
   
    //if it is already flag as invalid, return null
    if (!isValidExpression_)
    {
      return null;
    }
   
    if (evaluator_ == null)
    {
      //create the parser
      try
      {
        evaluator_ = new ExpressionEvaluator(
                      expression_,                       // expression
                      returnType_,                         // expressionType
                      varNames_.toArray(new String[0]),   // parameterNames
                      varTypes_.toArray(new Class<?>[0])   // parameterTypes
                  );
        isValidExpression_ = true;
      }
      catch(Exception ex)
      {
        //set the invalid flag to prevent re-parsing next time
        isValidExpression_ = false;
        throw new Exception("evaluate(): " + ex.toString());
      }     
    }
   
    //evaluate the expression
    Object result = null;
    try
    {
      result = evaluator_.evaluate(varValues_.toArray(new Object[0]));
    }
    catch (Exception ex)
    {
      throw new Exception("evaluate(): " + ex.toString());
    }
   
    return result;
  }

  /**
   * Create internal variable.
   * You must create all the necessary variable before you execute the expression.
   *
   * @param varName  - variable name
   * @param varType  - variable class type
   * @param initValue  - initial value
   * @return - the index in the variable list if successful, -1 otherwise
   */
  public int createVariable(String varName, Class<?> varType, Object initValue)
  {
    if (varName == null || varName.length() == 0 || varType == null || initValue == null)
    {
      return -1;
    }
   
    varNames_.add(varName);
    varTypes_.add(varType);
    varValues_.add(initValue);
   
    return varNames_.size()-1;
  }
 
  /**
   * Set internal variable value. Note: caller need to translate the raw value to generic object.
   * @param varName  - variable name
   * @param value    - new value
   * @return status of the operation
   */
  public boolean set(String varName, Object value)
  {
    if (value == null)
    {
      return false;
    }
   
    //can not simply use "idx = varnames_.indexOf(varName);" because the String object is immutable.
    //That is, even if the actual string value is the same, a different String object will return
    // back inequality.
    int idx = -1;
    for (int i=0; i<varNames_.size(); i++)
    {
      if (varNames_.get(i).compareTo(varName) == 0)
      {
        idx = i;
        break;
      }
    }
   
    if (idx >= 0)
    {
      varValues_.set(idx, value);
      return true;
    }
   
    return false;
  }
 
  /**
   * Set internal variable value. Note: caller need to translate the raw value to generic object.
   * @param idx    - variable index/position
   * @param value    - new value
   * @return status of the operation
   */
  public boolean set(int idx, Object value)
  {
    if (idx < 0 || idx >= varNames_.size() || value == null)
    {
      return false;
   
    varValues_.set(idx, value);
    return true;
  }
 
  /**
   * Get internal variable value.
   * @param varName    - variable name
   * @return - the variable value
   */
  public Object get(String varName)
  {
    int idx = -1;
    for (int i=0; i<varNames_.size(); i++)
    {
      if (varNames_.get(i).compareTo(varName) == 0)
      {
        idx = i;
        break;
      }
    }
   
    if (idx >= 0)
    {
      return varValues_.get(idx);
    }
    return null;
  }
 
  /**
   * Get internal variable value.
   * @param idx    - variable index/position
   * @return - the variable value
   */
  public Object get(int idx)
  {
    if (idx < 0 || idx >= varNames_.size())
    {
      return null;
   
    return varValues_.get(idx);
  }
}
TOP

Related Classes of tcg.common.util.ExpressionParser

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.