myspace / CommonLua /Classes /Context.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
3.32 kB
--- An object which can resolve a key to a value.
-- Context objects can be nested to create a complex value resolution structure.
-- The global function ResolveValue allows resolving a tuple to a value in an arbitrary context.
DefineClass.Context = {
__parents = {},
__hierarchy_cache = true,
}
function Context:new(obj)
return setmetatable(obj or {}, self)
end
function Context:ResolveValue(key)
local value = rawget(self, key)
if value ~= nil then return value end
for _, sub_context in ipairs(self) do
value = ResolveValue(sub_context, key)
if value ~= nil then return value end
end
end
-- change __index method to allow full member resolution without warning
function OnMsg.ClassesBuilt()
local context_class = g_Classes.Context
context_class.__index = function (self, key)
if type(key) == "string" then
return rawget(context_class, key) or context_class.ResolveValue(self, key)
end
end
end
function Context:IsKindOf(class)
if IsKindOf(self, class) then return true end
for _, sub_context in ipairs(self) do
if IsKindOf(sub_context, "Context") and sub_context:IsKindOf(class) or IsKindOf(sub_context, class) then
return true
end
end
end
function Context:IsKindOfClasses(...)
if IsKindOfClasses(self, ...) then return true end
for _, sub_context in ipairs(self) do
if IsKindOf(sub_context, "Context") and sub_context:IsKindOfClasses(...) or IsKindOfClasses(sub_context, ...) then
return true
end
end
end
function ForEachObjInContext(context, f, ...)
if not context then return end
if IsKindOf(context, "Context") then
for _, sub_context in ipairs(context) do
ForEachObjInContext(sub_context, f, ...)
end
else
f(context, ...)
end
end
function SubContext(context, t)
assert(not IsKindOf(t, "PropertyObject"))
t = t or {}
if IsKindOf(context, "PropertyObject") or type(context) ~= "table" then
t[#t + 1] = context
elseif type(context) == "table" then
for _, obj in ipairs(context) do
t[#t + 1] = obj
end
for k, v in pairs(context) do
if rawget(t, k) == nil then
t[k] = v
end
end
end
return Context:new(t)
end
function ResolveValue(context, key, ...)
if key == nil then return context end
if type(context) == "table" then
if IsKindOfClasses(context, "Context", "PropertyObject") then
return ResolveValue(context:ResolveValue(key), ...)
end
return ResolveValue(rawget(context, key), ...)
end
end
function ResolveFunc(context, key)
if key == nil then return end
if type(context) == "table" then
if IsKindOf(context, "Context") then
local f = rawget(context, key)
if type(f) == "function" then
return f
end
for _, sub_context in ipairs(context) do
local f, obj = ResolveFunc(sub_context, key)
if f ~= nil then return f, obj end
end
return
end
if IsKindOf(context, "PropertyObject") and context:HasMember(key) then
local f = context[key]
if type(f) == "function" then return f, context end
else
local f = rawget(context, key)
if f == false or type(f) == "function" then return f end
end
end
end
function ResolvePropObj(context)
if IsKindOf(context, "PropertyObject") then
return context
end
if IsKindOf(context, "Context") then
for _, sub_context in ipairs(context) do
local obj = ResolvePropObj(sub_context)
if obj then return obj end
end
end
end