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

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

import junit.framework.TestCase;
import woolpack.utils.UtilsConstants;

public class ScopeContainerTest extends TestCase {

	public void testConstructor() {
		try {
			new ScopeContainer(null, UtilsConstants.concurrentMap(
					new HashMap<String, Object>(), new Object()),
					UtilsConstants.concurrentMap(new HashMap<String, Object>(),
							new Object()), new HashMap<String, AbstractComponentDef>());
			fail();
		} catch (final NullPointerException expected) {
		}
		try {
			new ScopeContainer(new HashMap<String, Object>(), null,
					UtilsConstants.concurrentMap(new HashMap<String, Object>(),
							new Object()), new HashMap<String, AbstractComponentDef>());
			fail();
		} catch (final NullPointerException expected) {
		}
		try {
			new ScopeContainer(new HashMap<String, Object>(),
					UtilsConstants.concurrentMap(new HashMap<String, Object>(),
							new Object()), null,
					new HashMap<String, AbstractComponentDef>());
			fail();
		} catch (final NullPointerException expected) {
		}
		try {
			new ScopeContainer(new HashMap<String, Object>(),
					UtilsConstants.concurrentMap(new HashMap<String, Object>(),
							new Object()), UtilsConstants.concurrentMap(
							new HashMap<String, Object>(), new Object()), null);
			fail();
		} catch (final NullPointerException expected) {
		}
	}

	public void testNormal() {
		// TODO 同期化のテスト
		final Map<String, AbstractComponentDef> componentDefs = new HashMap<String, AbstractComponentDef>();
		componentDefs.put("prototypeKey0", new AbstractComponentDef(
				ComponentScope.PROTOTYPE) {
			private int count = 0;

			@Override
			protected Object newInstance() {
				return "prototypeValue" + String.valueOf(count++);
			}
		});
		componentDefs.put("requestKey0", new AbstractComponentDef(
				ComponentScope.REQUEST) {
			private int count = 0;

			@Override
			protected Object newInstance() {
				return "requestValue" + String.valueOf(count++);
			}
		});
		componentDefs.put("sessionKey0", new AbstractComponentDef(
				ComponentScope.SESSION) {
			private int count = 0;

			@Override
			protected Object newInstance() {
				return "sessionValue" + String.valueOf(count++);
			}
		});
		componentDefs.put("applicationKey0", new AbstractComponentDef(
				ComponentScope.APPLICATION) {
			private int count = 0;

			@Override
			protected Object newInstance() {
				return "applicationValue" + String.valueOf(count++);
			}
		});
		componentDefs.put("singletonKey0", new AbstractComponentDef(
				ComponentScope.SINGLETON) {
			private int count = 0;

			@Override
			protected Object newInstance() {
				return "singletonValue" + String.valueOf(count++);
			}
		});

		{
			final Map<String, Object> request = new HashMap<String, Object>();
			final ConcurrentMap<String, Object> session = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ConcurrentMap<String, Object> application = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ScopeContainer scopeContainer = new ScopeContainer(request,
					session, application, componentDefs);

			assertEquals("prototypeValue0", scopeContainer.get("prototypeKey0"));
			assertEquals("prototypeValue1", scopeContainer.get("prototypeKey0"));
			assertEquals("prototypeValue2", scopeContainer.get("prototypeKey0"));

			assertNull(request.get(ScopeContainer.KEY_PREFIX));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertEquals("requestValue0", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertEquals("requestValue0", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertEquals("requestValue0", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));

			assertNull(session.get(ScopeContainer.KEY_PREFIX));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue0", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue0", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue0", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));

			assertNull(application.get(ScopeContainer.KEY_PREFIX));
			assertEquals("applicationValue0", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue0", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));
			assertEquals("applicationValue0", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue0", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));
			assertEquals("applicationValue0", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue0", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));

			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
		}
		{
			final Map<String, Object> request = new HashMap<String, Object>();
			final ConcurrentMap<String, Object> session = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ConcurrentMap<String, Object> application = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ScopeContainer scopeContainer = new ScopeContainer(request,
					session, application, componentDefs);

			assertEquals("prototypeValue3", scopeContainer.get("prototypeKey0"));
			assertEquals("prototypeValue4", scopeContainer.get("prototypeKey0"));
			assertEquals("prototypeValue5", scopeContainer.get("prototypeKey0"));

			assertNull(request.get(ScopeContainer.KEY_PREFIX));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertEquals("requestValue1", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertEquals("requestValue1", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertEquals("requestValue1", request.get(ScopeContainer.KEY_PREFIX
					+ "requestKey0"));

			assertNull(session.get(ScopeContainer.KEY_PREFIX));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue1", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue1", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue1", session.get(ScopeContainer.KEY_PREFIX
					+ "sessionKey0"));

			assertNull(application.get(ScopeContainer.KEY_PREFIX));
			assertEquals("applicationValue1", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue1", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));
			assertEquals("applicationValue1", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue1", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));
			assertEquals("applicationValue1", scopeContainer
					.get("applicationKey0"));
			assertEquals("applicationValue1", application
					.get(ScopeContainer.KEY_PREFIX + "applicationKey0"));

			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
			assertEquals("singletonValue0", scopeContainer.get("singletonKey0"));
		}

		{
			final Map<String, Object> request = new HashMap<String, Object>();
			final ConcurrentMap<String, Object> session = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ConcurrentMap<String, Object> application = UtilsConstants
					.concurrentMap(new HashMap<String, Object>(), new Object());
			final ScopeContainer scopeContainer = new ScopeContainer(request,
					session, application, componentDefs);

			final Collection<String> expected = Arrays.asList("prototypeKey0",
					"requestKey0", "sessionKey0", "applicationKey0",
					"singletonKey0");
			assertTrue(expected.containsAll(scopeContainer.keySet()));
			assertTrue(scopeContainer.keySet().containsAll(expected));
		}
	}
}
