--[[--------------------------------------------------------------------------------- AceLibrary by Cladhaire Based on the concept by Iriel Design influenced by Tekkub This aims to be a standard for Ace embedded libraries, as the general stub they all use to register themselves. This concept of embedded libraries came as a result of a number of discussions in both #wowace and #wowi-lounge. See http://www.iriel.org/wow/addondev/embedlibrary1.html for more information ----------------------------------------------------------------------------------]] -- DO NOT CHANGE THESE VALUES ----------------------------- local ACELIBRARY_MAJOR = "AceLibrary" local ACELIBRARY_MINOR = 2 -- DO NOT CHANGE THESE VALUES ------------------------------ local genv = getfenv(0) local previous = genv[ACELIBRARY_MAJOR] if previous and not previous:NewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end local mt = {} local AceLibrary = setmetatable({}, mt) -- Instance replacement method. Handles "upgrading" to a new version function AceLibrary:ReplaceInstance(old,new) for k,v in pairs(old) do old[k]=nil end for k,v in pairs(new) do old[k]=v end end -- Returns a new stub. This allows multiple libraries to use the same stub function AceLibrary:NewStub(name) local newStub = {} self:ReplaceInstance(newStub, self) newStub.versions = {} newStub.libName = name return newStub end -- Returns true if the supplied version would be an upgrade to the current version -- This allows for bypass code in library declaration. function AceLibrary:NewVersion(version, minor) local versionData = self.versions[version] if not versionData or versionData.minor < minor then return true end end -- Returns the version of the given library with the highest minor revision function AceLibrary:GetInstance(version) if not version then error("You must specify a version when requesting a library instance", 2) end local versionData = self.versions[version] if not versionData then error(string.format("Cannot find a library instance of %s.", version), 2) return end return versionData.instance end -- Syntax sugar. AceLibrary("FooBar-1.0") mt.__call = AceLibrary.GetInstance -- Registers a new version of a given library. Takes the library object. function AceLibrary:Register(newInstance) if not newInstance.GetLibraryVersion then return end local version,minor = newInstance:GetLibraryVersion() local versionData = self.versions[version] if not versionData then -- This is new versionData = { instance=newInstance, minor=minor, old={}} self.versions[version] = versionData newInstance:LibActivate(self) return newInstance end if minor <= versionData.minor then -- This one is already obsolete if newInstance.LibDiscard then newInstance:LibDiscard() end return versionData.instance end -- This is an update local oldInstance = versionData.instance local oldList = versionData.old versionData.instance = newInstance versionData.minor = minor local skipCopy = newInstance:LibActivate(self, oldInstance, oldList) table.insert(oldList, oldInstance) if not skipCopy then for i,old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end end return newInstance end function AceLibrary:GetLibraryVersion() return ACELIBRARY_MAJOR, ACELIBRARY_MINOR end function AceLibrary:LibActivate(stub, oldInstance, oldList) if not self.versions then if oldInstance then self.versions = oldInstance.versions else self.versions = {} end end -- Expose the library in the global environment genv[ACELIBRARY_MAJOR] = self end if previous then previous:Register(AceLibrary) else AceLibrary.versions = {} AceLibrary.libName = version AceLibrary:Register(AceLibrary) end