/*******************************************************************************
 * 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.tests.model.api.util;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Locale;

import org.eclipse.birt.core.format.DateFormatter;
import org.eclipse.birt.core.format.NumberFormatter;
import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
import org.eclipse.birt.report.model.api.metadata.PropertyValueException;
import org.eclipse.birt.report.model.api.metadata.ValidationValueException;
import org.eclipse.birt.report.model.api.util.ParameterValidationUtil;
import org.eclipse.birt.report.model.i18n.ThreadResources;
import org.eclipse.birt.report.tests.model.BaseTestCase;

import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;


/**
 * Tests the ParameterUtil.
 */

public class ParameterValidationUtilTest extends BaseTestCase {

	/**
	 * @param name
	 */
	public ParameterValidationUtilTest(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
	}

	/**
	 * Tests the validation of the boolean type.
	 * 
	 * @throws Exception
	 */

	public void testBoolean() throws Exception {
		// in the JAPAN locale

		ThreadResources.setLocale(ULocale.ENGLISH);
		String value = null;

		assertEquals(null, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, null,
				Locale.JAPAN));
		assertEquals(null, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null,
				"", Locale.JAPAN)); //$NON-NLS-1$

		// the input value is locale dependent

		value = "\u771f"; //$NON-NLS-1$
		assertEquals(Boolean.TRUE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				new Locale("aa"))); //$NON-NLS-1$
		assertEquals(Boolean.TRUE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				new Locale("aa"))); //$NON-NLS-1$
		value = "\u5047"; //$NON-NLS-1$
		assertEquals(Boolean.FALSE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				new Locale("aa"))); //$NON-NLS-1$
		assertEquals(Boolean.FALSE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				new Locale("aa"))); //$NON-NLS-1$

		// the input value is locale independent

		value = "true"; //$NON-NLS-1$
		assertEquals(Boolean.TRUE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				Locale.JAPAN));
		assertEquals(Boolean.TRUE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				Locale.JAPAN));
		value = "false"; //$NON-NLS-1$
		assertEquals(Boolean.FALSE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				Locale.JAPAN));
		assertEquals(Boolean.FALSE, ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, value,
				Locale.JAPAN));

		// catch some exception
		try {
			ParameterValidationUtil.validate(
					DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null,
					"tru", Locale.JAPAN); //$NON-NLS-1$
			fail();
		} catch (ValidationValueException e) {
			System.out.println(e.getMessage());
			assertEquals(PropertyValueException.DESIGN_EXCEPTION_INVALID_VALUE,
					e.getErrorCode());
		}
		try {
			ParameterValidationUtil.validate(
					DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null,
					"fals", Locale.JAPAN); //$NON-NLS-1$
			fail();
		} catch (ValidationValueException e) {
			System.out.println(e.getMessage());
			assertEquals(PropertyValueException.DESIGN_EXCEPTION_INVALID_VALUE,
					e.getErrorCode());
		}
	}

	/**
	 * Tests the validation of the float and decimal type.
	 * 
	 * @throws Exception
	 * 
	 */

	public void testNumber() throws Exception {
		double input = 123.4564d;

		// validates the input and get the locale and format independent result
		String value = "123.0"; //$NON-NLS-1$
		ThreadResources.setLocale(ULocale.FRANCE);
		NumberFormatter formatter = new NumberFormatter(ThreadResources
				.getLocale());
		formatter
				.applyPattern(DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER);
		value = formatter.format(input);
		assertEquals("123.456", ParameterValidationUtil.validate( //$NON-NLS-1$
				DesignChoiceConstants.PARAM_TYPE_FLOAT,
				DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER, value,
				Locale.FRANCE).toString());
		ThreadResources.setLocale(ULocale.CHINA);
		formatter = new NumberFormatter(ThreadResources.getLocale());
		formatter
				.applyPattern(DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER);
		value = formatter.format(input);
		assertEquals("123.456", ParameterValidationUtil.validate( //$NON-NLS-1$
				DesignChoiceConstants.PARAM_TYPE_FLOAT,
				DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER, value,
				Locale.CHINA).toString());

		try {
			ParameterValidationUtil.validate(
					DesignChoiceConstants.PARAM_TYPE_DECIMAL,
					DesignChoiceConstants.NUMBER_FORMAT_TYPE_SCIENTIFIC,
					"ergh", //$NON-NLS-1$
					Locale.FRANCE);
			fail();
		} catch (ValidationValueException e) {
			System.out.println(e.getMessage());
			assertEquals(PropertyValueException.DESIGN_EXCEPTION_INVALID_VALUE,
					e.getErrorCode());
		}
	}

	public void testDateTime() throws Exception {
		// validates the input locale-dependent date time
		// and get the result locale-independent and standard
		// output string, test the result is the same with
		// the two different locale and input string about the same
		// date time

		String value1 = "1998-09-13 20:01:44"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_GENERAL_DATE, value1); //$NON-NLS-1$
		String value2 = "1998-09-13 00:00:00"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_LONG_DATE, value2); //$NON-NLS-1$
		String value3 = "1998-09-13 00:00:00"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_MUDIUM_DATE, value3); //$NON-NLS-1$
		String value4 = "1998-09-13 00:00:00"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_SHORT_DATE, value4); //$NON-NLS-1$
		String value5 = "1970-01-01 20:01:44"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_LONG_TIME, value5); //$NON-NLS-1$
		String value6 = "1970-01-01 20:01:44"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_MEDIUM_TIME, value6); //$NON-NLS-1$\
		String value7 = "1970-01-01 20:01:00"; //$NON-NLS-1$
		testDateTimeByFormat(
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_SHORT_TIME, value7); //$NON-NLS-1$
	}

	/**
	 * Tests the validation of the date time type.
	 * 
	 * @param format
	 *            the format choice string
	 * @param result
	 *            the validation result string
	 * 
	 * @throws Exception
	 * 
	 */

	private void testDateTimeByFormat( String format, String result )
	throws Exception
{
// in JAP locale

ThreadResources.setLocale( ULocale.JAPAN );
String value = null;
final SimpleDateFormat formatPattern = new SimpleDateFormat(
		"yyyy-MM-dd HH:mm:ss" ); //$NON-NLS-1$
Calendar dateCal = Calendar.getInstance( ThreadResources.getLocale( ) );
dateCal.set( 1998, 8, 13, 20, 1, 44 );
DateFormatter formatter = new DateFormatter( ThreadResources
		.getLocale( ) );
formatter.applyPattern( format );
value = formatter.format( dateCal.getTime( ) );
String resultJAP = formatPattern.format( ParameterValidationUtil
		.validate( DesignChoiceConstants.PARAM_TYPE_DATETIME, format,
				value, ULocale.JAPAN ) == null
		? null
		: ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_DATETIME, format,
				value, ULocale.JAPAN ) );
