package org.maachang.comet.httpd.engine.script;

import java.util.HashMap;

import org.maachang.comet.httpd.HttpdErrorDef;
import org.maachang.comet.httpd.HttpdStateException;
import org.maachang.comet.httpd.engine.script.scripts.AjaxScript;
import org.maachang.comet.httpd.engine.script.scripts.CometScript;
import org.maachang.comet.httpd.engine.script.scripts.CometTriggerScript;
import org.maachang.comet.httpd.engine.script.scripts.ControllerScript;
import org.maachang.comet.httpd.engine.script.scripts.EtcScript;
import org.maachang.comet.httpd.engine.script.scripts.FilterScript;
import org.maachang.comet.httpd.engine.script.scripts.InnerScript;
import org.maachang.comet.httpd.engine.script.scripts.JCometScript;
import org.maachang.comet.httpd.engine.script.scripts.JsonpScript;
import org.maachang.comet.httpd.engine.script.scripts.MhtmlScript;
import org.maachang.comet.httpd.engine.script.scripts.RpcScript;
import org.maachang.comet.httpd.engine.script.scripts.TemplateScript;

/**
 * WebApplication用スクリプトファクトリ.
 * 
 * @version 2007/08/24
 * @author masahito suzuki
 * @since MaachangComet 1.00
 */
public class WebAppScriptFactory {
    
    /**
     * カレントディレクトリ.
     */
    private String currentDirectory = null ;
    
    /**
     * アプリケーションスクリプト格納用.
     */
    private HashMap<String,Script> applications = null ;
    
    /**
     * コンストラクタ.
     */
    private WebAppScriptFactory() {
        
    }
    
    /**
     * コンストラクタ.
     * <BR><BR>
     * 条件を指定してオブジェクトを生成します.
     * <BR>
     * @param directory 対象のカレントディレクトリを設定します.
     * @exception Exception 例外.
     */
    public WebAppScriptFactory( String currentDirectory )
        throws Exception {
        currentDirectory = ScriptDef.trimCurrentDirectory( currentDirectory ) ;
        this.currentDirectory = currentDirectory ;
        this.applications = new HashMap<String,Script>() ;
    }
    
    /**
     * アプリケーションスクリプトを取得.
     * <BR><BR>
     * アプリケーションスクリプトを取得します.
     * <BR>
     * @param name 対象のアプリケーションスクリプト名を設定します.
     * @return Script アプリケーションスクリプトが返されます.
     * @exception Exception 例外.
     */
    public Script getApplication( String name )
        throws Exception {
        if( name == null || ( name = name.trim() ).length() <= 0 ) {
            throw new HttpdStateException( HttpdErrorDef.HTTP11_500,
                "対象アプリケーション名は不正です" ) ;
        }
        String key = null ;
        Script ret = null ;
        if( name.endsWith( ScriptDef.SCRIPT_PLUS ) == true ) {
            key = name.substring( 0,name.length()-ScriptDef.SCRIPT_PLUS.length() ) ;
        }
        else {
            key = name ;
        }
        ret = applications.get( key ) ;
        if( ret == null ) {
            synchronized( applications ) {
                if( name.endsWith( "/" + ScriptDef.FILTER_NAME ) == true ) {
                    ret = new FilterScript( key,currentDirectory ) ;
                }
                else if( name.endsWith( ScriptDef.SCRIPT_HTML_PLUS ) == true ) {
                    ret = new MhtmlScript( name,currentDirectory ) ;
                }
                else if( name.endsWith( ScriptDef.TEMPLATE_PLUS ) == true ) {
                    ret = new TemplateScript( name ) ;
                }
                else {
                    int type = ScriptDef.getScriptFileType( key+ScriptDef.SCRIPT_PLUS ) ;
                    switch( type ) {
                        case ScriptDef.SCRIPT_TYPE_BY_COMET :
                            if( key.endsWith( ScriptDef.SCRIPT_BY_JCOMET ) ) {
                                ret = new JCometScript( key,currentDirectory ) ;
                            }
                            else {
                                ret = new CometScript( key,currentDirectory ) ;
                            }
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_COMET_TRIGGER :
                            ret = new CometTriggerScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_AJAX :
                            ret = new AjaxScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_CONTROLLER :
                            ret = new ControllerScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_JSONP :
                            ret = new JsonpScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_RPC :
                            ret = new RpcScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_INNER :
                            ret = new InnerScript( key,currentDirectory ) ;
                            break ;
                        case ScriptDef.SCRIPT_TYPE_BY_FILTER :
                            ret = new FilterScript( key,currentDirectory ) ;
                            break ;
                        default :
                            ret = new EtcScript( key,currentDirectory ) ;
                            break ;
                    }
                }
                if( ret != null ) {
                    applications.put( key,ret ) ;
                }
            }
        }
        if( ret == null ) {
            throw new HttpdStateException( HttpdErrorDef.HTTP11_500,
                "対象アプリケーション名["+name+"]は存在しません" ) ;
        }
        return ret ;
    }
    
    /**
     * 指定アプリケーションスクリプトが存在するかチェック.
     * <BR><BR>
     * 指定されたアプリケーションスクリプトが存在するかチェックします.
     * <BR>
     * @param name 対象名を設定します.
     * @return boolean [true]の場合、存在します.
     */
    public boolean isApplication( String name ) {
        boolean ret = false ;
        try {
            getApplication( name ) ;
            ret = true ;
        } catch( Exception e ) {
            ret = false ;
        }
        return ret ;
    }
    
    /**
     * カレントディレクトリを取得.
     * <BR><BR>
     * 設定されているカレントディレクトリを取得します.
     * <BR>
     * @return String カレントディレクトリが返されます.
     */
    public String getCurrentDirectory() {
        return currentDirectory ;
    }
}

