/*
 * 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 junit.framework.TestCase;
import woolpack.utils.OGE;

public class ScopeContainerTest extends TestCase {

	public void testConstructor(){
		try{
			new ScopeContainer(null, new HashMap<String,Object>(), new HashMap<String,Object>(), new HashMap<String,ComponentDef>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ScopeContainer(new HashMap<String,Object>(), null, new HashMap<String,Object>(), new HashMap<String,ComponentDef>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ScopeContainer(new HashMap<String,Object>(), new HashMap<String,Object>(), null, new HashMap<String,ComponentDef>());
			fail();
		}catch(final NullPointerException expected){
		}
		try{
			new ScopeContainer(new HashMap<String,Object>(), new HashMap<String,Object>(), new HashMap<String,Object>(), null);
			fail();
		}catch(final NullPointerException expected){
		}
	}
	
	public void testNormal(){
		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 Map<String,Object> session = new HashMap<String,Object>();
			final Map<String,Object> application = new HashMap<String,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.CONTAINER_KEY));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertNotNull(request.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("requestValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertEquals("requestValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			assertEquals("requestValue0", scopeContainer.get("requestKey0"));
			assertEquals("requestValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			
			assertNull(session.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertNotNull(session.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("sessionValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			assertEquals("sessionValue0", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			
			assertNull(application.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("applicationValue0", scopeContainer.get("applicationKey0"));
			assertNotNull(application.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("applicationValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			assertEquals("applicationValue0", scopeContainer.get("applicationKey0"));
			assertEquals("applicationValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			assertEquals("applicationValue0", scopeContainer.get("applicationKey0"));
			assertEquals("applicationValue0", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			
			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 Map<String,Object> session = new HashMap<String,Object>();
			final Map<String,Object> application = new HashMap<String,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.CONTAINER_KEY));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertNotNull(request.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("requestValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertEquals("requestValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			assertEquals("requestValue1", scopeContainer.get("requestKey0"));
			assertEquals("requestValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].requestKey0").getValue(request));
			
			assertNull(session.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertNotNull(session.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("sessionValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			assertEquals("sessionValue1", scopeContainer.get("sessionKey0"));
			assertEquals("sessionValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].sessionKey0").getValue(session));
			
			assertNull(application.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("applicationValue1", scopeContainer.get("applicationKey0"));
			assertNotNull(application.get(ScopeContainer.CONTAINER_KEY));
			assertEquals("applicationValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			assertEquals("applicationValue1", scopeContainer.get("applicationKey0"));
			assertEquals("applicationValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			assertEquals("applicationValue1", scopeContainer.get("applicationKey0"));
			assertEquals("applicationValue1", new OGE("[\"" + ScopeContainer.CONTAINER_KEY + "\"].applicationKey0").getValue(application));
			
			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 Map<String,Object> session = new HashMap<String,Object>();
			final Map<String,Object> application = new HashMap<String,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));
		}
	}
}