assertEquals( result, resultJAP );

// in EN locale

ThreadResources.setLocale( ULocale.ENGLISH );
dateCal = Calendar.getInstance( ThreadResources.getLocale( ) );
dateCal.set( 1998, 8, 13, 20, 1, 44 );
formatter = new DateFormatter( ThreadResources.getLocale( ) );
formatter.applyPattern( format );
value = formatter.format( dateCal.getTime( ) );
String resultEN = formatPattern.format( ParameterValidationUtil
		.validate( DesignChoiceConstants.PARAM_TYPE_DATETIME, format,
				value, ULocale.ENGLISH ) == null
		? null
		: ParameterValidationUtil.validate(
				DesignChoiceConstants.PARAM_TYPE_DATETIME, format,
				value, ULocale.ENGLISH ) );
assertEquals( result, resultEN ); //$NON-NLS-1$

// the two result value is equal.

assertEquals( resultJAP, resultEN );
}

/**
* Tests the validation of the string type.
* 
* @throws Exception
*/

public void testString( ) throws Exception
{
ThreadResources.setLocale( ULocale.ENGLISH );
String value = null;

// upper case

// lower case

// validate without format

value = null;
assertEquals( null, ParameterValidationUtil.validate(
		DesignChoiceConstants.PARAM_TYPE_STRING, null, value,
		ULocale.ENGLISH ) );
value = ""; //$NON-NLS-1$
assertEquals( "", ParameterValidationUtil.validate( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING, null, value,
		ULocale.ENGLISH ) );
value = "ab CD e"; //$NON-NLS-1$
assertEquals( "ab CD e", ParameterValidationUtil.validate( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING, null, value,
		ULocale.ENGLISH ) );
value = "ab $#"; //$NON-NLS-1$
assertEquals( "ab $#", ParameterValidationUtil.validate( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING, null, value,
		ULocale.ENGLISH ) );
value = "(444)444-4444"; //$NON-NLS-1$
assertEquals( "4444444444", ParameterValidationUtil.validate( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING,
		DesignChoiceConstants.STRING_FORMAT_TYPE_PHONE_NUMBER, value,
		ULocale.ENGLISH ) );
}

