<commit_before>/*
 *************************************************************************
 * Copyright (c) 2006 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.report.data.adapter.impl;

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

import org.eclipse.birt.core.data.DataType;
import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IResultMetaData;
import org.eclipse.birt.data.engine.api.querydefn.GroupDefinition;
import org.eclipse.birt.data.engine.api.querydefn.QueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;
import org.eclipse.birt.data.engine.olap.api.cube.IDatasetIterator;
import org.eclipse.birt.report.data.adapter.api.DataRequestSession;
import org.eclipse.birt.report.model.api.LevelAttributeHandle;
import org.eclipse.birt.report.model.api.olap.CubeHandle;
import org.eclipse.birt.report.model.api.olap.DimensionHandle;
import org.eclipse.birt.report.model.api.olap.MeasureGroupHandle;
import org.eclipse.birt.report.model.api.olap.MeasureHandle;
import org.eclipse.birt.report.model.api.olap.TabularCubeHandle;
import org.eclipse.birt.report.model.api.olap.TabularDimensionHandle;
import org.eclipse.birt.report.model.api.olap.TabularHierarchyHandle;
import org.eclipse.birt.report.model.api.olap.TabularLevelHandle;

/**
 * This is an implementation of IDatasetIterator interface.
 *
 */
public class DataSetIterator implements IDatasetIterator
{

	//
	private boolean started = false;
	private IResultIterator it;
	private ResultMeta metadata;

	/**
	 * Create DataSetIterator for a hierarchy.
	 * 
	 * @param session
	 * @param hierHandle
	 * @throws BirtException
	 */
	public DataSetIterator( DataRequestSession session,
			TabularHierarchyHandle hierHandle ) throws BirtException
	{
		QueryDefinition query = new QueryDefinition( );
		query.setUsesDetails( true );

		query.setDataSetName( hierHandle.getDataSet( ).getName( ) );

		List resultMetaList = new ArrayList( );
		Map levelNameColumnNamePair = new HashMap( );

		this.prepareLevels( query,
				resultMetaList,
				levelNameColumnNamePair,
				hierHandle );

		this.it = session.prepare( query ).execute( null ).getResultIterator( );
		this.populateMeta( levelNameColumnNamePair, resultMetaList );
	}

	/**
	 * Create DataSetIterator for fact table.
	 * 
	 * @param session
	 * @param cubeHandle
	 * @throws BirtException
	 */
	public DataSetIterator( DataRequestSession session,
			TabularCubeHandle cubeHandle ) throws BirtException
	{
		QueryDefinition query = new QueryDefinition( );

		query.setUsesDetails( true );
		query.setDataSetName( cubeHandle.getDataSet( ).getName( ) );

		List dimensions = cubeHandle.getContents( CubeHandle.DIMENSIONS_PROP );
		List resultMetaList = new ArrayList( );
		HashMap levelNameColumnNamePair = new HashMap( );
		if ( dimensions != null )
		{
			for ( int i = 0; i < dimensions.size( ); i++ )
			{
				TabularDimensionHandle dimension = (TabularDimensionHandle) dimensions.get( i );
				List hiers = dimension.getContents( DimensionHandle.HIERARCHIES_PROP );

				//By now we only support one hierarchy per dimension.
				assert hiers.size( ) == 1;

				TabularHierarchyHandle hierHandle = (TabularHierarchyHandle) hiers.get( 0 );

				if ( hierHandle.getDataSet( ) == null
						|| hierHandle.getDataSet( )
								.getName( )
								.equals( cubeHandle.getDataSet( ).getName( ) ) )
				{
					prepareLevels( query,
							resultMetaList,
							levelNameColumnNamePair,
							hierHandle );
				}
				else
				{
					//TODO need model support.
					/*//Use different data set
					 Iterator it = cubeHandle.joinConditionsIterator( );
					 DimensionConditionHandle dimCondHandle = (DimensionConditionHandle) it.next( );
					 
					 if ( dimCondHandle.getHierarchy( ).equals( hierHandle ))
					 {
					 dimCondHandle.getPrimaryKeys( )
					 }*/
				}

			}
		}

		prepareMeasure( cubeHandle, query, resultMetaList );

		this.it = session.prepare( query ).execute( null ).getResultIterator( );

		populateMeta( levelNameColumnNamePair, resultMetaList );

	}

