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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import com.ibm.icu.util.ULocale;

import org.eclipse.birt.report.model.api.elements.ReportDesignConstants;
import org.eclipse.birt.report.model.api.metadata.IMetaLogger;
import org.eclipse.birt.report.model.i18n.ThreadResources;
import org.eclipse.birt.report.model.util.BaseTestCase;
import org.eclipse.birt.report.model.util.XMLParserException;

/**
 * Test case to test meta-data error logging. Test to check that all the
 * exceptions have been.
 * 
 */
public class MetaLoggerTest extends BaseTestCase
{

	private IMetaLogger logger = null;

	/**
	 * List of errors collected during parsing.
	 */

	private List errorList = null;

	// Two kinds of exception.

	private final static int METAREADER_EXCEPTION = 0;
	private final static int METADATA_EXCEPTION = 1;

	/**
	 * Constructor.
	 */

	public MetaLoggerTest( )
	{
		// clear up the manager, remove the default one.

		MetaLogManager.shutDown( );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp( ) throws Exception
	{
		// don not call super.setUp().
		// We wanna to hold the meta initialization.
		errorList = null;
	}

	/**
	 * Remove the logger from the manager, the stream locked by the logger will
	 * be released.
	 * 
	 */

	protected void clearup( )
	{
		if ( logger != null )
			MetaLogManager.removeLogger( logger );

		logger = null;
	}

	/**
	 * The golden and output file has a date-time in the front of the log file,
	 * we need to ignore this when doing the compare.
	 * 
	 * @param goldenFileName
	 *            golden file name.
	 * @param outputFileName
	 *            output file name.
	 * @return return true if two files are equals according to the logic.
	 * 
	 */

	protected boolean compareFileIgnoreDateTime( String goldenFileName,
			String outputFileName )
	{
		// release the output file first.
		clearup( );

		BufferedReader lineReaderA = null;
		BufferedReader lineReaderB = null;
		boolean same = true;

		try
		{
			goldenFileName = getClassFolder( ) + GOLDEN_FOLDER + goldenFileName;
			outputFileName = getClassFolder( ) + OUTPUT_FOLDER + outputFileName;

			lineReaderA = new BufferedReader( new FileReader( goldenFileName ) );
			lineReaderB = new BufferedReader( new FileReader( outputFileName ) );

			String strA = lineReaderA.readLine( ).trim( );
			String strB = lineReaderB.readLine( ).trim( );

			int prefixLen = FileMetaLogger.df.toPattern( ).length( );
			String datePrefix = null;

			while ( strA != null )
			{
				if ( strA.length( ) >= prefixLen )
				{
					// cut the dataTime prefix.

					datePrefix = strA.substring( 0, prefixLen ).trim( );

					try
					{
						FileMetaLogger.df.parse( datePrefix );

						// get the first line of the exception from A.

						strA = strA.substring( prefixLen );

						// get the first line of the corresponding exception
						// from B.

						while ( strB != null )
						{
							if ( strB.length( ) >= prefixLen )
							{
								datePrefix = strB.substring( 0, prefixLen )
										.trim( );
								try
								{
									FileMetaLogger.df.parse( datePrefix );

									strB = strB.substring( prefixLen );
									break;
								}
								catch ( ParseException e1 )
								{

								}
							}

							strB = lineReaderB.readLine( ).trim( );
						}

						same = strA.trim( ).equals( strB.trim( ) );

						if ( !same )
							return false;

						// read in the second line.
						strA = lineReaderA.readLine( ).trim( );
						strB = lineReaderB.readLine( ).trim( );

						same = strA.trim( ).equals( strB.trim( ) );

						if ( !same )
							return false;

					}
					catch ( ParseException e1 )
					{
						// ignore, strA has not been re-assigned.
					}
				}

				strA = lineReaderA.readLine( );
			}
		}
		catch ( IOException e )
		{
			e.printStackTrace( );
		}
		finally
		{
			try
			{
				if ( lineReaderA != null )
					lineReaderA.close( );
				if ( lineReaderB != null )
					lineReaderB.close( );
			}
			catch ( Exception e )
			{
				lineReaderA = null;
				lineReaderB = null;
			}
		}

		return true;
	}

	/**
	 * Create a new FileMetaLogger which will log the errors into a file
	 * specified by <code>fileName</code>. And then registered the logger
	 * onto the <code>MetaLogManager</code>.
	 * <p>
	 * For test case purpose, the log file will be deleted before passed on to
	 * the <code>FileMetaLogger</code>, because the
	 * <code>FileMetaLogger</code> will always append the errors to the
	 * existing log file. While in test case, we care only the errors caught in
	 * the current metadata loading.
	 * 
	 * @param fileName
	 *            file name of the log file
	 * @return The new <code>IMetaLogger</code> that was created which bound
	 *         to a file.
	 */

	private IMetaLogger createAndRegisterLogger( String fileName )
	{
		String outputPath = getClassFolder( ) + OUTPUT_FOLDER;

		File outputFolder = new File( outputPath );
		if ( !outputFolder.exists( ) )
		{
			outputFolder.mkdir( );
		}

		File logFile = new File( outputPath + fileName );
		if ( logFile.exists( ) )
		{
			logFile.delete( );
		}
		else
		{
			try
			{
				logFile.createNewFile( );
			}
			catch ( IOException e )
			{
			}
		}

		String name = getClassFolder( ) + OUTPUT_FOLDER + fileName;
		IMetaLogger logger = new FileMetaLogger( name );
		MetaLogManager.registerLogger( logger );

		return logger;
	}

	/**
	 * Reset and load the metadata with the specified rom file.
	 * 
	 * @param fileName
	 *            rom file name.
	 */

	private void loadMeta( String fileName )
	{
		ThreadResources.setLocale( ULocale.getDefault( ) );
		MetaDataDictionary.reset( );

		try
		{
			MetaDataReader.read( MetaLoggerTest.class
					.getResourceAsStream( "input/" + fileName ) ); //$NON-NLS-1$
		}
		catch ( MetaDataParserException e )
		{
			if ( e.getException( ) instanceof XMLParserException )
			{
				errorList = ( (XMLParserException) e.getException( ) )
						.getErrorList( );
			}
		}
	}

	/**
	 * Input file not exist.
	 * 
	 * @throws Exception
	 */

	public void test_FILE_NOT_FOUND( ) throws Exception
	{
		// this.logger = createAndRegisterLogger( "metaLog.log" ); //$NON-NLS-1$

		MetaDataDictionary.reset( );
		try
		{
			MetaDataReader.read( "input/none-exsit.def" ); //$NON-NLS-1$
		}
		catch ( MetaDataParserException e )
		{
			assertEquals(
					MetaDataParserException.DESIGN_EXCEPTION_FILE_NOT_FOUND, e
							.getErrorCode( ) );
		}
	}

	/**
	 * Parser Error.
	 * <p>
	 * In this case, input stream is null when passed to the parser.
	 * 
	 */

	public void test_PARSER_ERROR( )
	{
		// this.logger = createAndRegisterLogger( "metaLog1.log" );
		// //$NON-NLS-1$

		try
		{
			MetaDataReader.read( MetaLoggerTest.class
					.getResourceAsStream( "input/none-exsit.def" ) ); //$NON-NLS-1$
		}
		catch ( MetaDataParserException e )
		{
			assertEquals(
					MetaDataParserException.DESIGN_EXCEPTION_PARSER_ERROR, e
							.getErrorCode( ) );
		}
	}

	/**
	 * Tests the name required cases. Name required for:
	 * <ul>
	 * <li>ChoiceType</li>
	 * <li>Element</li>
	 * <li>Member</li>
	 * <li>Property</li>
	 * <li>Slot</li>
	 * <li>Slot Type</li>
	 * <li>Structure</li>
	 * <li>StyleProperty</li>
	 * <li>Style(Predefined)</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the followings names:
	 * <ul>
	 * <li>ChoiceType: fontFamily</li>
	 * <li>Element: JdbcDataSource</li>
	 * <li>Member: MapRule.operator</li>
	 * <li>Property: ReportDesign.author</li>
	 * <li>Slot: ReportDesign.styles</li>
	 * <li>Slot Type: Slot type of ReportDesign.masterPages</li>
	 * <li>Structure: HighlightRule</li>
	 * <li>StyleProperty: First styleProperty within Data (name =
	 * "background-color").</li>
	 * <li>Style: Predefined style: group-header-1</li>
	 * </ul>
	 */

	public void test_NAME_REQUIRED( )
	{
		// ChoiceType caught
		// Element caught
		// Member caught
		// Property caught
		// Slot caught
		// Slot Type caught
		// Structure caught
		// StyleProperty caught
		// Style(Predefined) caught

		// this.logger = createAndRegisterLogger( "metaLog2.log" );
		// //$NON-NLS-1$

		loadMeta( "romTest2.def" ); //$NON-NLS-1$ 
		assertEquals( 13, errorList.size( ) );
	}

	/**
	 * Tests display name key required cases. DisplayNameID required for:
	 * <ul>
	 * <li>ChoiceType</li>
	 * <li>Element</li>
	 * <li>Member</li>
	 * <li>Property</li>
	 * <li>Slot</li>
	 * <li>Structure</li>
	 * <li>Style(Predefined)</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the followings displayNameIDs:
	 * <ul>
	 * <li>ChoiceType: fontFamil.serif</li>
	 * <li>Element: JdbcDataSource</li>
	 * <li>Member: MapRule.operator</li>
	 * <li>Property: ReportDesign.author</li>
	 * <li>Slot: ReportDesign.styles</li>
	 * <li>Structure: CustomColor</li>
	 * <li>Style: Predefined style: group-header-1</li>
	 * </ul>
	 */

	public void test_DISPLAY_NAME_ID_REQUIRED( )
	{
		// Choice caught
		// Element caught
		// Member caught
		// Property caught
		// Slot caught
		// Structure caught
		// Style(Predefined) caught

		// this.logger = createAndRegisterLogger( "metaLog3.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest3.def" ); //$NON-NLS-1$ 
		assertEquals( 8, errorList.size( ) );
	}

	/**
	 * Tests multipleCardinality required case. multipleCardinality required
	 * for:
	 * <ul>
	 * <li>Slot</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the follwings multipleCardinality:
	 * <ul>
	 * <li>ReportDesign.styles</li>
	 * <li>ReportDesign.parameters</li>
	 * </ul>
	 */
	public void test_MULTIPLE_CARDINALITY_REQUIRED( )
	{
		// ReportDesign.styles caught
		// ReportDesign.parameters caught

		// this.logger = createAndRegisterLogger( "metaLog4.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest4.def" ); //$NON-NLS-1$

		assertEquals( 3, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_MULTIPLE_CARDINALITY_REQUIRED,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_MULTIPLE_CARDINALITY_REQUIRED,
				1, METAREADER_EXCEPTION );

	}

	/**
	 * Tests type required cases. Type required for:
	 * <ul>
	 * <li>Member</li>
	 * <li>Property</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the followings types:
	 * <ul>
	 * <li>Member: HighlightRule.operator</li>
	 * <li>Property: ReportDesign.author</li>
	 * </ul>
	 */

	public void test_TYPE_REQUIRED( )
	{
		// Member caught
		// Property caught

		// this.logger = createAndRegisterLogger( "metaLog5.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest5.def" ); //$NON-NLS-1$

		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_TYPE_REQUIRED, 0,
				METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_TYPE_REQUIRED, 1,
				METAREADER_EXCEPTION );
		assertEquals( 3, errorList.size( ) );
	}

