+++ /dev/null
---[[
-
-UCI Validation Layer - Dependency helper
-(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-(c) 2008 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-
-]]--
-
-local uvl = require "luci.uvl"
-local ERR = require "luci.uvl.errors".error
-local util = require "luci.util"
-local table = require "table"
-
-local type, unpack = type, unpack
-local ipairs, pairs = ipairs, pairs
-
-module "luci.uvl.dependencies"
-
-
-
-function _parse_reference( r, c, s, o )
- local ref = { }
- local vars = {
- config = c,
- section = s,
- option = o
- }
-
- for v in r:gmatch("[^.]+") do
- ref[#ref+1] = (v:gsub( "%$(.+)", vars ))
- end
-
- if #ref < 2 then
- table.insert(ref, 1, s or '$section')
- end
- if #ref < 3 then
- table.insert(ref, 1, c or '$config')
- end
-
- return ref
-end
-
-function _serialize_dependency( dep, v )
- local str
-
- for k, v in 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.depseen[object:cid()] then
- self.depseen[object:cid()] = true
- else
- return false, derr:child(ERR('DEP_RECURSIVE', object))
- end
-
- if object:scheme('depends') then
- local ok = true
- local valid = false
-
- 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, derr:child(ERR('SME_BADDEP',object,k))
- end
-
- local option = uvl.option( self, object.c, unpack(ref) )
-
- valid, err = self:_validate_option( option, true )
- if valid then
- if not (
- ( type(v) == "boolean" and option:value() ) or
- ( ref[3] and option:value() ) == v
- ) then
- subcondition = false
-
- 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
-
- local depstr = _serialize_dependency( dep, v )
- derr:child(ERR('DEP_NOTVALID', option, depstr):child(err))
-
- break
- end
- end
-
- if subcondition then
- ok = true
- break
- else
- ok = false
- end
- end
-
- if not ok then
- return false, derr
- end
- else
- return true
- end
-
- 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(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, derr:child(eerr:child(ERR('SME_BADDEP',enum,k)))
- end
-
- local option = luci.uvl.option( self, object.c, unpack(ref) )
-
- 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() ) == v
- ) then
- subcondition = false
-
- 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
-
- 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
-
- if not ok then
- return false, derr:child(eerr)
- end
- end
-
- return true
-end