/*******************************************************************************
 * 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.model.extension;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.birt.report.model.api.DesignFileException;
import org.eclipse.birt.report.model.api.OdaDataSetHandle;
import org.eclipse.birt.report.model.api.OdaDataSourceHandle;
import org.eclipse.birt.report.model.api.elements.ReportDesignConstants;
import org.eclipse.birt.report.model.api.metadata.IChoiceSet;
import org.eclipse.birt.report.model.api.metadata.IPropertyDefn;
import org.eclipse.birt.report.model.core.DesignElement;
import org.eclipse.birt.report.model.elements.DataSource;
import org.eclipse.birt.report.model.elements.OdaDataSet;
import org.eclipse.birt.report.model.elements.OdaDataSource;
import org.eclipse.birt.report.model.elements.SimpleDataSet;
import org.eclipse.birt.report.model.i18n.ThreadResources;
import org.eclipse.birt.report.model.metadata.AddOnExtensionLoader;
import org.eclipse.birt.report.model.metadata.ElementDefn;
import org.eclipse.birt.report.model.metadata.ElementPropertyDefn;
import org.eclipse.birt.report.model.metadata.ExtensionElementDefn;
import org.eclipse.birt.report.model.metadata.MetaDataDictionary;
import org.eclipse.birt.report.model.metadata.PropertyType;
import org.eclipse.birt.report.model.util.BaseTestCase;

import com.ibm.icu.util.ULocale;

/**
 * Tests the extension pointer of org.eclipse.birt.report.model.odaDriverModel.
 * <p>
 * Note: This test case is for Add-On extension point. Now no such extension
 * point is defined , this case is disabled.
 */

public class AddOnElementExtensionTestCase extends BaseTestCase
{

	private static final String TEST_ODA_DATA_SOURCE_NAME = "TestingOdaDataSource"; //$NON-NLS-1$
	private static final String TEST_ODA_DATA_SET_NAME = "TestingOdaDataSet"; //$NON-NLS-1$

	protected void setUp( ) throws Exception
	{
		super.setUp( );
		new AddOnExtensionLoader( ).load( );
		ThreadResources.setLocale( ULocale.ENGLISH );

	}

	/**
	 * Disables all test cases.
	 * @return
	 */

	public static Test suite( )
	{
		TestSuite suite = new TestSuite( "Test for Addon" ); //$NON-NLS-1$

		// $JUnit-BEGIN$
		// $JUnit-END$

		return suite;
	}

	/**
	 * Tests the element definition and property definition of ODA element.
	 */

