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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import woolpack.TestUtils;

import junit.framework.TestCase;

public class UtilsConstantsTest extends TestCase {

	public void testDefaultValueMap(){
		final Map<String,String> map = UtilsConstants.defaultValueMap(new HashMap<String,String>(), "C");
		map.put("a", "A");
		map.put("b", "B");
		assertEquals("A", map.get("a"));
		assertEquals("B", map.get("b"));
		assertEquals("C", map.get("c"));
		assertEquals("C", map.get("d"));
	}	

	public void testUnoverwritableMap(){
		final Map<String,String> map = UtilsConstants.unoverwritableMap(new HashMap<String,String>());
		map.put("a", "z");
		map.put("b", "z");
		try{
			map.put("a", "y");
			fail();
		}catch(final IllegalArgumentException expected){
			assertEquals("duplicate: a", expected.getMessage());
		}
		{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("c", "z");
			tmp.put("d", "z");
			map.putAll(tmp);
		}
		try{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("e", "z");
			tmp.put("b", "z");
			map.putAll(tmp);
			fail();
		}catch(final IllegalArgumentException expected){
			assertEquals("duplicate: b", expected.getMessage());
		}
	}
	
	public void testNotNullMap(){
		final Map<String,String> map = UtilsConstants.notNullMap(new HashMap<String,String>());
		map.put("a", "z");
		map.put("b", "z");
		try{
			map.put(null, "y");
			fail();
		}catch(final NullPointerException expected){
		}
		map.put("c", "z");
		try{
			map.put("d", null);
			fail();
		}catch(final NullPointerException expected){
		}
		{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("e", "z");
			tmp.put("f", "z");
			map.putAll(tmp);
		}
		try{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("g", "z");
			tmp.put(null, "z");
			map.putAll(tmp);
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("h", "z");
			tmp.put("i", null);
			map.putAll(tmp);
			fail();
		}catch(final NullPointerException expected){
		}
	}
	
	public void testKeyNotEmptyMap(){
		final Map<String,String> map = UtilsConstants.keyNotEmptyMap(new HashMap<String,String>());
		map.put("a", "z");
		map.put("b", "z");
		{
			final Map<String,String> tmp = new HashMap<String,String>();
			map.put("c", "z");
			map.put("d", "z");
			map.putAll(tmp);
		}
		try{
			map.put("", "y");
			fail();
		}catch(final StringIndexOutOfBoundsException expected){
		}
		{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("c", "z");
			tmp.put("d", "z");
			map.putAll(tmp);
		}
		try{
			final Map<String,String> tmp = new HashMap<String,String>();
			tmp.put("e", "z");
			tmp.put("", "z");
			map.putAll(tmp);
			fail();
		}catch(final StringIndexOutOfBoundsException expected){
		}
	}
	
	public void testUnmodifiableIterable(){
		final Iterable<String> iterable;
		{
			final List<String> list = new ArrayList<String>();
			list.add("a");
			iterable = UtilsConstants.unmodifiableIterable(list);
		}
		final Iterator<String> it = iterable.iterator();
		assertTrue(it.hasNext());
		assertEquals("a", it.next());
		assertFalse(it.hasNext());
		try{
			it.remove();
			fail();
		}catch(final UnsupportedOperationException expected){
		}
	}
	
	public void testToListFromNull(){
		final List list = UtilsConstants.toList(null);
		assertEquals(1, list.size());
		assertNull(list.get(0));
	}
	
	public void testToListFromPrimitiveArray(){
		final int[] array = new int[2];
		final List list = UtilsConstants.toList(array);
		assertEquals(2, list.size());
		list.set(1, new Integer(3));
		assertEquals(3, array[1]);
		assertEquals(new Integer(3), list.get(1));
	}
	
	public void testToListFromObjectArray(){
		final Integer[] array = new Integer[2];
		final List list = UtilsConstants.toList(array);
		assertEquals(2, list.size());
		list.set(1, new Integer(3));
		assertEquals(new Integer(3), array[1]);
		assertEquals(new Integer(3), list.get(1));
	}
	
	public void testToListFromList(){
		final List target = new ArrayList();
		assertEquals(target, UtilsConstants.toList(target));
	}
	
	public void testToListFromObject(){
		final Integer target = new Integer(3);
		final List list = UtilsConstants.toList(target);
		assertEquals(1, list.size());
		assertEquals(target, list.get(0));
	}
	
	public void testToCollectionFromCollection(){
		final Collection target = new ArrayList();
		assertEquals(target, UtilsConstants.toCollection(target));
	}
	
	public void testToIterableFromIterable(){
		final Iterable target = new ArrayList();
		assertEquals(target, UtilsConstants.toIterable(target));
	}

