JavaScriptEvaluator.java :  » Report » jasperreports-3.7.2 » net » sf » jasperreports » compilers » Java Open Source

Java Open Source » Report » jasperreports 3.7.2 
jasperreports 3.7.2 » net » sf » jasperreports » compilers » JavaScriptEvaluator.java
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
 */
package net.sf.jasperreports.compilers;

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

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRExpressionChunk;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.fill.JREvaluator;
import net.sf.jasperreports.engine.fill.JRFillField;
import net.sf.jasperreports.engine.fill.JRFillParameter;
import net.sf.jasperreports.engine.fill.JRFillVariable;
import net.sf.jasperreports.engine.util.JRClassLoader;
import net.sf.jasperreports.engine.util.JRStringUtil;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.ScriptableObject;

/**
 * JavaScript expression evaluator.
 * 
 * @author Lucian Chirita (lucianc@users.sourceforge.net)
 * @version $Id: JavaScriptEvaluator.java 3717 2010-04-09 10:01:33Z teodord $
 */
public class JavaScriptEvaluator extends JREvaluator
{
  
  /**
   * Base JavaScript value class.
   */
  public abstract static class JSValue
  {
    private final ScriptableObject scope;

    protected JSValue(ScriptableObject scope)
    {
      this.scope = scope;
    }
    
    protected final Object toJSValue(Object value)
    {
      return Context.javaToJS(value, scope);
    }
  }
  
  /**
   * Parameter class used in JavaScript expressions.
   */
  public static class JSParameter extends JSValue
  {
    private final JRFillParameter parameter;
    
    public JSParameter(JRFillParameter parameter, ScriptableObject scope)
    {
      super(scope);
      this.parameter = parameter;
    }
    
    public Object getValue()
    {
      return toJSValue(parameter.getValue());
    }
  }
  
  /**
   * Field class used in JavaScript expressions.
   */
  public static class JSField extends JSValue
  {
    private final JRFillField field;
    
    public JSField(JRFillField field, ScriptableObject scope)
    {
      super(scope);
      this.field = field;
    }
    
    public Object getValue()
    {
      return toJSValue(field.getValue());
    }
    
    public Object getOldValue()
    {
      return toJSValue(field.getOldValue());
    }
  }
  
  /**
   * Variable class used in JavaScript expressions.
   */
  public static class JSVariable extends JSValue
  {
    private final JRFillVariable variable;
    
    public JSVariable(JRFillVariable variable, ScriptableObject scope)
    {
      super(scope);
      this.variable = variable;
    }
    
    public Object getValue()
    {
      return toJSValue(variable.getValue());
    }
    
    public Object getOldValue()
    {
      return toJSValue(variable.getOldValue());
    }
    
    public Object getEstimatedValue()
    {
      return toJSValue(variable.getEstimatedValue());
    }
  }
  
  protected static JavaScriptCompileData.Expression createJSExpression(JRExpression expression)
  {
    StringBuffer defaultExpr = new StringBuffer();
    StringBuffer oldExpr = new StringBuffer();
    StringBuffer estimatedExpr = new StringBuffer();
    
    JRExpressionChunk[] chunks = expression.getChunks();
    if (chunks == null)
    {
      defaultExpr.append("null");
      oldExpr.append("null");
      estimatedExpr.append("null");
    }
    else
    {
      for (int i = 0; i < chunks.length; i++)
      {
        JRExpressionChunk chunk = chunks[i];
        switch (chunk.getType())
        {
        case JRExpressionChunk.TYPE_TEXT:
          defaultExpr.append(chunk.getText());
          oldExpr.append(chunk.getText());
          estimatedExpr.append(chunk.getText());
          break;
        case JRExpressionChunk.TYPE_PARAMETER:
          String paramName = getParameterVar(chunk.getText());
          defaultExpr.append(paramName);
          defaultExpr.append(".getValue()");
          oldExpr.append(paramName);
          oldExpr.append(".getValue()");
          estimatedExpr.append(paramName);
          estimatedExpr.append(".getValue()");
          break;
        case JRExpressionChunk.TYPE_VARIABLE:
          String varName = getVariableVar(chunk.getText());
          defaultExpr.append(varName);
          defaultExpr.append(".getValue()");
          oldExpr.append(varName);
          oldExpr.append(".getOldValue()");
          estimatedExpr.append(varName);
          estimatedExpr.append(".getEstimatedValue()");
          break;
        case JRExpressionChunk.TYPE_FIELD:
          String fieldName = getFieldVar(chunk.getText());
          defaultExpr.append(fieldName);
          defaultExpr.append(".getValue()");
          oldExpr.append(fieldName);
          oldExpr.append(".getOldValue()");
          estimatedExpr.append(fieldName);
          estimatedExpr.append(".getValue()");
          break;
        }
      }
    }
    
    return new JavaScriptCompileData.Expression(expression.getValueClassName(),
        defaultExpr.toString(), estimatedExpr.toString(), oldExpr.toString());
  }

