vanilla-wow-addons – Rev 1
?pathlinks?
--[[
Name: AceOO-2.0
Revision: $Rev: 11577 $
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
Website: http://www.wowace.com/
Documentation: http://www.wowace.com/index.php/AceOO-2.0
SVN: http://svn.wowace.com/root/trunk/Ace2/AceOO-2.0
Description: Library to provide an object-orientation framework.
Dependencies: AceLibrary
]]
local MAJOR_VERSION = "AceOO-2.0"
local MINOR_VERSION = "$Revision: 11577 $"
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
local table_setn
do
local version = GetBuildInfo()
if string.find(version, "^2%.") then
-- 2.0.0
table_setn = function() end
else
table_setn = table.setn
end
end
local AceOO = {
error = AceLibrary.error,
argCheck = AceLibrary.argCheck
}
-- @function getuid
-- @brief Obtain a unique string identifier for the object in question.
-- @param t The object to obtain the uid for.
-- @return The uid string.
local function pad(cap)
return string.rep('0', 8 - string.len(cap)) .. cap
end
local function getuid(t)
local mt = getmetatable(t)
setmetatable(t, nil)
local str = tostring(t)
setmetatable(t, mt)
local _,_,cap = string.find(str, '[^:]*: 0x(.*)$')
if cap then return pad(cap) end
_,_,cap = string.find(str, '[^:]*: (.*)$')
if cap then return pad(cap) end
end
local function getlibrary(o)
if type(o) == "table" then
return o
elseif type(o) == "string" then
if not AceLibrary:HasInstance(o) then
AceOO:error("Library %q does not exist.", o)
end
return AceLibrary(o)
end
end
-- @function Factory
-- @brief Construct a factory for the creation of objects.
-- @param obj The object whose init method will be called on the new factory
-- object.
-- @param newobj The object whose init method will be called on the new
-- objects that the Factory creates, to initialize them.
-- @param (a1..a20) Arguments which will be passed to obj.init() in addition
-- to the Factory object.
-- @return The new factory which creates a newobj when its new method is called,
-- or when it is called directly (__call metamethod).
local Factory
do
local function new(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
local t = {}
local uid = getuid(t)
local l = getlibrary
obj:init(t, l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7),
l(a8), l(a9), l(a10), l(a11), l(a12), l(a13),
l(a14), l(a15), l(a16), l(a17), l(a18), l(a19),
l(a20))
t.uid = uid
return t
end
local function createnew(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18,
a19, a20)
local o = self.prototype
local l = getlibrary
return new(o, l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7),
l(a8), l(a9), l(a10), l(a11), l(a12), l(a13),
l(a14), l(a15), l(a16), l(a17), l(a18), l(a19),
l(a20))
end
function Factory(obj, newobj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18,
a19, a20)
local t = new(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
t.prototype = newobj
t.new = createnew
getmetatable(t).__call = t.new
return t
end
end
local function objtostring(self)
if self.ToString then
return self:ToString()
elseif self.GetLibraryVersion then
return (self:GetLibraryVersion())
elseif self.super then
local s = "Sub-" .. tostring(self.super)
local first = true
if self.interfaces then
for interface in pairs(self.interfaces) do
if first then
s = s .. "(" .. tostring(interface)
first = false
else
s = s .. ", " .. tostring(interface)
end
end
end
if self.mixins then
for mixin in pairs(self.mixins) do
if first then
s = s .. tostring(mixin)
first = false
else
s = s .. ", " .. tostring(mixin)
end
end
end
if first then
if self.uid then
return s .. ":" .. self.uid
else
return s
end
else
return s .. ")"
end
else
return self.uid and 'Subclass:' .. self.uid or 'Subclass'
end
end
-- @table Object
-- @brief Base of all objects, including Class.
--
-- @method init
-- @brief Initialize a new object.
-- @param newobject The object to initialize
-- @param class The class to make newobject inherit from
local Object
do
Object = {}
function Object:init(newobject, class)
local parent = class or self
if not rawget(newobject, 'uid') then
newobject.uid = getuid(newobject)
end
local mt = {
__index = parent,
__tostring = objtostring,
}
setmetatable(newobject, mt)
end
Object.uid = getuid(Object)
setmetatable(Object, { __tostring = function() return 'Object' end })
end
local Interface
local function validateInterface(object, interface)
if not object.class and object.prototype then
object = object.prototype
end
for k,v in pairs(interface.interface) do
if tostring(type(object[k])) ~= v then
return false
end
end
if interface.superinterfaces then
for superinterface in pairs(interface.superinterfaces) do
if not validateInterface(object, superinterface) then
return false
end
end
end
if type(object.class) == "table" and rawequal(object.class.prototype, object) then
if not object.class.interfaces then
rawset(object.class, 'interfaces', {})
end
object.class.interfaces[interface] = true
elseif type(object.class) == "table" and type(object.class.prototype) == "table" then
validateInterface(object.class.prototype, interface)
-- check if class is proper, thus preventing future checks.
end
return true
end
-- @function inherits
-- @brief Return whether an Object or Class inherits from a given
-- parent.
-- @param object Object or Class to check
-- @param parent Parent to test inheritance from
-- @return whether an Object or Class inherits from a given
-- parent.
local function inherits(object, parent)
object = getlibrary(object)
if type(parent) == "string" then
if not AceLibrary:HasInstance(parent) then
return false
else
parent = AceLibrary(parent)
end
end
AceOO:argCheck(parent, 2, "table")
if type(object) ~= "table" then
return false
end
local current
if object.class then
current = object.class
else
current = object
end
if type(current) ~= "table" then
return false
end
if rawequal(current, parent) then
return true
end
if parent.class then
while true do
if rawequal(current, Object) then
break
end
if current.mixins then
for mixin in pairs(current.mixins) do
if rawequal(mixin, parent) then
return true
end
end
end
if current.interfaces then
for interface in pairs(current.interfaces) do
if rawequal(interface, parent) then
return true
end
end
end
current = current.super
if type(current) ~= "table" then
break
end
end
local isInterface = false
local curr = parent.class
while true do
if rawequal(curr, Object) then
break
elseif rawequal(curr, Interface) then
isInterface = true
break
end
curr = curr.super
if type(curr) ~= "table" then
break
end
end
return isInterface and validateInterface(object, parent)
else
while true do
if rawequal(current, parent) then
return true
elseif rawequal(current, Object) then
return false
end
current = current.super
if type(current) ~= "table" then
return false
end
end
end
end
-- @table Class
-- @brief An object factory which sets up inheritence and supports
-- 'mixins'.
--
-- @metamethod Class call
-- @brief Call ClassFactory:new() to create a new class.
--
-- @method Class new
-- @brief Construct a new object.
-- @param (a1..a20) Arguments to pass to the object init function.
-- @return The new object.
--
-- @method Class init
-- @brief Initialize a new class.
-- @param parent Superclass.
-- @param (a1..a20) Mixins.
--
-- @method Class ToString
-- @return A string representing the object, in this case 'Class'.
local initStatus
local Class
local Mixin
local autoEmbed = false
local function traverseInterfaces(bit, total)
if bit.superinterfaces then
for interface in pairs(bit.superinterfaces) do
if not total[interface] then
total[interface] = true
traverseInterfaces(interface, total)
end
end
end
end
local class_new
do
Class = Factory(Object, setmetatable({}, {__index = Object}), Object)
Class.super = Object
local function protostring(t)
return '<' .. tostring(t.class) .. ' prototype>'
end
local function classobjectstring(t)
if t.ToString then
return t:ToString()
elseif t.GetLibraryVersion then
return (t:GetLibraryVersion())
else
return '<' .. tostring(t.class) .. ' instance>'
end
end
local function classobjectequal(self, other)
if type(self) == "table" and self.Equals then
return self:Equals(other)
elseif type(other) == "table" and other.Equals then
return other:Equals(self)
elseif type(self) == "table" and self.CompareTo then
return self:CompareTo(other) == 0
elseif type(other) == "table" and other.CompareTo then
return other:CompareTo(self) == 0
else
return rawequal(self, other)
end
end
local function classobjectlessthan(self, other)
if type(self) == "table" and self.IsLessThan then
return self:IsLessThan(other)
elseif type(other) == "table" and other.IsLessThanOrEqualTo then
return not other:IsLessThanOrEqualTo(self)
elseif type(self) == "table" and self.CompareTo then
return self:CompareTo(other) < 0
elseif type(other) == "table" and other.CompareTo then
return other:CompareTo(self) > 0
elseif type(other) == "table" and other.IsLessThan and other.Equals then
return other:Equals(self) or other:IsLessThan(self)
else
AceOO:error("cannot compare two objects")
end
end
local function classobjectlessthanequal(self, other)
if type(self) == "table" and self.IsLessThanOrEqualTo then
return self:IsLessThanOrEqualTo(other)
elseif type(other) == "table" and other.IsLessThan then
return not other:IsLessThan(self)
elseif type(self) == "table" and self.CompareTo then
return self:CompareTo(other) <= 0
elseif type(other) == "table" and other.CompareTo then
return other:CompareTo(self) >= 0
elseif type(self) == "table" and self.IsLessThan and self.Equals then
return self:Equals(other) or self:IsLessThan(other)
else
AceOO:error("cannot compare two incompatible objects")
end
end
local function classobjectadd(self, other)
if type(self) == "table" and self.Add then
return self:Add(other)
else
AceOO:error("cannot add two incompatible objects")
end
end
local function classobjectsub(self, other)
if type(self) == "table" and self.Subtract then
return self:Subtract(other)
else
AceOO:error("cannot subtract two incompatible objects")
end
end
local function classobjectunm(self, other)
if type(self) == "table" and self.UnaryNegation then
return self:UnaryNegation(other)
else
AceOO:error("attempt to negate an incompatible object")
end
end
local function classobjectmul(self, other)
if type(self) == "table" and self.Multiply then
return self:Multiply(other)
else
AceOO:error("cannot multiply two incompatible objects")
end
end
local function classobjectdiv(self, other)
if type(self) == "table" and self.Divide then
return self:Divide(other)
else
AceOO:error("cannot divide two incompatible objects")
end
end
local function classobjectpow(self, other)
if type(self) == "table" and self.Exponent then
return self:Exponent(other)
else
AceOO:error("cannot exponentiate two incompatible objects")
end
end
local function classobjectconcat(self, other)
if type(self) == "table" and self.Concatenate then
return self:Concatenate(other)
else
AceOO:error("cannot concatenate two incompatible objects")
end
end
function class_new(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
if self.virtual then
AceOO:error("Cannot instantiate a virtual class.")
end
local o = self.prototype
local newobj = {}
if o.class and o.class.instancemeta then
setmetatable(newobj, o.class.instancemeta)
else
Object:init(newobj, o)
end
if self.interfaces and not self.interfacesVerified then
-- Verify the interfaces
for interface in pairs(self.interfaces) do
for field,kind in pairs(interface.interface) do
if tostring(type(newobj[field])) ~= kind then
AceOO:error("Class did not satisfy all interfaces. %q is required to be a %s. It is a %s", field, kind, tostring(type(newobj[field])))
end
end
end
self.interfacesVerified = true
end
local tmp = initStatus
initStatus = newobj
newobj:init(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
if initStatus then
initStatus = tmp
AceOO:error("Initialization not completed, be sure to call the superclass's init method.")
return
end
initStatus = tmp
return newobj
end
local classmeta = {
__tostring = objtostring,
__call = function(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
return self:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
a13, a14, a15, a16, a17, a18, a19, a20)
end,
}
function Class:init(newclass, parent, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16,
a17, a18, a19, a20)
parent = parent or self
local total
if parent.class then
total = {
parent, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16,
a17, a18, a19, a20
}
parent = self
else
total = {
a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16,
a17, a18, a19, a20
}
end
if not inherits(parent, Class) then
AceOO:error("Classes must inherit from a proper class")
end
if parent.sealed then
AceOO:error("Cannot inherit from a sealed class")
end
for i,v in ipairs(total) do
if inherits(v, Mixin) and v.class then
if not newclass.mixins then
newclass.mixins = {}
end
if newclass.mixins[v] then
AceOO:error("Cannot explicitly inherit from the same mixin twice")
end
newclass.mixins[v] = true
elseif inherits(v, Interface) and v.class then
if not newclass.interfaces then
newclass.interfaces = {}
end
if newclass.interfaces[v] then
AceOO:error("Cannot explicitly inherit from the same interface twice")
end
newclass.interfaces[v] = true
else
AceOO:error("Classes can only inherit from one or zero classes and any number of mixins or interfaces")
end
end
if parent.interfaces then
if newclass.interfaces then
for interface in pairs(parent.interfaces) do
newclass.interfaces[interface] = true
end
else
newclass.interfaces = parent.interfaces
end
end
for k in pairs(total) do
total[k] = nil
end
table_setn(total, 0)
newclass.super = parent
newclass.prototype = setmetatable(total, {
__index = parent.prototype,
__tostring = protostring,
})
total = nil
newclass.instancemeta = {
__index = newclass.prototype,
__tostring = classobjectstring,
__eq = classobjectequal,
__lt = classobjectlessthan,
__le = classobjectlessthanequal,
__add = classobjectadd,
__sub = classobjectsub,
__unm = classobjectunm,
__mul = classobjectmul,
__div = classobjectdiv,
__pow = classobjectpow,
__concat = classobjectconcat,
}
setmetatable(newclass, classmeta)
newclass.new = class_new
if newclass.mixins then
-- Fold in the mixins
local err, msg
for mixin in pairs(newclass.mixins) do
local ret
autoEmbed = true
ret, msg = pcall(mixin.embed, mixin, newclass.prototype)
autoEmbed = false
if not ret then
err = true
break
end
end
if err then
local pt = newclass.prototype
for k,v in pairs(pt) do
pt[k] = nil
end
-- method conflict
AceOO:error(msg)
end
end
newclass.prototype.class = newclass
if newclass.interfaces then
for interface in pairs(newclass.interfaces) do
traverseInterfaces(interface, newclass.interfaces)
end
end
if newclass.mixins then
for mixin in pairs(newclass.mixins) do
if mixin.interfaces then
if not newclass.interfaces then
newclass.interfaces = {}
end
for interface in pairs(mixin.interfaces) do
newclass.interfaces[interface] = true
end
end
end
end
end
function Class:ToString()
if type(self.GetLibraryVersion) == "function" then
return (self:GetLibraryVersion())
else
return "Class"
end
end
local tmp
function Class.prototype:init()
if rawequal(self, initStatus) then
initStatus = nil
else
AceOO:error("Improper self passed to init. You must do MyClass.super.prototype.init(self, ...)", 2)
end
self.uid = getuid(self)
local current = self.class
while true do
if current == Class then
break
end
if current.mixins then
for mixin in pairs(current.mixins) do
if type(mixin.OnInstanceInit) == "function" then
mixin:OnInstanceInit(self)
end
end
end
current = current.super
end
end
end
-- @object ClassFactory
-- @brief A factory for creating classes. Rarely used directly.
local ClassFactory = Factory(Object, Class, Object)
function Class:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
a12, a13, a14, a15, a16, a17, a18, a19, a20)
local x = ClassFactory:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
a12, a13, a14, a15, a16, a17, a18, a19, a20)
if AceOO.classes then
AceOO.classes[x] = true
end
return x
end
getmetatable(Class).__call = Class.new
-- @class Mixin
-- @brief A class to create mixin objects, which contain methods that get
-- "mixed in" to class prototypes.
--
-- @object Mixin prototype
-- @brief The prototype that mixin objects inherit their methods from.
--
-- @method Mixin prototype embed
-- @brief Mix in the methods of our object which are listed in our interface
-- to the supplied target table.
--
-- @method Mixin prototype init
-- @brief Initialize the mixin object.
-- @param newobj The new object we're initializing.
-- @param interface The interface we implement (the list of methods our
-- prototype provides which should be mixed into the target
-- table by embed).
do
Mixin = Class()
function Mixin:ToString()
if self.GetLibraryVersion then
return (self:GetLibraryVersion())
else
return 'Mixin'
end
end
local function _Embed(state, field, target)
field = next(state.export, field)
if field == nil then
return
end
if rawget(target, field) or (target[field] and target[field] ~= state[field]) then
AceOO:error("Method conflict in attempt to mixin. Field %q", field)
end
target[field] = state[field]
local ret,msg = pcall(_Embed, state, field, target)
if not ret then
-- Mix in the next method according to the defined interface. If that
-- fails due to a conflict, re-raise to back out the previous mixed
-- methods.
target[field] = nil
AceOO:error(msg)
end
end
function Mixin.prototype:embed(target)
local mt = getmetatable(target)
setmetatable(target, nil)
local err, msg = pcall(_Embed, self, nil, target)
if not err then
setmetatable(target, mt)
AceOO:error(msg)
return
end
if type(self.embedList) == "table" then
self.embedList[target] = true
end
if type(target.class) ~= "table" then
target[self] = true
end
if not autoEmbed and type(self.OnManualEmbed) == "function" then
self:OnManualEmbed(target)
end
setmetatable(target, mt)
end
function Mixin.prototype:activate(oldLib, oldDeactivate)
if oldLib and oldLib.embedList then
for target in pairs(oldLib.embedList) do
local mt = getmetatable(target)
setmetatable(target, nil)
for field in pairs(oldLib.export) do
target[field] = nil
end
setmetatable(target, mt)
end
self.embedList = oldLib.embedList
for target in pairs(self.embedList) do
self:embed(target)
end
else
self.embedList = setmetatable({}, {__mode="k"})
end
end
function Mixin.prototype:init(export, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16,
a17, a18, a19, a20)
AceOO:argCheck(export, 2, "table")
for k,v in pairs(export) do
if type(k) ~= "number" then
AceOO:error("All keys to argument #2 must be numbers.")
elseif type(v) ~= "string" then
AceOO:error("All values to argument #2 must be strings.")
end
end
local num = table.getn(export)
for i = 1, num do
local v = export[i]
export[i] = nil
export[v] = true
end
table_setn(export, 0)
local interfaces
if a1 then
local l = getlibrary
interfaces = { l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), l(a8),
l(a9), l(a10), l(a11), l(a12), l(a13), l(a14), l(a15), l(a16),
l(a17), l(a18), l(a19), l(a20) }
for _,v in ipairs(interfaces) do
if not v.class or not inherits(v, Interface) then
AceOO:error("Mixins can inherit only from interfaces")
end
end
local num = table.getn(interfaces)
for i = 1, num do
local v = interfaces[i]
interfaces[i] = nil
interfaces[v] = true
end
table_setn(interfaces, 0)
for interface in pairs(interfaces) do
traverseInterfaces(interface, interfaces)
end
for interface in pairs(interfaces) do
for field,kind in pairs(interface.interface) do
if kind ~= "nil" then
local good = false
for bit in pairs(export) do
if bit == field then
good = true
break
end
end
if not good then
AceOO:error("Mixin does not fully accommodate field %q", field)
end
end
end
end
end
self.super = Mixin.prototype
Mixin.super.prototype.init(self)
self.export = export
self.interfaces = interfaces
end
end
-- @class Interface
-- @brief A class to create interfaces, which contain contracts that classes
-- which inherit from this must comply with.
--
-- @object Interface prototype
-- @brief The prototype that interface objects must adhere to.
--
-- @method Interface prototype init
-- @brief Initialize the mixin object.
-- @param interface The interface we contract (the hash of fields forced).
-- @param (a1..a20) Superinterfaces
do
Interface = Class()
function Interface:ToString()
if self.GetLibraryVersion then
return (self:GetLibraryVersion())
else
return 'Instance'
end
end
function Interface.prototype:init(interface, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
Interface.super.prototype.init(self)
AceOO:argCheck(interface, 2, "table")
for k,v in pairs(interface) do
if type(k) ~= "string" then
AceOO:error("All keys to argument #2 must be numbers.")
elseif type(v) ~= "string" then
AceOO:error("All values to argument #2 must be strings.")
elseif v ~= "nil" and v ~= "string" and v ~= "number" and v ~= "table" and v ~= "function" then
AceOO:error('All values to argument #2 must either be "nil", "string", "number", "table", or "function".')
end
end
local l = getlibrary
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), l(a8), l(a9), l(a10), l(a11), l(a12), l(a13), l(a14), l(a15), l(a16), l(a17), l(a18), l(a19), l(a20)
if a1 then
self.superinterfaces = {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20}
for k,v in ipairs(self.superinterfaces) do
if not inherits(v, Interface) or not v.class then
AceOO:error('Cannot provide a non-Interface to inherit from')
end
end
local num = table.getn(self.superinterfaces)
for i = 1, num do
local v = self.superinterfaces[i]
self.superinterfaces[i] = nil
self.superinterfaces[v] = true
end
table_setn(self.superinterfaces, 0)
end
self.interface = interface
end
end
-- @function Classpool
-- @brief Obtain a read only class from our pool of classes, indexed by the
-- superclass and mixins.
-- @param sc The superclass of the class we want.
-- @param (m1..m20) Mixins of the class we want's objects.
-- @return A read only class from the class pool.
local Classpool
do
local pool = setmetatable({}, {__mode = 'v'})
local function newindex(k, v)
AceOO:error('Attempt to modify a read-only class.')
end
local function protonewindex(k, v)
AceOO:error('Attempt to modify a read-only class prototype.')
end
local function ts(bit)
if type(bit) ~= "table" then
return tostring(bit)
elseif getmetatable(bit) and bit.__tostring then
return tostring(bit)
elseif type(bit.GetLibraryVersion) == "function" then
return bit:GetLibraryVersion()
else
return tostring(bit)
end
end
local t
local function getcomplexuid(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9,
m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
if not t then t = {} end
if sc then if sc.uid then table.insert(t, sc.uid) else AceOO:error("%s is not an appropriate class/mixin", ts(sc)) end
if m1 then if m1.uid then table.insert(t, m1.uid) else AceOO:error("%s is not an appropriate mixin", ts(m1)) end
if m2 then if m2.uid then table.insert(t, m2.uid) else AceOO:error("%s is not an appropriate mixin", ts(m2)) end
if m3 then if m3.uid then table.insert(t, m3.uid) else AceOO:error("%s is not an appropriate mixin", ts(m3)) end
if m4 then if m4.uid then table.insert(t, m4.uid) else AceOO:error("%s is not an appropriate mixin", ts(m4)) end
if m5 then if m5.uid then table.insert(t, m5.uid) else AceOO:error("%s is not an appropriate mixin", ts(m5)) end
if m6 then if m6.uid then table.insert(t, m6.uid) else AceOO:error("%s is not an appropriate mixin", ts(m6)) end
if m7 then if m7.uid then table.insert(t, m7.uid) else AceOO:error("%s is not an appropriate mixin", ts(m7)) end
if m8 then if m8.uid then table.insert(t, m8.uid) else AceOO:error("%s is not an appropriate mixin", ts(m8)) end
if m9 then if m9.uid then table.insert(t, m9.uid) else AceOO:error("%s is not an appropriate mixin", ts(m9)) end
if m10 then if m10.uid then table.insert(t, m10.uid) else AceOO:error("%s is not an appropriate mixin", ts(m10)) end
if m11 then if m11.uid then table.insert(t, m11.uid) else AceOO:error("%s is not an appropriate mixin", ts(m11)) end
if m12 then if m12.uid then table.insert(t, m12.uid) else AceOO:error("%s is not an appropriate mixin", ts(m12)) end
if m13 then if m13.uid then table.insert(t, m13.uid) else AceOO:error("%s is not an appropriate mixin", ts(m13)) end
if m14 then if m14.uid then table.insert(t, m14.uid) else AceOO:error("%s is not an appropriate mixin", ts(m14)) end
if m15 then if m15.uid then table.insert(t, m15.uid) else AceOO:error("%s is not an appropriate mixin", ts(m15)) end
if m16 then if m16.uid then table.insert(t, m16.uid) else AceOO:error("%s is not an appropriate mixin", ts(m16)) end
if m17 then if m17.uid then table.insert(t, m17.uid) else AceOO:error("%s is not an appropriate mixin", ts(m17)) end
if m18 then if m18.uid then table.insert(t, m18.uid) else AceOO:error("%s is not an appropriate mixin", ts(m18)) end
if m19 then if m19.uid then table.insert(t, m19.uid) else AceOO:error("%s is not an appropriate mixin", ts(m19)) end
if m20 then if m20.uid then table.insert(t, m20.uid) else AceOO:error("%s is not an appropriate mixin", ts(m20)) end
end end end end end end end end end end end end end end end end end end end end end
table.sort(t)
local uid = table.concat(t, '')
for k in pairs(t) do t[k] = nil end
table_setn(t, 0)
return uid
end
local classmeta
function Classpool(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9,
m10, m11, m12, m13, m14, m15, m16,
m17, m18, m19, m20)
local l = getlibrary
sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20 = l(sc), l(m1), l(m2), l(m3), l(m4), l(m5), l(m6), l(m7), l(m8), l(m9), l(m10), l(m11), l(m12), l(m13), l(m14), l(m15), l(m16), l(m17), l(m18), l(m19), l(m20)
if sc and sc.class then
sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20 = Class, sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19
end
sc = sc or Class
local key = getcomplexuid(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
if not pool[key] then
local class = Class(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9,
m10, m11, m12, m13, m14, m15, m16, m17,
m18, m19, m20)
if not classmeta then
classmeta = {}
local mt = getmetatable(class)
for k,v in pairs(mt) do
classmeta[k] = v
end
classmeta.__newindex = newindex
end
-- Prevent the user from adding methods to this class.
-- NOTE: I'm not preventing modifications of existing class members,
-- but it's likely that only a truly malicious user will be doing so.
class.sealed = true
setmetatable(class, classmeta)
getmetatable(class.prototype).__newindex = protonewindex
pool[key] = class
end
return pool[key]
end
end
AceOO.Factory = Factory
AceOO.Object = Object
AceOO.Class = Class
AceOO.Mixin = Mixin
AceOO.Interface = Interface
AceOO.Classpool = Classpool
AceOO.inherits = inherits
-- Library handling bits
local function activate(self, oldLib, oldDeactivate)
AceOO = self
Factory = self.Factory
Object = self.Object
Class = self.Class
ClassFactory.prototype = Class
Mixin = self.Mixin
Interface = self.Interface
Classpool = self.Classpool
if oldLib then
self.classes = oldLib.classes
end
if not self.classes then
self.classes = setmetatable({}, {__mode="k"})
else
for class in pairs(self.classes) do
class.new = class_new
end
end
if oldDeactivate then
oldDeactivate(oldLib)
end
end
AceLibrary:Register(AceOO, MAJOR_VERSION, MINOR_VERSION, activate)
AceOO = AceLibrary(MAJOR_VERSION)