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

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import junit.framework.TestCase;
import woolpack.TestBean;
import woolpack.TestUtils;
import woolpack.action.ActionConstants;
import woolpack.action.ActionDef;
import woolpack.action.ActionInvoker;
import woolpack.action.ForwardDef;
import woolpack.dom.DomContext;
import woolpack.dom.DomExpression;
import woolpack.dom.Serial;
import woolpack.utils.OGE;

public class ActionBuilderTest extends TestCase {
	
	private ActionInvoker defs;
	private ActionBuilder builder;
	
	@Override protected void setUp(){
		final ForwardDef expectedForwardDef = new ForwardDef("forwardId0", new OGE("local.forwardBean0"), ActionConstants.NOT_THROWABLE);
		final Map<String,ActionDef> map = new HashMap<String,ActionDef>();
		map.put("id0", new ActionDef(new OGE("myBean"), new OGE("container.myBean.executeVoid()"), expectedForwardDef));
		map.put("id1", new ActionDef(new OGE("myBean"), new OGE("container.myBean.executeInt()"), expectedForwardDef));
		map.put("id2", new ActionDef(new OGE("myBean"), new OGE("container.myBean.executeException()"), expectedForwardDef));
		defs = new ActionInvoker(map, new ForwardDef("forwardId2", new OGE("local.forwardBean2"), ActionConstants.ANY));
		builder = new ActionBuilder(defs, Arrays.asList("name", "id"));
	}

	public void testConstructor(){
		try{
			new ActionBuilder(null, Arrays.asList("name", "id"), OGE.NULL, OGE.NULL);
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ActionBuilder(defs, null, OGE.NULL, OGE.NULL);
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ActionBuilder(defs, Arrays.asList("name", "id"), null, OGE.NULL);
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ActionBuilder(defs, Arrays.asList("name", "id"), OGE.NULL, null);
			fail();
		}catch(final NullPointerException expected){
		}
	}
	
	public void testGet(){
		final ActionBuilder builder = new ActionBuilder(defs, Arrays.asList("name", "id"), new OGE("forwardComponent0"), new OGE("return0"));
		assertEquals(new OGE("forwardComponent0"), builder.getForwardComponentOGEOGE());
		assertEquals(new OGE("return0"), builder.getReturnOGE());
	}
	
	public void testGetActionExpressionReturnVoid(){ 
		final DomContext context = new DomContext();
		context.setId("id0");
		new OGE("input = #{\"myInt\":{\"7\"}}").getValue(context);
		context.setContainer(Collections.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().interpret(context);
		assertEquals("forwardId0", context.getId());
		assertEquals(new OGE("local.forwardBean0"), ActionBuilder.DEFAULT_FORWARD_COMPONENT_OGE_OGE.getValue(context));
		assertNull(ActionBuilder.DEFAULT_RETURN_OGE.getValue(context));
	}
	
	public void testGetActionExpressionReturnInteger(){ 
		final DomContext context = new DomContext();
		context.setId("id1");
		new OGE("input = #{\"myInt\":{\"7\"}}").getValue(context);
		context.setContainer(Collections.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().interpret(context);
		assertEquals("forwardId0", context.getId());
		assertEquals(new OGE("local.forwardBean0"), ActionBuilder.DEFAULT_FORWARD_COMPONENT_OGE_OGE.getValue(context));
		assertEquals(new Integer(1), ActionBuilder.DEFAULT_RETURN_OGE.getValue(context));
	}
	
	public void testGetActionExpressionException(){ 
		final DomContext context = new DomContext();
		context.setId("id2");
		new OGE("input = #{\"myInt\":{\"7\"}}").getValue(context);
		context.setContainer(Collections.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().interpret(context);
		assertEquals("forwardId2", context.getId());
		assertEquals(new OGE("local.forwardBean2"), ActionBuilder.DEFAULT_FORWARD_COMPONENT_OGE_OGE.getValue(context));
		Iterator iterator = ((Iterable)ActionBuilder.DEFAULT_RETURN_OGE.getValue(context)).iterator();
		assertTrue(iterator.hasNext());
		assertEquals("java.lang.IndexOutOfBoundsException", iterator.next());
		assertFalse(iterator.hasNext());
	}

	public void testGetAutoUpdateExpression(){
		final DomExpression expression = new Serial(
				TestUtils.getToNodeForm(
						"<TEXTAREA name=\"textarea0\" >value0</TEXTAREA>"+ 
						"<DIV id=\"div0\" >value0</DIV>"+ 
						"<SPAN id=\"span0\" >value0</SPAN>"+ 
						"<INPUT name=\"input0\" value=\"value0\" />"+ 
						"<SPAN id=\"span1\" >spanvalue1</SPAN>"),
				builder.getAutoUpdateExpression());
		{
			final DomContext context = new DomContext();
			new OGE("local.forwardBean0 = #{\"textarea0\":\"textareavalue0\", \"div0\":\"divvalue0\", \"span0\":\"spanvalue0\", \"input0\":\"inputvalue0\"}").getValue(context);
			ActionBuilder.DEFAULT_FORWARD_COMPONENT_OGE_OGE.setValue(context, new OGE("local.forwardBean0"));
			expression.interpret(context);

			assertTrue(TestUtils.equalsForm(context, 
					"<TEXTAREA name=\"textarea0\" >textareavalue0</TEXTAREA>"+ 
					"<DIV id=\"div0\" >divvalue0</DIV>"+ 
					"<SPAN id=\"span0\" >spanvalue0</SPAN>"+ 
					"<INPUT name=\"input0\" value=\"inputvalue0\" />"+ 
					"<SPAN id=\"span1\" >spanvalue1</SPAN>"));
		}
		{
			final DomContext context = new DomContext();
			ActionBuilder.DEFAULT_FORWARD_COMPONENT_OGE_OGE.setValue(context, new OGE("local.forwardBean0"));
			expression.interpret(context);

			assertTrue(TestUtils.equalsForm(context, 
					"<TEXTAREA name=\"textarea0\" >value0</TEXTAREA>"+ 
					"<DIV id=\"div0\" >value0</DIV>"+ 
					"<SPAN id=\"span0\" >value0</SPAN>"+ 
					"<INPUT name=\"input0\" value=\"value0\" />"+ 
					"<SPAN id=\"span1\" >spanvalue1</SPAN>"));
		}
	}
}
