<commit_before>/*******************************************************************************
 * Copyright (c) 2008 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.chart.reportitem;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.olap.OLAPException;
import javax.olap.cursor.EdgeCursor;
import javax.olap.cursor.RowDataNavigation;

import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.impl.ChartModelHelper;
import org.eclipse.birt.chart.reportitem.i18n.Messages;
import org.eclipse.birt.chart.reportitem.plugin.ChartReportItemPlugin;
import org.eclipse.birt.chart.util.ChartUtil;
import org.eclipse.birt.chart.util.ChartExpressionUtil.ExpressionCodec;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.data.engine.olap.api.ICubeCursor;
import org.eclipse.birt.data.engine.olap.api.ICubeQueryResults;
import org.eclipse.birt.data.engine.olap.api.query.IBaseCubeQueryDefinition;
import org.eclipse.birt.data.engine.olap.api.query.ICubeQueryDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IDimensionDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IEdgeDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IHierarchyDefinition;
import org.eclipse.birt.data.engine.olap.api.query.ILevelDefinition;
import org.eclipse.birt.report.engine.extension.ICubeResultSet;

/**
 * The class implements evaluating for sharing xtab or chart view for xtab.
 */

public class SharedCubeResultSetEvaluator extends BIRTCubeResultSetEvaluator
{

	private int fRowInnerLevelIndex;
	private int fColInnerLevelIndex;

	private CursorPositionNode fMainPositionNodes;
	private CursorPositionNode fSubPositionNodes;
	private boolean fIsColEdgeAsMainCursor;

	/**
	 * Constructor.
	 * 
	 * @param rs
	 * @param cm
	 */
	public SharedCubeResultSetEvaluator( ICubeResultSet rs, Chart cm )
	{
		super( rs );
		parseLevelIndex( rs.getCubeQuery( ), cm );
	}

	/**
	 * Constructor.
	 * 
	 * @param qr
	 * @param queryDefinition
	 * @param cm
	 */
	public SharedCubeResultSetEvaluator( ICubeQueryResults qr,
			IBaseCubeQueryDefinition queryDefinition, Chart cm )
			throws BirtException
	{
		super( qr );
		parseLevelIndex( queryDefinition, cm );
	}

	/**
	 * Parse the dimension levels on row edge and column edge to find out the
	 * level index used by category series and Y optional.
	 * 
	 * @param queryDefintion
	 * @param cm
	 */
	private void parseLevelIndex( IBaseCubeQueryDefinition queryDefintion,
			Chart cm )
	{
		fRowInnerLevelIndex = -1;
		fColInnerLevelIndex = -1;
		if ( queryDefintion instanceof ICubeQueryDefinition )
		{
			List rowLevelNames = Collections.EMPTY_LIST;
			List colLevelNames = Collections.EMPTY_LIST;

			String[] categoryExprs = ChartUtil.getCategoryExpressions( cm );

			ICubeQueryDefinition cqd = (ICubeQueryDefinition) queryDefintion;
			IEdgeDefinition rowED = cqd.getEdge( ICubeQueryDefinition.ROW_EDGE );
			IEdgeDefinition colED = cqd.getEdge( ICubeQueryDefinition.COLUMN_EDGE );
			if ( rowED != null )
			{
				rowLevelNames = getLevelNames( rowED );
				if ( categoryExprs != null && categoryExprs.length > 0 )
				{
					fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
							rowLevelNames );
					if ( fRowInnerLevelIndex < 0 && colED != null )
					{
						// Row level isn't find on row edge, find it on column
						// edge.
						rowLevelNames = getLevelNames( colED );
						fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
								rowLevelNames );
						fIsColEdgeAsMainCursor = true;
						return;
					}
				}
			}

