/*******************************************************************************
 * 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.report.designer.data.ui.dataset;

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.data.engine.api.IBaseDataSetDesign;
import org.eclipse.birt.data.engine.api.IBaseDataSourceDesign;
import org.eclipse.birt.report.designer.data.ui.datasource.PropertyBindingPage;
import org.eclipse.birt.report.designer.data.ui.property.AbstractPropertyDialog;
import org.eclipse.birt.report.designer.data.ui.property.PropertyNode;
import org.eclipse.birt.report.designer.data.ui.util.DTPUtil;
import org.eclipse.birt.report.designer.data.ui.util.DataSetProvider;
import org.eclipse.birt.report.designer.data.ui.util.DataUIConstants;
import org.eclipse.birt.report.designer.data.ui.util.IHelpConstants;
import org.eclipse.birt.report.designer.data.ui.util.Utility;
import org.eclipse.birt.report.designer.internal.ui.util.ExceptionHandler;
import org.eclipse.birt.report.designer.nls.Messages;
import org.eclipse.birt.report.designer.ui.dialogs.properties.IPropertyPage;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.model.api.DataSetHandle;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.JointDataSetHandle;
import org.eclipse.birt.report.model.api.OdaDataSetHandle;
import org.eclipse.birt.report.model.api.OdaDataSourceHandle;
import org.eclipse.birt.report.model.api.ScriptDataSetHandle;
import org.eclipse.birt.report.model.api.activity.NotificationEvent;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.core.Listener;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.datatools.connectivity.oda.OdaException;
import org.eclipse.datatools.connectivity.oda.design.DataSetDesign;
import org.eclipse.datatools.connectivity.oda.design.DesignSessionResponse;
import org.eclipse.datatools.connectivity.oda.design.DesignerState;
import org.eclipse.datatools.connectivity.oda.design.ui.designsession.DataSetDesignSession;
import org.eclipse.datatools.connectivity.oda.design.ui.designsession.DesignSessionUtil;
import org.eclipse.datatools.connectivity.oda.design.ui.manifest.UIManifestExplorer;
import org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetEditorPage;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.preference.IPreferencePageContainer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.PropertyPage;

/**
 * Presents data set editor dialog.
 *  
 */

public class DataSetEditor extends AbstractPropertyDialog implements IPreferencePageContainer
{

	private ItemModelManager itemModelManager = new ItemModelManager( );
	private DataModelManager dataModelManager = new DataModelManager( );
	private DataSetDesignSession m_designSession = null;
	
	private boolean includeInputParameterPage = false;
	private boolean includeOutputParameterPage = false;
	private boolean needToFocusOnOutput = false;
	
	private HistoryToolBar historyBar;

	/**
	 * The constructor.
	 * 
	 * @param parentShell
	 */
	public DataSetEditor( Shell parentShell,  DataSetHandle ds, boolean needToFocusOnOutput )
	{
		super( parentShell ,ds );

		if ( !( ds instanceof JointDataSetHandle )
				&& ds.getDataSource( ) == null )
		{
			throw new RuntimeException( Messages.getFormattedString( "dataset.editor.error.noDataSource", new String[]{ds.getName( )} ) );//$NON-NLS-1$
		}
		
		this.needToFocusOnOutput = needToFocusOnOutput;
		// get the data source and dataset type from handle
		String dataSourceType, dataSetType;
		if ( ds instanceof OdaDataSetHandle )
		{
			OdaDataSourceHandle dataSource = (OdaDataSourceHandle) ( (OdaDataSetHandle) ds ).getDataSource( );
			dataSourceType = dataSource.getExtensionID( );
			dataSetType = ( (OdaDataSetHandle) ds ).getExtensionID( );
		}
		else if ( ds instanceof ScriptDataSetHandle )
		{
			dataSourceType = DataUIConstants.DATA_SOURCE_SCRIPT;
			dataSetType = DataUIConstants.DATA_SET_SCRIPT;
		}
		else if ( ds instanceof JointDataSetHandle )
		{
			dataSourceType = "";
			dataSetType = "";
			addJointDataSetPage( );
		}
		else
		{
			throw new RuntimeException( Messages.getFormattedString( "dataset.editor.error.noDataSource", new String[]{ds.getClass( ).getName( )} ) );//$NON-NLS-1$
		}
		
		// according to the data source type, get the extension point.If
		// extention is birt, populate birt page. or the ODA Custom page will be
		// populated.
		if ( !( ds instanceof JointDataSetHandle ) )
		{
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.datasourceselectionpage", Messages.getString( "dataset.editor.dataSource" ), null, new DataSetDataSourceSelectionPage( ) ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

			if ( DesignSessionUtil.hasValidOdaDesignUIExtension( dataSourceType ) )
			{
				addCustomPageODAV3( (OdaDataSetHandle) ds,
						dataSourceType,
						dataSetType );
			}

			else
				addBirtPage( dataSourceType, dataSetType );
		}
		// add common pages, just like computedColumn page, parameter page,
		// output column page etc.
		addCommonPage( ds );
		
		// start model manager to process the edit transaction
		itemModelManager.start( ds );
	}

