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

import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.VariableResolver;

import org.apache.myfaces.orchestra.conversation.basic.LogConversationMessager;
import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
import org.apache.myfaces.orchestra.frameworkAdapter.local.LocalFrameworkAdapter;
import org.apache.shale.test.base.AbstractJsfTestCase;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.web.jsf.DelegatingVariableResolver;

public class TestSerializableConverter extends AbstractDependencyInjectionSpringContextTests
{
    static class ShaleHandler extends AbstractJsfTestCase
    {
        public ShaleHandler()
        {
            super("none");
        }
        
        public void doSetUp() throws Exception
        {
            this.setUp();
        }
        
        public void doTearDown() throws Exception
        {
            this.tearDown();
        }
    }

    ShaleHandler shale = new ShaleHandler();

    protected String[] getConfigLocations()
    {
        return new String[]
            {
                "classpath:org/apache/myfaces/orchestra/lib/jsf/TestSerializableConverter.xml"
            };
    }

    protected void onSetUp() throws Exception
    {
        super.onSetUp();
        shale.doSetUp();

        LocalFrameworkAdapter frameworkAdapter = new LocalFrameworkAdapter();
        frameworkAdapter.setApplicationContext(applicationContext);
        frameworkAdapter.setConversationMessager(new LogConversationMessager());
        FrameworkAdapter.setCurrentInstance(frameworkAdapter);

    }

    protected void onTearDown() throws Exception
    {
        shale.doTearDown();
        super.onTearDown();
    }

    static class SpringVariableResolver extends DelegatingVariableResolver
    {
        BeanFactory factory;
        SpringVariableResolver(BeanFactory factory, VariableResolver orig)
        {
            super(orig);
            this.factory = factory;
        }

        protected BeanFactory getBeanFactory(FacesContext facesContext)
        {
            return factory;
        }
    }

    /**
     * Test saving and restoring of a SerializableConverter that references
     * a Converter object that does not implement StateHolder.
     */
    public void testStateless() throws Exception
    {
        Object result;

        // as for testStateful, but converter does not implement StateHolder
        // define a stateful converter
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Application app = facesContext.getApplication();

        // DelegatingResolver requires a WebApplicationContext object...
        SpringVariableResolver springResolver = new SpringVariableResolver(applicationContext, app.getVariableResolver());
        app.setVariableResolver(springResolver);

        SerializableConverter conv = new SerializableConverter("statelessConverter");
        UIComponent component = null;
        result = conv.getAsObject(facesContext, component, "aabb");
        assertEquals("AABB", result);
        
        Object state = conv.saveState(facesContext);
        
        SerializableConverter conv2 = new SerializableConverter();
        conv2.restoreState(facesContext, state);
        result = conv.getAsObject(facesContext, component, "ccdd");
        assertEquals("CCDD", result);
    }

    public void testStateful() throws Exception
    {
        Object result;

        // as for testStateful, but converter does not implement StateHolder
        // define a stateful converter
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Application app = facesContext.getApplication();

        // DelegatingResolver requires a WebApplicationContext object...
        SpringVariableResolver springResolver = new SpringVariableResolver(applicationContext, app.getVariableResolver());
        app.setVariableResolver(springResolver);

        SerializableConverter conv = new SerializableConverter("statefulConverter");
        UIComponent component = null;
        result = conv.getAsObject(facesContext, component, "aabb");
        assertEquals("AABB:18", result);
        
        Object state = conv.saveState(facesContext);
        
        SerializableConverter conv2 = new SerializableConverter();
        conv2.restoreState(facesContext, state);
        result = conv.getAsObject(facesContext, component, "ccdd");
        assertEquals("CCDD:19", result);
    }
}
