vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[
Name: AceDB-2.0
Revision: $Rev: 4763 $
Author(s): ckknight (ckknight@gmail.com)
Inspired By: AceDB 1.x by Turan (<email here>)
Website: http://www.wowace.com/
Documentation: http://wiki.wowace.com/index.php/AceDB-2.0
SVN: http://svn.wowace.com/root/trunk/Ace2/AceDB-2.0
Description: Mixin to allow for fast, clean, and featureful saved variable
             access.
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0
]]

local MAJOR_VERSION = "AceDB-2.0"
local MINOR_VERSION = "$Revision: 4763 $"

if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end

if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end

-- localize --
local ACTIVE = "Active"
local STATE = "State"
local TOGGLE_ACTIVE = "Suspend/resume this addon"
local MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Active|r", [false] = "|cffff0000Suspended|r" }
local SET_PROFILE = "Set profile for this addon"
local SET_PROFILE_USAGE = "{char || class || realm || <profile name>}"
local PROFILE = "Profile"
local PLAYER_OF_REALM = "%s of %s"
-- localize --

local AceOO = AceLibrary("AceOO-2.0")
local AceEvent
local Mixin = AceOO.Mixin
local AceDB = Mixin {
                                                "RegisterDB",
                                                "RegisterDefaults",
                                                "ResetDB",
                                                "SetProfile",
                                                "GetProfile",
                                                "ToggleActive",
                                                "IsActive",
                                                "AcquireDBNamespace",
                                                "ToggleStandby", -- remove at 2006-07-21
                                                "IsEnabled", -- remove at 2006-07-21
                                        }

local _G = getfenv(0)

local function inheritDefaults(t, defaults)
        if not defaults then
                return t
        end
        for k,v in pairs(defaults) do
                if k == "*" then
                        local v = v
                        if type(v) == "table" then
                                setmetatable(t, {
                                        __index = function(self, key)
                                                if key == nil then
                                                        return nil
                                                end
                                                self[key] = {}
                                                inheritDefaults(self[key], v)
                                                return self[key]
                                        end
                                } )
                        else
                                setmetatable(t, {
                                        __index = function(self, key)
                                                if key == nil then
                                                        return nil
                                                end
                                                self[key] = v
                                                return self[key]
                                        end
                                } )
                        end
                        for key in pairs(t) do
                                if (defaults[key] == nil or key == "*") and type(t[key]) == "table" then
                                        inheritDefaults(t[key], v)
                                end
                        end
                else
                        if type(v) == "table" then
                                if type(t[k]) ~= "table" then
                                        t[k] = {}
                                end
                                inheritDefaults(t[k], v)
                        elseif t[k] == nil then
                                t[k] = v
                        end
                end
        end
        return t
end

local _,race = UnitRace("player")
local faction
if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" then
        faction = FACTION_HORDE
else
        faction = FACTION_ALLIANCE