	public void testSimilarKeyMap(){
		final Map<String,String> mapA = new HashMap<String,String>();
		mapA.put("hoge_piyo", "hoge_piyo");
		mapA.put("NARU_HODO", "NARU_HODO");
		mapA.put("fooBar", "fooBar");
		mapA.put("GinowanOkinawa", "GinowanOkinawa");
		final Map<String,String> mapB = UtilsConstants.similarKeyMap(mapA);
		
		assertEquals(mapA.get("hoge_piyo"), mapB.get("hoge_piyo"));
		assertEquals(mapA.get("hoge_piyo"), mapB.get("HOGE_PIYO"));
		assertEquals(mapA.get("hoge_piyo"), mapB.get("hogePiyo"));
		assertEquals(mapA.get("hoge_piyo"), mapB.get("HogePiyo"));
		
		assertEquals(mapA.get("NARU_HODO"), mapB.get("NARU_HODO"));
		assertEquals(mapA.get("NARU_HODO"), mapB.get("naru_hodo"));
		assertEquals(mapA.get("NARU_HODO"), mapB.get("naruHodo"));
		assertEquals(mapA.get("NARU_HODO"), mapB.get("NaruHodo"));
		
		assertEquals(mapA.get("fooBar"), mapB.get("fooBar"));
		assertEquals(mapA.get("fooBar"), mapB.get("FooBar"));
		assertEquals(mapA.get("fooBar"), mapB.get("foo_bar"));
		assertEquals(mapA.get("fooBar"), mapB.get("FOO_BAR"));
		
		assertEquals(mapA.get("GinowanOkinawa"), mapB.get("GinowanOkinawa"));
		assertEquals(mapA.get("GinowanOkinawa"), mapB.get("ginowanOkinawa"));
		assertEquals(mapA.get("GinowanOkinawa"), mapB.get("GINOWAN_OKINAWA"));
		assertEquals(mapA.get("GinowanOkinawa"), mapB.get("ginowan_okinawa"));

		assertTrue(mapB.containsKey("hoge_piyo"));
		assertTrue(mapB.containsKey("HOGE_PIYO"));
		assertTrue(mapB.containsKey("hogePiyo"));
		assertTrue(mapB.containsKey("HogePiyo"));
		assertFalse(mapB.containsKey("HogePiyo "));
		
		assertNull(mapB.get("hoge_piy0"));
	}
	
	public void testToMessageList(){
		assertEquals(
				Arrays.asList(new String[]{"message0", "message1", "message2"}),
				Arrays.asList(UtilsConstants.toMessageList(
						new Exception("message0", new Exception("message1", new Exception("message2")))
						).toArray(new String[0])));
		assertEquals(
				Arrays.asList(new String[]{"message0", "message2"}),
				Arrays.asList(UtilsConstants.toMessageList(
						new Exception("message0", new Exception(null, new Exception("message2")))
						).toArray(new String[0])));
		assertEquals(
				Arrays.asList(new String[]{"message1", "message2"}),
				Arrays.asList(UtilsConstants.toMessageList(
						new Exception(new Exception("message1", new Exception("message2")))
						).toArray(new String[0])));
		assertEquals(
				Arrays.asList(new String[]{"message0", "message2"}),
				Arrays.asList(UtilsConstants.toMessageList(
						new Exception("message0", new Exception(new Exception("message2")))
						).toArray(new String[0])));
		assertEquals(
				Arrays.asList(new String[]{"message0", "message1", "java.lang.IllegalArgumentException"}),
				Arrays.asList(UtilsConstants.toMessageList(
						new Exception("message0", new Exception("message1", new IllegalArgumentException()))
						).toArray(new String[0])));
	}
	
	private void checkEquals(final boolean expected, final String oge0, final String oge1){
		assertEquals(expected, TestUtils.equals(new OGE(oge0).getValue(null), new OGE(oge1).getValue(null)));
	}
	
	public void testEquals(){
		checkEquals(true, "null", "null");
		checkEquals(false, "1", "null");
		checkEquals(false, "null", "1");
		
		checkEquals(true, "1", "1");
		checkEquals(false, "1", "2");
		
		checkEquals(true, "{1,2}", "{1,2}");
		checkEquals(false, "{1,2}", "{2,1}");
		checkEquals(false, "{1,2}", "{1,3}");
		checkEquals(false, "{1,2}", "{1}");
		
		checkEquals(true, "new java.util.HashSet({1,2})", "{1,2}");
		checkEquals(true, "new java.util.HashSet({1,2})", "{2,1}");
		checkEquals(false, "new java.util.HashSet({1,2})", "{1,3}");
		checkEquals(false, "new java.util.HashSet({1,2})", "{1}");
		
		checkEquals(true, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.LinkedHashMap@{1:11,2:12}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.LinkedHashMap@{2:12,1:11}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.LinkedHashMap@{1:11,2:13}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.LinkedHashMap@{1:11,3:12}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.LinkedHashMap@{1:11}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:12}", "#@java.util.LinkedHashMap@{1:11,2:12}");
		
		checkEquals(true, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.HashMap@{1:11,2:12}");
		checkEquals(true, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.HashMap@{2:12,1:11}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.HashMap@{1:11,2:13}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.HashMap@{1:11,3:12}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:11,2:12}", "#@java.util.HashMap@{1:11}");
		checkEquals(false, "#@java.util.LinkedHashMap@{1:12}", "#@java.util.HashMap@{1:11,2:12}");
		
		checkEquals(false, "#{1:11}", "1");
		checkEquals(false, "1", "#{1:11}");
		
		checkEquals(false, "{1}", "1");
		checkEquals(false, "1", "{1}");
		
		checkEquals(false, "#{1:11}", "{1}");
		checkEquals(false, "{1}", "#{1:11}");
		
		checkEquals(true, "#{1:{1,2}}", "#{1:{1,2}}");
		checkEquals(false, "#{1:{1,2}}", "#{1:{2,1}}");
		checkEquals(false, "#{1:{1,2}}", "#{1:{1,3}}");
		checkEquals(false, "#{1:{1,2}}", "#{1:{1}}");
		
		checkEquals(true, "#{1:new java.util.HashSet({1,2})}", "#{1:{1,2}}");
		checkEquals(true, "#{1:new java.util.HashSet({1,2})}", "#{1:{2,1}}");
		checkEquals(false, "#{1:new java.util.HashSet({1,2})}", "#{1:{1,3}}");
		checkEquals(false, "#{1:new java.util.HashSet({1,2})}", "#{1:{1}}");
	}
}