	public void testOdaDataSourceMetadata( )
	{
		MetaDataDictionary dd = MetaDataDictionary.getInstance( );
		ExtensionElementDefn extDefn = (ExtensionElementDefn) dd
				.getExtension( TEST_ODA_DATA_SOURCE_NAME );
		ElementDefn baseElementDefn = (ElementDefn) dd
				.getElement( ReportDesignConstants.ODA_DATA_SOURCE );

		assertNotNull( extDefn );

		assertEquals( TEST_ODA_DATA_SOURCE_NAME, extDefn.getName( ) );
		assertEquals( baseElementDefn.getDisplayName( ), extDefn
				.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( baseElementDefn.getDisplayNameKey( ), extDefn
				.getDisplayNameKey( ) ); //$NON-NLS-1$
		assertEquals( baseElementDefn.allowsUserProperties( ), extDefn
				.allowsUserProperties( ) );
		assertEquals( baseElementDefn.canExtend( ), extDefn.canExtend( ) );
		assertEquals( baseElementDefn.getName( ), extDefn.getExtends( ) );
		assertEquals( null, extDefn.getJavaClass( ) );
		assertEquals( baseElementDefn.getSelector( ), extDefn.getSelector( ) );
		assertEquals( baseElementDefn.getNameOption( ), extDefn.getNameOption( ) );
		assertEquals( baseElementDefn.getNameSpaceID( ), extDefn
				.getNameSpaceID( ) );
		assertEquals( baseElementDefn, extDefn.getParent( ) );

		assertEquals( TEST_ODA_DATA_SOURCE_NAME, extDefn.getName( ) ); //$NON-NLS-1$
		List propList = extDefn.getProperties( );
		assertTrue( propList.size( ) > 5 );

		assertNotNull( extDefn.getProperty( DesignElement.DISPLAY_NAME_ID_PROP ) );
		assertNotNull( extDefn.getProperty( DataSource.AFTER_CLOSE_METHOD ) );
		assertNotNull( extDefn.getProperty( OdaDataSource.DRIVER_NAME_PROP ) );
		assertNotNull( extDefn.getProperty( "UserName" ) ); //$NON-NLS-1$

		ElementPropertyDefn prop = (ElementPropertyDefn) extDefn
				.getProperty( "UserName" ); //$NON-NLS-1$
		assertEquals( prop, extDefn.getProperty( "UserName" ) ); //$NON-NLS-1$
		assertEquals( "UserName", prop.getName( ) ); //$NON-NLS-1$
		assertEquals( "User Name", prop.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( PropertyType.STRING_TYPE, prop.getTypeCode( ) );
		assertEquals( false, prop.isList( ) );
		assertEquals( null, prop.getGroupName( ) );
		assertEquals( null, prop.getChoices( ) );
		assertEquals( null, prop.getStructDefn( ) );
		assertEquals( "default test", prop.getDefault( ) ); //$NON-NLS-1$
		assertEquals( true, prop.canInherit( ) );

		prop = (ElementPropertyDefn) extDefn.getProperty( "dataProp1" ); //$NON-NLS-1$
		assertEquals( "dataProp1", prop.getName( ) ); //$NON-NLS-1$
		assertEquals( "Data Property 1", prop.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( "Group 1", prop.getGroupName( ) ); //$NON-NLS-1$

		// Tests the default display name and resource bundle provider

		prop = (ElementPropertyDefn) extDefn.getProperty( "dataProp4" ); //$NON-NLS-1$
		assertEquals( "dataProp4", prop.getName( ) ); //$NON-NLS-1$
		assertEquals( "Default Data Property 4", prop.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( "Default Group 2", prop.getGroupName( ) ); //$NON-NLS-1$
		IChoiceSet choiceSet = prop.getChoices( );
		assertEquals(
				"Default Cube", choiceSet.getChoices( )[0].getDisplayName( ) ); //$NON-NLS-1$
	}

	/**
	 * Tests the metadata information of OdaDataSet.
	 */

	public void testOdaDataSetMetadata( )
	{
		MetaDataDictionary dd = MetaDataDictionary.getInstance( );
		ExtensionElementDefn extDefn = (ExtensionElementDefn) dd
				.getExtension( TEST_ODA_DATA_SET_NAME );
		ElementDefn baseElementDefn = (ElementDefn) dd
				.getElement( ReportDesignConstants.ODA_DATA_SET );

		assertNotNull( extDefn );

		assertEquals( TEST_ODA_DATA_SET_NAME, extDefn.getName( ) );
		assertEquals( baseElementDefn.getDisplayName( ), extDefn
				.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( baseElementDefn.getDisplayNameKey( ), extDefn
				.getDisplayNameKey( ) ); //$NON-NLS-1$
		assertEquals( baseElementDefn.allowsUserProperties( ), extDefn
				.allowsUserProperties( ) );
		assertEquals( baseElementDefn.canExtend( ), extDefn.canExtend( ) );
		assertEquals( baseElementDefn.getName( ), extDefn.getExtends( ) );
		assertEquals( null, extDefn.getJavaClass( ) );
		assertEquals( baseElementDefn.getSelector( ), extDefn.getSelector( ) );
		assertEquals( baseElementDefn.getNameOption( ), extDefn.getNameOption( ) );
		assertEquals( baseElementDefn.getNameSpaceID( ), extDefn
				.getNameSpaceID( ) );
		assertEquals( baseElementDefn, extDefn.getParent( ) );

		assertEquals( TEST_ODA_DATA_SET_NAME, extDefn.getName( ) ); //$NON-NLS-1$
		List propList = extDefn.getProperties( );
		assertTrue( propList.size( ) > 5 );

		assertNotNull( extDefn.getProperty( DesignElement.DISPLAY_NAME_ID_PROP ) );
		assertNotNull( extDefn.getProperty( SimpleDataSet.COLUMN_HINTS_PROP ) );
		assertNotNull( extDefn.getProperty( "dataSetProp1" ) ); //$NON-NLS-1$

		ElementPropertyDefn prop = (ElementPropertyDefn) extDefn
				.getProperty( "dataSetProp1" ); //$NON-NLS-1$
		assertEquals( prop, extDefn.getProperty( "dataSetProp1" ) ); //$NON-NLS-1$
		assertEquals( "dataSetProp1", prop.getName( ) ); //$NON-NLS-1$
		assertEquals( "dataSetProp1", prop.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( PropertyType.STRING_TYPE, prop.getTypeCode( ) );
		assertEquals( false, prop.isList( ) );
		assertEquals( null, prop.getGroupName( ) );
		assertEquals( null, prop.getChoices( ) );
		assertEquals( null, prop.getStructDefn( ) );
		assertEquals( "default test", prop.getDefault( ) ); //$NON-NLS-1$
		assertEquals( true, prop.canInherit( ) );

		prop = (ElementPropertyDefn) extDefn.getProperty( "dataSetProp4" ); //$NON-NLS-1$
		assertEquals( "dataSetProp4", prop.getName( ) ); //$NON-NLS-1$
		assertEquals( "dataSetProp4", prop.getDisplayName( ) ); //$NON-NLS-1$
		assertEquals( "group1", prop.getGroupName( ) ); //$NON-NLS-1$

	}

	/**
	 * Tests the API access for ODA element
	 * 
	 * @throws Exception
	 */

	public void testHandle( ) throws Exception
	{
		openDesign( "OdaDriverExtensionTest.xml" ); //$NON-NLS-1$

		// Test Data Source

		OdaDataSourceHandle odaDataSource = (OdaDataSourceHandle) designHandle
				.findDataSource( "extendedDataSource" ); //$NON-NLS-1$
		assertNotNull( odaDataSource );

		odaDataSource = (OdaDataSourceHandle) designHandle.getDataSources( )
				.get( 0 );
		assertNotNull( odaDataSource );
		assertEquals( "extendedDataSource", odaDataSource.getName( ) ); //$NON-NLS-1$

		assertEquals( "UserA", odaDataSource.getProperty( "UserName" ) ); //$NON-NLS-1$//$NON-NLS-2$
		assertEquals( "DoNotKnow", odaDataSource.getProperty( "Password" ) ); //$NON-NLS-1$//$NON-NLS-2$

		List list = odaDataSource.getExtensionPropertyDefinitionList( );
		assertEquals( 6, list.size( ) );

		odaDataSource.setProperty( "UserName", "UserB" ); //$NON-NLS-1$ //$NON-NLS-2$
		assertEquals( "UserB", odaDataSource.getProperty( "UserName" ) ); //$NON-NLS-1$//$NON-NLS-2$

		// Test DataSet

		OdaDataSetHandle odaDataSet = (OdaDataSetHandle) designHandle
				.findDataSet( "myDataSet" ); //$NON-NLS-1$
		assertNotNull( odaDataSet );

		odaDataSet = (OdaDataSetHandle) designHandle.getDataSets( ).get( 0 );
		assertNotNull( odaDataSet );
		assertEquals( "myDataSet", odaDataSet.getName( ) ); //$NON-NLS-1$

		assertEquals( "file", odaDataSet.getProperty( "dataSetProp1" ) ); //$NON-NLS-1$//$NON-NLS-2$
		assertEquals( "time", odaDataSet.getProperty( "dataSetProp2" ) ); //$NON-NLS-1$//$NON-NLS-2$
		assertEquals( "date", odaDataSet.getProperty( "dataSetProp3" ) ); //$NON-NLS-1$//$NON-NLS-2$

		list = odaDataSet.getExtensionPropertyDefinitionList( );
		assertEquals( 4, list.size( ) );

		odaDataSet.setProperty( "dataSetProp1", "file modified" ); //$NON-NLS-1$ //$NON-NLS-2$
		assertEquals( "file modified", odaDataSet.getProperty( "dataSetProp1" ) ); //$NON-NLS-1$//$NON-NLS-2$

		saveAsInTempDir( "OdaDriverExtensionTest_out.xml" ); //$NON-NLS-1$
		compareTextFileAsResource( AddOnElementExtensionTestCase.class,
				"OdaDriverExtensionTest_golden.xml", //$NON-NLS-1$
				"OdaDriverExtensionTest_out.xml" ); //$NON-NLS-1$
	}

	/**
	 * Tests the case that extension is not found.
	 * 
	 * @throws DesignFileException
	 *             if any exception
	 */

	public void testExtensionNotFound( ) throws DesignFileException
	{

		openDesign( "ExtensionNotFoundTest.xml" ); //$NON-NLS-1$
		OdaDataSourceHandle odaDataSource = (OdaDataSourceHandle) designHandle
				.findDataSource( "extendedDataSource" ); //$NON-NLS-1$

		odaDataSource.getExtensionPropertyDefinitionList( );
		assertEquals( Collections.EMPTY_LIST, odaDataSource
				.getExtensionPropertyDefinitionList( ) );

		OdaDataSourceHandle odaNotExistedExtension = designHandle
				.getElementFactory( ).newOdaDataSource(
						"odaDataSource", "notExistedExtension" ); //$NON-NLS-1$//$NON-NLS-2$

		assertNull( odaNotExistedExtension );

	}

	/**
	 * tests the element factory new oda element method. If the extension name
	 * is not given, the oda data set will be created as a ROM element.If the
	 * extension name is given, the check will be done for the name. Null will
	 * be returned if the extension name is not found in the metadata
	 * dictionary.
	 * 
	 * @throws DesignFileException
	 */
	public void testElementFactory( ) throws DesignFileException
	{
		openDesign( "OdaDriverExtensionTest.xml" ); //$NON-NLS-1$
		OdaDataSetHandle dataSetHandle = designHandle.getElementFactory( )
				.newOdaDataSet( "newDataSet", "wrongExtensionName" ); //$NON-NLS-1$//$NON-NLS-2$
		assertNull( dataSetHandle );
		dataSetHandle = designHandle.getElementFactory( ).newOdaDataSet(
				"newDataSet", null ); //$NON-NLS-1$//$NON-NLS-2$
		assertNotNull( dataSetHandle );
		dataSetHandle = designHandle.getElementFactory( ).newOdaDataSet(
				"newDataSet", "TestingOdaDataSet" ); //$NON-NLS-1$//$NON-NLS-2$
		assertNotNull( dataSetHandle );
		assertEquals( "TestingOdaDataSet", dataSetHandle.getExtensionName( ) ); //$NON-NLS-1$

		OdaDataSourceHandle odaDataSource = designHandle.getElementFactory( )
				.newOdaDataSource( "newDataSource", "wrongExtensionName" ); //$NON-NLS-1$//$NON-NLS-2$
		assertNull( odaDataSource );

		odaDataSource = designHandle.getElementFactory( ).newOdaDataSource(
				"newDataSource", null ); //$NON-NLS-1$//$NON-NLS-2$
		assertNotNull( odaDataSource );

		IPropertyDefn propDefn = odaDataSource.getElement( ).getPropertyDefn(
				OdaDataSource.AFTER_CLOSE_METHOD );
		assertNotNull( propDefn );

		propDefn = odaDataSource.getElement( ).getPropertyDefn(
				OdaDataSource.DRIVER_NAME_PROP );
		assertNotNull( propDefn );

		OdaDataSetHandle odaDataSet = designHandle.getElementFactory( )
				.newOdaDataSet( "newDataSet", null ); //$NON-NLS-1$//$NON-NLS-2$
		assertNotNull( odaDataSet );

		propDefn = odaDataSet.getElement( ).getPropertyDefn(
				OdaDataSet.DATA_SOURCE_PROP );
		assertNotNull( propDefn );

	}

	/**
	 * Tests property definition.
	 * 
	 * @throws DesignFileException
	 *             if any exception
	 */

	public void testPropertyDefinition( ) throws DesignFileException
	{
		openDesign( "OdaDriverExtensionTest.xml" ); //$NON-NLS-1$

		// Test Data Source

		OdaDataSourceHandle odaDataSource = (OdaDataSourceHandle) designHandle
				.findDataSource( "extendedDataSource" ); //$NON-NLS-1$
		assertNotNull( odaDataSource );

		Set allProperties = new HashSet( );
		List list = ( (OdaDataSource) odaDataSource.getElement( ) )
				.getPropertyDefns( );
		Iterator iter = list.iterator( );
		while ( iter.hasNext( ) )
		{
			ElementPropertyDefn propDefn = (ElementPropertyDefn) iter.next( );

			assertFalse( allProperties.contains( propDefn.getName( ) ) );
			allProperties.add( propDefn.getName( ) );
		}
	}

	/**
	 * Tests the encrypted provided.
	 * 
	 * @throws Exception
	 */

	public void testEncryptedProperty( ) throws Exception
	{
		openDesign( "OdaDriverExtensionTest_1.xml" ); //$NON-NLS-1$

		OdaDataSourceHandle dataSource = (OdaDataSourceHandle) designHandle
				.findDataSource( "myDataSource" ); //$NON-NLS-1$ 
		OdaDataSourceHandle dataSource2 = (OdaDataSourceHandle) designHandle
				.findDataSource( "myDataSource2" ); //$NON-NLS-1$

		assertEquals( "DoNotKnow", dataSource.getProperty( "Password" ) ); //$NON-NLS-1$ //$NON-NLS-2$
		assertEquals( "123456", dataSource2.getProperty( "Password" ) ); //$NON-NLS-1$ //$NON-NLS-2$

		saveAs( "OdaDriverExtensionTest_out_1.xml" ); //$NON-NLS-1$

		assertTrue( compareTextFile( "OdaDriverExtensionTest_golden_1.xml", //$NON-NLS-1$
				"OdaDriverExtensionTest_out_1.xml" ) ); //$NON-NLS-1$
	}
}