	/**
	 * add page for org.eclipse.datatools.connectivity.oda.design.ui.dataSource
	 * @param dataSetHandle
	 */
	private void addCustomPageODAV3( OdaDataSetHandle dataSetHandle,
			String dataSourceType, String dataSetType )
	{
		try
		{
			m_designSession = DataSetDesignSession.startEditDesign( DTPUtil.getInstance( )
					.createDesignSessionRequest( dataSetHandle ) );
		}
		catch ( OdaException e )
		{
			// TODO Auto-generated catch block
			e.printStackTrace( );
		}
		if ( m_designSession != null )
			populateEditorPage( m_designSession, dataSourceType, dataSetType );

	}

	/**
	 * populate editor page
	 * 
	 * @param m_designSession
	 * @param dataSourceType
	 * @param dataSetType
	 */
	private void populateEditorPage( DataSetDesignSession m_designSession,
			String dataSourceType, String dataSetType )
	{
		try
		{
			DataSetEditorPage[] dataSetEditorPages = m_designSession.getEditorPages( );
			for ( int i = 0; i < dataSetEditorPages.length; i++ )
			{
				DataSetEditorPage dataSetEditorPage = dataSetEditorPages[i];
				PropertyPageWrapper propertyPageWrapper = new PropertyPageWrapper( dataSetEditorPage );

				addPageTo( dataSetEditorPage.getPagePath( ),
						dataSetEditorPage.getPageId( ),
						dataSetEditorPage.getTitle( ),
						null,
						propertyPageWrapper );

				if ( dataSetEditorPage.hasInitialFocus( ) )
					setDefaultNode( dataSetEditorPage.getPageId( ) );
			}
		}
		catch ( OdaException e )
		{
			ExceptionHandler.handle( e );
		}

		try
		{
			includeInputParameterPage = UIManifestExplorer.getInstance( )
					.getDataSetUIElement( dataSourceType, dataSetType )
					.supportsInParameters( );
			includeOutputParameterPage = UIManifestExplorer.getInstance( )
					.getDataSetUIElement( dataSourceType, dataSetType )
					.supportsOutParameters( );
		}
		catch ( OdaException ex )
		{
			ExceptionHandler.handle( ex );
		}
	}
	
