/*
 * 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,ComponentDef>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ScopeContainer(new HashMap<String,Object>(), null, UtilsConstants.concurrentMap(new HashMap<String,Object>(), new Object()), new HashMap<String,ComponentDef>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ScopeContainer(new HashMap<String,Object>(), UtilsConstants.concurrentMap(new HashMap<String,Object>(), new Object()), null, new HashMap<String,ComponentDef>());
			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,ComponentDef> componentDefs = new HashMap<String,ComponentDef>();
		componentDefs.put("prototypeKey0", new ComponentDef(ComponentScope.PROTOTYPE){
			private int count = 0;
			@Override
			protected Object newInstance() {
				return "prototypeValue" + String.valueOf(count++);
			}});
		componentDefs.put("requestKey0", new ComponentDef(ComponentScope.REQUEST){
			private int count = 0;
			@Override
			protected Object newInstance() {
				return "requestValue" + String.valueOf(count++);
			}});
		componentDefs.put("sessionKey0", new ComponentDef(ComponentScope.SESSION){
			private int count = 0;
			@Override
			protected Object newInstance() {
				return "sessionValue" + String.valueOf(count++);
			}});
		componentDefs.put("applicationKey0", new ComponentDef(ComponentScope.APPLICATION){
			private int count = 0;
			@Override
			protected Object newInstance() {
				return "applicationValue" + String.valueOf(count++);
			}});
		componentDefs.put("singletonKey0", new ComponentDef(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));
		}
	}
}
