module( "luci.uvl.dependencies", package.seeall )
+local ERR = luci.uvl.errors
+
function _parse_reference( r, c, s, o )
local ref = { }
local vars = {
return ref
end
+function _serialize_dependency( dep, v )
+ local str
+
+ for k, v in luci.util.spairs( dep,
+ function(a,b)
+ a = ( type(dep[a]) ~= "boolean" and "_" or "" ) .. a
+ b = ( type(dep[b]) ~= "boolean" and "_" or "" ) .. b
+ return a < b
+ end
+ ) do
+ str = ( str and str .. " and " or "" ) .. k ..
+ ( type(v) ~= "boolean" and "=" .. v or "" )
+ end
+
+ return str
+end
+
function check( self, object, nodeps )
+ local derr = ERR.DEPENDENCY(object)
+
if not self.beenthere[object:cid()] then
self.beenthere[object:cid()] = true
else
- return false, "Recursive dependency for '" .. object:sid() .. "' found"
+ return false, derr:child(ERR.DEP_RECURSIVE(object))
end
- local item = object.type == luci.uvl.TYPE_SECTION
- and object:section() or object:option()
-
- if item.depends then
- local ok = false
- local valid, err = false,
- string.format( 'In dependency check for %s "%s":',
- ( object.type == luci.uvl.TYPE_SECTION and "section" or "option" ),
- object:cid() )
+ if object:scheme('depends') then
+ local ok = true
+ local valid = false
- for _, dep in ipairs(item.depends) do
+ for _, dep in ipairs(object:scheme('depends')) do
local subcondition = true
for k, v in pairs(dep) do
-- XXX: better error
local ref = _parse_reference( k, unpack(object.cref) )
if not ref then
- return false, "Ambiguous dependency reference '" .. k ..
- "' for object '" .. object:sid() .. "' given"
+ return false, derr:child(ERR.SME_BADDEP(object,k))
end
- local option = luci.uvl.option(
- self, object.config,
- object.config[ref[2]]
- and object.config[ref[2]]['.type']
- or object.sref[2],
- ref[1], ref[2], ref[3]
- )
+ local option = luci.uvl.option( self, object.c, unpack(ref) )
- valid, err2 = self:_validate_option( option, true )
+ valid, err = self:_validate_option( option, true )
if valid then
if not (
- ( type(v) == "boolean" and object.config[ref[2]][ref[3]] ) or
- ( ref[3] and object.config[ref[2]][ref[3]] ) == v
+ ( type(v) == "boolean" and option:value() ) or
+ ( ref[3] and option:value() ) == v
) then
subcondition = false
- err = err .. "\n" ..
- self.log.dump_dependency( dep, ref, v )
+
+ local depstr = _serialize_dependency( dep, v )
+ derr:child(
+ type(v) == "boolean"
+ and ERR.DEP_NOVALUE(option, depstr)
+ or ERR.DEP_NOTEQUAL(option, {depstr, v})
+ )
+
break
end
else
subcondition = false
- err = err .. "\n" ..
- self.log.dump_dependency( dep, ref, nil, err2 )
+
+ local depstr = _serialize_dependency( dep, v )
+ derr:child(ERR.DEP_NOTVALID(option, depstr):child(err))
+
break
end
end
if subcondition then
- return true
+ ok = true
+ break
+ else
+ ok = false
end
end
- return false, err
+ if not ok then
+ return false, derr
+ end
+ else
+ return true
end
- if item.type == "enum" and item.enum_depends[object:value()] then
- local ok = false
- local valid, err = false,
- string.format( 'In dependency check for enum value "%s.%s":',
- object:cid(), object:value() )
+ if object:scheme("type") == "enum" and
+ object:scheme("enum_depends")[object:value()]
+ then
+ local ok = true
+ local valid = false
+ local enum = object:enum()
+ local eerr = ERR.DEP_BADENUM(enum)
- for _, dep in ipairs(item.enum_depends[object:value()]) do
+ for _, dep in ipairs(enum:scheme('enum_depends')[object:value()]) do
local subcondition = true
for k, v in pairs(dep) do
-- XXX: better error
local ref = _parse_reference( k, unpack(object.cref) )
if not ref then
- return false, "Ambiguous dependency reference '" .. k ..
- "' for enum '" .. object:sid() .. "." ..
- object:value() .. "' given"
+ return false, derr:child(eerr:child(ERR.SME_BADDEP(enum,k)))
end
- local option = luci.uvl.option(
- self, object.config,
- object.config[ref[2]]
- and object.config[ref[2]]['.type']
- or object.sref[2],
- ref[1], ref[2], ref[3]
- )
+ local option = luci.uvl.option( self, object.c, unpack(ref) )
- valid, err2 = self:_validate_option( option, true )
+ valid, err = self:_validate_option( option, true )
if valid then
if not (
( type(v) == "boolean" and object.config[ref[2]][ref[3]] ) or
- ( ref[3] and object.config[ref[2]][ref[3]] ) == v
+ ( ref[3] and object:config() ) == v
) then
subcondition = false
- err = err .. "\n" ..
- self.log.dump_dependency( dep, ref, v )
+
+ local depstr = _serialize_dependency( dep, v )
+ eerr:child(
+ type(v) == "boolean"
+ and ERR.DEP_NOVALUE(option, depstr)
+ or ERR.DEP_NOTEQUAL(option, {depstr, v})
+ )
+
break
end
else
subcondition = false
- err = err .. "\n" ..
- self.log.dump_dependency( dep, ref, nil, err2 )
+
+ local depstr = _serialize_dependency( dep, v )
+ eerr:child(ERR.DEP_NOTVALID(option, depstr):child(err))
+
break
end
end
if subcondition then
return true
+ else
+ ok = false
end
end
- return false, err
+ if not ok then
+ return false, derr:child(eerr)
+ end
end
return true