	/**
	 * Tests name space. nameSpace of element can only be one of followings:
	 * <ul>
	 * <li>none</li>
	 * <li>masterPage</li>
	 * <li>parameter</li>
	 * <li>element</li>
	 * <li>dataSource</li>
	 * <li>dataSet</li>
	 * <li>style</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file set the DataSource.namespace =
	 * "invalid-namespace"
	 * 
	 */
	public void test_INVALID_NAME_SPACE( )
	{
		// DataSource.namespace caught

		// this.logger = createAndRegisterLogger( "metaLog6.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest6.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_NAME_SPACE, 0,
				METAREADER_EXCEPTION );
	}

	/**
	 * Tests xml name required cases. XML Name required for:
	 * <ul>
	 * <li>Choice</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the xml name for:
	 * <ul>
	 * <li>Choice: fontWeight.lighter</li>
	 * </ul>
	 */
	public void test_XML_NAME_REQUIRED( )
	{
		// fontWeight.normal caught

		// this.logger = createAndRegisterLogger( "metaLog7.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest7.def" ); //$NON-NLS-1$ 
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_XML_NAME_REQUIRED, 0,
				METAREADER_EXCEPTION );
		assertEquals( 2, errorList.size( ) );
	}

	/**
	 * Default value for a property is not valid.
	 * 
	 * <p>
	 * In this case, input file has the follwing wrong default value:
	 * 
	 * ReportDesign.units.default="none-exsit-units"
	 * 
	 */
	public void test_INVALID_DEFAULT( )
	{
		// ReportDesign.unis caught

		// this.logger = createAndRegisterLogger( "metaLog8.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest8.def" ); //$NON-NLS-1$ 
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_DEFAULT, 0,
				METAREADER_EXCEPTION );
		assertEquals( 2, errorList.size( ) );
	}

	/**
	 * Tests the invalid type cases. Invalid type required for:
	 * <ul>
	 * <li>Property</li>
	 * <li>Member</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file has the following wrong type:
	 * <ul>
	 * <li>Property: ReportDesing.author.type="none-exsit-type"</li>
	 * <li>Member: HighlightRule.operator.type="none-exsit-type"</li>
	 * </ul>
	 */
	public void test_INVALID_TYPE( )
	{
		// Property caught
		// Member caught

		// this.logger = createAndRegisterLogger( "metaLog9.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest9.def" ); //$NON-NLS-1$ 
		assertErrorCode( MetaDataParserException.DESIGN_EXCEPTION_INVALID_TYPE,
				0, METAREADER_EXCEPTION );
		assertErrorCode( MetaDataParserException.DESIGN_EXCEPTION_INVALID_TYPE,
				1, METAREADER_EXCEPTION );
		assertEquals( 3, errorList.size( ) );
	}

	/*
	 * 
	 * 
	 * public void test_BUILD_FAILED( ) { }
	 * 
	 */

	/**
	 * 
	 * DisplayNameId required for PropertyGroup.
	 * <p>
	 * In this case, input file missing the following displayNameId:
	 * <ul>
	 * <li>Style.font</li>
	 * </ul>
	 */
	public void test_GROUP_NAME_ID_REQUIRED( )
	{
		// Style.font caught

		// this.logger = createAndRegisterLogger( "metaLog11.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest11.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_GROUP_NAME_ID_REQUIRED,
				0, METAREADER_EXCEPTION );
	}

	/**
	 * 
	 * For property which type = "choice", ChoiceType indicated by detailType
	 * must have been defined already and valid.
	 * 
	 * <p>
	 * In this case, input file set the following wrong detail type:
	 * <ul>
	 * <li>Member: MapRule.operator.detailType="none-exist-choiceset"</li>
	 * <li>Property: ReportDesign.units.detailType="none-exist-choiceset"</li>
	 * </ul>
	 */

	public void test_INVALID_CHOICE_TYPE( )
	{
		// Member caught
		// Property caught

		// this.logger = createAndRegisterLogger( "metaLog12.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest12.def" ); //$NON-NLS-1$ 
		assertEquals( 3, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_CHOICE_TYPE,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_CHOICE_TYPE,
				1, METAREADER_EXCEPTION );
	}

	/**
	 * 
	 * For property which type = "choice", detailType must be specified.
	 * 
	 * <p>
	 * In this case, input file missing the following detailType:
	 * <ul>
	 * <li>Member: MapRule.operator.detailType=""</li>
	 * <li>Property: ReportDesign.units.detailType=""</li>
	 * </ul>
	 */
	public void test_CHOICE_TYPE_REQUIRED( )
	{
		// Member caught
		// Property caught

		// this.logger = createAndRegisterLogger( "metaLog13.log" );
		// //$NON-NLS-1$

		loadMeta( "romTest13.def" ); //$NON-NLS-1$ 
		assertEquals( 3, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_CHOICE_TYPE_REQUIRED,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_CHOICE_TYPE_REQUIRED,
				1, METAREADER_EXCEPTION );
	}

	/**
	 * Tests structure type required cases. If type="StructList", detailType
	 * must be specified for:
	 * <ul>
	 * <li>Property</li>
	 * <li>Member</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the detailType for a property
	 * type="StuctList":
	 * <ul>
	 * <li>Property: ReportDesign.colorPalette.detailType=""</li>
	 * <li>Member: Add a test member DrillThroughSearchKeys.testMember
	 * type="structList" detailType=""</li>
	 * </ul>
	 */
	public void test_STRUCT_TYPE_REQUIRED( )
	{
		// Property caught
		// Member caught

		// this.logger = createAndRegisterLogger( "metaLog14.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest14.def" ); //$NON-NLS-1$ 
		assertEquals( 3, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_STRUCT_TYPE_REQUIRED,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_STRUCT_TYPE_REQUIRED,
				1, METAREADER_EXCEPTION );
	}

	/**
	 * If type="StructList", the Structure specified by detailType must already
	 * have been defined.
	 * 
	 * <ul>
	 * <li>Property</li>
	 * <li>Member</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file have the following wrong detailTypes for
	 * property type="StuctList":
	 * <ul>
	 * <li>Property:
	 * ReportDesign.colorPalette.detailType="none-exsit-structureList"</li>
	 * <li>Member: Add a test member DrillThroughSearchKeys.testMember
	 * type="structList" detailType="not-defined-yet".</li>
	 * </ul>
	 */
	public void test_INVALID_STRUCT_TYPE( )
	{
		// Property caught
		// Member caught

		// this.logger = createAndRegisterLogger( "metaLog15.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest15.def" ); //$NON-NLS-1$ 
		assertEquals( 2, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_STRUCT_TYPE,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_STRUCT_TYPE,
				1, METAREADER_EXCEPTION );
	}

	/**
	 * 
	 * If type="element", detailType must be specified.
	 * <ul>
	 * <li>Choice</li>
	 * </ul>
	 * 
	 * <p>
	 * In this case, input file missing the detailType for a property
	 * type="Element":
	 * <ul>
	 * <li>Property: DataSet.dataSource.detailType</li>
	 * </ul>
	 */
	public void test_ELEMENT_REF_TYPE_REQUIRED( )
	{
		// Property caught
		// this.logger = createAndRegisterLogger( "metaLog16.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest16.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_ELEMENT_REF_TYPE_REQUIRED,
				0, METAREADER_EXCEPTION );
	}

	// Followings are cases from logging MetaDataException.

	/**
	 * Missing element name when adding an element to the meta dictionary.
	 */
	public void test_MISSING_ELEMENT_NAME( )
	{
		// This exception can never be caught during meta parsing.
		// In the ElementDefnState, state will return when elementName = null or
		// // "".

		ElementDefn newElement = new ElementDefn( );
		try
		{
			MetaDataDictionary.getInstance( ).addElementDefn( newElement );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_ELEMENT_NAME, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing element name when adding an element to the meta-data dictionary. Error code:MISSING_ELEMENT_NAME", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Duplicate element name when adding to the metadata dictionary.
	 * <p>
	 * In this case, input file have defined two elementDefn with the same name
	 * "DataSource".
	 * 
	 */
	public void test_DUPLICATE_ELEMENT_NAME( )
	{
		// Duplication of DataSource caught.

		// this.logger = createAndRegisterLogger( "metaLog17.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest17.def" ); //$NON-NLS-1$ 
		assertEquals( 2, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_DUPLICATE_ELEMENT_NAME, 0,
				METADATA_EXCEPTION );

		MetaDataDictionary.reset( );
		ElementDefn elementA = new ElementDefn( );
		elementA.setName( "Name" ); //$NON-NLS-1$

		ElementDefn elementB = new ElementDefn( );
		elementB.setName( "Name" ); //$NON-NLS-1$

		try
		{
			MetaDataDictionary.getInstance( ).addElementDefn( elementA );
			MetaDataDictionary.getInstance( ).addElementDefn( elementB );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_DUPLICATE_ELEMENT_NAME,
					e.getErrorCode( ) );
			assertEquals(
					"Message:Duplicate element names when adding the element [Name] to the meta-data dictionary. Error code:DUPLICATE_ELEMENT_NAME", //$NON-NLS-1$ 
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Predefined stye must have a name.
	 * 
	 */

	public void test_MISSING_STYLE_NAME( )
	{
		// This exception can never be caught during meta parsing.
		// In the ElementDefnState, state will return when elementName = null or
		// // "".

		PredefinedStyle style = new PredefinedStyle( );

		try
		{
			MetaDataDictionary.getInstance( ).addPredefinedStyle( style );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_STYLE_NAME, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing style name when adding a predefined style to the meta-data dictionary. Error code:MISSING_STYLE_NAME", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Duplicate predefined style name when adding to the metadata dictionary.
	 * <p>
	 * In this case, input file have defined two predefined style with the same
	 * name "group-header-1".
	 * 
	 */
	public void test_DUPLICATE_STYLE_NAME( )
	{
		// this.logger = createAndRegisterLogger( "metaLog18.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest18.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_DUPLICATE_STYLE_NAME, 0,
				METADATA_EXCEPTION );

		MetaDataDictionary.reset( );
		ElementDefn elementA = new ElementDefn( );
		elementA.setName( "Name" ); //$NON-NLS-1$

		ElementDefn elementB = new ElementDefn( );
		elementB.setName( "Name" );//$NON-NLS-1$

		try
		{
			MetaDataDictionary.getInstance( ).addElementDefn( elementA );
			MetaDataDictionary.getInstance( ).addElementDefn( elementB );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_DUPLICATE_ELEMENT_NAME,
					e.getErrorCode( ) );
			assertEquals(
					"Message:Duplicate element names when adding the element [Name] to the meta-data dictionary. Error code:DUPLICATE_ELEMENT_NAME", //$NON-NLS-1$  
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Missing Style element, rom must have definition for the style element.
	 * <p>
	 * In this case, input file missing element name="Style"
	 */
	public void test_STYLE_TYPE_MISSING( )
	{
		// this.logger = createAndRegisterLogger( "metaLog19.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest19.def" ); //$NON-NLS-1$
		assertEquals( 59, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_STYLE_TYPE_MISSING,
				0, METADATA_EXCEPTION );
	}

	/**
	 * Element can not have two properties with the same name.
	 * <p>
	 * In this case, input file has two property name="author" defined on
	 * ReportDesign, "displayName" defined on DataSource and "font-family"
	 * defined on MasterPage.
	 */

	public void test_DUPLICATE_PROPERTY( )
	{
		// this.logger = createAndRegisterLogger( "metaLog20.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest20.def" ); //$NON-NLS-1$ 
		assertEquals( 3, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_DUPLICATE_PROPERTY,
				0, METADATA_EXCEPTION );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_DUPLICATE_PROPERTY,
				1, METADATA_EXCEPTION );
	}

	/**
	 * Element extends from another element that was not found.
	 * <p>
	 * In this case, input file has the following violation:
	 * ScalarParameter.extends="none-exsit-parent" (which should be Parameter)
	 * 
	 */
	public void test_ELEMENT_PARENT_NOT_FOUND( )
	{
		// this.logger = createAndRegisterLogger( "metaLog21.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest21.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_ELEMENT_PARENT_NOT_FOUND, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * 1. "hasStyle" attribute of an element is false, but it has
	 * StyleProperties defined on it.
	 * <p>
	 * 2. "hasStyle" attribute of an element is true and it is an container(slot
	 * count>0), but it has StyleProperties defined on it.
	 * <p>
	 * In this case, input file has the following violation: 1.
	 * DataSource.hasStyle = false. But it has defined a styleProperty "color"
	 * on it.
	 * <p>
	 * 2. GraphicMasterPage.hasStyle = "true" and slotCount > 0. But it has
	 * defined a styleProperty "color" on it.
	 */
	public void test_ILLEGAL_STYLE_PROPS( )
	{
		// case1 caught
		// case2 caught

		// this.logger = createAndRegisterLogger( "metaLog22.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest22.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_ILLEGAL_STYLE_PROPS, 0,
				METADATA_EXCEPTION );

		// this.logger = createAndRegisterLogger( "metaLog23.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest23.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_ILLEGAL_STYLE_PROPS, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * If element A is abstract then its parent must also be abstract.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * JdbcDataSource extends from DataSource.
	 * <p>
	 * DataSource.isAbstract = "false", JdbcDataSource.isAbstract = "true".
	 * 
	 */
	public void test_ILLEGAL_ABSTRACT_ELEMENT( )
	{
		// this.logger = createAndRegisterLogger( "metaLog24.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest24.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_ILLEGAL_ABSTRACT_ELEMENT, 0,
				METADATA_EXCEPTION );
	}

	public void test_INVALID_STYLE_PROP_OPTION( )
	{
		// sanity check, can not construct the case.
	}

	/**
	 * Style property defined on element was not found.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * Define a <StyleProperty name="none-exsit-styleProperty"/> on Label
	 * 
	 */
	public void test_STYLE_PROP_NOT_FOUND( )
	{
		// this.logger = createAndRegisterLogger( "metaLog25.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest25.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_STYLE_PROP_NOT_FOUND, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * The PropertyType of the property has not been set. ( propDefn.getType() ==
	 * null )
	 * 
	 */

	public void test_PROP_TYPE_ERROR( )
	{
		// This build time exception can never be caught during parsing.
		// In the PropertyState, state will return when
		// dictionary.getPropertyType( type ) == null.
		// This property will be exsit when building the element.

		PropertyDefn propDefn = new SystemPropertyDefn( );
		propDefn.setName( "Property1" ); //$NON-NLS-1$

		try
		{
			propDefn.build( );
		}
		catch ( MetaDataException e )
		{
			assertEquals( MetaDataException.DESIGN_EXCEPTION_PROP_TYPE_ERROR, e
					.getErrorCode( ) );
			assertEquals(
					"Message:PropertyType of the property [Property1] has not been set. ( propDefn.getType() == null ) Error code:PROP_TYPE_ERROR", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * The ChoiceSet has not been set on the property definition. ( type==
	 * PropertyType.CHOICE_TYPE && getChoices() == null )
	 * 
	 */
	public void test_MISSING_PROP_CHOICES( )
	{
		PropertyDefn propDefn = new SystemPropertyDefn( );
		propDefn.setName( "Property1" ); //$NON-NLS-1$
		propDefn.setType( MetaDataDictionary.getInstance( ).getPropertyType(
				PropertyType.CHOICE_TYPE ) );

		try
		{
			propDefn.build( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_PROP_CHOICES, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing ChoiceSet for choice type property [Property1]. Error code:MISSING_PROP_CHOICES", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * A slot should hold at least one content element.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * ParameterGroup has slot, but with no content type.
	 * 
	 */

	public void test_MISSING_SLOT_TYPE( )
	{
		// this.logger = createAndRegisterLogger( "metaLog26.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest26.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_MISSING_SLOT_TYPE,
				0, METADATA_EXCEPTION );
	}

	/**
	 * Slot displayNameID attribute must be specified.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * ParameterGroup.parameters.displayNameID="".
	 */

	public void test_MISSING_SLOT_NAME( )
	{
		// this.logger = createAndRegisterLogger( "metaLog27.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest27.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_MISSING_SLOT_NAME,
				0, METADATA_EXCEPTION );
	}

	/**
	 * Slot type for the element is not valid, the target element definition can
	 * not be found.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * ParameterGroup.parameters.type1.name="none-exsit-type".
	 */

	public void test_INVALID_SLOT_TYPE( )
	{
		// this.logger = createAndRegisterLogger( "metaLog28.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest28.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_INVALID_SLOT_TYPE,
				0, METADATA_EXCEPTION );
	}

	/**
	 * Some element: 1)Style 2)ReportElement 3)ReportDesign must been defined in
	 * rom.def.
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * ReportDesign not defined.
	 */

	public void test_ELEMENT_NAME_CONST( )
	{
		// this.logger = createAndRegisterLogger( "metaLog29.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest29.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_ELEMENT_NAME_CONST,
				0, METADATA_EXCEPTION );
	}

	/**
	 * Missing choice set name when adding a Choice Set to the meta dictionary.
	 * 
	 */
	public void test_MISSING_CHOICE_SET_NAME( )
	{
		ChoiceSet choices1 = new ChoiceSet( null );
		try
		{
			MetaDataDictionary.getInstance( ).addChoiceSet( choices1 );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_CHOICE_SET_NAME,
					e.getErrorCode( ) );
			assertEquals(
					"Message:Missing choice set name when adding a Choice Set to the meta-data dictionary. Error code:MISSING_CHOICE_SET_NAME", //$NON-NLS-1$ 
					e.getMessage( ).trim( ) ); //$NON-NLS-1$ 
		}
	}

	/**
	 * Duplicate choice set names when adding the choice set to the meta
	 * dictionary.
	 * 
	 */
	public void test_DUPLICATE_CHOICE_SET_NAME( )
	{
		ChoiceSet choices1 = new ChoiceSet( "choices1" ); //$NON-NLS-1$ 
		ChoiceSet choices2 = new ChoiceSet( "choices1" ); //$NON-NLS-1$ 
		try
		{
			MetaDataDictionary.getInstance( ).addChoiceSet( choices1 );
			MetaDataDictionary.getInstance( ).addChoiceSet( choices2 );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_DUPLICATE_CHOICE_SET_NAME,
					e.getErrorCode( ) );
			assertEquals(
					"Message:Duplicate choice set names when adding the choice set [choices1] to the meta-data dictionary. Error code:DUPLICATE_CHOICE_SET_NAME", //$NON-NLS-1$ 
					e.getMessage( ).trim( ) );
			//$NON-NLS-1$ 
		}
	}

	/**
	 * Missing structure name when adding a structure to the meta dictionary.
	 * 
	 */
	public void test_MISSING_STRUCT_NAME( )
	{
		StructureDefn structDefn = new StructureDefn( null );
		try
		{
			MetaDataDictionary.getInstance( ).addStructure( structDefn );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_STRUCT_NAME, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing structure name when adding a structure to the meta-data dictionary. Error code:MISSING_STRUCT_NAME", //$NON-NLS-1$
					e.getMessage( ).trim( ) ); //$NON-NLS-1$ 
		}
	}

	/**
	 * Duplicate structure name when adding the structure to the meta
	 * dictionary.
	 * 
	 */

	public void test_DUPLICATE_STRUCT_NAME( )
	{
		StructureDefn structDefn1 = new StructureDefn( "struct" ); //$NON-NLS-1$ 
		StructureDefn structDefn2 = new StructureDefn( "struct" ); //$NON-NLS-1$ 
		try
		{
			MetaDataDictionary.getInstance( ).addStructure( structDefn1 );
			MetaDataDictionary.getInstance( ).addStructure( structDefn2 );
			fail( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_DUPLICATE_STRUCT_NAME, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Duplicate structure names when adding the structure [struct] to the meta-data dictionary. Error code:DUPLICATE_STRUCT_NAME", //$NON-NLS-1$ 
					e.getMessage( ).trim( ) );

		}
	}

	/**
	 * The detail sturcture definition has not been set on the property
	 * definition. ( type == PropertyType.STRUCT_LIST_TYPE && getStructDefn() ==
	 * null)
	 * 
	 */

	public void test_MISSING_STRUCT_DEFN( )
	{
		PropertyDefn prop = new SystemPropertyDefn( );
		prop.setName( "prop1" ); //$NON-NLS-1$
		prop.setType( MetaDataDictionary.getInstance( ).getPropertyType(
				PropertyType.STRUCT_TYPE ) );
		prop.setDetails( null );
		prop.setOwner( (ElementDefn) MetaDataDictionary.getInstance( )
				.getElement( ReportDesignConstants.TABLE_ITEM ) );

		try
		{
			prop.build( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_STRUCT_DEFN, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing structure definition for structure list type property [prop1] in [Table]. Error code:MISSING_STRUCT_DEFN", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * The detail referenced element name has not been set on the property
	 * definition.( type == ELEMENT_REF_TYPE && detail == null )
	 * 
	 */

	public void test_MISSING_ELEMENT_TYPE( )
	{
		PropertyDefn prop = new SystemPropertyDefn( );
		prop.setName( "prop1" ); //$NON-NLS-1$
		prop.setType( MetaDataDictionary.getInstance( ).getPropertyType(
				PropertyType.ELEMENT_REF_TYPE ) );
		prop.setDetails( null );

		try
		{
			prop.build( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_MISSING_ELEMENT_TYPE, e
							.getErrorCode( ) );
			assertEquals(
					"Message:Missing element reference for element reference type property [prop1]. Error code:MISSING_ELEMENT_TYPE", //$NON-NLS-1$
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Element referenced by the property was not defined. (
	 * dictionary.getElement(name) == null )
	 * 
	 */

	public void test_UNDEFINED_ELEMENT_TYPE( )
	{
		PropertyDefn prop = new SystemPropertyDefn( );
		prop.setName( "prop1" ); //$NON-NLS-1$
		prop.setType( MetaDataDictionary.getInstance( ).getPropertyType(
				PropertyType.ELEMENT_REF_TYPE ) );
		prop.setDetails( "none-exsit-element-ref" ); //$NON-NLS-1$

		try
		{
			prop.build( );
		}
		catch ( MetaDataException e )
		{
			assertEquals(
					MetaDataException.DESIGN_EXCEPTION_UNDEFINED_ELEMENT_TYPE,
					e.getErrorCode( ) );
			assertEquals(
					"Message:Element [none-exsit-element-ref] referenced by property [prop1] is not defined. Error code:UNDEFINED_ELEMENT_TYPE", //$NON-NLS-1$ 
					e.getMessage( ).trim( ) );
		}
	}

	/**
	 * Element referenced by the property is an unnamed element.
	 * (namespace=='no_namespace').
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * DataSet.dataSource.type = "element" and DataSet.dataSource.detailType =
	 * "DataSource".
	 * <p>
	 * But, DataSource.nameSpace="none"
	 */

	public void test_UNNAMED_ELEMENT_TYPE( )
	{
		// this.logger = createAndRegisterLogger( "metaLog30.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest30.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_UNNAMED_ELEMENT_TYPE, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * Inconsistent property, style property cannot also be intrinsic.
	 * (isIntrinsic( ) && isStyleProperty( ) )
	 * <p>
	 * In this case, input file has the following violations:
	 * <p>
	 * Style.font-family.isStyleProperty = "true" and its isIntrinsic="true".
	 */

	public void test_INCONSISTENT_PROP_TYPE( )
	{
		// this.logger = createAndRegisterLogger( "metaLog31.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest31.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_INCONSISTENT_PROP_TYPE, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * missing javaClass attribute for a element definition that is not
	 * abstract.
	 * <p>
	 * In this case, input file has the following violations: ReportDesign is
	 * none-abstract, it missing the javaClass attribute.
	 * 
	 */

	public void test_MISSING_JAVA_CLASS( )
	{
		// this.logger = createAndRegisterLogger( "metaLog32.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest32.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode( MetaDataException.DESIGN_EXCEPTION_MISSING_JAVA_CLASS,
				0, METADATA_EXCEPTION );

	}

	/**
	 * The specified element java class cannot be instantiated maybe because it
	 * is an interface or is an abstract class or that the specified java class
	 * doesn't not provide a default constructor( or a constructor that takes no
	 * argument ).
	 * 
	 * <p>
	 * In this case, input file has the following violations:
	 * ReportDesign.javaClass="org.eclipse.birt.report.model.core.RootElement",
	 * which is an abstract class.
	 */

	public void test_JAVA_CLASS_INITIALIZE_ERROR( )
	{
		// this.logger = createAndRegisterLogger( "metaLog33.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest33.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_JAVA_CLASS_INITIALIZE_ERROR,
				0, METADATA_EXCEPTION );

	}

	/**
	 * The specified element java class can not be found in the current class
	 * path.
	 * <p>
	 * In this case, input file has the following violations:
	 * ReportDesign.javaClass="none-exsit-class-name".
	 * 
	 */

	public void test_JAVA_CLASS_JAVA_CLASS_LOAD_ERROR( )
	{
		// this.logger = createAndRegisterLogger( "metaLog34.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest34.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_JAVA_CLASS_LOAD_ERROR, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * The specified element java class is not a Design Element, that is, the
	 * class is not a kind of <code>DesignElement</code>.
	 * <p>
	 * In this case, input file has the following violations:
	 * ReportDesign.javaClass="java.util.HashMap", which is not a DesignElement.
	 * 
	 */
	public void test_INVALID_ELEMENT_JAVA_CLASS( )
	{
		// this.logger = createAndRegisterLogger( "metaLog35.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest35.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );

		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_INVALID_ELEMENT_JAVA_CLASS,
				0, METADATA_EXCEPTION );
	}

	/**
	 * In one element definition, two methods have the same name.
	 * 
	 */
	public void test_DUPLICATE_METHOD_NAME( )
	{
		// this.logger = createAndRegisterLogger( "metaLog36.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest36.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );

		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_DUPLICATE_ELEMENT_NAME, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * In one element method definition, two arguments have the same name.
	 * 
	 */
	public void test_DUPLICATE_ARGUMENT_NAME( )
	{
		// this.logger = createAndRegisterLogger( "metaLog37.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest37.def" ); //$NON-NLS-1$ 
		assertEquals( 1, errorList.size( ) );

		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_DUPLICATE_ARGUMENT_NAME, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * <Allowed></Allowed> indicates the restriction information, it can only
	 * apply to a dimension or a choice property.
	 * 
	 * <p>
	 * In this case, input file has the following in valid restriction.
	 * <ul>
	 * <li>Property: Style.font-family is a string property.</li>
	 * </ul>
	 */

	public void test_RESTRICTION_NOT_ALLOWED( )
	{
		// this.logger = createAndRegisterLogger( "metaLog38.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest38.def" ); //$NON-NLS-1$ 

		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_RESTRICTION_NOT_ALLOWED,
				0, METAREADER_EXCEPTION );
	}

	/**
	 * <Allowed>in,cm </Allowed> indicates the restriction information, it can
	 * only apply to a dimension or a choice property.
	 * <p>
	 * And the information in it should be in the original unit or choice set.
	 * <p>
	 * In this case, input file has the following in valid restriction.
	 * <ul>
	 * <li>Property: Style.font-size is a dimension property. allowed =
	 * "in,cm,XXXX", "XXXX" is not valid</li>
	 * <li>Property: Style.font-style is a choice property. allowed =
	 * "italic,YYYY", "YYYY" is not valid</li>
	 * TODO: Restriction on Member.
	 * 
	 * </ul>
	 */

	public void test_INVALID_RESTRICTION( )
	{
		// this.logger = createAndRegisterLogger( "metaLog39.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest39.def" ); //$NON-NLS-1$ 

		assertEquals( 2, errorList.size( ) );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_RESTRICTION,
				0, METAREADER_EXCEPTION );
		assertErrorCode(
				MetaDataParserException.DESIGN_EXCEPTION_INVALID_RESTRICTION,
				1, METAREADER_EXCEPTION );
	}

	/**
	 * Test that default value not in the allowed choices.
	 * <p>
	 * In the case 1: ReportDesign.units has an allowed choices[in,cm,mm,pt].
	 * But the default value for it is px, not in the list.
	 */

	public void test_INVALID_DEFAULT_VALUE( )
	{
		// this.logger = createAndRegisterLogger( "metaLog40.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest40.def" ); //$NON-NLS-1$

		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_INVALID_DEFAULT_VALUE, 0,
				METADATA_EXCEPTION );
	}

	/**
	 * Test that default value not in the allowed choices.
	 * <p>
	 * In the case Style.font-size is a dimension type, allowed [in,cm], but
	 * default value is 12pt, where pt is not allowed
	 */

	public void test_INVALID_DEFAULT_VALUE2( )
	{
		// this.logger = createAndRegisterLogger( "metaLog41.log" );
		// //$NON-NLS-1$
		loadMeta( "romTest41.def" ); //$NON-NLS-1$

		assertEquals( 1, errorList.size( ) );
		assertErrorCode(
				MetaDataException.DESIGN_EXCEPTION_INVALID_DEFAULT_VALUE, 0,
				METADATA_EXCEPTION );
	}

	// Followings are cases from logging MetaDataException.

	/**
	 * Assert one error code.
	 * 
	 * @param expected
	 *            expected error code string.
	 * @param index
	 *            error index in the error list.
	 * @param type
	 *            0 for MetaReaderException; 1 for MetaDataException.
	 */

	private void assertErrorCode( String expected, int index, int type )
	{
		assert type == METAREADER_EXCEPTION || type == METADATA_EXCEPTION;

		assertErrorCode( expected, index, index, type );
	}

	/**
	 * Assert sevaral errors in the error list. Assert there error code.
	 * 
	 * @param expected
	 *            expected error code string
	 * @param from
	 *            from index in the error list.
	 * @param to
	 *            to index in the error list.
	 * @param type
	 *            type 0 for MetaReaderException; 1 for MetaDataException.
	 */

	private void assertErrorCode( String expected, int from, int to, int type )
	{
		assert errorList.size( ) > to;
		assert from <= to;
		assert from >= 0;

		for ( int i = from; i < to; i++ )
		{
			if ( type == 0 )
			{
				assertEquals( expected, ( (MetaDataParserException) errorList
						.get( i ) ).getErrorCode( ) );
			}
			else if ( type == 1 )
			{
				assertEquals(
						expected,
						( (MetaDataException) ( (MetaDataParserException) errorList
								.get( i ) ).getException( ) ).getErrorCode( ) );

			}
		}
	}

}
