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

import junit.framework.TestCase;
import woolpack.action.ActionDef;
import woolpack.action.ActionInvoker;
import woolpack.action.ForwardDef;
import woolpack.adapter.OGE;
import woolpack.bool.BoolUtils;
import woolpack.el.EL;
import woolpack.el.ELUtils;
import woolpack.el.FixEL;
import woolpack.el.PathEL;
import woolpack.fn.Fn;
import woolpack.fn.FnUtils;
import woolpack.test.TestBean;
import woolpack.utils.Utils;
import woolpack.xml.XmlUtils;

public class ActionBuilderTest extends TestCase {

	private ActionInvoker defs;
	private ActionBuilder builder;
	private EL localForwardBean0 = new PathEL("local.forwardBean0");
	private EL localForwardBean2 = new PathEL("local.forwardBean2");

	@Override
	protected void setUp() {
		final ForwardDef expectedForwardDef = new ForwardDef("forwardId0",
				localForwardBean0, BoolUtils.NOT_THROWABLE);
		defs = new ActionInvoker(FnUtils.switching(Utils
				.map("id0", new ActionDef(
						ELUtils.NULL,
						new OGE("container.myBean.executeVoid()"),
						expectedForwardDef))
				.map("id1", new ActionDef(
						ELUtils.NULL,
						new OGE("container.myBean.executeInt()"),
						expectedForwardDef))
				.map("id2", new ActionDef(
						ELUtils.NULL,
						new OGE("container.myBean.executeException()"),
						expectedForwardDef))),
				new ForwardDef("forwardId2",
				localForwardBean2, FnUtils.fix(true)));
		builder = new ActionBuilder(defs, Arrays.asList("name", "id"));
	}

	public void testGet() {
		final EL el0 = new FixEL("forwardComponent0");
		final EL el1 = new FixEL("return0");
		final ActionBuilder builder = new ActionBuilder(defs, Arrays.asList("name", "id"), el0, el1);
		assertEquals(el0, builder.getForwardComponentELEL());
		assertEquals(el1, builder.getReturnEL());
	}

	public void testGetActionExpressionReturnVoid() {
		final EEContext context = new EEContext();
		context.setId("id0");
		context.setInput(Utils.map("myInt", 7));
		context.setContainer(Collections.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().exec(context);
		assertEquals("forwardId0", context.getId());
		assertSame(localForwardBean0,
				ActionBuilder.DEFAULT_FORWARD_COMPONENT_EL_EL.getValue(context));
		assertNull(ActionBuilder.DEFAULT_RETURN_EL.getValue(context));
	}

	public void testGetActionExpressionReturnInteger() {
		final EEContext context = new EEContext();
		context.setId("id1");
		context.setInput(Utils.map("myInt", 7));
		context.setContainer(Collections.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().exec(context);
		assertEquals("forwardId0", context.getId());
		assertSame(localForwardBean0,
				ActionBuilder.DEFAULT_FORWARD_COMPONENT_EL_EL.getValue(context));
		assertEquals(Integer.valueOf(1), ActionBuilder.DEFAULT_RETURN_EL
				.getValue(context));
	}

	public void testGetActionExpressionException() {
		final EEContext context = new EEContext();
		context.setId("id2");
		context.setInput(Utils.map("myInt", 7));
		context
				.setContainer(Collections
						.singletonMap("myBean", new TestBean()));
		builder.getActionExpression().exec(context);
		assertEquals("forwardId2", context.getId());
		assertSame(localForwardBean2,
				ActionBuilder.DEFAULT_FORWARD_COMPONENT_EL_EL.getValue(context));
		final Iterator iterator = ((Iterable) ActionBuilder.DEFAULT_RETURN_EL
				.getValue(context)).iterator();
		assertTrue(iterator.hasNext());
		assertEquals("java.lang.IndexOutOfBoundsException", iterator.next());
		assertFalse(iterator.hasNext());
	}

	public void testGetAutoUpdateExpression() {
		final Fn<EEContext, Void> expression = builder.getAutoUpdateExpression();
		{
			final EEContext context = new EEContext();
			context.setNode(XmlUtils.convert(
					"<HTML><BODY>"
					+ "<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>"
					+ "</BODY></HTML>"));
			context.getLocal().put(
					"forwardBean0",
					Utils.map(
							"textarea0", "textareavalue0").map("div0",
							"divvalue0").map("span0", "spanvalue0").map(
							"input0", "inputvalue0"));
			ActionBuilder.DEFAULT_FORWARD_COMPONENT_EL_EL.setValue(context,
					new PathEL("local.forwardBean0"));
			expression.exec(context);

			assertTrue(XmlUtils.equalsNode(XmlUtils.convert(
					"<HTML><BODY>"
					+ "<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>"
					+ "</BODY></HTML>"), context.getNode()));
		}
		{
			final EEContext context = new EEContext();
			ActionBuilder.DEFAULT_FORWARD_COMPONENT_EL_EL.setValue(context,
					new PathEL("local.forwardBean0"));
			context.setNode(XmlUtils.convert(
					"<HTML><BODY>"
					+ "<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>"
					+ "</BODY></HTML>"));
			expression.exec(context);

			assertTrue(XmlUtils.equalsNode(XmlUtils.convert(
					"<HTML><BODY>"
					+ "<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>"
					+ "</BODY></HTML>"), context.getNode()));
		}
	}
}
