
/*******************************************************************************
 * Copyright (c) 2004, 2007 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/
package org.eclipse.birt.data.engine.olap.util.filter;

import org.eclipse.birt.core.data.DataTypeUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.script.ScriptContext;
import org.eclipse.birt.core.script.ScriptExpression;
import org.eclipse.birt.data.engine.api.IBaseExpression;
import org.eclipse.birt.data.engine.api.IFilterDefinition;
import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.olap.script.OLAPExpressionCompiler;
import org.eclipse.birt.data.engine.script.ScriptEvalUtil;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

/**
 * 
 */

public class JSMeasureFilterEvalHelper implements IJSMeasureFilterEvalHelper
{

	private ScriptableObject scope;
	private DummyMeasureObject dataObj;
	private IBaseExpression expr;
	private ScriptContext cx;
	public JSMeasureFilterEvalHelper( Scriptable parentScope, ScriptContext cx, IFilterDefinition cubeFilter) throws DataException
	{
		assert cubeFilter!=null;
		initialize( parentScope, cubeFilter, cx );
	}
	
	/**
	 * 
	 * @param parentScope
	 * @param cubeFilter
	 * @param cx
	 */
	private void initialize( Scriptable parentScope,
			IFilterDefinition cubeFilter,
			ScriptContext cx )
	{
		this.scope = cx.getContext( ).initStandardObjects( );
		this.scope.setParentScope( parentScope );
		this.dataObj = new DummyMeasureObject();
		this.expr = cubeFilter.getExpression( );
		OLAPExpressionCompiler.compile( cx.getContext( ), this.expr );
		this.cx = cx;
		this.scope.put( org.eclipse.birt.data.engine.script.ScriptConstants.MEASURE_SCRIPTABLE, this.scope, this.dataObj );
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.birt.data.engine.olap.util.filter.IJSMeasureFilterEvalHelper#evaluateFilter(org.eclipse.birt.data.engine.olap.util.filter.IFacttableRow)
	 */
	public boolean evaluateFilter( IFacttableRow facttableRow )
			throws DataException
	{
		this.dataObj.setCurrentRow( facttableRow );
		
		try
		{
			Object result = ScriptEvalUtil.evalExpr( expr, cx, scope, ScriptExpression.defaultID, 0 );
			return DataTypeUtil.toBoolean( result ).booleanValue( );
		}
		catch ( BirtException e )
		{
			throw DataException.wrap( e );
		}
	}

	/**
	 * 
	 *
	 */
	private class DummyMeasureObject extends ScriptableObject
	{
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		//
		private IFacttableRow row;
			
		/*
		 * (non-Javadoc)
		 * @see org.mozilla.javascript.ScriptableObject#getClassName()
		 */
		public String getClassName( )
		{
			return "DummyMeasureObject";
		}
		
		/**
		 * Set the current row for the evaluation.
		 * @param row
		 */
		public void setCurrentRow( IFacttableRow row )
		{
			this.row = row;
		}
		
		/*
		 * (non-Javadoc)
		 * @see org.mozilla.javascript.ScriptableObject#get(java.lang.String, org.mozilla.javascript.Scriptable)
		 */
		public Object get( String measureName, Scriptable scope )
		{
			try
			{
				return this.row.getMeasureValue( measureName );
			}
			catch ( DataException e )
			{
				return null;
			}
		}
	}
}