end
local charID = string.format(PLAYER_OF_REALM, UnitName("player"), (string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1")))
local realm = string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1")
local realmID = realm .. " - " .. faction
local classID = UnitClass("player")

AceDB.CHAR_ID = charID
AceDB.REALM_ID = realmID
AceDB.CLASS_ID = classID

AceDB.FACTION = faction
AceDB.REALM = realm
AceDB.NAME = UnitName("player")

local caseInsensitive_mt = {
        __index = function(self, key)
                if type(key) ~= "string" then
                        return nil
                end
                local lowerKey = string.lower(key)
                for k,v in pairs(self) do
                        if string.lower(k) == lowerKey then
                                return self[k]
                        end
                end
        end,
        __newindex = function(self, key, value)
                if type(key) ~= "string" then
                        return error("table index is nil", 2)
                end
                local lowerKey = string.lower(key)
                for k in pairs(self) do
                        if string.lower(k) == lowerKey then
                                rawset(self, k, nil)
                                rawset(self, key, value)
                                return
                        end
                end
                rawset(self, key, value)
        end
}

local db_mt = { __index = function(db, key)
        if key == "char" then
                if db.charName then
                        if type(_G[db.charName]) ~= "table" then
                                _G[db.charName] = {}
                        end
                        if type(_G[db.charName].raw) ~= "table" then
                                _G[db.charName].global = {}
                        end
                        rawset(db, 'char', _G[db.charName].global)
                else
                        if type(db.raw.chars) ~= "table" then
                                db.raw.chars = {}
                        end
                        local id = charID
                        if type(db.raw.chars[id]) ~= "table" then
                                db.raw.chars[id] = {}
                        end
                        rawset(db, 'char', db.raw.chars[id])
                end
                if db.defaults and db.defaults.char then
                        inheritDefaults(db.char, db.defaults.char)
                end
                return db.char
        elseif key == "realm" then
                if type(db.raw.realms) ~= "table" then
                        db.raw.realms = {}
                end
                local id = realmID
                if type(db.raw.realms[id]) ~= "table" then
                        db.raw.realms[id] = {}
                end
                rawset(db, 'realm', db.raw.realms[id])
                if db.defaults and db.defaults.realm then
                        inheritDefaults(db.realm, db.defaults.realm)
                end
                return db.realm
        elseif key == "account" then
                if type(db.raw.account) ~= "table" then
                        db.raw.account = {}
                end
                rawset(db, 'account', db.raw.account)
                if db.defaults and db.defaults.account then
                        inheritDefaults(db.account, db.defaults.account)
                end
                return db.account
        elseif key == "class" then
                if type(db.raw.classes) ~= "table" then
                        db.raw.classes = {}
                end
                local id = classID
                if type(db.raw.classes[id]) ~= "table" then
                        db.raw.classes[id] = {}
                end
                rawset(db, 'class', db.raw.classes[id])
                if db.defaults and db.defaults.class then
                        inheritDefaults(db.class, db.defaults.class)
                end
                return db.class
        elseif key == "profile" then
                if type(db.raw.profiles) ~= "table" then
                        db.raw.profiles = setmetatable({}, caseInsensitive_mt)
                else
                        setmetatable(db.raw.profiles, caseInsensitive_mt)
                end
                local id = db.raw.currentProfile[charID]
                if id == "char" then
                        id = "char/" .. charID
                elseif id == "class" then
                        id = "class/" .. classID
                elseif id == "realm" then
                        id = "realm/" .. realmID
                end
                if type(db.raw.profiles[id]) ~= "table" then
                        db.raw.profiles[id] = {}
                end
                rawset(db, 'profile', db.raw.profiles[id])
                if db.defaults and db.defaults.profile then
                        inheritDefaults(db.profile, db.defaults.profile)
                end
                return db.profile
        elseif key == "raw" or key == "defaults" or key == "name" or key == "charName" or key == "namespaces" then
                return nil
        end
        error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
end, __newindex = function(db, key, value)
        error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
end }

local namespace_mt = { __index = function(namespace, key)
        local db = namespace.db
        local name = namespace.name
        if key == "char" then
                if db.charName then
                        if type(_G[db.charName]) ~= "table" then
                                _G[db.charName] = {}
                        end
                        if type(_G[db.charName].namespaces) ~= "table" then
                                _G[db.charName].namespaces = {}
                        end
                        if type(_G[db.charName].namespaces[name]) ~= "table" then
                                _G[db.charName].namespaces[name] = {}
                        end
                        rawset(namespace, 'char', _G[db.charName].namespaces[name])
                else
                        if type(db.raw.namespaces) ~= "table" then
                                db.raw.namespaces = {}
                        end
                        if type(db.raw.namespaces[name]) ~= "table" then
                                db.raw.namespaces[name] = {}
                        end
                        if type(db.raw.namespaces[name].chars) ~= "table" then
                                db.raw.namespaces[name].chars = {}
                        end
                        local id = charID
                        if type(db.raw.namespaces[name].chars[id]) ~= "table" then
                                db.raw.namespaces[name].chars[id] = {}
                        end
                        rawset(namespace, 'char', db.raw.namespaces[name].chars[id])
                end
                if namespace.defaults and namespace.defaults.char then
                        inheritDefaults(namespace.char, namespace.defaults.char)
                end
                return namespace.char
        elseif key == "realm" then
                if type(db.raw.namespaces) ~= "table" then
                        db.raw.namespaces = {}
                end
                if type(db.raw.namespaces[name]) ~= "table" then
                        db.raw.namespaces[name] = {}
                end
                if type(db.raw.namespaces[name].realms) ~= "table" then
                        db.raw.namespaces[name].realms = {}
                end
                local id = realmID
                if type(db.raw.namespaces[name].realms[id]) ~= "table" then
                        db.raw.namespaces[name].realms[id] = {}
                end
                rawset(namespace, 'realm', db.raw.namespaces[name].realms[id])
                if namespace.defaults and namespace.defaults.realm then
                        inheritDefaults(namespace.realm, namespace.defaults.realm)
                end
                return namespace.realm
        elseif key == "account" then
                if type(db.raw.namespaces) ~= "table" then
                        db.raw.namespaces = {}
                end
                if type(db.raw.namespaces[name]) ~= "table" then
                        db.raw.namespaces[name] = {}
                end
                if type(db.raw.namespaces[name].account) ~= "table" then
                        db.raw.namespaces[name].account = {}
                end
                rawset(namespace, 'account', db.raw.namespaces[name].account)
                if namespace.defaults and namespace.defaults.account then
                        inheritDefaults(namespace.account, namespace.defaults.account)
                end
                return namespace.account
        elseif key == "class" then
                if type(db.raw.namespaces) ~= "table" then
                        db.raw.namespaces = {}
                end
                if type(db.raw.namespaces[name]) ~= "table" then
                        db.raw.namespaces[name] = {}
                end
                if type(db.raw.namespaces[name].classes) ~= "table" then
                        db.raw.namespaces[name].classes = {}
                end
                local id = classID
                if type(db.raw.namespaces[name].classes[id]) ~= "table" then
                        db.raw.namespaces[name].classes[id] = {}
                end
                rawset(namespace, 'class', db.raw.namespaces[name].classes[id])
                if namespace.defaults and namespace.defaults.class then
                        inheritDefaults(namespace.class, namespace.defaults.class)
                end
                return namespace.class
        elseif key == "profile" then
                if type(db.raw.namespaces) ~= "table" then
                        db.raw.namespaces = {}
                end
                if type(db.raw.namespaces[name]) ~= "table" then
                        db.raw.namespaces[name] = {}
                end
                if type(db.raw.namespaces[name].profiles) ~= "table" then
                        db.raw.namespaces[name].profiles = setmetatable({}, caseInsensitive_mt)
                else
                        setmetatable(db.raw.namespaces[name].profiles, caseInsensitive_mt)
                end
                local id = db.raw.currentProfile[charID]
                if id == "char" then
                        id = "char/" .. charID
                elseif id == "class" then
                        id = "class/" .. classID
                elseif id == "realm" then
                        id = "realm/" .. realmID
                end
                if type(db.raw.namespaces[name].profiles[id]) ~= "table" then
                        db.raw.namespaces[name].profiles[id] = {}
                end
                rawset(namespace, 'profile', db.raw.namespaces[name].profiles[id])
                if namespace.defaults and namespace.defaults.profile then
                        inheritDefaults(namespace.profile, namespace.defaults.profile)
                end
                return namespace.profile
        elseif key == "defaults" or key == "name" or key == "db" then
                return nil
        end
        error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
end, __newindex = function(db, key, value)
        error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2)
end }

function AceDB:InitializeDB(addonName)
        local db = self.db
        
        if not db then
                if addonName then
                        AceDB.addonsLoaded[addonName] = true
                end
                return
        end
        
        if db.raw then
                -- someone manually initialized
                return
        end
        
        if type(_G[db.name]) ~= "table" then
                _G[db.name] = {}
        end
        rawset(db, 'raw', _G[db.name])
        if not db.raw.currentProfile then
                db.raw.currentProfile = {}
        end
        if not db.raw.currentProfile[charID] then
                db.raw.currentProfile[charID] = "default"
        end
        if db.raw.disabled then
                setmetatable(db.raw.disabled, caseInsensitive_mt)
        end
        setmetatable(db, db_mt)
end

function AceDB:RegisterDB(name, charName)
        AceDB:argCheck(name, 2, "string")
        AceDB:argCheck(charName, 3, "string", "nil")
        if self.db then
                AceDB:error("Cannot call \"RegisterDB\" if self.db is set.")
        end
        local stack = debugstack()
        local addonName = string.gsub(stack, ".-\n.-\\AddOns\\(.-)\\.*", "%1")
        self.db = {
                name = name,
                charName = charName
        }
        if AceDB.addonsLoaded[addonName] then
                AceDB.InitializeDB(self, addonName)
        else
                AceDB.addonsToBeInitialized[self] = addonName
        end
        AceDB.registry[self] = true
end

function AceDB:RegisterDefaults(kind, defaults, a3)
        local name
        if a3 then
                name, kind, defaults = kind, defaults, a3
                AceDB:argCheck(name, 2, "string")
                AceDB:argCheck(kind, 3, "string")
                AceDB:argCheck(defaults, 4, "table")
                if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then
                        AceDB:error("Bad argument #3 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind)
                end
        else
                AceDB:argCheck(kind, 2, "string")
                AceDB:argCheck(defaults, 3, "table")
                if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then
                        AceDB:error("Bad argument #2 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind)
                end
        end
        if type(self.db) ~= "table" or type(self.db.name) ~= "string" then
                AceDB:error("Cannot call \"RegisterDefaults\" unless \"RegisterDB\" has been previously called.")
        end
        local db
        if name then
                local namespace = self:AcquireDBNamespace(name)
                if namespace.defaults and namespace.defaults[kind] then
                        AceDB:error("\"RegisterDefaults\" has already been called for %q::%q.", name, kind)
                end
                db = namespace
        else
                if self.db.defaults and self.db.defaults[kind] then
                        AceDB:error("\"RegisterDefaults\" has already been called for %q.", kind)
                end
                db = self.db
        end
        if not db.defaults then
                rawset(db, 'defaults', {})
        end
        db.defaults[kind] = defaults
        if rawget(db, kind) then
                inheritDefaults(db[kind], defaults)
        end
end

function AceDB:ResetDB(kind)
        AceDB:checkArg(kind, 2, "nil", "string")
        if not self.db or not self.db.raw then
                AceDB:error("Cannot call \"ResetDB\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
        end
        local db = self.db
        if kind == nil then
                if db.charName then
                        _G[db.charName] = nil
                end
                _G[db.name] = nil
                rawset(db, 'raw', nil)
                AceDB.InitializeDB(self)
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'account', nil)
                        rawset(v, 'char', nil)
                        rawset(v, 'class', nil)
                        rawset(v, 'profile', nil)
                        rawset(v, 'realm', nil)
                end
        elseif kind == "account" then
                db.raw.account = nil
                rawset(db, 'account', nil)
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'account', nil)
                end
        elseif kind == "char" then
                if db.charName then
                        _G[db.charName] = nil
                else
                        db.raw.chars[charID] = nil
                        for name,v in pairs(db.raw.namespaces) do
                                if v.chars then
                                        v.chars[charID] = nil
                                end
                        end
                end
                rawset(db, 'char', nil)
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'char', nil)
                end
        elseif kind == "realm" then
                db.raw.realms[realmID] = nil
                rawset(db, 'realm', nil)
                for name,v in pairs(db.raw.namespaces) do
                        if v.realms then
                                v.realms[realmID] = nil
                        end
                end
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'realm', nil)
                end
        elseif kind == "class" then
                db.raw.realms[classID] = nil
                rawset(db, 'class', nil)
                for name,v in pairs(db.raw.namespaces) do
                        if v.classes then
                                v.classes[classID] = nil
                        end
                end
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'class', nil)
                end
        elseif kind == "profile" then
                local id = db.raw.currentProfile[charID]
                if id == "char" then
                        id = "char/" .. charID
                elseif id == "class" then
                        id = "class/" .. classID
                elseif id == "realm" then
                        id = "realm/" .. realmID
                end
                db.raw.profiles[id] = nil
                rawset(db, 'profile', nil)
                for name,v in pairs(db.raw.namespaces) do
                        if v.profiles then
                                v.profiles[id] = nil
                        end
                end
                for name,v in pairs(db.namespaces) do
                        rawset(v, 'profile', nil)
                end
        end
