/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package woolpack.locale;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import junit.framework.TestCase;
import woolpack.dom.Count;
import woolpack.dom.DomConstants;
import woolpack.dom.DomContext;
import woolpack.dom.DomExpression;
import woolpack.dom.XmlToNode;
import woolpack.test.TestUtils;
import woolpack.utils.IOExceptionReaderFactory;

public class LocaleIdTest extends TestCase {
	
	public void testConstructor(){
		try{
			new LocaleId(null, new ThreadLocal<Locale>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new LocaleId(DomConstants.NULL, null);
			fail();
		}catch(final NullPointerException expected){
		}
	}
	
	public void testSearch(){
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final List<String> result = new ArrayList<String>();
		final Count counter = new Count(new DomExpression(){
			public void interpret(DomContext context) {
				result.add(context.getId());
			}
		});
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();
		context.setId("id0");
		
		final Locale defaultLocale = Locale.getDefault();
		try{
			Locale.setDefault(new Locale("ja", "JP", "POSIX"));

			result.clear();
			threadLocal.set(new Locale("en", "US", "WIN"));
			try{
				expression.interpret(context);
				fail();
			}catch(final RuntimeException expected){
			}
			assertEquals(7, counter.getCount());
			assertTrue(TestUtils.equals(Arrays.asList(
					"id0_en_US_WIN",
					"id0_en_US",
					"id0_en",
					"id0_ja_JP_POSIX",
					"id0_ja_JP",
					"id0_ja",
					"id0"
					), result));

			result.clear();
			threadLocal.set(null);
			try{
				expression.interpret(context);
				fail();
			}catch(final RuntimeException expected){
			}
			assertEquals(11, counter.getCount());
			assertTrue(TestUtils.equals(Arrays.asList(
					"id0_ja_JP_POSIX",
					"id0_ja_JP",
					"id0_ja",
					"id0"
					), result));
		}finally{
			Locale.setDefault(defaultLocale);
		}
		
	}

	public void testNormal(){
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(TestUtils.getToNodeBody("test"));
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		expression.interpret(context);
		assertEquals(1, counter.getCount());
		assertTrue(TestUtils.equalsBody(context, "test"));
	}

	public void testIOException(){
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(new XmlToNode(new IOExceptionReaderFactory()));
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try{
			expression.interpret(context);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof IOException);
		}
	}

	public void testException(){
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(new DomExpression(){
			public void interpret(DomContext context) {
				throw new RuntimeException();
			}
		});
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try{
			expression.interpret(context);
			fail();
		}catch(final RuntimeException expected){
			assertNull(expected.getCause());
		}
	}

	public void testNull(){
		final ThreadLocal<Locale> threadLocal = new ThreadLocal<Locale>();
		final Count counter = new Count(DomConstants.NULL);
		final DomExpression expression = new LocaleId(counter, threadLocal);
		final DomContext context = new DomContext();

		threadLocal.set(Locale.JAPANESE);
		context.setId("id0");
		try{
			expression.interpret(context);
			fail();
		}catch(final RuntimeException expected){
			assertNull(expected.getCause());
		}
	}
}