  protected static String getParameterVar(String name)
  {
    return "param_" + JRStringUtil.getJavaIdentifier(name);
  }

  protected static String getVariableVar(String name)
  {
    return "var_" + JRStringUtil.getJavaIdentifier(name);
  }

  protected static String getFieldVar(String name)
  {
    return "field_" + JRStringUtil.getJavaIdentifier(name);
  }
  
  private final JavaScriptCompileData compileData;
  private Context context;
  private ScriptableObject scope;
  private Map loadedTypes = new HashMap();
  private Map compiledExpressions = new HashMap();

  /**
   * Create a JavaScript expression evaluator.
   * 
   * @param compileData the report compile data
   */
  public JavaScriptEvaluator(JavaScriptCompileData compileData)
  {
    this.compileData = compileData;
  }

  protected void customizedInit(Map parametersMap, Map fieldsMap,
      Map variablesMap) throws JRException
  {
    context = ContextFactory.getGlobal().enterContext();//TODO exit context
    context.getWrapFactory().setJavaPrimitiveWrap(false);
    scope = context.initStandardObjects();
    
    for (Iterator it = parametersMap.entrySet().iterator(); it.hasNext();)
    {
      Map.Entry entry = (Map.Entry) it.next();
      String name = (String) entry.getKey();
      JRFillParameter param = (JRFillParameter) entry.getValue();
      JSParameter jsParam = new JSParameter(param, scope);
      scope.put(getParameterVar(name), scope, jsParam);
    }

    for (Iterator it = variablesMap.entrySet().iterator(); it.hasNext();)
    {
      Map.Entry entry = (Map.Entry) it.next();
      String name = (String) entry.getKey();
      JRFillVariable var = (JRFillVariable) entry.getValue();
      JSVariable jsVar = new JSVariable(var, scope);
      scope.put(getVariableVar(name), scope, jsVar);
    }

    if (fieldsMap != null)
    {
      for (Iterator it = fieldsMap.entrySet().iterator(); it.hasNext();)
      {
        Map.Entry entry = (Map.Entry) it.next();
        String name = (String) entry.getKey();
        JRFillField field = (JRFillField) entry.getValue();
        JSField jsField = new JSField(field, scope);
        scope.put(getFieldVar(name), scope, jsField);
      }
    }
  }
  
  protected Object evaluate(int id) throws Throwable //NOSONAR
  {
    JavaScriptCompileData.Expression expression = getExpression(id);
    return evaluateExpression(expression.getJavaType(), 
        expression.getDefaultExpression());
  }

  protected Object evaluateEstimated(int id) throws Throwable //NOSONAR
  {
    JavaScriptCompileData.Expression expression = getExpression(id);
    return evaluateExpression(expression.getJavaType(), 
        expression.getEstimatedExpression());
  }

  protected Object evaluateOld(int id) throws Throwable //NOSONAR
  {
    JavaScriptCompileData.Expression expression = getExpression(id);
    return evaluateExpression(expression.getJavaType(), 
        expression.getOldExpression());
  }

  protected JavaScriptCompileData.Expression getExpression(int id)
  {
    return compileData.getExpression(id);
  }
  
  protected Object evaluateExpression(String type, String expression)
  {
    Script compiledExpression = getCompiledExpression(expression);
    Object value = compiledExpression.exec(context, scope);
    
    Class typeClass = getTypeClass(type);
    Object javaValue;
    try
    {
      javaValue = Context.jsToJava(value, typeClass);
    }
    catch (EvaluatorException e)
    {
      throw new JRRuntimeException(e);
    }
    return javaValue;
  }
  
  protected Script getCompiledExpression(String expression)
  {
    Script compiledExpression = (Script) compiledExpressions.get(expression);
    if (compiledExpression == null)
    {
      compiledExpression = context.compileString(expression, "expression", 0, null);
      compiledExpressions.put(expression, compiledExpression);
    }
    return compiledExpression;
  }
  
  protected Class getTypeClass(String type)
  {
    Class typeClass = (Class) loadedTypes.get(type);
    if (typeClass == null)
    {
      try
      {
        typeClass = JRClassLoader.loadClassForName(type);
      }
      catch (ClassNotFoundException e)
      {
        throw new JRRuntimeException("Unable to load class " + type, e);
      }
      loadedTypes.put(type, typeClass);
    }
    return typeClass;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.