			if ( colED != null )
			{
				if ( rowED == null && fRowInnerLevelIndex < 0 )
				{
					// Only column edge is defined on xtab, find row level index
					// on column edge.
					rowLevelNames = getLevelNames( colED );
					if ( categoryExprs != null && categoryExprs.length > 0 )
					{
						fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
								rowLevelNames );
						fIsColEdgeAsMainCursor = true;
					}
				}
				else
				{
					colLevelNames = getLevelNames( colED );
					String[] yOptionalExprs = ChartUtil.getYOptoinalExpressions( cm );
					if ( yOptionalExprs != null && yOptionalExprs.length > 0 )
					{
						fColInnerLevelIndex = findInnerLevelIndex( yOptionalExprs[0],
								colLevelNames );
					}
				}
			}
		}
	}


	/**
	 * Find the inner level index from specified expression.
	 * 
	 * @param expr
	 * @return
	 */
	private int findInnerLevelIndex( String expr, List<String> levelNames )
	{
		int index = -1;
		if ( ChartUtil.isEmpty( expr ) )
		{
			return index;
		}

		ExpressionCodec exprCodec = ChartModelHelper.instance( )
				.createExpressionCodec( );
		Collection<String> bindingNames = exprCodec.getBindingNames( expr );

		for ( String bindName : bindingNames )
		{
			int levelIndex = levelNames.indexOf( bindName );
			if ( levelIndex > index )
			{
				index = levelIndex;
			}
		}

		return index;
	}

	/**
	 * Returns level names in edge definition.
	 * 
	 * @param ed
	 * @return
	 */
	private List getLevelNames( IEdgeDefinition ed )
	{
		List levelNames = new ArrayList( );
		List<IDimensionDefinition> dimensions = ed.getDimensions( );
		for ( IDimensionDefinition d : dimensions )
		{
			List<IHierarchyDefinition> hieDefs = d.getHierarchy( );<commit_msg>- Summary: Fix a bug of parsing cube expression in cube result set evaluator.(#28128)<commit_after>/*******************************************************************************
 * Copyright (c) 2008 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.chart.reportitem;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.olap.OLAPException;
import javax.olap.cursor.EdgeCursor;
import javax.olap.cursor.RowDataNavigation;

import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.impl.ChartModelHelper;
import org.eclipse.birt.chart.reportitem.i18n.Messages;
import org.eclipse.birt.chart.reportitem.plugin.ChartReportItemPlugin;
import org.eclipse.birt.chart.util.ChartExpressionUtil.ExpressionCodec;
import org.eclipse.birt.chart.util.ChartUtil;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.data.engine.api.IScriptExpression;
import org.eclipse.birt.data.engine.api.querydefn.Binding;
import org.eclipse.birt.data.engine.olap.api.ICubeCursor;
import org.eclipse.birt.data.engine.olap.api.ICubeQueryResults;
import org.eclipse.birt.data.engine.olap.api.query.IBaseCubeQueryDefinition;
import org.eclipse.birt.data.engine.olap.api.query.ICubeQueryDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IDimensionDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IEdgeDefinition;
import org.eclipse.birt.data.engine.olap.api.query.IHierarchyDefinition;
import org.eclipse.birt.data.engine.olap.api.query.ILevelDefinition;
import org.eclipse.birt.report.engine.extension.ICubeResultSet;

/**
 * The class implements evaluating for sharing xtab or chart view for xtab.
 */

public class SharedCubeResultSetEvaluator extends BIRTCubeResultSetEvaluator
{

	private int fRowInnerLevelIndex;
	private int fColInnerLevelIndex;

	private CursorPositionNode fMainPositionNodes;
	private CursorPositionNode fSubPositionNodes;
	private boolean fIsColEdgeAsMainCursor;

	/**
	 * Constructor.
	 * 
	 * @param rs
	 * @param cm
	 */
	public SharedCubeResultSetEvaluator( ICubeResultSet rs, Chart cm )
	{
		super( rs );
		parseLevelIndex( rs.getCubeQuery( ), cm );
	}

	/**
	 * Constructor.
	 * 
	 * @param qr
	 * @param queryDefinition
	 * @param cm
	 */
	public SharedCubeResultSetEvaluator( ICubeQueryResults qr,
			IBaseCubeQueryDefinition queryDefinition, Chart cm )
			throws BirtException
	{
		super( qr );
		parseLevelIndex( queryDefinition, cm );
	}

	/**
	 * Parse the dimension levels on row edge and column edge to find out the
	 * level index used by category series and Y optional.
	 * 
	 * @param queryDefintion
	 * @param cm
	 */
	private void parseLevelIndex( IBaseCubeQueryDefinition queryDefintion,
			Chart cm )
	{
		fRowInnerLevelIndex = -1;
		fColInnerLevelIndex = -1;
		if ( queryDefintion instanceof ICubeQueryDefinition )
		{
			List<String> rowLevelNames = Collections.emptyList( );
			List<String> colLevelNames = Collections.emptyList( );

			String[] categoryExprs = ChartUtil.getCategoryExpressions( cm );

			ICubeQueryDefinition cqd = (ICubeQueryDefinition) queryDefintion;
			IEdgeDefinition rowED = cqd.getEdge( ICubeQueryDefinition.ROW_EDGE );
			IEdgeDefinition colED = cqd.getEdge( ICubeQueryDefinition.COLUMN_EDGE );
			
			// Gets cube binding expressions map.
			Map<String, String> cubeBindingMap = new HashMap<String, String>();
			List bindingList = cqd.getBindings( );
			for ( int i = 0; i < bindingList.size( ); i++  )
			{
				Binding b = (Binding) bindingList.get( i );
				if ( b.getExpression( ) instanceof IScriptExpression )
				{
					cubeBindingMap.put( b.getBindingName( ), ((IScriptExpression)b.getExpression( )).getText( ) );
				}
			}
			
			if ( rowED != null )
			{
				rowLevelNames = getLevelNames( rowED );
				if ( categoryExprs != null && categoryExprs.length > 0 )
				{
					fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
							rowLevelNames, cubeBindingMap );
					if ( fRowInnerLevelIndex < 0 && colED != null )
					{
						// Row level isn't find on row edge, find it on column
						// edge.
						rowLevelNames = getLevelNames( colED );
						fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
								rowLevelNames, cubeBindingMap );
						fIsColEdgeAsMainCursor = true;
						return;
					}
				}
			}

			if ( colED != null )
			{
				if ( rowED == null && fRowInnerLevelIndex < 0 )
				{
					// Only column edge is defined on xtab, find row level index
					// on column edge.
					rowLevelNames = getLevelNames( colED );
					if ( categoryExprs != null && categoryExprs.length > 0 )
					{
						fRowInnerLevelIndex = findInnerLevelIndex( categoryExprs[0],
								rowLevelNames, cubeBindingMap );
						fIsColEdgeAsMainCursor = true;
					}
				}
				else
				{
					colLevelNames = getLevelNames( colED );
					String[] yOptionalExprs = ChartUtil.getYOptoinalExpressions( cm );
					if ( yOptionalExprs != null && yOptionalExprs.length > 0 )
					{
						fColInnerLevelIndex = findInnerLevelIndex( yOptionalExprs[0],
								colLevelNames, cubeBindingMap );
					}
				}
			}
		}
	}


	/**
	 * Find the inner level index from specified expression.
	 * 
	 * @param expr
	 * @param levelNames
	 * @param cubeBindingMap
	 * @return
	 */
	private int findInnerLevelIndex( String expr, List<String> levelNames, Map<String, String> cubeBindingMap )
	{
		int index = -1;
		if ( ChartUtil.isEmpty( expr ) )
		{
			return index;
		}

		ExpressionCodec exprCodec = ChartModelHelper.instance( )
				.createExpressionCodec( );
		Collection<String> bindingNames = exprCodec.getBindingNames( expr );
		for ( String bindName : bindingNames )
		{
			String cubeBindingExpr = cubeBindingMap.get( bindName );
			if( cubeBindingExpr == null )
			{
				continue;
			}
			String[] lNames = exprCodec.getLevelNames( cubeBindingExpr );
			for ( int i = 1; i < lNames.length; i++ )
			{
				int levelIndex = levelNames.indexOf( lNames[i] );
				if ( levelIndex > index )
				{
					index = levelIndex;
				}
			}
		}

		return index;
	}

	/**
	 * Returns level names in edge definition.
	 * 
	 * @param ed
	 * @return
	 */
	private List<String> getLevelNames( IEdgeDefinition ed )
	{
		List<String> levelNames = new ArrayList<String>( );
		List<IDimensionDefinition> dimensions = ed.getDimensions( );
		for ( IDimensionDefinition d : dimensions )
		{
			List<IHierarchyDefinition> hieDefs = d.getHierarchy( );
{'fraction_non_alphanumeric': 0.12142128794415248, 'fraction_numerical': 0.004000313750098047, 'mean_word_length': 3.7824456114028506, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, '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': '6547022', 'n_tokens_mistral': 4533, 'n_tokens_neox': 3853, 'n_words': 883}