end

local function cleanDefaults(t, defaults)
        if defaults then
                for k,v in pairs(defaults) do
                        if k == "*" then
                                if type(v) == "table" then
                                        for k in pairs(t) do
                                                if (defaults[k] == nil or k == "*") and type(t[k]) == "table" then
                                                        if cleanDefaults(t[k], v) then
                                                                t[k] = nil
                                                        end
                                                end
                                        end
                                else
                                        for k in pairs(t) do
                                                if (defaults[k] == nil or k == "*") and t[k] == v then
                                                        t[k] = nil
                                                end
                                        end
                                end
                        else
                                if type(v) == "table" then
                                        if type(t[k]) == "table" then
                                                if cleanDefaults(t[k], v) then
                                                        t[k] = nil
                                                end
                                        end
                                elseif t[k] == v then
                                        t[k] = nil
                                end
                        end
                end
        end
        return not next(t)
end

function AceDB:GetProfile()
        if not self.db or not self.db.raw then
                return nil
        end
        local profile = self.db.raw.currentProfile[charID]
        if profile == "char" then
                return "char", "char/" .. charID
        elseif profile == "class" then
                return "class", "class/" .. classID
        elseif profile == "realm" then
                return "realm", "realm/" .. realmID
        end
        return profile, profile
end

local function copyTable(to, from)
        setmetatable(to, nil)
        for k,v in pairs(from) do
                if type(k) == "table" then
                        k = copyTable({}, k)
                end
                if type(v) == "table" then
                        v = copyTable({}, v)
                end
                to[k] = v
        end
        table.setn(to, table.getn(from))
        setmetatable(to, from)
        return to
