<commit_before>/*
 *************************************************************************
 * 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;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.birt.core.data.DataTypeUtil;
import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.script.ScriptContext;
import org.eclipse.birt.core.util.IOUtil;
import org.eclipse.birt.data.engine.api.DataEngineContext;
import org.eclipse.birt.data.engine.api.IBaseExpression;
import org.eclipse.birt.data.engine.api.IBaseQueryDefinition;
import org.eclipse.birt.data.engine.api.IBinding;
import org.eclipse.birt.data.engine.api.IDataScriptEngine;
import org.eclipse.birt.data.engine.api.IQueryResults;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IResultMetaData;
import org.eclipse.birt.data.engine.api.IShutdownListener;
import org.eclipse.birt.data.engine.api.ISubqueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.BaseQueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.Binding;
import org.eclipse.birt.data.engine.api.querydefn.GroupDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;
import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.core.security.FileSecurity;
import org.eclipse.birt.data.engine.executor.ResultClass;
import org.eclipse.birt.data.engine.expression.ExpressionCompilerUtil;
import org.eclipse.birt.data.engine.i18n.ResourceConstants;
import org.eclipse.birt.data.engine.impl.PreparedSubquery.SubQueryExecutor;
import org.eclipse.birt.data.engine.impl.document.IDInfo;
import org.eclipse.birt.data.engine.impl.document.IRDSave;
import org.eclipse.birt.data.engine.impl.document.QueryResultInfo;
import org.eclipse.birt.data.engine.impl.document.RDUtil;
import org.eclipse.birt.data.engine.odi.IResultClass;
import org.eclipse.birt.data.engine.odi.IResultObject;
import org.eclipse.birt.data.engine.script.ScriptEvalUtil;
import org.mozilla.javascript.Scriptable;

/**
 * An iterator on a result set from a prepared and executed report query.
 * Multiple ResultIterator objects could be associated with the same
 * QueryResults object.
 */
public class ResultIterator implements IResultIterator
{
	private RDSaveHelper 			rdSaveHelper;
	private Scriptable 				scope;
	
	protected org.eclipse.birt.data.engine.odi.IResultIterator odiResult;
	
	// needed service
	private IServiceForResultSet 	resultService;
	
	// util to findGroup
	private GroupUtil 				groupUtil;
	
	// util to get row id
	protected RowIDUtil 				rowIDUtil;
	
	// used for evaluate binding column value
	private Map 					boundColumnValueMap = new HashMap( );
	private BindingColumnsEvalUtil 	bindingColumnsEvalUtil;
	
	private boolean isFirstNext = true;
	
	private OutputStream metaOutputStream = null;
	private DataOutputStream rowOutputStream = null;
	
	// log instance
	private static Logger logger = Logger.getLogger( ResultIterator.class.getName( ) );

	private List columnList = null;
	private List preparedList = null;
	
	private int rawIdStartingValue = 0;
	
	private IShutdownListener listener;
	
	/**
	 * Constructor for report query (which produces a QueryResults)
	 * 
	 * @param context
	 * @param queryResults
	 * @param query
	 * @param odiResult
	 * @param scope
	 * @throws DataException
	 */
	ResultIterator( IServiceForResultSet rService,
			org.eclipse.birt.data.engine.odi.IResultIterator odiResult,
			Scriptable scope, int rawIdStartingValue ) throws DataException
	{
		Object[] params = {
				rService, odiResult, scope
		};
		logger.entering( ResultIterator.class.getName( ),
				"ResultIterator",
				params );
		assert rService != null
				&& rService.getQueryResults( ) != null && odiResult != null
				&& scope != null;

		this.resultService = rService;
		this.odiResult = odiResult;
		this.scope = scope;
		this.rawIdStartingValue = rawIdStartingValue;
		
		if ( rService.getSession( ).getEngineContext( ).getMode( ) == DataEngineContext.MODE_GENERATION
				|| rService.getSession( ).getEngineContext( ).getMode( ) == DataEngineContext.DIRECT_PRESENTATION )
			this.validateManualBindingExpressions( this.resultService.getQueryDefn( )
					.getBindings( ) );
		if( needCache() && !this.isEmpty( ) )
		{
			try 
			{
				createCacheOutputStream( );
				saveMetaData( );
				IOUtil.writeInt(this.rowOutputStream, this.odiResult.getRowCount());
			} 
			catch (IOException e) 
			{
				throw new DataException( ResourceConstants.CREATE_CACHE_TEMPFILE_ERROR );
			}
		}
		addEngineShutdownListener( );
		
		this.start( );
		prepareBindingColumnsEvalUtil( );
		prepareCurrentRow();
		
		logger.exiting( ResultIterator.class.getName( ), "ResultIterator" );
	}