	/**
	 * 
	 * @param cubeHandle
	 * @param query
	 * @param resultMetaList
	 */
	private void prepareMeasure( TabularCubeHandle cubeHandle,
			QueryDefinition query, List resultMetaList )
	{
		List measureGroups = cubeHandle.getContents( CubeHandle.MEASURE_GROUPS_PROP );
		for ( int i = 0; i < measureGroups.size( ); i++ )
		{
			MeasureGroupHandle mgh = (MeasureGroupHandle) measureGroups.get( i );
			List measures = mgh.getContents( MeasureGroupHandle.MEASURES_PROP );
			for ( int j = 0; j < measures.size( ); j++ )
			{
				MeasureHandle measure = (MeasureHandle) measures.get( j );
				String function = measure.getFunction( );
				if ( query.getGroups( ).size( ) > 0 )
				{
					ScriptExpression se = populateExpression( query,
							measure,
							function );

					query.addResultSetExpression( measure.getName( ), se );
				}
				else
				{
					query.addResultSetExpression( measure.getName( ),
							new ScriptExpression( measure.getMeasureExpression( ) ) );
				}

				ColumnMeta meta = new ColumnMeta( measure.getName( ) );
				//TODO after model finish support measure type, use data type defined in
				//measure handle.
				meta.setDataType( DataType.DOUBLE_TYPE );
				resultMetaList.add( meta );
			}
		}
	}

