summaryrefslogtreecommitdiffstats
path: root/acf/model/node.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf/model/node.lua')
-rw-r--r--acf/model/node.lua275
1 files changed, 0 insertions, 275 deletions
diff --git a/acf/model/node.lua b/acf/model/node.lua
deleted file mode 100644
index 56d3416..0000000
--- a/acf/model/node.lua
+++ /dev/null
@@ -1,275 +0,0 @@
---[[
-Copyright (c) 2012-2013 Kaarle Ritvanen
-See LICENSE file for license details
---]]
-
-local M = {}
-
-local raise = require('acf.error').raise
-
-local object = require('acf.object')
-local class = object.class
-local isinstance = object.isinstance
-local super = object.super
-
-local pth = require('acf.path')
-local util = require('acf.util')
-
-
-M.BoundMember = class()
-
-function M.BoundMember:init(parent, name, field)
- local pmt = getmetatable(parent)
- local mt = {}
-
- function mt.__index(t, k)
- local member = field[k]
- if type(member) ~= 'function' then return member end
- return function(self, ...)
- return member(
- field,
- {
- txn=pmt.txn,
- parent=parent,
- path=pth.join(pmt.path, name),
- addr=pth.to_absolute(
- field.addr or pth.escape(name), pmt.addr
- )
- },
- ...
- )
- end
- end
-
- setmetatable(self, mt)
-end
-
-
-M.TreeNode = class()
-
-function M.TreeNode:init(context)
- local mt = getmetatable(self)
- util.update(mt, context)
-
- mt.dereference = true
- mt.meta = {}
- function mt.get(k, create) return mt.load(k, {create=create}) end
-
- if not mt.txn then return end
-
- if mt.parent then
- mt.meta['ui-name'] = getmetatable(mt.parent).mmeta(
- pth.name(mt.path)
- )['ui-name']
- end
-
- function mt.save(k, v) rawset(self, k, v) end
- function mt.__index(t, k) return mt.get(k) end
- function mt.__newindex(t, k, v) mt.save(k, v) end
-
- function mt.has_permission(user, permission)
- local p = permission..mt.path
- if mt.txn:fetch('/auth/permissions')[p] then
- return user:check_permission(p)
- end
-
- if ({create=true, delete=true})[permission] then
- permission = 'modify'
- end
- return M.has_permission(mt.parent, user, permission)
- end
-
- mt.txn.validable[mt.path] = mt.addr
-end
-
-function M.TreeNode:fetch(path, create)
- if type(path) == 'string' then path = pth.split(path) end
-
- if #path == 0 then return self end
-
- local mt = getmetatable(self)
- local name = path[1]
- if not mt.member(name) then
- raise(mt.path, 'Member does not exist: '..name)
- end
-
- local next = mt.get(name, create)
- if next == nil and (not create or #path > 1) then
- raise(mt.path, 'Subordinate does not exist: '..name)
- end
-
- table.remove(path, 1)
- if #path > 0 and type(next) ~= 'table' then
- raise(pth.join(mt.path, name), 'Is a primitive value')
- end
-
- return M.TreeNode.fetch(next, path, create)
-end
-
-function M.TreeNode:search_refs(path)
- if type(path) == 'string' then path = pth.split(path) end
-
- if #path == 0 then return {} end
-
- local mt = getmetatable(self)
- local name = path[1]
- table.remove(path, 1)
-
- local function collect(name)
- local next = mt.load(name)
- if not next then return {} end
-
- local member = mt.member(name)
- if member.deleted then return {member} end
-
- return isinstance(next, M.TreeNode) and M.TreeNode.search_refs(
- next, path
- ) or {}
- end
-
- if name == pth.wildcard then
- local res = {}
- for _, member in ipairs(mt.members()) do
- util.extend(res, collect(member))
- end
- return res
- end
-
- return collect(name)
-end
-
-
-M.Collection = class(M.TreeNode)
-
-function M.Collection:init(context, params)
- super(self, M.Collection):init(context)
-
- self.init = nil
- self.fetch = nil
- self.search_refs = nil
-
- local mt = getmetatable(self)
- local field = M.BoundMember(self, pth.wildcard, params.field)
-
- function mt.topology() return field:topology() end
-
- function mt.member(name)
- return M.BoundMember(self, name, params.field)
- end
-
- function mt.load(k, options) return mt.member(k):load(options) end
-
- if not mt.txn then return end
-
- mt.meta.type = 'collection'
- mt.meta.members = field:meta()
- mt.meta['ui-member'] = params.ui_member or mt.meta['ui-name']:gsub('s$', '')
- mt.meta.widget = params.layout
-
- function mt.mmeta(name)
- local res = util.copy(mt.meta.members)
- if name ~= pth.wildcard then
- res['ui-name'] = mt.meta['ui-member']..' '..name
- end
- return res
- end
-
- function mt.members() return mt.txn:get(mt.addr) or {} end
-
- function mt.validate()
- if #mt.members() > 0 then return end
- if params.required then raise(mt.path, 'Collection cannot be empty') end
- if params.destroy then
- mt.txn:set(mt.addr)
- validate(mt.parent)
- end
- end
-
- function mt.save(k, v) mt.member(k):save(v) end
-end
-
-
-M.List = class(M.Collection)
-
-function M.List:init(context, params)
- super(self, M.List):init(context, params)
-
- local mt = getmetatable(self)
- mt.meta.type = 'list'
-
- local save = mt.save
- function mt.save(k, v)
- assert(type(k) == 'number')
- if v == nil then
- local len = #mt.members()
- while k < len do
- mt.save(k, mt.load(k + 1, {dereference=false}))
- k = k + 1
- end
- end
- save(k, v)
- end
-
- function mt.insert(v, i)
- local len = #mt.members()
- if not i then i = len + 1 end
- for j = len,i,-1 do mt.save(j + 1, mt.load(j, {dereference=false})) end
- mt.save(i, v)
- end
-end
-
-
--- experimental
-M.Mixed = class(M.Collection)
-
-function M.Mixed:init(context, params)
- super(self, M.Mixed):init(context, params)
-
- -- TODO dynamic meta: list non-leaf children
- local mt = getmetatable(self)
- mt.meta = {type='mixed', ['ui-name']=mt.path}
- function mt.mmeta(name)
- return {type='mixed', ['ui-name']=pth.join(mt.path, name)}
- end
-end
-
-
-local function meta_func(attr)
- return function(node, ...)
- local res = getmetatable(node)[attr]
- if type(res) == 'function' then return res(...) end
- return res
- end
-end
-
-for _, mf in ipairs{
- 'addr', 'has_permission', 'insert', 'meta', 'mmeta', 'path', 'topology'
-} do M[mf] = meta_func(mf) end
-
-
-function M.pairs(tbl, dereference)
- if not isinstance(tbl, M.TreeNode) then return pairs(tbl) end
-
- local mt = getmetatable(tbl)
- if dereference == nil then dereference = mt.dereference end
-
- local res = {}
- for _, member in ipairs(mt.members()) do
- res[member] = mt.load(member, {dereference=dereference})
- end
- return pairs(res)
-end
-
-local function _ipairs(mt, i)
- i = i + 1
- local v = mt.load(i)
- if v == nil then return end
- return i, v
-end
-function M.ipairs(tbl)
- if not isinstance(tbl, M.TreeNode) then return ipairs(tbl) end
- return _ipairs, getmetatable(tbl), 0
-end
-
-
-return M