public void testGetDisplayValue( )
{
// date time type
Calendar dateCal = Calendar.getInstance( ThreadResources.getLocale( ) );
dateCal.set( 1998, 8, 13, 20, 1, 44 );
Date dateValue = dateCal.getTime( );

assertEquals(
		"13 septembre 1998", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
				DesignChoiceConstants.PARAM_TYPE_DATETIME,
				DesignChoiceConstants.DATETIEM_FORMAT_TYPE_LONG_DATE,
				dateValue, ULocale.FRANCE ) );
// no format, then we display in (medium, medium) pattern
assertEquals(
		"Sep 13, 1998 8:01:44 PM", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
						DesignChoiceConstants.PARAM_TYPE_DATETIME,
						null, dateValue ) );

// float type
Double doubleValue = new Double( "12345.456" ); //$NON-NLS-1$
assertEquals( "12345.456", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_FLOAT,
		DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER,
		doubleValue, ULocale.ENGLISH ) );
assertEquals( "12345,456", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_FLOAT,
		DesignChoiceConstants.NUMBER_FORMAT_TYPE_GENERAL_NUMBER,
		doubleValue, ULocale.GERMAN ) );
assertEquals( "Currency12345", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_FLOAT,
		DesignChoiceConstants.NUMBER_FORMAT_TYPE_CURRENCY, doubleValue,
		ULocale.GERMAN ) );

// decimal type
BigDecimal decimalValue = new BigDecimal( "12345678" ); //$NON-NLS-1$
assertEquals( "12.345.678,00", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_DECIMAL,
		DesignChoiceConstants.NUMBER_FORMAT_TYPE_STANDARD,
		decimalValue, ULocale.GERMAN ) );
assertEquals( "12,345,678.00", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_DECIMAL,
		DesignChoiceConstants.NUMBER_FORMAT_TYPE_STANDARD,
		decimalValue, ULocale.ENGLISH ) );

// string type
String stringValue = "0211234567"; //$NON-NLS-1$
assertEquals( "(021)123-4567", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING,
		DesignChoiceConstants.STRING_FORMAT_TYPE_PHONE_NUMBER,
		stringValue, ULocale.GERMAN ) );
assertEquals( "(021)123-4567", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING,
		DesignChoiceConstants.STRING_FORMAT_TYPE_PHONE_NUMBER,
		stringValue, ULocale.ENGLISH ) );
assertEquals( "021123-4567", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_STRING,
		DesignChoiceConstants.STRING_FORMAT_TYPE_ZIP_CODE_4,
		stringValue, ULocale.GERMAN ) );

// boolean type
assertEquals( "false", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, Boolean.FALSE,
		ULocale.ENGLISH ) );
assertEquals( "\u5047", ParameterValidationUtil.getDisplayValue( //$NON-NLS-1$
		DesignChoiceConstants.PARAM_TYPE_BOOLEAN, null, Boolean.FALSE,
		new ULocale( "aa" ) ) ); //$NON-NLS-1$
}
}