	/**
	 * 
	 * @param query
	 * @param measure
	 * @param function
	 * @return
	 */
	private ScriptExpression populateExpression( QueryDefinition query,
			MeasureHandle measure, String function )
	{
		ScriptExpression se = null;
		if ( function.equals( "sum" ) )
		{
			se = new ScriptExpression( "Total.sum("
					+ measure.getMeasureExpression( ) + ",null,"
					+ query.getGroups( ).size( ) + ")" );

		}
		else if ( function.equals( "count" ) )
		{
			se = new ScriptExpression( "Total.count("
					+ "null," + query.getGroups( ).size( ) + ")" );
		}
		else if ( function.equals( "min" ) )
		{
			se = new ScriptExpression( "Total.min("
					+ measure.getMeasureExpression( ) + ",null,"<commit_msg>CheckIN:Fix 180114 Exception is thrown out when preview a report with a crosstable [1102]<commit_after>/*
 *************************************************************************
 * Copyright (c) 2006 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.report.data.adapter.impl;

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

import org.eclipse.birt.core.data.DataType;
import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.data.engine.api.IResultIterator;
import org.eclipse.birt.data.engine.api.IResultMetaData;
import org.eclipse.birt.data.engine.api.querydefn.GroupDefinition;
import org.eclipse.birt.data.engine.api.querydefn.QueryDefinition;
import org.eclipse.birt.data.engine.api.querydefn.ScriptExpression;
import org.eclipse.birt.data.engine.olap.api.cube.IDatasetIterator;
import org.eclipse.birt.report.data.adapter.api.DataRequestSession;
import org.eclipse.birt.report.model.api.LevelAttributeHandle;
import org.eclipse.birt.report.model.api.olap.CubeHandle;
import org.eclipse.birt.report.model.api.olap.DimensionHandle;
import org.eclipse.birt.report.model.api.olap.MeasureGroupHandle;
import org.eclipse.birt.report.model.api.olap.MeasureHandle;
import org.eclipse.birt.report.model.api.olap.TabularCubeHandle;
import org.eclipse.birt.report.model.api.olap.TabularDimensionHandle;
import org.eclipse.birt.report.model.api.olap.TabularHierarchyHandle;
import org.eclipse.birt.report.model.api.olap.TabularLevelHandle;

/**
 * This is an implementation of IDatasetIterator interface.
 *
 */
public class DataSetIterator implements IDatasetIterator
{

	//
	private boolean started = false;
	private IResultIterator it;
	private ResultMeta metadata;

	/**
	 * Create DataSetIterator for a hierarchy.
	 * 
	 * @param session
	 * @param hierHandle
	 * @throws BirtException
	 */
	public DataSetIterator( DataRequestSession session,
			TabularHierarchyHandle hierHandle ) throws BirtException
	{
		QueryDefinition query = new QueryDefinition( );
		query.setUsesDetails( true );

		query.setDataSetName( hierHandle.getDataSet( ).getName( ) );

		List resultMetaList = new ArrayList( );
		Map levelNameColumnNamePair = new HashMap( );

		this.prepareLevels( query,
				resultMetaList,
				levelNameColumnNamePair,
				hierHandle );

		this.it = session.prepare( query ).execute( null ).getResultIterator( );
		this.populateMeta( levelNameColumnNamePair, resultMetaList );
	}

	/**
	 * Create DataSetIterator for fact table.
	 * 
	 * @param session
	 * @param cubeHandle
	 * @throws BirtException
	 */
	public DataSetIterator( DataRequestSession session,
			TabularCubeHandle cubeHandle ) throws BirtException
	{
		QueryDefinition query = new QueryDefinition( );

		query.setUsesDetails( true );
		query.setDataSetName( cubeHandle.getDataSet( ).getName( ) );

		List dimensions = cubeHandle.getContents( CubeHandle.DIMENSIONS_PROP );
		List resultMetaList = new ArrayList( );
		HashMap levelNameColumnNamePair = new HashMap( );
		if ( dimensions != null )
		{
			for ( int i = 0; i < dimensions.size( ); i++ )
			{
				TabularDimensionHandle dimension = (TabularDimensionHandle) dimensions.get( i );
				List hiers = dimension.getContents( DimensionHandle.HIERARCHIES_PROP );

				//By now we only support one hierarchy per dimension.
				assert hiers.size( ) == 1;

				TabularHierarchyHandle hierHandle = (TabularHierarchyHandle) hiers.get( 0 );

				if ( hierHandle.getDataSet( ) == null
						|| hierHandle.getDataSet( )
								.getName( )
								.equals( cubeHandle.getDataSet( ).getName( ) ) )
				{
					prepareLevels( query,
							resultMetaList,
							levelNameColumnNamePair,
							hierHandle );
				}
				else
				{
					//TODO need model support.
					/*//Use different data set
					 Iterator it = cubeHandle.joinConditionsIterator( );
					 DimensionConditionHandle dimCondHandle = (DimensionConditionHandle) it.next( );
					 
					 if ( dimCondHandle.getHierarchy( ).equals( hierHandle ))
					 {
					 dimCondHandle.getPrimaryKeys( )
					 }*/
				}

			}
		}

		prepareMeasure( cubeHandle, query, resultMetaList );

		this.it = session.prepare( query ).execute( null ).getResultIterator( );

		populateMeta( levelNameColumnNamePair, resultMetaList );

	}

	/**
	 * 
	 * @param cubeHandle
	 * @param query
	 * @param resultMetaList
	 */
	private void prepareMeasure( TabularCubeHandle cubeHandle,
			QueryDefinition query, List resultMetaList )
	{
		List measureGroups = cubeHandle.getContents( CubeHandle.MEASURE_GROUPS_PROP );
		for ( int i = 0; i < measureGroups.size( ); i++ )
		{
			MeasureGroupHandle mgh = (MeasureGroupHandle) measureGroups.get( i );
			List measures = mgh.getContents( MeasureGroupHandle.MEASURES_PROP );
			for ( int j = 0; j < measures.size( ); j++ )
			{
				MeasureHandle measure = (MeasureHandle) measures.get( j );
				String function = measure.getFunction( );
				if ( query.getGroups( ).size( ) > 0 )
				{
					ScriptExpression se = populateExpression( query,
							measure,
							function );

					query.addResultSetExpression( measure.getName( ), se );
				}
				else
				{
					query.addResultSetExpression( measure.getName( ),
							new ScriptExpression( measure.getMeasureExpression( ) ) );
				}

				ColumnMeta meta = new ColumnMeta( measure.getName( ) );
				//TODO after model finish support measure type, use data type defined in
				//measure handle.
				meta.setDataType( DataType.DOUBLE_TYPE );
				resultMetaList.add( meta );
			}
		}
	}

	/**
	 * 
	 * @param query
	 * @param measure
	 * @param function
	 * @return
	 */
	private ScriptExpression populateExpression( QueryDefinition query,
			MeasureHandle measure, String function )
	{
		ScriptExpression se = null;
		
		if ( function == null || function.equals( "sum" ) )
		{
			se = new ScriptExpression( "Total.sum("
					+ measure.getMeasureExpression( ) + ",null,"
					+ query.getGroups( ).size( ) + ")" );

		}
		else if ( function.equals( "count" ) )
		{
			se = new ScriptExpression( "Total.count("
					+ "null," + query.getGroups( ).size( ) + ")" );
		}
		else if ( function.equals( "min" ) )
		{
			se = new ScriptExpression( "Total.min("
					+ measure.getMeasureExpression( ) + ",null,"
{'fraction_non_alphanumeric': 0.1310500564546481, 'fraction_numerical': 0.002860368837034249, 'mean_word_length': 3.7671331180480805, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, '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': '4160025', 'n_tokens_mistral': 4594, 'n_tokens_neox': 3899, 'n_words': 876}