/*
 * $Id: BeanConfig.java,v 1.4 2006/04/26 16:59:43 sugimotokenichi Exp $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日: 2006/02/20
 */
package feat2.config;

import feat2.Action;
import feat2.CommandContext;
import feat2.FeatErrors;
import feat2.FeatRuntimeException;
import feat2.HTTPSessionException;
import feat2.config.type.Scope;


/**
 * Beanの設定。
 * @author SUGIMOTO Ken-ichi
 */
public class BeanConfig extends ActionConfigBase {

    //private static Log log = LogFactory.getLog(BeanAction.class);

    private Scope scope;

    // プロパティ -------------------------------------------------------------

    public Scope getScope() {
        return scope;
    }
    public void setScope(Scope scope) {
        this.scope = scope;
    }

    // Configのメソッド -------------------------------------------------------

    public String getElementName() {
        return "bean";
    }


    // ActionConfigBaseのメソッド ---------------------------------------------

    public Action getActionInstance() {
        return new BeanAction(getActionClass(), getName().getValue());
    }

    public boolean validate(FeatErrors errs) {

        boolean ret = super.validate(errs);

        // scope

        if ( scope == null )
            scope = new Scope("local");

        return ret;

    }


    // 内部クラス -------------------------------------------------------------

    public class BeanAction implements Action {

        private Class beanClass;
        private String beanName;
        private Object bean;

        /**
         * @param beanClass 引数無のコンストラクタでインスタンスが作れることを確認したクラスを渡す
         */
        private BeanAction(Class beanClass, String beanName) {
            this.beanClass = beanClass;
            this.beanName = beanName;
        }

        public Object execute(CommandContext ctx) {
            return bean;
        }

        public Object getBean(CommandContext ctx) throws HTTPSessionException {

            bean = ctx.getAttribute(beanName, scope);
            if ( bean == null ) {
                bean = createBeanInstance();
                ctx.setAttribute(beanName, bean, scope);
            }

            /* TODO 削除
            if ( scope.isLocal() ) {
                bean = ctx.getAttribute(beanName);
                if ( bean == null ) {
                    bean = createBeanInstance();
                }
            }

            else if ( scope.isRequest() ) {
                bean = ctx.getRequest().getAttribute(beanName);
                if ( bean == null ) {
                    bean = createBeanInstance();
                    ctx.getRequest().setAttribute(beanName, bean);
                }
            }

            else if ( scope.isSession() ) {
                HttpSession session = ctx.getSession();
                if ( session == null )
                    throw new HTTPSessionException("Beanをセットしようとしましたがセッションが得られませんでした "+getConfigPath());

                bean = session.getAttribute(beanName);
                if ( bean == null ) {
                    bean = createBeanInstance();
                    session.setAttribute(beanName, bean);
                }
            }

            else if ( scope.isUser() ) {
            }

            else if ( scope.isApplication() ) {
                bean = ctx.getServletContext().getAttribute(beanName);
                if ( bean == null) {
                    bean = createBeanInstance();
                    ctx.getServletContext().setAttribute(beanName, bean);
                }
            }*/

            return bean;
        }

        private Object createBeanInstance() {

            try {
                return beanClass.newInstance();
            }
            catch (InstantiationException ex) {
                throw new FeatRuntimeException(ex);
            }
            catch (IllegalAccessException ex) {
                throw new FeatRuntimeException(ex);
            }

        }

    }

}
