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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;
import woolpack.container.ContainerContext;
import woolpack.container.ContainerUtils;
import woolpack.fn.Fn;
import woolpack.fn.FnUtils;
import woolpack.utils.Utils;

public class WebUtilsTest extends TestCase {
	public void testScope() throws Exception {
		// TODO 同期化のテスト
		final List<String> list = new ArrayList<String>();
		final Fn<ContainerContext<WebContext>, Object, RuntimeException> fn =
			new Fn<ContainerContext<WebContext>, Object, RuntimeException>() {
			public Object exec(final ContainerContext c) {
				return c.getKey() + "a";
			}
		};

		final ContainerContext<WebContext> context = new ContainerContext<WebContext>();
		context.setFn(FnUtils.exec(FnUtils.join(
				ContainerUtils.<ContainerContext<WebContext>>getKey(),
				FnUtils.switching(
						Utils.<Object, Fn<? super ContainerContext<WebContext>, ?, ? extends Exception>>
						map("r", WebUtils.request(FnUtils.recode(fn, "r", list)))
						.map("s", WebUtils.session(FnUtils.recode(fn, "s", list)))
						.map("a", WebUtils.application(FnUtils.recode(fn, "a", list)))
						.map("z", new Fn<ContainerContext<WebContext>, Object, Exception>() {
							public Object exec(final ContainerContext<WebContext> c) throws Exception {
								final Map<String, Object> map = new HashMap<String, Object>();
								map.put("r", c.visit("r"));
								map.put("s", c.visit("s"));
								map.put("a", c.visit("a"));
								return map;
							}
						})
				))));
		final SimpleWebContext webContext = new SimpleWebContext();
		webContext.setRequest(new HashMap<String, Object>());
		webContext.setSession(Utils.concurrentMap(new HashMap<String, Object>(), new Object()));
		webContext.setApplication(Utils.concurrentMap(new HashMap<String, Object>(), new Object()));
		context.setSubContext(webContext);

		list.clear();
		assertTrue(webContext.getRequest().isEmpty());
		assertEquals("ra", context.visit("r"));
		assertEquals(1, list.size());
		assertEquals("ra", context.visit("r"));
		assertEquals(1, list.size());
		assertEquals(Utils.map("woolpack.web.WebUtils.r", "ra"), webContext.getRequest());
		webContext.getRequest().clear();
		assertEquals("ra", context.visit("r"));
		assertEquals(2, list.size());
		
		list.clear();
		assertTrue(webContext.getSession().isEmpty());
		assertEquals("sa", context.visit("s"));
		assertEquals(1, list.size());
		assertEquals("sa", context.visit("s"));
		assertEquals(1, list.size());
		assertEquals(Utils.map("woolpack.web.WebUtils.s", "sa"), webContext.getSession());
		webContext.getSession().clear();
		assertEquals("sa", context.visit("s"));
		assertEquals(2, list.size());

		list.clear();
		assertTrue(webContext.getApplication().isEmpty());
		assertEquals("aa", context.visit("a"));
		assertEquals(1, list.size());
		assertEquals("aa", context.visit("a"));
		assertEquals(1, list.size());
		assertEquals(Utils.map("woolpack.web.WebUtils.a", "aa"), webContext.getApplication());
		webContext.getApplication().clear();
		assertEquals("aa", context.visit("a"));
		assertEquals(2, list.size());

		list.clear();
		assertEquals(
				Utils.map("r", "ra").map("s", "sa").map("a", "aa"),
				context.visit("z"));
		assertTrue(list.isEmpty());
	}

	public void testClearSession() {
		final SimpleWebContext c = new SimpleWebContext();
		c.setSession(Utils.concurrentMap(
				new HashMap<String, Object>(), new Object()));
		c.getSession().put("key0", "value0");
		c.getSession().put("key1", "value1");
		assertFalse(c.getSession().isEmpty());
		WebUtils.CLEAR_SESSION.exec(c);
		assertTrue(c.getSession().isEmpty());
	}
	
	public void testAccessor() throws Exception {
		final SimpleWebContext c = new SimpleWebContext();
		c.setRequest(new HashMap<String, Object>());
		c.setSession(Utils.concurrentMap(new HashMap<String, Object>(), new Object()));
		c.setApplication(Utils.concurrentMap(new HashMap<String, Object>(), new Object()));
		
		assertSame(c.getRequest(), WebUtils.REQUEST_EL.getValue(c));
		assertSame(c.getSession(), WebUtils.SESSION_EL.getValue(c));
		assertSame(c.getApplication(), WebUtils.APPLICATION_EL.getValue(c));
		
		assertSame(c.getRequest(), WebUtils.requestFn().exec(c));
		assertSame(c.getSession(), WebUtils.sessionFn().exec(c));
		assertSame(c.getApplication(), WebUtils.applicationFn().exec(c));
	}
}
