/*******************************************************************************
 * Copyright (c) 2004 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.impl.document.viewing;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

import org.eclipse.birt.core.util.IOUtil;
import org.eclipse.birt.data.engine.api.DataEngineContext;
import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.executor.cache.CacheRequest;
import org.eclipse.birt.data.engine.executor.cache.OdiAdapter;
import org.eclipse.birt.data.engine.executor.cache.SmartCache;
import org.eclipse.birt.data.engine.i18n.ResourceConstants;
import org.eclipse.birt.data.engine.impl.DataEngineSession;
import org.eclipse.birt.data.engine.impl.document.RDGroupUtil;
import org.eclipse.birt.data.engine.impl.document.StreamWrapper;
import org.eclipse.birt.data.engine.impl.document.SubQueryIndexUtil;
import org.eclipse.birt.data.engine.impl.document.stream.StreamManager;
import org.eclipse.birt.data.engine.impl.document.util.ExprDataResultSet2;
import org.eclipse.birt.data.engine.impl.document.util.IExprDataResultSet;

/**
 * This class is used when there is subquery definition in original query
 * definition. It will generate the row index information for sub query.
 */
public class CachedSubExprResultSet extends BaseCachedResultSet
{
	//private int groupIndex;   	// save to which folder	
	//private int[] groupInfoIndex; //save to subQueryInfo
	
	private int[] offsetIndex; 		//save to group info folder
	private int oldSubQueryIndex;
	private DataEngineSession session;
	
	/**
	 * @param oldParentGroupInfo
	 * @param validRowIndex
	 * @param currParentID
	 * @throws DataException 
	 */
	public CachedSubExprResultSet( StreamManager streamManager,
			SubQueryIndexUtil subQueryManager, int currParentIndex,
			RDGroupUtil rdGroupUtil, DataEngineSession session )
			throws DataException
	{
		this.rdGroupUtil = rdGroupUtil;
		this.rdGroupUtil.setCacheProvider( this );
		this.session = session;
		this.doPrepare( streamManager, subQueryManager, currParentIndex );
		this.next( );
	}

	/**
	 * @param streamManager
	 * @param subQueryManager
	 * @param currParentIndex
	 * @throws DataException
	 */
	private void doPrepare( StreamManager streamManager,
			SubQueryIndexUtil subQueryManager, int currParentIndex )
			throws DataException
	{
		oldSubQueryIndex = subQueryManager.getOldGroupInstanceIndex( currParentIndex );
		offsetIndex = subQueryManager.getRowOffsetOfSubQuery( currParentIndex );
		//groupInfoIndex = subQueryManager.getGroupStartAndEndIndex( currParentIndex );

		IExprDataResultSet exprDataResultSet = new ExprDataResultSet2( streamManager.getInStream( DataEngineContext.EXPR_VALUE_STREAM,
				StreamManager.ROOT_STREAM,
				StreamManager.SELF_SCOPE ),
				streamManager.getInStream( DataEngineContext.EXPR_ROWLEN_STREAM,
						StreamManager.ROOT_STREAM,
						StreamManager.SELF_SCOPE ),
				offsetIndex,
				ExprMetaUtil.loadExprMetaInfo( streamManager.getInStream( DataEngineContext.EXPR_META_STREAM,
						StreamManager.ROOT_STREAM,
						StreamManager.SELF_SCOPE ) ) );
		
		this.resultClass = exprDataResultSet.getResultClass( );
		this.smartCache = new SmartCache( new CacheRequest( -1,
				new ArrayList( ),
				null,
				new DummyEventHandler( ) ),
				new OdiAdapter( exprDataResultSet ),
				resultClass, this.session );
		this.rowCount = this.smartCache.getCount( );
	}

	/*
	 * @see org.eclipse.birt.data.engine.odi.IResultIterator#doSave(org.eclipse.birt.data.engine.impl.document.StreamWrapper,
	 *      boolean)
	 */
	public void doSave( StreamWrapper streamsWrapper, boolean isSubQuery )
			throws DataException
	{
		try
		{
			// save the data of sub query
			IOUtil.writeInt( streamsWrapper.getStreamForParentIndex( ),
					oldSubQueryIndex );
			OutputStream outputStream = streamsWrapper.getStreamForRowIndexInfo( );
			for ( int i = 0; i < offsetIndex.length; i++ )
				IOUtil.writeInt( outputStream, offsetIndex[i] );
			
			// save the data of group information
			// such a information is no use, since the order of the data for the
			// sub query may be changed a lot, and then the group information of
			// original sub query will be wholly invalid.
			IOUtil.writeInt( streamsWrapper.getStreamForGroupInfo( ), 0 );
		}
		catch ( IOException e )
		{
			throw new DataException( ResourceConstants.RD_SAVE_ERROR,
					e,
					"Result Data" );
		}
	}

}