	/**
	 * 
	 */
	private void addEngineShutdownListener( )
	{
		listener = new IShutdownListener( ) {

			public void dataEngineShutdown( )
			{
				try<commit_msg>CheckIn:Fix an issue which might cause NPE in stress test[15571]<commit_after>/*
 *************************************************************************
 * 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;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.birt.core.data.DataTypeUtil;
import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.script.ScriptContext;
import org.eclipse.birt.core.util.IOUtil;
import org.eclipse.birt.data.engine.api.DataEngineContext;
import org.eclipse.birt.data.engine.api.IBaseExpression;
import org.eclipse.birt.data.engine.api.IBaseQueryDefinition;
import org.eclipse.birt.data.engine.api.IBinding;
import org.eclipse.birt.data.engine.api.IDataScriptEngine;
import org.eclipse.birt.data.engine.api.IQueryResults;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IResultMetaData;
import org.eclipse.birt.data.engine.api.IShutdownListener;
import org.eclipse.birt.data.engine.api.ISubqueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.BaseQueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.Binding;
import org.eclipse.birt.data.engine.api.querydefn.GroupDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;
import org.eclipse.birt.data.engine.core.DataException;
import org.eclipse.birt.data.engine.core.security.FileSecurity;
import org.eclipse.birt.data.engine.executor.ResultClass;
import org.eclipse.birt.data.engine.expression.ExpressionCompilerUtil;
import org.eclipse.birt.data.engine.i18n.ResourceConstants;
import org.eclipse.birt.data.engine.impl.PreparedSubquery.SubQueryExecutor;
import org.eclipse.birt.data.engine.impl.document.IDInfo;
import org.eclipse.birt.data.engine.impl.document.IRDSave;
import org.eclipse.birt.data.engine.impl.document.QueryResultInfo;
import org.eclipse.birt.data.engine.impl.document.RDUtil;
import org.eclipse.birt.data.engine.odi.IResultClass;
import org.eclipse.birt.data.engine.odi.IResultObject;
import org.eclipse.birt.data.engine.script.ScriptEvalUtil;
import org.mozilla.javascript.Scriptable;

/**
 * An iterator on a result set from a prepared and executed report query.
 * Multiple ResultIterator objects could be associated with the same
 * QueryResults object.
 */
public class ResultIterator implements IResultIterator
{
	private RDSaveHelper 			rdSaveHelper;
	private Scriptable 				scope;
	
	protected org.eclipse.birt.data.engine.odi.IResultIterator odiResult;
	
	// needed service
	private IServiceForResultSet 	resultService;
	
	// util to findGroup
	private GroupUtil 				groupUtil;
	
	// util to get row id
	protected RowIDUtil 				rowIDUtil;
	
	// used for evaluate binding column value
	private Map 					boundColumnValueMap = new HashMap( );
	private BindingColumnsEvalUtil 	bindingColumnsEvalUtil;
	
	private boolean isFirstNext = true;
	
	private OutputStream metaOutputStream = null;
	private DataOutputStream rowOutputStream = null;
	
	// log instance
	private static Logger logger = Logger.getLogger( ResultIterator.class.getName( ) );

	private List columnList = null;
	private List preparedList = null;
	
	private int rawIdStartingValue = 0;
	
	private IShutdownListener listener;
	
	/**
	 * Constructor for report query (which produces a QueryResults)
	 * 
	 * @param context
	 * @param queryResults
	 * @param query
	 * @param odiResult
	 * @param scope
	 * @throws DataException
	 */
	ResultIterator( IServiceForResultSet rService,
			org.eclipse.birt.data.engine.odi.IResultIterator odiResult,
			Scriptable scope, int rawIdStartingValue ) throws DataException
	{
		Object[] params = {
				rService, odiResult, scope
		};
		logger.entering( ResultIterator.class.getName( ),
				"ResultIterator",
				params );
		assert rService != null
				&& rService.getQueryResults( ) != null && odiResult != null
				&& scope != null;

		this.resultService = rService;
		this.odiResult = odiResult;
		this.scope = scope;
		this.rawIdStartingValue = rawIdStartingValue;
		
		if ( rService.getSession( ).getEngineContext( ).getMode( ) == DataEngineContext.MODE_GENERATION
				|| rService.getSession( ).getEngineContext( ).getMode( ) == DataEngineContext.DIRECT_PRESENTATION )
			this.validateManualBindingExpressions( this.resultService.getQueryDefn( )
					.getBindings( ) );
		if( needCache() && !this.isEmpty( ) )
		{
			try 
			{
				createCacheOutputStream( );
				saveMetaData( );
				IOUtil.writeInt(this.rowOutputStream, this.odiResult.getRowCount());
			} 
			catch (IOException e) 
			{
				throw new DataException( ResourceConstants.CREATE_CACHE_TEMPFILE_ERROR );
			}
		}
		
		this.start( );
		prepareBindingColumnsEvalUtil( );
		prepareCurrentRow();

		// add shutdown listener when initial work has been done.
		addEngineShutdownListener( );
		
		logger.exiting( ResultIterator.class.getName( ), "ResultIterator" );
	}

	/**
	 * 
	 */
	private void addEngineShutdownListener( )
	{
		listener = new IShutdownListener( ) {

			public void dataEngineShutdown( )
			{
				try
{'fraction_non_alphanumeric': 0.1246411079209593, 'fraction_numerical': 0.0022800202668468166, 'mean_word_length': 4.682821497120921, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2280932', 'n_tokens_mistral': 3806, 'n_tokens_neox': 3495, 'n_words': 725}