/*
 * $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.tiles.context.portlet;

import java.util.Map;

import org.apache.shale.test.mock.MockPortletContext;
import org.apache.shale.test.mock.MockPortletRequest;
import org.apache.shale.test.mock.MockPortletResponse;
import org.apache.shale.test.mock.MockPortletSession;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.context.TilesRequestContext;

import junit.framework.TestCase;

/**
 * @version $Rev$ $Date$
 */
public class PortletTilesRequestContextTest extends TestCase {

    /**
     * The used request context.
     */
    private TilesRequestContext context;

    /** {@inheritDoc} */
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        MockPortletContext servletContext = new MockPortletContext();
        servletContext
                .addInitParameter("initParameter1", "initParameterValue1");
        MockPortletSession session = new MockPortletSession(servletContext);
        MockPortletRequest request = new MockPortletRequest(session);
        MockPortletResponse response = new MockPortletResponse();
        request.addParameter("myParam", "value1");
        request.addParameter("myParam", "value2");

        context = new PortletTilesRequestContext(servletContext, request,
                response);

        Map<String, Object> requestScope = context.getRequestScope();
        requestScope.put("attribute1", "value1");
        requestScope.put("attribute2", "value2");

        Map<String, Object> sessionScope = context.getSessionScope();
        sessionScope.put("sessionAttribute1", "sessionValue1");
        sessionScope.put("sessionAttribute2", "sessionValue2");

        Map<String, Object> applicationScope = ((TilesApplicationContext) context)
                .getApplicationScope();
        applicationScope.put("applicationAttribute1", "applicationValue1");
        applicationScope.put("applicationAttribute2", "applicationValue2");
    }

    /**
     * Tests getting the header.
     */
    public void testGetHeader() {
        Map<String, String> map = context.getHeader();
        assertTrue("The portlet cannot have headers!", map.isEmpty());
        doTestReadMap(map, String.class, String.class, "header map");
    }

    /**
     * Tests getting the header values.
     */
    public void testGetHeaderValues() {
        Map<String, String[]> map = context.getHeaderValues();
        assertTrue("The portlet cannot have headers!", map.isEmpty());
        doTestReadMap(map, String.class, String[].class, "header values map");
    }

    /**
     * Tests getting request parameters.
     */
    public void testGetParam() {
        Map<String, String> map = context.getParam();
        assertTrue("The parameters do not contain a set value", "value1"
                .equals(map.get("myParam"))
                || "value2".equals(map.get("myParam")));
        doTestReadMap(map, String.class, String.class, "parameter map");
    }

    /**
     * Tests getting request parameters values.
     */
    public void testGetParamValues() {
        Map<String, String[]> map = context.getParamValues();
        String[] array = map.get("myParam");
        assertTrue(
                "The parameters not contain a set value",
                array.length == 2
                        && (("value1".equals(array[0]) && "value2"
                                .equals(array[1])) || ("value1"
                                .equals(array[1]) && "value2".equals(array[0]))));
        doTestReadMap(map, String.class, String[].class, "parameter values map");
    }

    /**
     * Tests getting request scope attributes.
     */
    public void testGetRequestScope() {
        Map<String, Object> map = context.getRequestScope();
        assertTrue("The request scope does not contain a set value", "value1"
                .equals(map.get("attribute1")));
        assertTrue("The request scope does not contain a set value", "value2"
                .equals(map.get("attribute2")));
        doTestReadMap(map, String.class, Object.class, "request scope map");
    }

    /**
     * Tests getting session scope attributes.
     */
    public void testGetSessionScope() {
        Map<String, Object> map = context.getSessionScope();
        assertTrue("The session scope does not contain a set value",
                "sessionValue1".equals(map.get("sessionAttribute1")));
        assertTrue("The session scope does not contain a set value",
                "sessionValue2".equals(map.get("sessionAttribute2")));
        doTestReadMap(map, String.class, Object.class, "session scope map");
    }

    /**
     * Tests getting application scope attributes.
     */
    public void testGetApplicationScope() {
        Map<String, Object> map = ((TilesApplicationContext) context)
                .getApplicationScope();
        assertTrue("The application scope does not contain a set value",
                "applicationValue1".equals(map.get("applicationAttribute1")));
        assertTrue("The application scope does not contain a set value",
                "applicationValue2".equals(map.get("applicationAttribute2")));
        doTestReadMap(map, String.class, Object.class, "application scope map");
    }

    /**
     * Tests getting init parameters..
     */
    public void testGetInitParams() {
        Map<String, String> map = ((TilesApplicationContext) context)
                .getInitParams();
        assertTrue("The init parameters do not contain a set value",
                "initParameterValue1".equals(map.get("initParameter1")));
        doTestReadMap(map, String.class, String.class,
                "init parameters scope map");
    }

    /**
     * Tests a generic map.
     *
     * @param <K> The key type.
     * @param <V> The value type.
     * @param currentMap The map to check.
     * @param keyClass The key class.
     * @param valueClass The value class.
     * @param mapName The name of the map to test (for messages).
     */
    private <K, V> void doTestReadMap(Map<K, V> currentMap, Class<K> keyClass,
            Class<V> valueClass, String mapName) {
        int size1, size2;
        size1 = currentMap.keySet().size();
        size2 = currentMap.entrySet().size();
        assertEquals("The map" + mapName
                + " has keySet and entrySet of different size", size1, size2);
        for (K key : currentMap.keySet()) {
            assertTrue("The key is not of class" + keyClass.getName(), keyClass
                    .isInstance(key));
            V value = currentMap.get(key);
            assertTrue("The value is not of class" + valueClass.getName(),
                    valueClass.isInstance(value));
            assertTrue("The map " + mapName
                    + " does not return the correct value for 'containsValue'",
                    currentMap.containsValue(value));
        }
    }
}
