boolean[] argDefs = aggrInfo.func.getParameterDefn( );
boolean[] argDefs = aggrInfo.aggregation.getParameterDefn( );
	private boolean onRow( int aggrIndex, int startingGroupLevel,			int endingGroupLevel, Scriptable scope, boolean populateValue )			throws DataException	{		AggregateTable.AggrExprInfo aggrInfo = aggrTable.getAggrInfo( aggrIndex );		Accumulator acc = null;		boolean newGroup = false;		if (startingGroupLevel <= aggrInfo.groupLevel) 		{			// A new group starts for this aggregate; call start() on			// accumulator			newGroup = true;			acc = accumulatorManagers[aggrIndex].next( );			acc.start();		}		else 		{			acc = accumulatorManagers[aggrIndex].getCurrentAccumulator( );		}					// Apply filtering on row		boolean accepted = true;		if ( aggrInfo.filter != null )		{			try			{				Object filterResult = ResultIterator.evaluateCompiledExpression( aggrInfo.filter,						odiResult,						scope );				if ( filterResult == null )					accepted = true;				else					accepted = DataTypeUtil.toBoolean( filterResult )							.booleanValue( );			}			catch ( BirtException e )			{				logger.logp( Level.FINE,						DataEngineImpl.class.getName( ),						"onRow",						"An error is thrown by DataTypeUtil.",						e );				if ( invalidAggrMsg == null )					invalidAggrMsg = new HashMap( );				invalidAggrMsg.put( new Integer( aggrIndex ), e );				return false;			}		}		if ( accepted )		{			// Calculate arguments to the aggregate function			boolean[] argDefs = aggrInfo.func.getParameterDefn( );			assert argDefs.length == aggrArgs[aggrIndex].length;			try			{				for ( int i = 0; i < argDefs.length; i++ )				{					// Note that static arguments only need to be calculated					// once at					// the					// start of the iteration					if ( argDefs[i] || newGroup )					{						CompiledExpression argExpr = aggrInfo.args[i];						aggrArgs[aggrIndex][i] = ResultIterator.evaluateCompiledExpression( argExpr,								odiResult,								scope );					}				}				acc.onRow( aggrArgs[aggrIndex] );			}			catch ( DataException e )			{				if ( invalidAggrMsg == null )					invalidAggrMsg = new HashMap( );				invalidAggrMsg.put( new Integer( aggrIndex ), e );				return false;			}		}		// If this is a running aggregate, get value for current row		boolean isRunning = ( aggrInfo.func.getType( ) == IAggregation.RUNNING_AGGR );		if ( isRunning && populateValue )		{			Object value = acc.getValue( );			aggrValues[aggrIndex].add( value );//			assert aggrValues[aggrIndex].size( ) == odiResult.getCurrentResultIndex( ) + 1;		}		if ( endingGroupLevel <= aggrInfo.groupLevel )		{			// Current group ends for this aggregate; call finish() on			// accumulator			acc.finish( );			// For non-running aggregates, this is the time to call getValue			if ( (!isRunning) && populateValue )			{				Object value = acc.getValue( );				aggrValues[aggrIndex].add( value );//				assert aggrInfo.groupLevel == 0//						? ( aggrValues[aggrIndex].size( ) == 1 )//						: ( aggrValues[aggrIndex].size( ) == odiResult.getCurrentGroupIndex( aggrInfo.groupLevel ) + 1 );			}		}		return true;	}