/*
 * 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.HashMap;
import java.util.Map;

import junit.framework.TestCase;
import ognl.MethodFailedException;
import ognl.OgnlException;
import woolpack.TestBean;

public class OGETest extends TestCase {

	public void testConstructor(){
		try{
			new OGE(null);
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new OGE("!");
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
		try{
			new OGE("");
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testSetGet(){
		final Map<String, String> map = new HashMap<String, String>();
		map.put("param0", "value0");
		assertEquals("value0", new OGE("param0").getValue(map));
		
		new OGE("param1").setValue(map, "value1");
		assertEquals("value1", new OGE("param1").getValue(map));

		assertNull(new OGE("param2").getValue(map));

		new OGE("param3").setValue(map, null);
		assertNull(new OGE("param3").getValue(map));
	}
	
	public void testGetException(){
		final Map map = new HashMap();
		try{
			new OGE("param0.param1").getValue(map);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testGetStringException(){
		final Map map = new HashMap();
		try{
			new OGE("param0.param1").getString(map);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testSetException(){
		final Map map = new HashMap();
		try{
			new OGE("param0.param1").setValue(map, "a");
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testSetValuesSingle(){
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("myBean", new TestBean());
		{
			final Map<String, Object> paramMap = new HashMap<String, Object>();
			paramMap.put("myInt", new Integer(3));
			new OGE("myBean").setValues(root, paramMap);
			assertEquals(new Integer(3), new OGE("myBean.myInt").getValue(root));
		}
		{
			final Map<String, Object> paramMap = new HashMap<String, Object>();
			paramMap.put("myInt", "5");
			new OGE("myBean").setValues(root, paramMap);
			assertEquals(new Integer(5), new OGE("myBean.myInt").getValue(root));
		}
	}
	
	public void testSetValuesInteger(){
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("myBean", new TestBean());
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("myInt", new Integer[]{new Integer(3)});
		paramMap.put("myCollection", new Integer[]{new Integer(11), new Integer(13)});
		paramMap.put("myIntArray", new Integer[]{new Integer(5), new Integer(7)});
		
		new OGE("myBean").setValues(root, paramMap);

		assertEquals(new Integer(3), new OGE("myBean.myInt").getValue(root));
		assertEquals(new Integer(2), new OGE("myBean.myIntArray.length").getValue(root));
		assertEquals(new Integer(5), new OGE("myBean.myIntArray[0]").getValue(root));
		assertEquals(new Integer(7), new OGE("myBean.myIntArray[1]").getValue(root));
		assertEquals(Boolean.TRUE, new OGE("myBean.myCollection == {11, 13}").getValue(root));
	}
	
	public void testSetValuesInt(){
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("myBean", new TestBean());
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("myInt", new int[]{3});
		paramMap.put("myCollection", new int[]{11, 13});
		paramMap.put("myIntArray", new int[]{5, 7});
		
		new OGE("myBean").setValues(root, paramMap);

		assertEquals(new Integer(3), new OGE("myBean.myInt").getValue(root));
		assertEquals(new Integer(2), new OGE("myBean.myIntArray.length").getValue(root));
		assertEquals(new Integer(5), new OGE("myBean.myIntArray[0]").getValue(root));
		assertEquals(new Integer(7), new OGE("myBean.myIntArray[1]").getValue(root));
		assertEquals(Boolean.TRUE, new OGE("myBean.myCollection == {11, 13}").getValue(root));
	}
	
	public void testSetValuesString(){
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("myBean", new TestBean());
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("myInt", new String[]{"3"});
		paramMap.put("myIntArray", new String[]{"5", "7"});
		paramMap.put("myCollection", new String[]{"11", "13"});
		
		new OGE("myBean").setValues(root, paramMap);

		assertEquals(new Integer(3), new OGE("myBean.myInt").getValue(root));
		assertEquals(new Integer(2), new OGE("myBean.myIntArray.length").getValue(root));
		assertEquals(new Integer(5), new OGE("myBean.myIntArray[0]").getValue(root));
		assertEquals(new Integer(7), new OGE("myBean.myIntArray[1]").getValue(root));
		assertEquals(Boolean.TRUE, new OGE("myBean.myCollection == {\"11\", \"13\"}").getValue(root));
	}
	
//	public void testSetValuesException0(){
//		final Map<String, Object> root = new HashMap<String, Object>();
//		root.put("myBean", new Object());
//		try{
//			final Map<String, Object> paramMap = new HashMap<String, Object>();
//			paramMap.put("myInt", new Integer(3));
//			new OGE("yourBean").setValues(root, paramMap);
//			fail();
//		}catch(final RuntimeException expected){
//			assertTrue(expected.getCause() instanceof OgnlException);
//		}
//	}
	
	public void testSetValuesException1(){
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("myBean", new Object());
		try{
			final Map<String, Object> paramMap = new HashMap<String, Object>();
			paramMap.put("myInt", new Integer(3));
			new OGE("myBean.yourBean").setValues(root, paramMap);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testInvoke() throws MethodFailedException{
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("component0", new TestBean());
		{
			final Object result = new OGE("component0.executeVoid()").invoke(root);
			assertNull(result);
		}
		{
			Object result = new OGE("component0.executeInt()").invoke(root);
			assertEquals(new Integer(1), result);

			result = new OGE("component0.executeInt()").invoke(root);
			assertEquals(new Integer(2), result);
		}
		try{
			new OGE("component0.executeException()").invoke(root);
			fail();
		}catch(final MethodFailedException e){
			assertTrue(e.getReason() instanceof IndexOutOfBoundsException);
		}
	}
	
	public void testInvokeMethodNotFound() throws MethodFailedException{
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("component0", new TestBean());
		try{
			new OGE("component0.executeNotFound()").invoke(root);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testInvokeException() throws MethodFailedException{
		final Map<String, Object> root = new HashMap<String, Object>();
		root.put("component0", new TestBean());
		try{
			new OGE("component0.notFoundProperty").invoke(root);
			fail();
		}catch(final RuntimeException expected){
			assertTrue(expected.getCause() instanceof OgnlException);
		}
	}
	
	public void testEquals(){
		assertTrue(new OGE("a").equals(new OGE("a")));
		assertFalse(new OGE("a").equals(new OGE("b")));
		assertFalse(new OGE("a").equals(new Object()));
	}
	
	public void testHashCode(){
		assertEquals("a".hashCode(), new OGE("a").hashCode());
		assertEquals("b".hashCode(), new OGE("b").hashCode());
	}
}