end

local stage = 3
if tonumber(date("%Y%m%d")) < 20060713 then
        stage = 1
elseif tonumber(date("%Y%m%d")) < 20060720 then
        stage = 2
end

function AceDB:SetProfile(name, copyFrom)
        AceDB:argCheck(name, 2, "string")
        AceDB:argCheck(copyFrom, 3, "string", "nil")
        if not self.db or not self.db.raw then
                AceDB:error("Cannot call \"SetProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
        end
        local db = self.db
        local copy = false
        local lowerName = string.lower(name)
        local lowerCopyFrom = copyFrom and string.lower(copyFrom)
        if string.sub(lowerName, 1, 5) == "char/" or string.sub(lowerName, 1, 6) == "realm/" or string.sub(lowerName, 1, 6) == "class/" then
                if stage <= 2 then
                        if string.sub(lowerName, 1, 5) == "char/" then
                                name, copyFrom = "char", name
                        else
                                name, copyFrom = string.sub(lowerName, 1, 5), name
                        end
                        lowerName = string.lower(name)
                        lowerCopyFrom = string.lower(copyFrom)
                        if stage == 2 then
                                local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1")
                                DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - Bad argument #2 to `SetProfile'. Cannot start with char/, realm/, or class/. This will cause an error on July 20, 2006.")
                        end
                else
                        AceDB:error("Bad argument #2 to `SetProfile'. Cannot start with char/, realm/, or class/.")
                end
        end
        if copyFrom then
                if string.sub(lowerCopyFrom, 1, 5) == "char/" then
                        AceDB:assert(lowerName == "char", "If argument #3 starts with `char/', argument #2 must be `char'")
                elseif string.sub(lowerCopyFrom, 1, 6) == "realm/" then
                        AceDB:assert(lowerName == "realm", "If argument #3 starts with `realm/', argument #2 must be `realm'")
                elseif string.sub(lowerCopyFrom, 1, 6) == "class/" then
                        AceDB:assert(lowerName == "class", "If argument #3 starts with `class/', argument #2 must be `class'")
                else
                        AceDB:assert(lowerName ~= "char" and lowerName ~= "realm" and lowerName ~= "class", "If argument #3 does not start with a special prefix, that prefix cannot be copied to.")
                end
                if not db.raw.profiles or not db.raw.profiles[copyFrom] then
                        AceDB:error("Cannot copy profile %q, it does not exist.", copyFrom)
                elseif (string.sub(lowerName, 1, 5) == "char/" and string.sub(lowerName, 6) == string.lower(charID)) or (string.sub(lowerName, 1, 6) == "realm/" and string.sub(lowerName, 7) == string.lower(realmID)) or (string.sub(lowerName, 1, 6) == "class/" and string.sub(lowerName, 7) == string.lower(classID)) then
                        AceDB:error("Cannot copy profile %q, it is currently in use.", name)
                end
        end
        local oldName = db.raw.currentProfile[charID]
        if type(self.OnProfileDisable) == "function" then
                self:OnProfileDisable()
        end
        local oldProfileData = db.profile
        local realName = name
        if lowerName == "char" then
                realName = name .. "/" .. charID
        elseif lowerName == "realm/" then
                realName = name .. "/" .. realmID
        elseif lowerName == "class/" then
                realName = name .. "/" .. classID
        end
        local active = self:IsActive()
        db.raw.currentProfile[charID] = name
        rawset(db, 'profile', nil)
        if copyFrom then
                for k,v in pairs(db.profile) do
                        db.profile[k] = nil
                end
                copyTable(db.profile, db.raw.profiles[copyFrom])
                inheritDefaults(db.profile, db.defaults and db.defaults.profile)
        end
        if type(self.OnProfileEnable) == "function" then
                self:OnProfileEnable(oldName, oldProfileData)
        end
        if cleanDefaults(oldProfileData, db.defaults and db.defaults.profile) then
                db.raw.profiles[oldName] = nil
                if not next(db.raw.profiles) then
                        db.raw.profiles = nil
                end
        end
        local newactive = self:IsActive()
        if active ~= newactive then
                if AceOO.inherits(self, "AceAddon-2.0") then
                        local AceAddon = AceLibrary("AceAddon-2.0")
                        if not AceAddon.addonsStarted[self] then
                                return
                        end
                end
                if newactive then
                        if type(self.OnEnable) == "function" then
                                self:OnEnable()
                        end
                else
                        local current = self.class
                        while true do
                                if current == AceOO.Class then
                                        break
                                end
                                if current.mixins then
                                        for mixin in pairs(current.mixins) do
                                                if type(mixin.OnEmbedDisable) == "function" then
                                                        mixin:OnEmbedDisable(self)
                                                end
                                        end
                                end
                                current = current.super
                        end
                        if type(self.OnDisabled) == "function" then
                                self:OnDisable()
                        end
                end
        end
end

local stage = 3
if tonumber(date("%Y%m%d")) < 20060714 then
        stage = 1
elseif tonumber(date("%Y%m%d")) < 20060721 then
        stage = 2
end

function AceDB:IsActive()
        return not self.db or not self.db.raw or not self.db.raw.disabled or not self.db.raw.disabled[self.db.raw.currentProfile[charID]]
end

function AceDB:ToggleActive(state)
        AceDB:argCheck(state, 2, "boolean", "nil")
        if not self.db or not self.db.raw then
                AceDB:error("Cannot call \"ToggleActive\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.")
        end
        local db = self.db
        if not db.raw.disabled then
                db.raw.disabled = setmetatable({}, caseInsensitive_mt)
        end
        local profile = db.raw.currentProfile[charID]
        local disable
        if state == nil then
                disable = not db.raw.disabled[profile]
        else
                disable = not state
                if disable == db.raw.disabled[profile] then
                        return
                end
        end
        db.raw.disabled[profile] = disable or nil
        if AceOO.inherits(self, "AceAddon-2.0") then
                local AceAddon = AceLibrary("AceAddon-2.0")
                if not AceAddon.addonsStarted[self] then
                        return
                end
        end
        if not disable then
                if type(self.OnEnable) == "function" then
                        self:OnEnable()
                end
        else
                local current = self.class
                while true do
                        if current == AceOO.Class then
                                break
                        end
                        if current.mixins then
                                for mixin in pairs(current.mixins) do
                                        if type(mixin.OnEmbedDisable) == "function" then
                                                mixin:OnEmbedDisable(self)
                                        end
                                end
                        end
                        current = current.super
                end
                if type(self.OnDisable) == "function" then
                        self:OnDisable()
                end
        end
        return not disable
end

if stage <= 2 then
        function AceDB:IsEnabled()
                if stage == 2 then
                        local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1")
                        DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - :IsEnabled() has been replaced by :IsActive(). This will cause an error on July 21, 2006.")
                end
                return self:IsActive()
        end
        function AceDB:ToggleStandby()
                if stage == 2 then
                        local line = string.gsub(debugstack(), ".-\n(.-)\n.*", "%1")
                        DEFAULT_CHAT_MESSAGE:AddMessage(line .. " - :ToggleStandby() has been replaced by :ToggleActive([state]). This will cause an error on July 21, 2006.")
                end
                return self:ToggleActive()
        end
end

function AceDB:embed(target)
        self.super.embed(self, target)
        if not AceEvent then
                AceDB:error(MAJOR_VERSION .. " requires AceEvent-2.0")
        end
end

function AceDB:ADDON_LOADED(name)
        AceDB.addonsLoaded[name] = true
        for addon, addonName in pairs(AceDB.addonsToBeInitialized) do
                if name == addonName then
                        AceDB.InitializeDB(addon, name)
                        AceDB.addonsToBeInitialized[addon] = nil
                end
        end
end

function AceDB:PLAYER_LOGOUT()
        for addon in pairs(AceDB.registry) do
                local db = addon.db
                if db then
                        setmetatable(db, nil)
                        if db.char and cleanDefaults(db.char, db.defaults and db.defaults.char) then
                                if db.charName and _G[db.charName].global == db.char then
                                        _G[db.charName].global = nil
                                        if not next(_G[db.charName]) then
                                                _G[db.charName] = nil
                                        end
                                else
                                        db.raw.chars[charID] = nil
                                        if not next(db.raw.chars) then
                                                db.raw.chars = nil
                                        end
                                end
                        end
                        if db.realm and cleanDefaults(db.realm, db.defaults and db.defaults.realm) then
                                db.raw.realms[realmID] = nil
                                if not next(db.raw.realms) then
                                        db.raw.realms = nil
                                end
                        end
                        if db.class and cleanDefaults(db.class, db.defaults and db.defaults.class) then
                                db.raw.classes[classID] = nil
                                if not next(db.raw.classes) then
                                        db.raw.classes = nil
                                end
                        end
                        if db.account and cleanDefaults(db.account, db.defaults and db.defaults.account) then
                                db.raw.account = nil
                        end
                        if db.profile and cleanDefaults(db.profile, db.defaults and db.defaults.profile) then
                                db.raw.profiles[db.raw.currentProfile[charID] or "default"] = nil
                                if not next(db.raw.profiles) then
                                        db.raw.profiles = nil
                                end
                        end
                        if db.namespaces then
                                for name,v in pairs(db.namespaces) do
                                        setmetatable(v, nil)
                                        if v.char and cleanDefaults(v.char, v.defaults and v.defaults.char) then
                                                if db.charName and _G[db.charName] and _G[db.charName].namespaces and _G[db.charName].namespaces[name] == v then
                                                        _G[db.charName].namespaces[name] = nil
                                                        if not next(_G[db.charName].namespaces) then
                                                                _G[db.charName].namespaces = nil
                                                                if not next(_G[db.charName]) then
                                                                        _G[db.charName] = nil
                                                                end
                                                        end
                                                else
                                                        db.raw.namespaces[name].chars[charID] = nil
                                                        if not next(db.raw.namespaces[name].chars) then
                                                                db.raw.namespaces[name].chars = nil
                                                        end
                                                end
                                        end
                                        if v.realm and cleanDefaults(v.realm, v.defaults and v.defaults.realm) then
                                                db.raw.namespaces[name].realms[realmID] = nil
                                                if not next(db.raw.namespaces[name].realms) then
                                                        db.raw.namespaces[name].realms = nil
                                                end
                                        end
                                        if v.class and cleanDefaults(v.class, v.defaults and v.defaults.class) then
                                                db.raw.namespaces[name].classes[classID] = nil
                                                if not next(db.raw.namespaces[name].classes) then
                                                        db.raw.namespaces[name].classes = nil
                                                end
                                        end
                                        if v.account and cleanDefaults(v.account, v.defaults and v.defaults.account) then
                                                db.raw.namespaces[name].account = nil
                                        end
                                        if v.profile and cleanDefaults(v.profile, v.defaults and v.defaults.profile) then
                                                db.raw.namespaces[name].profiles[db.raw.currentProfile[charID] or "default"] = nil
                                                if not next(db.raw.namespaces[name].profiles) then
                                                        db.raw.namespaces[name].profiles = nil
                                                end
                                        end
                                        if not next(db.raw.namespaces[name]) then
                                                db.raw.namespaces[name] = nil
                                        end
                                end
                                if not next(db.raw.namespaces) then
                                        db.raw.namespaces = nil
                                end
                        end
                        if db.raw.disabled then
                                if not next(db.raw.disabled) then
                                        db.raw.disabled = nil
                                end
                        end
                        if db.raw.currentProfile then
                                for k,v in pairs(db.raw.currentProfile) do
                                        if string.lower(v) == "default" then
                                                db.raw.currentProfile[k] = nil
                                        end
                                end
                                if not next(db.raw.currentProfile) then
                                        db.raw.currentProfile = nil
                                end
                        end
                        if not next(db.raw) then
                                _G[db.name] = nil
                        end
                end
        end
end

function AceDB:AcquireDBNamespace(name)
        AceDB:argCheck(name, 2, "string")
        local db = self.db
        if not db then
                AceDB:error("Cannot call `AcquireDBNamespace' before `RegisterDB' has been called.", 2)
        end
        if not db.namespaces then
                rawset(db, 'namespaces', {})
        end
        if not db.namespaces[name] then
                local namespace = {}
                db.namespaces[name] = namespace
                namespace.db = db
                namespace.name = name
                setmetatable(namespace, namespace_mt)
        end
        return db.namespaces[name]
end

local options
function AceDB:GetAceOptionsDataTable(target)
        if not options then
                options = {
                        standby = {
                                cmdName = STATE,
                                guiName = ACTIVE,
                                name = ACTIVE,
                                desc = TOGGLE_ACTIVE,
                                type = "toggle",
                                get = "IsActive",
                                set = "ToggleActive",
                                map = MAP_ACTIVESUSPENDED,
                        },
                        profile = {
                                name = PROFILE,
                                desc = SET_PROFILE,
                                get = "GetProfile",
                                set = "SetProfile",
                                usage = SET_PROFILE_USAGE,
                                type = "text",
                                validate = function(x) return not tonumber(x) end,
                        }
                }
        end
        return options
end

local function activate(self, oldLib, oldDeactivate)
        AceDB = self
        AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0")
        
        self.super.activate(self, oldLib, oldDeactivate)
        
        for t in pairs(self.embedList) do
                if t.db then
                        rawset(t.db, 'char', nil)
                        rawset(t.db, 'realm', nil)
                        rawset(t.db, 'class', nil)
                        rawset(t.db, 'account', nil)
                        rawset(t.db, 'profile', nil)
                        setmetatable(t.db, db_mt)
                end
        end
        
        if oldLib then
                self.addonsToBeInitialized = oldLib.addonsToBeInitialized
                self.addonsLoaded = oldLib.addonsLoaded
                self.registry = oldLib.registry
        end
        if not self.addonsToBeInitialized then
                self.addonsToBeInitialized = {}
        end
        if not self.addonsLoaded then
                self.addonsLoaded = {}
        end
        if not self.registry then
                self.registry = {}
        end
        
        if oldLib then
                oldDeactivate(oldLib)
        end
end

local function external(self, major, instance)
        if major == "AceEvent-2.0" then
                AceEvent = instance
                
                AceEvent:embed(self)
                
                self:RegisterEvent("ADDON_LOADED")
                self:RegisterEvent("PLAYER_LOGOUT")
        end
end

AceLibrary:Register(AceDB, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
AceDB = AceLibrary(MAJOR_VERSION)