	/**
	 * add several common use page for Birt data set editor
	 * 
	 * @param ds
	 */
	private void addCommonPage( DataSetHandle ds )
	{
		
		if ( ds instanceof ScriptDataSetHandle )
		{
			// Output column is replaced by column definition page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.outputcolumnpage", Messages.getString( "dataset.editor.outputColumns" ), null, new OutputColumnDefnPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Parameter page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.parameterspage", Messages.getString( "dataset.editor.parameters" ), null, new DataSetParametersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Parameter is removed
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.filterspage", Messages.getString( "dataset.editor.filters" ), null, new DataSetFiltersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Cache preference page
			addCachePreferencePage( ds );
			// Result set preview page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.resultsetpreviewpage", Messages.getString( "dataset.editor.preview" ), null, new ResultSetPreviewPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		}
		else if ( ds instanceof OdaDataSetHandle )
		{
			// Output column page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.outputcolumnpage", Messages.getString( "dataset.editor.outputColumns" ), null, new OutputColumnsPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Computed column page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.computedcolumnspage", Messages.getString( "dataset.editor.computedColumns" ), null, new DataSetComputedColumnsPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// flatfile driver need not parameter page to be displayed.
			if ( includeInputParameterPage )
				addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.parameterspage", Messages.getString( "dataset.editor.parameters" ), null, new DataSetParametersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$		
			// Filter page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.filterspage", Messages.getString( "dataset.editor.filters" ), null, new DataSetFiltersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Property binding page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.property", Messages.getString( "datasource.editor.property" ), null, new PropertyBindingPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Cache preference page
			addCachePreferencePage( ds );
			// Output parameters page
			if ( includeOutputParameterPage )
				addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.outputparameterpreviewpage", Messages.getString( "dataset.editor.outputparameters" ), null, new OutputParameterPreviewPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Result set preview page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.resultsetpreviewpage", Messages.getString( "dataset.editor.preview" ), null, new ResultSetPreviewPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		}
		else if ( ds instanceof JointDataSetHandle )
		{
			// Output column page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.outputcolumnpage", Messages.getString( "dataset.editor.outputColumns" ), null, new OutputColumnsPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Computed column page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.computedcolumnspage", Messages.getString( "dataset.editor.computedColumns" ), null, new DataSetComputedColumnsPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.parameterspage", Messages.getString( "dataset.editor.parameters" ), null, new DataSetParametersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Filter page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.filterspage", Messages.getString( "dataset.editor.filters" ), null, new DataSetFiltersPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// Result set preview page
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.resultsetpreviewpage", Messages.getString( "dataset.editor.preview" ), null, new ResultSetPreviewPage( ) );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		if ( needToFocusOnOutput )
			setDefaultNode( "org.eclipse.birt.datasource.editor.dataset.outputcolumnpage" );
	}
	
	/**
	 * 
	 * @param ds
	 */
	private void addCachePreferencePage( DataSetHandle ds )
	{
		IPropertyPage cachePage = new CachePreferencePage( );
		try
		{
			( (CachePreferencePage) cachePage ).setBaseDesign( getDataSetDesign( ds ),
					getDataSourceDesign( ds ) );
		}
		catch ( BirtException e )
		{
			// should not arrive here
		}
		finally
		{
			addPageTo( "/", "org.eclipse.birt.datasource.editor.dataset.cachePreferencepage", Messages.getString( "dataset.editor.settings" ), null, cachePage );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
	}
	
	/**
	 * 
	 * add joint data set page
	 */
	private void addJointDataSetPage( )
	{
		addPageTo( "/",
				"org.eclipse.birt.datasource.editor.dataset.jointDataSetPage",
				Messages.getString( "JointDataSetPage.query" ),
				null,
				new JointDataSetPage( Messages.getString( "dataset.editor.dataSource" ) ) );
	}

	/**
	 * add page for org.eclipse.birt.report.designer.ui.odadatasource
	 * @param dataSourceType
	 * @param dataSetType
	 */
	private void addBirtPage( String dataSourceType, String dataSetType )
	{
		try
		{
			IConfigurationElement element = DataSetProvider.findDataSetElement( dataSetType,
					dataSourceType );
			if ( element != null )
			{
				String supportParameterPage = element.getAttribute( "addsDataSetParametersPage" );
				if ( supportParameterPage != null )
					includeInputParameterPage = Boolean.valueOf( supportParameterPage )
							.booleanValue( );

				// Now get all the editor pages
				IConfigurationElement[] editorPages = element.getChildren( "dataSetEditorPage" );//$NON-NLS-1$
				if ( editorPages != null )
				{
					boolean hasFocus = false;
					for ( int n = 0; n < editorPages.length; n++ )
					{
						IPropertyPage page = (IPropertyPage) editorPages[n].createExecutableExtension( "class" );//$NON-NLS-1$
						addPageTo( editorPages[n].getAttribute( "path" ), editorPages[n].getAttribute( "name" ), editorPages[n].getAttribute( "displayName" ), null, page );//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						if ( hasFocus == false )
						{
							String initFocusAttr = editorPages[n].getAttribute( "initFocus" ); //$NON-NLS-1$
							if ( initFocusAttr != null
									&& initFocusAttr.equalsIgnoreCase( "true" ) ) //$NON-NLS-1$
							{
								setDefaultNode( editorPages[n].getAttribute( "name" ) ); //$NON-NLS-1$
								hasFocus = true;
							}
							else if ( n == editorPages.length - 1 )
							{
								setDefaultNode( editorPages[0].getAttribute( "name" ) ); //$NON-NLS-1$
							}
						}
					}
				}
			}
		}
		catch ( CoreException e1 )
		{
			ExceptionHandler.handle( e1 );
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractPropertyDialog#performOk()
	 */
	public boolean performOk( )
	{
		try
		{
			if ( m_designSession != null )
			{
				DTPUtil.getInstance( )
						.updateDataSetHandle( m_designSession.finish( )
								.getResponse( ),
								(OdaDataSetHandle) getHandle( ),
								false );
			}
		}
		catch ( OdaException e )
		{
			ExceptionHandler.handle( e );
		}

		itemModelManager.destory( false );
		return true;
	}
		
	/**
	 * 
	 * @param designerState
	 */
	public void updateROMDesignerState( DesignerState designerState )
	{
		dataModelManager.updateROMDesignerState( designerState,
				this.getHandle( ) );
	}

	/**
	 * update dataset design
	 * 
	 */
	public void updateDataSetDesign( String propName )
	{
		try
		{
			if ( m_designSession != null )
			{
                DesignSessionResponse response = 
                    m_designSession.finish( ).getResponse( );

                DataSetDesign dataSetDesign = response.getDataSetDesign( );
				dataModelManager.updateDataSetDesign( dataSetDesign,
						getHandle( ),
						propName );
				m_designSession = DataSetDesignSession.startEditDesign( 
                        DTPUtil.getInstance().createDesignSessionRequest( 
                                dataSetDesign, response.getDesignerState() ) );
				populateDataSetEditor( );
			}
		}
		catch ( OdaException e )
		{
			// TODO Auto-generated catch block
			e.printStackTrace( );
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractPropertyDialog#performCancel()
	 */
	public boolean performCancel( )
	{
		if ( m_designSession != null )
		{
			m_designSession.cancel( );
		}

		itemModelManager.destory( true );
		return true;
	}

	/**
	 * Returns the current model handle.
	 *  
	 */
	public DataSetHandle getHandle( )
	{
		return (DataSetHandle) getModel( );
	}
		
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite)
	 */
	protected Control createContents( Composite parent )
	{
		String title = Messages.getFormattedString(
				"dataset.edit", new String[]{getHandle( ).getName( )} );//$NON-NLS-1$
		getShell( ).setText( title );
		
		Control control = super.createContents( parent );
		Utility.setSystemHelp( control, IHelpConstants.CONEXT_ID_DATASET_EDIT );
		
		return control;
	}
	
	/**
	 * Gets all columns items from dataset list
	 * @return DataSetViewData[]
	 */
	public DataSetViewData[] getCurrentItemModel( )
	{
		return itemModelManager.getCurrentItemModel( );
	}

	/**
	 * Gets all columns items from dataset list
	 * 
	 * @param useColumnHint
	 * @param suppressErrorMessage
	 * @return DataSetViewData[]
	 */
	public DataSetViewData[] getCurrentItemModel( boolean useColumnHint,
			boolean suppressErrorMessage )
	{
		return itemModelManager.getCurrentItemModel( useColumnHint,
				suppressErrorMessage );
	}
	
	/**
	 * Set the modelChanged status to "true"
	 * 
	 */
	public void enableLinkedParamChanged( )
	{
		this.itemModelManager.enableLinkedParamChanged( );
	}

	/**
	 * @return if the model has changed or the weak-linked report parameter has
	 *         changed, return true;
	 */
	public boolean modelChanged( )
	{
		return this.itemModelManager.modelChanged( );
	}
	
	/**
	 * 
	 * @return
	 * @throws OdaException
	 */
	public DataSetDesign getCurrentDataSetDesign( ) throws OdaException
	{
		if ( m_designSession != null )
		{
			DesignSessionResponse response = m_designSession.finish( )
					.getResponse( );

			DataSetDesign dataSetDesign = response.getDataSetDesign( );

			m_designSession = DataSetDesignSession.startEditDesign( DTPUtil.getInstance( )
					.createDesignSessionRequest( dataSetDesign,
							response.getDesignerState( ) ) );
			populateDataSetEditor( );
			return dataSetDesign;
		}
		else
			return null;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.dialogs.Dialog#okPressed()
	 */
	protected void okPressed( )
	{
		super.okPressed( );
		
		try
		{
			DataSetUIUtil.updateColumnCache( this.getHandle( ) );

		}
		catch ( Exception e )
		{
			ExceptionHandler.handle( e );
		}
				
		//First call ok on all the pages
		if ( super.rootNode.hasSubNodes( ) )
		{
			PropertyNode[] nodes = rootNode.getSubNodes( );
			for ( int n = 0; n < nodes.length; n++ )
			{
				//Check whether the current page can be closed
				if ( nodes[n].getPage( ) instanceof DataSetParametersPage )
				{
					if ( viewer == null && viewer.getTree( ) == null )
						return;

					DataSetParametersPage page = (DataSetParametersPage) nodes[n].getPage( );
					if ( !page.canFinish( ) && !viewer.getTree( ).isDisposed( ) )
					{
						TreeItem firstNode = viewer.getTree( ).getItems( )[n];
						StructuredSelection select = new StructuredSelection( firstNode.getData( ) );
						viewer.setSelection( select );
						String name = ( (DataSetParametersPage) nodes[n].getPage( ) ).getNoneValuedParameterName( );
						this.setMessage( Messages.getFormattedString( "dataset.editor.error.noInputParameterDefaultValue",
								new Object[]{
									name
								} ),
								IMessageProvider.ERROR );
						return;
					}
				}
			}
		}
	}
		
	/**
	 * get data set design
	 * 
	 * @param ds
	 * @throws EngineException
	 */
	private IBaseDataSetDesign getDataSetDesign( DataSetHandle ds )
			throws BirtException
	{
		return DataSetProvider.getCurrentInstance( ).createDataSetDesign( ds );
	}

	/**
	 * get data source design
	 * 
	 * @param ds
	 * @throws EngineException
	 */
	private IBaseDataSourceDesign getDataSourceDesign( DataSetHandle ds )
			throws BirtException
	{
		return DataSetProvider.getCurrentInstance( )
				.createDataSourceDesign( ds.getDataSource( ) );
	}
	
	/**
	 * 
	 * @return
	 */
	public DataModelManager getDataModelManager( )
	{
		return this.dataModelManager;
	}
		
	/**
	 * get current PropertyPage
	 * @return
	 */
	private PropertyPage getCurrentPropertyPage( )
	{
		if ( getCurrentNode( ) != null )
		{
			IPropertyPage ipropertyPage = getCurrentNode( ).getPage( );
			if ( ipropertyPage instanceof PropertyPageWrapper )
				return ( (PropertyPageWrapper) ipropertyPage ).getPropertyPage( );
		}

		return null;
	}
	
	/**
	 * populate dataSetEditor page in design session
	 *
	 */
	private void populateDataSetEditor( )
	{
		if ( m_designSession == null )
		{
			return;
		}
		DataSetEditorPage[] dataSetEditorPages;
		try
		{
			dataSetEditorPages = m_designSession.getEditorPages( );
		}
		catch ( OdaException e )
		{
			return;
		}
		for ( int i = 0; i < dataSetEditorPages.length; i++ )
		{
			DataSetEditorPage dataSetEditorPage = dataSetEditorPages[i];
			PropertyPageWrapper propertyPageWrapper = new PropertyPageWrapper( dataSetEditorPage );

			// First call ok on all the pages
			if ( super.rootNode.hasSubNodes( ) )
			{
				PropertyNode[] nodes = rootNode.getSubNodes( );
				for ( int n = 0; n < nodes.length; n++ )
				{
					if ( nodes[n] != null
							&& nodes[n].getId( )
									.equals( dataSetEditorPage.getPageId( ) ) )
					{
						nodes[n].setPage( propertyPageWrapper );
						nodes[n].setContainer( this );
						nodes[n].createPageControl( getPropertyPane( ) );
					}
				}
			}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#getPreferenceStore()
	 */
	public IPreferenceStore getPreferenceStore( )
	{
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateButtons()
	 */
	public void updateButtons( )
	{
		PropertyPage propertyPage = getCurrentPropertyPage( );

		if ( propertyPage != null && getOkButton( ) != null )
			getOkButton( ).setEnabled( propertyPage.isValid( ) );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateMessage()
	 */
	public void updateMessage( )
	{
		PropertyPage propertyPage = getCurrentPropertyPage( );

		if ( propertyPage != null )
			setMessage( propertyPage.getMessage( ),
					propertyPage.getMessageType( ) );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateTitle()
	 */
	public void updateTitle( )
	{
		// TODO Auto-generated method stub
		
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractPropertyDialog#createTitleArea(org.eclipse.swt.widgets.Composite)
	 */
	public Composite createTitleArea( Composite parent )
	{
		GridLayout layout = (GridLayout) parent.getLayout( );
		layout.numColumns = 2;
		layout.marginHeight = 0;
		parent.setLayout( layout );

		createMessageComposite( parent );
		createToolbarComposite( parent );

		return null;
	}
	
	/**
	 * 
	 * @param parent
	 */
	private void createMessageComposite( Composite parent )
	{
		super.createTitleArea( parent );
	}
	
	/**
	 * 
	 * @param parent
	 */
	private void createToolbarComposite( Composite parent )
	{
		historyBar = new HistoryToolBar( parent, viewer, SWT.FLAT
				| SWT.HORIZONTAL );
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.birt.report.designer.ui.dialogs.properties.AbstractPropertyDialog#showSelectionPage(org.eclipse.birt.report.designer.ui.dialogs.properties.PropertyNode)
	 */
	public void showSelectionPage( PropertyNode selectedNode )
	{
		super.showSelectionPage( selectedNode );

		if ( super.showPage && historyBar != null )
			historyBar.addHistoryNode( selectedNode );
	}	

	/**
	 * whether support input parameter
	 * @return
	 */
	public boolean supportsInParameters( )
	{
		return this.includeInputParameterPage;
	}

	/**
	 * whether support output parameter
	 * @return
	 */
	public boolean supportsOutputParameters( )
	{
		return this.includeOutputParameterPage;
	}
		
	/**
	 * Helper class which is a itemModel manager.
	 */
	private static class ItemModelManager implements Listener
	{
		private DataSetHandle ds = null;
		private boolean itemModelChanged = true;
		private boolean linkedParameterChanged = true;
		private DataSetViewData[] savedItemModel = null;
		private String savedQueryText = null;
		
		/**
		 * Start action
		 * @param ds model to be listened
		 */
		public void start( DataSetHandle dataSet )
		{
			assert dataSet != null;
			
			this.ds = dataSet;

			if ( ds instanceof OdaDataSetHandle )
				this.savedQueryText = (( OdaDataSetHandle )ds).getQueryText();
			
			this.savedItemModel = DataSetProvider.getCurrentInstance( ).getCachedDataSetItemModel( ds );//.getDataSetItemModel( ds );
			
			this.ds.addListener(this);
		}
		
		/**
		 * Destroy action
		 * @param rollback
		 * 		true: rollback to savedItemModel
		 * 		false: do nothing 
		 */
		public void destory( boolean rollback )
		{
			if ( rollback )
			{
				if ( ds instanceof OdaDataSetHandle )
				{
					try
					{
						( (OdaDataSetHandle) ds ).setQueryText( this.savedQueryText );
						DataSetProvider.getCurrentInstance( )
								.getDataSetDesign( ds, true, true );
						
					}
					catch ( SemanticException e )
					{
						//should not arrive here.
					}
					catch ( BirtException e )
					{
						//should not arrive here
					}
				}
				
				DataSetProvider.getCurrentInstance( ).setModelOfDataSetHandle( this.ds, savedItemModel );
			}
			ds.removeListener( this );
		}
		
		/*
		 * @see org.eclipse.birt.report.model.api.core.Listener#elementChanged(org.eclipse.birt.report.model.api.DesignElementHandle,
		 *      org.eclipse.birt.report.model.api.activity.NotificationEvent)
		 */
		public void elementChanged( DesignElementHandle focus, NotificationEvent ev )
		{
			itemModelChanged = true;
		}
		
		/**
		 * Set the linked parameter changed status to 'true'
		 *
		 */
		public void enableLinkedParamChanged( )
		{
			linkedParameterChanged = true;
		}
		
		/**
		 * 
		 * @return the model changed or not
		 */
		public boolean modelChanged( )
		{
			return this.itemModelChanged || linkedParameterChanged;
		}
		
		/**
		 * Gets all columns items from dataset list
		 * @return DataSetItemModel[]
		 */
		public DataSetViewData[] getCurrentItemModel( )
		{
			DataSetViewData[] dataSetItem = DataSetProvider.getCurrentInstance( )
					.getColumns( ds, itemModelChanged );
			itemModelChanged = false;
			linkedParameterChanged = false;
			return dataSetItem;
		}
		
		/**
		 * Gets all columns items from dataset list
		 * @param useColumnHint
		 * @param suppressErrorMessage
		 * @return DataSetItemModel[]
		 */
		public DataSetViewData[] getCurrentItemModel( boolean useColumnHint, boolean suppressErrorMessage )
		{
			DataSetViewData[] dataSetItem = DataSetProvider.getCurrentInstance( )
					.getColumns( ds,
							itemModelChanged,
							useColumnHint,
							suppressErrorMessage );
			itemModelChanged = false;
			linkedParameterChanged = false;
			return dataSetItem;
		}
		
	}
}