// model実装.
//

////////////////////////////////////////////////////////////////////////////////
// BaseModel.
////////////////////////////////////////////////////////////////////////////////

// 基本モデルオブジェクト.
baseModel = function(modelName) {
    if( isNull( modelName ) ) {
        return null ;
    }
    modelName = trim( modelName ) ;
    // modelを有効にする.
    if( create_base_model() == false ) {
        return null ;
    }
    
    // model用データ格納条件.
    var baseMap = new java.util.HashMap() ;
    
    // 楽観的ロックエラーが発生したかチェック.
    baseMap.put( "isOptimisticLock",
        function(params) {
            if( isNull( params[SubModel.ERROR_OPTIMISTIC_LOCK] ) == false ) {
                return true ;
            }
            return false ;
        }
    ) ;
    
    // インスタンス生成用.
    baseMap.put( "bean",
        function( map ) {
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return null ;
                }
            }
            var ret = SubModel.dbmap( script_model().getMetaByJson(modelName) ) ;
            // デフォルト値が存在する場合は、それをbeanに設定する.
            if( isNull( this.defaultColumns ) == false ) {
                var df = this.defaultColumns ;
                for( var k in df ) {
                    ret[k] = df[k] ;
                }
            }
            // map情報が渡された場合、
            if( isNull( map ) == false && valueof( map ) == 'map' ) {
                var coreMap = ret.core ;
                for( var k in map ) {
                    if( coreMap.containsKey( k ) ) {
                        ret[k] = map[k] ;
                    }
                }
            }
            return ret ;
        }
    ) ;
    // 保存用.
    baseMap.put( "save",
        function(params) {
            if( isNull( params ) ) {
                return false ;
            }
            if( script_model().isType == false ) {
                return false ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return false ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var map = SubModel.convertParamByMap( params ) ;
            if( map == null || map.size() <= 0 ) {
                return false ;
            }
            SubModel.removeManyColumn( map ) ;
            var insertFlag = false ;
            var res = script_model().save( modelName,map ) ;
            if( res <= -1 ) {
                // 楽観的ロック例外.
                params[SubModel.ERROR_OPTIMISTIC_LOCK] = true ;
                return false ;
            }
            if( params[SubModel.COLUMN_ID] == null && res != null && typeof(res) == "object" ) {
                if( res instanceof java.lang.Long ) {
                    params[SubModel.COLUMN_ID]=""+res;
                    insertFlag = true ;
                }
            }
            var tmp = null ;
            var createAt = map.get( SubModel.COLUMN_CREATE_TIME ) ;
            var updateAt = map.get( SubModel.COLUMN_UPDATE_TIME ) ;
            var versionValue = map.get( SubModel.COLUMN_OPTIMISTIC_LOCK ) ;
            if( createAt != null && insertFlag == true ) {
                tmp = org.maachang.comet.httpd.engine.script.dao.DaoUtil.convertDateByString( createAt ) ;
                params[SubModel.COLUMN_CREATE_TIME] = SubModel.createStringByDate( tmp ) ;
            }
            if( updateAt != null ) {
                tmp = org.maachang.comet.httpd.engine.script.dao.DaoUtil.convertDateByString( updateAt ) ;
                params[SubModel.COLUMN_UPDATE_TIME] = SubModel.createStringByDate( tmp ) ;
            }
            if( versionValue != null ) {
                params[SubModel.COLUMN_OPTIMISTIC_LOCK] = ""+versionValue ;
            }
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            // 更新通知.
            script_model().setUpdateOrDeleteTable( modelName ) ;
            return true ;
        }
    ) ;
    // 指定更新用.
    baseMap.put( "update",
        function(where,params) {
            if( isNull( where ) ) {
                where = "" ;
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return false ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return false ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            script_model().update( modelName,where,list ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            // 更新通知.
            script_model().setUpdateOrDeleteTable( modelName ) ;
            return true ;
        }
    ) ;
    // 指定削除用(Join).
    baseMap.put( "rjfind",
        function(where,params) {
            return baseMap.get( "removeFind" )( where,params,true,true ) ;
        }
    ) ;
    // 指定削除用(Join).
    baseMap.put( "removeFindJoin",
        function(where,params) {
            return baseMap.get( "removeFind" )( where,params,true,true ) ;
        }
    ) ;
    // 指定削除用(ImageJoin).
    baseMap.put( "rifind",
        function(where,params) {
            return baseMap.get( "removeFind" )( where,params,false,true ) ;
        }
    ) ;
    // 指定削除用(ImageJoin).
    baseMap.put( "removeFindImageJoin",
        function(where,params) {
            return baseMap.get( "removeFind" )( where,params,false,true ) ;
        }
    ) ;
    // 指定削除用.
    baseMap.put( "rfind",
        function(where,params) {
            return baseMap.get( "removeFind" )( where,params,false,false ) ;
        }
    ) ;
    // 指定削除用.
    baseMap.put( "removeFind",
        function(where,params,join,imgJoin) {
            if( isNull( where ) ) {
                where = "" ;
            }
            else {
                where = trim( where ) ;
                if( where.length > 0 && startsWith( where.toLowerCase(),"where " ) == false ) {
                    where = "where " + where ;
                }
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return false ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return false ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            var joinMap = null ;
            if( join == true ) {
                joinMap = SubModel.getModelBySrcJoinKeys( modelName,baseMap ) ;
            }
            var imgMap = null ;
            var imgMan = null ;
            if( imgJoin == true ) {
                imgMap = SubModel.getModelByImageJoin( baseMap ) ;
                if( isNull( imgMap ) == false ) {
                    imgMan = script_model().getImageOp() ;
                }
            }
            if( isNull( imgMap ) || isNull( imgMan ) ) {
                imgMap = null ;
                imgMan = null ;
            }
            script_model().remove( modelName,imgMan,imgMap,joinMap,where,list ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            // 更新通知.
            script_model().setUpdateOrDeleteTable( modelName ) ;
            return true ;
        }
    ) ;
    // 削除用(Join).
    baseMap.put( "removeJoin",
        function(params) {
            return baseMap.get( "remove" )( params,true,true ) ;
        }
    ) ;
    // 削除用(Join).
    baseMap.put( "removej",
        function(params) {
            return baseMap.get( "remove" )( params,true,true ) ;
        }
    ) ;
    // 削除用(ImageJoin).
    baseMap.put( "removeImageJoin",
        function(params) {
            return baseMap.get( "remove" )( params,false,true ) ;
        }
    ) ;
    // 削除用(ImageJoin).
    baseMap.put( "removei",
        function(params) {
            return baseMap.get( "remove" )( params,false,true ) ;
        }
    ) ;
    // 削除用
    baseMap.put( "remove",
        function(params,join,imgJoin) {
            if( isNull( params ) ) {
                return false ;
            }
            if( script_model().isType == false ) {
                return false ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return false ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var map = SubModel.convertParamByMap( params ) ;
            if( map == null || map.size() <= 0 ) {
                return false ;
            }
            SubModel.removeManyColumn( map ) ;
            var joinMap = null ;
            if( join == true ) {
                joinMap = SubModel.getModelBySrcJoinKeys( modelName,baseMap ) ;
            }
            var imgMap = null ;
            var imgMan = null ;
            if( imgJoin == true ) {
                imgMap = SubModel.getModelByImageJoin( baseMap ) ;
                if( isNull( imgMap ) == false ) {
                    imgMan = script_model().getImageOp() ;
                }
            }
            if( isNull( imgMap ) || isNull( imgMan ) ) {
                imgMap = null ;
                imgMan = null ;
            }
            script_model().removeData( modelName,imgMan,imgMap,joinMap,map ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            // 更新通知.
            script_model().setUpdateOrDeleteTable( modelName ) ;
            return true ;
        }
    ) ;
    // 指定取得用(Join).
    baseMap.put( "findJoin",
        function(where,params,sort) {
            return baseMap.get( "find" )( where,params,sort,true,false ) ;
        }
    ) ;
    // 指定取得用(Many).
    baseMap.put( "findMany",
        function(where,params,sort) {
            return baseMap.get( "find" )( where,params,sort,false,true ) ;
        }
    ) ;
    // 指定取得用.
    baseMap.put( "find",
        function(where,params,sort,join,many) {
            if( isNull( where ) ) {
                where = "" ;
            }
            else {
                where = trim( where ) ;
                if( where.length > 0 && startsWith( where.toLowerCase(),"where " ) == false ) {
                    where = "where " + where ;
                }
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return null ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return null ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            if( isNull( sort ) ) {
                sort = null ;
            }
            if( sort != null && ( sort = trim( sort ) ).length > 0 ) {
                if( startsWith( sort.toLowerCase(),"order by" ) == false ) {
                    sort = "order by "+sort ;
                }
                where += " " + sort ;
            }
            var joinMap = null ;
            if( join == true ) {
                joinMap = SubModel.getModelByJoinKeys( baseMap ) ;
            }
            var manyMap = null ;
            if( many == true ) {
                manyMap = SubModel.getModelBySrcJoinKeys( modelName,baseMap ) ;
            }
            var ret = script_model().find( modelName,joinMap,manyMap,where,list ) ;
            ret = SubModel.convertResultByJList( ret ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            return ret ;
        }
    ) ;
    // 指定取得用(Join).
    baseMap.put( "limitJoin",
        function(offset,limit,where,params,sort) {
            return baseMap.get( "limit" )( offset,limit,where,params,sort,true,false ) ;
        }
    ) ;
    // 指定取得用(Many).
    baseMap.put( "limitMany",
        function(offset,limit,where,params,sort) {
            return baseMap.get( "limit" )( offset,limit,where,params,sort,true,false ) ;
        }
    ) ;
    // 指定取得用(リミット指定).
    baseMap.put( "limit",
        function(offset,limit,where,params,sort,join,many) {
            if( isNull( offset ) ) {
                offset = 0 ;
            }
            if( isNull( limit ) ) {
                limit = -1 ;
            }
            if( isNull( where ) ) {
                where = "" ;
            }
            else {
                where = trim( where ) ;
                if( where.length > 0 && startsWith( where.toLowerCase(),"where " ) == false ) {
                    where = "where " + where ;
                }
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return null ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return null ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            if( isNull( sort ) ) {
                sort = null ;
            }
            if( sort != null && ( sort = trim( sort ) ).length > 0 ) {
                if( startsWith( sort.toLowerCase(),"order by" ) == false ) {
                    sort = "order by "+sort ;
                }
                where += " " + sort ;
            }
            var joinMap = null ;
            if( join == true ) {
                joinMap = SubModel.getModelByJoinKeys( baseMap ) ;
            }
            var manyMap = null ;
            if( many == true ) {
                manyMap = SubModel.getModelBySrcJoinKeys( modelName,baseMap ) ;
            }
            var ret = script_model().limit( modelName,joinMap,manyMap,offset,limit,where,list ) ;
            ret = SubModel.convertResultByJList( ret ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            return ret ;
        }
    ) ;
    // 指定取得用(最初の１件目だけを取得)(Join).
    baseMap.put( "firstJoin",
        function(where,params,sort) {
            return baseMap.get( "first" )( where,params,sort,true,false ) ;
        }
    ) ;
    // 指定取得用(最初の１件目だけを取得)(Many).
    baseMap.put( "firstMany",
        function(where,params,sort) {
            return baseMap.get( "first" )( where,params,sort,false,true ) ;
        }
    ) ;
    // 指定取得用(最初の１件目だけを取得).
    baseMap.put( "first",
        function(where,params,sort,join,many) {
            if( isNull( where ) ) {
                where = "" ;
            }
            else {
                where = trim( where ) ;
                if( where.length > 0 && startsWith( where.toLowerCase(),"where " ) == false ) {
                    where = "where " + where ;
                }
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return null ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return null ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            if( isNull( sort ) ) {
                sort = null ;
            }
            if( sort != null && ( sort = trim( sort ) ).length > 0 ) {
                if( startsWith( sort.toLowerCase(),"order by" ) == false ) {
                    sort = "order by "+sort ;
                }
                where += " " + sort ;
            }
            var joinMap = null ;
            if( join == true ) {
                joinMap = SubModel.getModelByJoinKeys( baseMap ) ;
            }
            var manyMap = null ;
            if( many == true ) {
                manyMap = SubModel.getModelBySrcJoinKeys( modelName,baseMap ) ;
            }
            var ret = script_model().first( modelName,joinMap,manyMap,where,list ) ;
            ret = SubModel.convertResultByJList( ret ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            return ret ;
        }
    ) ;
    // 指定数取得.
    baseMap.put( "count",
        function(where,params) {
            if( isNull( where ) ) {
                where = "" ;
            }
            else {
                where = trim( where ) ;
                if( where.length > 0 && startsWith( where.toLowerCase(),"where " ) == false ) {
                    where = "where " + where ;
                }
            }
            if( isNull( params ) ) {
                params = null ;
            }
            else if( valueof( params ) != "array" ) {
                params = [ params ] ;
            }
            if( script_model().isType == false ) {
                return 0 ;
            }
            if( script_model().isCreate() == false ) {
                create_base_model() ;
                if( script_model().isCreate() == false ) {
                    return 0 ;
                }
            }
            var time = null ;
            if( script_model().isDebug() == true ) {
                time = new Date().getTime() ;
            }
            var list = null ;
            if( params != null ) {
                list = SubModel.convertParamByList( params ) ;
                if( list == null || list.size() <= 0 ) {
                    list = null ;
                }
            }
            var ret = script_model().count( modelName,where,list ) ;
            if( script_model().isDebug() == true ) {
                debugLog( "## [" + ( new Date().getTime() - time ) + "ms]" ) ;
            }
            return parseValue( ret ) ;
        }
    ) ;
    // missing_method対応.
    return JSAdapter({
        __get__ : function (name) {
            if( isNull( name ) ) {
                return null ;
            }
            if( baseMap.containsKey( name ) ) {
                return baseMap.get( name ) ;
            } ;
            var missing = null ;
            var pms = name.split( "_" ) ;
            if( pms.length >= 3 ) {
                if( pms[ 1 ].toLowerCase() == "by" ) {
                    var funcName = pms[ 0 ].toLowerCase() ;
                    if( funcName == "find" || funcName == "removefind" ||
                        funcName == "first" || funcName == "count" ||
                        funcName == "findjoin" ||
                        funcName == "rfind" || funcName == "rjfind" || funcName == "rifind" ||
                        funcName == "removefindjoin" || funcName == "removefindimagejoin" ||
                        funcName == "firstjoin" || funcName == "findmany" ||
                        funcName == "firstmany" ) {
                        missing = function(params,sort) {
                            if( isNull( params ) ) {
                                params = null ;
                            }
                            if( isNull( sort ) ) {
                                sort = null ;
                            }
                            var where = "" ;
                            var len = pms.length ;
                            for( var i = 2 ; i < len ; i ++ ) {
                                var columnName = org.maachang.dao.dbms.DbUtil.convertJavaNameByDBName( pms[ i ] ) ;
                                pms[ i ] = pms[ i ].toLowerCase() ;
                                if( ( i & 0x00000001 ) == 0 ) {
                                    //if( pms[ i ] == "and" || pms[ i ] == "or" ) {
                                    if( pms[ i ] == "and" ) {
                                        return false ;
                                    }
                                    where += " $"+columnName+"=?" ;
                                }
                                else {
                                    //if( pms[ i ] == "and" || pms[ i ] == "or" ) {
                                    if( pms[ i ] == "and" ) {
                                        where += " " + pms[ i ] ;
                                    }
                                    else {
                                        return false ;
                                    }
                                }
                            }
                            if( funcName ==  "find" || funcName ==  "first" ||
                                funcName ==  "findjoin" || funcName ==  "firstjoin" ||
                                funcName ==  "findmany" || funcName ==  "firstmany" ) {
                                if( sort != null && ( sort = trim( sort ) ).length > 0 ) {
                                    if( startsWith( sort.toLowerCase(),"order by" ) == false ) {
                                        sort = "order by "+sort ;
                                    }
                                    where += " " + sort ;
                                }
                            }
                            where = "where " + where ;
                            if( funcName == "removefind" ) {
                                funcName = "removeFind" ;
                            }
                            else if( funcName == "rfind" ) {
                                funcName = "rfind" ;
                            }
                            else if( funcName == "rjfind" ) {
                                funcName = "rjfind" ;
                            }
                            else if( funcName == "rifind" ) {
                                funcName = "rifind" ;
                            }
                            else if( funcName == "removefindjoin" ) {
                                funcName = "removeFindJoin" ;
                            }
                            else if( funcName == "removefindimagejoin" ) {
                                funcName = "removeFindImageJoin" ;
                            }
                            else if( endsWith( funcName,"join" ) ) {
                                funcName = funcName.substring( 0,funcName.length - "join".length ) + "Join" ;
                            }
                            else if( endsWith( funcName,"many" ) ) {
                                funcName = funcName.substring( 0,funcName.length - "many".length ) + "Many" ;
                            }
                            return baseMap.get( funcName )( where,params ) ;
                        } ;
                    }
                    else if( funcName == "limit" || funcName == "limitjoin" || funcName == "limitmany" ) {
                        missing = function(offset,limit,params,sort) {
                            if( isNull( offset ) ) {
                                offset = 0 ;
                            }
                            if( isNull( limit ) ) {
                                limit = -1 ;
                            }
                            if( isNull( params ) ) {
                                params = null ;
                            }
                            if( isNull( sort ) ) {
                                sort = null ;
                            }
                            var where = "" ;
                            var len = pms.length ;
                            for( var i = 2 ; i < len ; i ++ ) {
                                var columnName = org.maachang.dao.dbms.DbUtil.convertJavaNameByDBName( pms[ i ] ) ;
                                pms[ i ] = pms[ i ].toLowerCase() ;
                                if( ( i & 0x00000001 ) == 0 ) {
                                    //if( pms[ i ] == "and" || pms[ i ] == "or" ) {
                                    if( pms[ i ] == "and" ) {
                                        return false ;
                                    }
                                    where += " $"+columnName+"=?" ;
                                }
                                else {
                                    //if( pms[ i ] == "and" || pms[ i ] == "or" ) {
                                    if( pms[ i ] == "and" ) {
                                        where += " " + pms[ i ] ;
                                    }
                                    else {
                                        return false ;
                                    }
                                }
                            }
                            if( sort != null && ( sort = trim( sort ) ).length > 0 ) {
                                if( startsWith( sort.toLowerCase(),"order by" ) == false ) {
                                    sort = "order by "+sort ;
                                }
                                where += " " + sort ;
                            }
                            where = "where " + where ;
                            if( funcName == "limitjoin" ) {
                                funcName = "limitJoin" ;
                            }
                            if( funcName == "limitmany" ) {
                                funcName = "limitMany" ;
                            }
                            return baseMap.get( funcName )( offset,limit,where,params ) ;
                        } ;
                    }
                }
            }
            return missing ;
        },
        __has__ : function (name) {
            if( isNull( name ) ) {
                return null ;
            }
            return baseMap.containsKey(name);
        },
        __put__ : function (name, value) {
            if( isNull( name ) || isNull( value ) ) {
                return ;
            }
            if( value != null ) {
                baseMap.put( name,parseValue( value ) ) ;
            } ;
        },
        __delete__ : function (name) {
            if( isNull( name ) ) {
                return ;
            }
            baseMap.remove( name ) ;
        },
        __getIds__ : function () {
            return null ;
        }
    }) ;
} ;

