summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2015-01-30 00:09:23 +0200
committerKaarle Ritvanen <kaarle.ritvanen@datakunkku.fi>2015-01-30 00:09:46 +0200
commit07a0eb180872401b271de40190603df8f3ab3db2 (patch)
tree35de2598fc5013946b2ddefcd9d613f6d4a5fabe
parent23d685c951cb52c5a895acda5fca3390eda49c80 (diff)
downloadaconf-07a0eb180872401b271de40190603df8f3ab3db2.tar.bz2
aconf-07a0eb180872401b271de40190603df8f3ab3db2.tar.xz
specify search pattern for references
-rw-r--r--aconf/model/init.lua43
-rw-r--r--aconf/model/model.lua2
-rw-r--r--aconf/model/node.lua76
-rw-r--r--aconf/model/root.lua7
-rw-r--r--aconf/path.lua6
-rw-r--r--aconf/transaction/init.lua9
6 files changed, 81 insertions, 62 deletions
diff --git a/aconf/model/init.lua b/aconf/model/init.lua
index 663c7f8..01b4791 100644
--- a/aconf/model/init.lua
+++ b/aconf/model/init.lua
@@ -74,7 +74,8 @@ M.Reference = class(Field)
function M.Reference:init(params)
super(self, M.Reference):init(
util.setdefaults(
- params, {on_delete='restrict', scope='/', widget='reference'}
+ params,
+ {on_delete='restrict', scope='/', search='*', widget='reference'}
)
)
self.dtype = 'reference'
@@ -84,7 +85,7 @@ end
function M.Reference:topology(context)
local res = super(self, M.Reference):topology(context)
- res[1].scope = self.scope
+ update(res[1], {scope=self.scope, search=self.search})
return res
end
@@ -92,34 +93,38 @@ function M.Reference:abs_scope(context)
return M.path.to_absolute(self.scope, node.path(context.parent))
end
--- assume one-level refs for now
function M.Reference:_choice(context)
local res = {}
+ local onelevel = self.search == '*'
- local obj = relabel(
- 'system', node.fetch, context.parent, self:abs_scope(context)
- )
- assert(isinstance(obj, node.Collection))
+ local obj = relabel('system', node.fetch, context.parent, self.scope)
+ assert(isinstance(obj, node.TreeNode))
- for k, v in pairs(obj) do
+ for _, v in ipairs(node.search(obj, self.search)) do
local ch = {enabled=true}
- if isinstance(v, node.TreeNode) then
- ch.ref = node.path(v)
- if M.path.is_subordinate(context.path, ch.ref) then ch = nil end
- if ch then
- ch['ui-value'] = M.path.name(ch.ref)
- ch.be_value = M.path.escape(ch['ui-value'])
- ch.value = self.dereference and ch.ref or ch.be_value
+ if isinstance(v.value, node.TreeNode) then
+ ch.ref = node.path(v.value)
+ if M.path.is_subordinate(context.path, ch.ref) then ch = nil
+ else
+ update(
+ ch,
+ {
+ be_value=v.path,
+ value=self.dereference and ch.ref or v.path,
+ ['ui-value']=onelevel and M.path.name(v.path) or v.path
+ }
+ )
if self.filter then
- assert(isinstance(v, model.Model))
- if not v:match(self.filter) then ch.enabled = false end
+ assert(isinstance(v.value, model.Model))
+ if not v.value:match(self.filter) then ch.enabled = false end
end
end
else
- local ep = M.path.escape(v)
- update(ch, {be_value=ep, value=ep, ['ui-value']=v})
+ assert(onelevel)
+ local ep = M.path.escape(v.value)
+ update(ch, {be_value=ep, value=ep, ['ui-value']=v.value})
end
if ch then table.insert(res, ch) end
diff --git a/aconf/model/model.lua b/aconf/model/model.lua
index 8ad2cda..a1780c9 100644
--- a/aconf/model/model.lua
+++ b/aconf/model/model.lua
@@ -239,6 +239,8 @@ function M.Model:fetch(path, create)
return getmetatable(self).fetch(path, create)
end
+function M.Model:search(path) return getmetatable(self).search(path) end
+
function M.Model:match(filter)
local tload = getmetatable(getmetatable(self).escalate).load
for k, v in pairs(filter) do
diff --git a/aconf/model/node.lua b/aconf/model/node.lua
index 0b4d36d..91f0256 100644
--- a/aconf/model/node.lua
+++ b/aconf/model/node.lua
@@ -135,6 +135,47 @@ function M.TreeNode:init(context, params)
end
+ function mt._search(path, prefix)
+ if #path == 0 then return {{path=prefix, value=self}} end
+
+ local mt = getmetatable(self)
+
+ local name = path[1]
+ table.remove(path, 1)
+
+ local function collect(name)
+ local next = mt.load(name, {dereference=false})
+ if not next then return {} end
+
+ if isinstance(next, M.TreeNode) then
+ return getmetatable(next)._search(
+ copy(path), pth.join(prefix, name)
+ )
+ end
+
+ assert(#path == 0)
+ return {
+ {
+ value=next,
+ deleted=function(path) mt.member(name):deleted(path) end
+ }
+ }
+ 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
+
+ function mt.search(path) return mt._search(pth.split(path), '') end
+
+
local permissions = {}
function mt._has_permission(permission) end
@@ -221,39 +262,6 @@ function M.TreeNode:init(context, params)
mt.txn.validable[mt.path] = mt.addr
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(getmetatable(self).escalate)
-
- local name = path[1]
- table.remove(path, 1)
-
- local function collect(name)
- local next = mt.load(name, {dereference=false})
- 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)
@@ -263,7 +271,6 @@ function M.Collection:init(context, params)
)
self.init = nil
- self.search_refs = nil
local mt = getmetatable(self)
local field = M.BoundMember(self, pth.wildcard, params.field)
@@ -447,6 +454,7 @@ for _, mf in ipairs{
'parent',
'path',
'save',
+ 'search',
'topology'
} do M[mf] = meta_func(mf) end
diff --git a/aconf/model/root.lua b/aconf/model/root.lua
index d92ac2d..9b05488 100644
--- a/aconf/model/root.lua
+++ b/aconf/model/root.lua
@@ -1,5 +1,5 @@
--[[
-Copyright (c) 2012-2014 Kaarle Ritvanen
+Copyright (c) 2012-2015 Kaarle Ritvanen
See LICENSE file for license details
--]]
@@ -82,7 +82,10 @@ function M.register(name, field, params)
root:fetch(pth.to_absolute(record.scope, pth.parent(record.path)))
)
set('scope', scope)
- table.insert(M.topology(scope, true).referrers, record.path)
+ table.insert(
+ M.topology(pth.rawjoin(scope, record.search), true).referrers,
+ record.path
+ )
end
end
end
diff --git a/aconf/path.lua b/aconf/path.lua
index e13f17c..85fc347 100644
--- a/aconf/path.lua
+++ b/aconf/path.lua
@@ -1,5 +1,5 @@
--[[
-Copyright (c) 2012-2014 Kaarle Ritvanen
+Copyright (c) 2012-2015 Kaarle Ritvanen
See LICENSE file for license details
--]]
@@ -33,7 +33,9 @@ function M.rawjoin(p1, p2, ...)
end
function M.join(parent, ...)
- return M.rawjoin(parent, table.unpack(map(M.escape, {...})))
+ local args = map(M.escape, {...})
+ if parent > '' then table.insert(args, 1, parent) end
+ return M.rawjoin(table.unpack(args))
end
diff --git a/aconf/transaction/init.lua b/aconf/transaction/init.lua
index faa5d7e..2aabec5 100644
--- a/aconf/transaction/init.lua
+++ b/aconf/transaction/init.lua
@@ -1,5 +1,5 @@
--[[
-Copyright (c) 2012-2014 Kaarle Ritvanen
+Copyright (c) 2012-2015 Kaarle Ritvanen
See LICENSE file for license details
--]]
@@ -68,13 +68,12 @@ function ModelTransaction:set_multiple(mods)
end
function ModelTransaction:check_deleted(path)
- -- assume one-level refs for now
- local top = root.topology(pth.parent(path))
+ local top = root.topology(path)
if top then
local errors = ErrorDict()
for _, refs in ipairs(top.referrers) do
- for _, ref in ipairs(self.root:search_refs(refs)) do
- errors:collect(ref.deleted, ref, path)
+ for _, ref in ipairs(getmetatable(self.root).escalate:search(refs)) do
+ errors:collect(ref.deleted, path)
end
end
errors:raise()