diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-06-27 15:10:29 +0300 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2013-06-28 13:24:36 +0300 |
commit | e6ed4efcbd9b87641e471d0879ab8ff70867f544 (patch) | |
tree | f9161d7d33940d2a8334a1bb788e5136912aa024 /acf | |
parent | a68e8d3ed61c991b5b5af1de3a19d74c3ed21d74 (diff) | |
download | aconf-e6ed4efcbd9b87641e471d0879ab8ff70867f544.tar.bz2 aconf-e6ed4efcbd9b87641e471d0879ab8ff70867f544.tar.xz |
collect topological information on models
Diffstat (limited to 'acf')
-rw-r--r-- | acf/model/field.lua | 14 | ||||
-rw-r--r-- | acf/model/init.lua | 2 | ||||
-rw-r--r-- | acf/model/model.lua | 28 | ||||
-rw-r--r-- | acf/model/node.lua | 10 | ||||
-rw-r--r-- | acf/model/root.lua | 39 | ||||
-rw-r--r-- | acf/util.lua | 5 |
6 files changed, 85 insertions, 13 deletions
diff --git a/acf/model/field.lua b/acf/model/field.lua index 1c903b0..beb6b28 100644 --- a/acf/model/field.lua +++ b/acf/model/field.lua @@ -14,7 +14,7 @@ local object = require('acf.object') local class = object.class local super = object.super -local map = require('acf.util').map +local util = require('acf.util') local function contains(list, value) @@ -52,7 +52,7 @@ function Field:init(params) super(self, Field):init(params) if self.choice and not self['ui-choice'] then - self['ui-choice'] = map( + self['ui-choice'] = util.map( function(name) return self:auto_ui_name(name) end, self.choice ) @@ -79,6 +79,10 @@ end function Field:btype(context) return self.dtype end +function Field:topology(context) + return {{path=context.path, addr=context.addr}} +end + function Field:load(context) local value = context.txn:get(context.addr, self:btype(context)) if value == nil then return self.default end @@ -172,6 +176,12 @@ end TreeNode = class(Field) +function TreeNode:topology(context) + local res = super(self, TreeNode):topology(context) + util.extend(res, node.topology(self:load(context, true))) + return res +end + function TreeNode:load(context, create) if not ( create or self.create or context.txn:get(context.addr, 'table') diff --git a/acf/model/init.lua b/acf/model/init.lua index 19cb848..ba3eae5 100644 --- a/acf/model/init.lua +++ b/acf/model/init.lua @@ -168,6 +168,8 @@ function Mixed:init(params) self.pfield = Field() end +function Mixed:topology(context) return {} end + function Mixed:load(context) local value = self.pfield:load(context) if type(value) == 'table' then return super(self, Mixed):load(context) end diff --git a/acf/model/model.lua b/acf/model/model.lua index 11e7fed..e4cffa4 100644 --- a/acf/model/model.lua +++ b/acf/model/model.lua @@ -120,8 +120,26 @@ function Model:init(context) return BoundMember(self, m) end + local function _members(tpe) + local res = {} + for _, name in ipairs(self.members) do + local m = member(name, false, tpe) + if m then table.insert(res, m) end + end + return res + end + + function mt.topology() + local res = {} + for _, f in ipairs(_members(Field)) do util.extend(res, f:topology()) end + return res + end + function mt.valid_member(name) return member(name) end + if not mt.txn then return end + + function mt.mmeta(name) return member(name, true):meta() end function mt.load(k, create) @@ -157,12 +175,7 @@ function Model:init(context) function mt.save(k, v) return member(k, true, Field):save(v) end local function tmeta(tpe) - local res = {} - for _, name in ipairs(self.members) do - local m = member(name, false, tpe) - if m then table.insert(res, m:meta()) end - end - return res + return util.map(function(m) return m:meta() end, _members(tpe)) end mt.meta.type = 'model' @@ -174,8 +187,7 @@ function Model:init(context) end function mt.validate() - for _, name in ipairs(mt.members()) do - local f = member(name, false, Field) + for _, f in ipairs(_members(Field)) do if not f.compute then f:validate_saved() end end end diff --git a/acf/model/node.lua b/acf/model/node.lua index 380f809..eb06b2d 100644 --- a/acf/model/node.lua +++ b/acf/model/node.lua @@ -56,6 +56,9 @@ function TreeNode:init(context) util.update(mt, context) mt.meta = {} + + if not mt.txn then return end + if mt.parent then mt.meta['ui-name'] = getmetatable(mt.parent).mmeta( pth.name(mt.path) @@ -118,6 +121,10 @@ function Collection:init(context, params) local field = BoundMember(self, params.field) local mt = getmetatable(self) + function mt.topology() return field:topology(pth.wildcard) end + function mt.valid_member(name) return true end + + if not mt.txn then return end mt.meta.type = 'collection' mt.meta.members = field:meta(pth.wildcard) @@ -125,8 +132,6 @@ function Collection:init(context, params) mt.meta['ui-name'], 's$', '' ) - function mt.valid_member(name) return true end - function mt.mmeta(name) local res = util.copy(mt.meta.members) res['ui-name'] = mt.meta['ui-member']..' '..name @@ -210,6 +215,7 @@ meta = meta_func('meta') mmeta = meta_func('mmeta') parent = meta_func('parent') path = meta_func('path') +topology = meta_func('topology') validate = meta_func('validate') diff --git a/acf/model/root.lua b/acf/model/root.lua index f0f21c1..f273c4a 100644 --- a/acf/model/root.lua +++ b/acf/model/root.lua @@ -5,11 +5,14 @@ See LICENSE file for license details module(..., package.seeall) -local node = require('acf.model.node') local model = require('acf.model.model') +local node = require('acf.model.node') local object = require('acf.object') local pth = require('acf.path') +local util = require('acf.util') +local setdefault = util.setdefault + RootModel = model.new() @@ -27,7 +30,41 @@ function RootModel:meta(path) return node.mmeta(self:search(pth.parent(path), true), pth.name(path)) end + +local _topology = {} + +function topology(addr, create) + local top = _topology + if type(addr) == 'table' then addr = util.copy(addr) + else addr = pth.split(addr) end + + local function defaults(top) + return util.setdefaults(top, {members={}, paths={}}) + end + + while #addr > 0 do + if create then + top = setdefault(defaults(top).members, addr[1], {}) + else + top = top.members[addr[1]] or top.members[pth.wildcard] + if not top then return end + end + table.remove(addr, 1) + end + + return defaults(top) +end + function register(name, field, params) params.create = true RootModel[name] = model.to_field(field, params) + + _topology = {} + + -- TODO optimize: do not traverse already registered models + for i, record in ipairs(node.topology(RootModel())) do + local top = topology(record.addr, true) + setdefault(top, 'order', i) + table.insert(top.paths, record.path) + end end diff --git a/acf/util.lua b/acf/util.lua index cc44fc2..63276ec 100644 --- a/acf/util.lua +++ b/acf/util.lua @@ -23,6 +23,11 @@ function copy(var) return type(var) == 'table' and setdefaults({}, var) or var end +function extend(dst, src) + for _, v in ipairs(src) do table.insert(dst, v) end + return dst +end + function keys(tbl) local res = {} for k, v in pairs(tbl) do table.insert(res, k) end |