/*
 * 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.myfaces.orchestra.frameworkAdapter.local;

import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.beans.BeansException;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * A FrameworkAdapter which uses local maps to simulate a servlet environment.
 * <p>
 * This is intended when Orchestra functionality is desired outside of any real
 * request/response type system. One example is where a job scheduler (eg quartz)
 * is used to execute background threads that want to execute the same beans that
 * can also be used. In this case:
 * <ol>
 * <li>Create a new Thread object
 * <li>Create a new LocalFrameworkAdapter instance
 * <li>Within the new thread, call FrameworkAdapter.setInstance.
 * </ol>
 * When Orchestra methods are invoked from within the new thread, calls made to the
 * framework adapter will be handled by the created LocalFrameworkAdapter instance,
 * and will not interact with the user session, the original request or response.
 * Because the session is new, no conversations will be inherited from the environment
 * in which that new thread was created.
 * <p>
 * This class is not expected to be used very often.
 * <p>
 * Note that this adapter relies on Spring and thus you have to ensure
 * {@link #setApplicationContext} is called.
 * <p>
 * Note also that because this is intended for use only without a real request
 * and response, there is no corresponding Filter class.
 * <p>
 * This class does not override the inherited createConversationMessager method, so
 * it is mandatory for anyone using this class to explicitly call method
 * setConversationMessager before using an instance of this adapter.
 */
public class LocalFrameworkAdapter extends FrameworkAdapter implements ApplicationContextAware
{
    private ConfigurableApplicationContext configurableApplicationContext;

    private final Map sessionMap = new HashMap();
    private final Map requestMap = new HashMap();
    private final Map requestParameterMap = new HashMap();
    private final Map initMap = new HashMap();

    public String getInitParameter(String key)
    {
        return (String) initMap.get(key);
    }

    public Object getRequestParameterAttribute(String key)
    {
        return requestParameterMap.get(key);
    }

    public boolean containsRequestParameterAttribute(String key)
    {
        return requestParameterMap.containsKey(key);
    }

    public void setRequestParameterAttribute(String key , Object value)
    {
        requestParameterMap.put(key, value);
    }

    public Object getRequestAttribute(String key)
    {
        return requestMap.get(key);
    }

    public void setRequestAttribute(String key, Object value)
    {
        requestMap.put(key, value);
    }

    public void clearRequestMap()
    {
        requestMap.clear();
    }

    public boolean containsRequestAttribute(String key)
    {
        return requestMap.containsKey(key);
    }

    public Object getSessionAttribute(String key)
    {
        return sessionMap.get(key);
    }

    public void setSessionAttribute(String key, Object value)
    {
        sessionMap.put(key, value);
    }

    public boolean containsSessionAttribute(String key)
    {
        return sessionMap.containsKey(key);
    }

    protected ConfigurableApplicationContext getApplicationContext()
    {
        return configurableApplicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        setApplicationContext((ConfigurableApplicationContext) applicationContext);
    }

    public void setApplicationContext(ConfigurableApplicationContext configurableApplicationContext)
    {
        this.configurableApplicationContext = configurableApplicationContext;
    }

    public void redirect(String url) throws IOException
    {
    }

    public Object getBean(String name)
    {
        if (!getApplicationContext().containsBean(name))
        {
            return null;
        }
        return getApplicationContext().getBean(name);
    }

    public void invokeNavigation(String navigationName)
    {
    }
}
