+
+
+--- Object representation of an uvl item - base class.
+uvlitem = util.class()
+
+function uvlitem.cid(self)
+ if #self.cref == 1 then
+ return self.cref[1]
+ else
+ local r = { unpack(self.cref) }
+ local c = self.c
+ if c and c[r[2]] and c[r[2]]['.anonymous'] and c[r[2]]['.index'] then
+ r[2] = '@' .. c[r[2]]['.type'] ..
+ '[' .. tostring(c[r[2]]['.index']) .. ']'
+ end
+ return table.concat( r, '.' )
+ end
+end
+
+function uvlitem.sid(self)
+ return table.concat( self.sref, '.' )
+end
+
+function uvlitem.scheme(self, opt)
+ local s = self.s and self.s.packages
+ s = s and s[self.sref[1]]
+ if #self.sref == 4 or #self.sref == 3 then
+ s = s and s.variables
+ s = s and s[self.sref[2]]
+ s = s and s[self.sref[3]]
+ elseif #self.sref == 2 then
+ s = s and s.sections
+ s = s and s[self.sref[2]]
+ end
+
+ if s and opt then
+ return s[opt]
+ elseif s then
+ return s
+ end
+end
+
+function uvlitem.config(self, opt)
+ local c = self.c
+
+ if #self.cref >= 2 and #self.cref <= 4 then
+ c = c and self.c[self.cref[2]] or nil
+ if #self.cref >= 3 then
+ c = c and c[self.cref[3]] or nil
+ end
+ end
+
+ if c and opt then
+ return c[opt]
+ elseif c then
+ return c
+ end
+end
+
+function uvlitem.title(self)
+ return self:scheme() and self:scheme('title') or
+ self.cref[3] or self.cref[2] or self.cref[1]
+end
+
+function uvlitem.type(self)
+ if self.t == TYPE_CONFIG then
+ return 'config'
+ elseif self.t == TYPE_SECTION then
+ return 'section'
+ elseif self.t == TYPE_OPTION then
+ return 'option'
+ elseif self.t == TYPE_ENUM then
+ return 'enum'
+ end
+end
+
+function uvlitem.error(self, ...)
+ if not self.e then
+ local errconst = { ERR.CONFIG, ERR.SECTION, ERR.OPTION, ERR.OPTION }
+ self.e = errconst[#self.cref]( self )
+ end
+
+ return self.e:child( ... )
+end
+
+function uvlitem.errors(self)
+ return self.e
+end
+
+function uvlitem.ok(self)
+ return not self:errors()
+end
+
+function uvlitem.parent(self)
+ if self.p then
+ return self.p
+ elseif #self.cref == 3 or #self.cref == 4 then
+ return section( self.s, self.c, self.cref[1], self.cref[2] )
+ elseif #self.cref == 2 then
+ return config( self.s, self.c, self.cref[1] )
+ else
+ return nil
+ end
+end
+
+function uvlitem._loadconf(self, co, c, configdir)
+ co = co or self._configcache
+ if not co then
+ local err
+ co, err = uci.cursor(configdir):get_all(c)
+
+ if err then
+ self:error(ERR.UCILOAD(self, err))
+ end
+
+ self._configcache = co
+ end
+ return co
+end
+
+
+--- Object representation of a scheme.
+-- @class scheme
+-- @cstyle instance
+-- @name luci.uvl.scheme
+
+--- Scheme instance constructor.
+-- @class function
+-- @name scheme
+-- @param scheme Scheme instance
+-- @param co Configuration data
+-- @param c Configuration name
+-- @return Config instance
+scheme = util.class(uvlitem)
+
+function scheme.__init__(self, scheme, co, c)
+ if not c then
+ c, co = co, nil
+ end
+
+ self.cref = { c }
+ self.sref = { c }
+ self.c = self:_loadconf(co, c, scheme.configdir)
+ self.s = scheme
+ self.t = TYPE_SCHEME
+end
+
+--- Add an error to scheme.
+-- @return Scheme error context
+function scheme.error(self, ...)
+ if not self.e then self.e = ERR.SCHEME( self ) end
+ return self.e:child( ... )
+end
+
+--- Get an associated config object.
+-- @return Config instance
+function scheme.config(self)
+ local co = config( self.s, self.cref[1] )
+ co.p = self
+
+ return co
+end
+
+--- Get all section objects associated with this scheme.
+-- @return Table containing all associated luci.uvl.section instances
+function scheme.sections(self)
+ local v = { }
+ if self.s.packages[self.sref[1]].sections then
+ for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do
+ v[#v+1] = option(
+ self.s, self.c, self.cref[1], self.cref[2], o
+ )
+ end
+ end
+ return v
+end
+
+--- Get an associated section object.
+-- @param s Section to select
+-- @return Section instance
+function scheme.section(self, s)
+ local so = section( self.s, self.c, self.cref[1], s )
+ so.p = self
+
+ return so
+end
+
+
+--- Object representation of a config.
+-- @class config
+-- @cstyle instance
+-- @name luci.uvl.config
+
+--- Config instance constructor.
+-- @class function
+-- @name config
+-- @param scheme Scheme instance
+-- @param co Configuration data
+-- @param c Configuration name
+-- @return Config instance
+config = util.class(uvlitem)
+
+function config.__init__(self, scheme, co, c)
+ if not c then
+ c, co = co, nil
+ end
+ self.cref = { c }
+ self.sref = { c }
+ self.c = self:_loadconf(co, c, scheme.configdir)
+ self.s = scheme
+ self.t = TYPE_CONFIG
+end
+
+--- Get all section objects associated with this config.
+-- @return Table containing all associated luci.uvl.section instances
+function config.sections(self)
+ local v = { }
+ if self.s.packages[self.sref[1]].sections then
+ for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do
+ v[#v+1] = option(
+ self.s, self.c, self.cref[1], self.cref[2], o
+ )
+ end
+ end
+ return v
+end
+
+--- Get an associated section object.
+-- @param s Section to select
+-- @return Section instance
+function config.section(self, s)
+ local so = section( self.s, self.c, self.cref[1], s )
+ so.p = self
+
+ return so
+end
+
+
+--- Object representation of a scheme/config section.
+-- @class module
+-- @cstyle instance
+-- @name luci.uvl.section
+
+--- Section instance constructor.
+-- @class function
+-- @name section
+-- @param scheme Scheme instance
+-- @param co Configuration data
+-- @param c Configuration name
+-- @param s Section name
+-- @return Section instance
+section = util.class(uvlitem)
+
+function section.__init__(self, scheme, co, c, s)
+ self.cref = { c, s }
+ self.sref = { c, co and co[s] and co[s]['.type'] or s }
+ self.c = self:_loadconf(co, c, scheme.configdir)
+ self.s = scheme
+ self.t = TYPE_SECTION
+end
+
+--- Get all option objects associated with this section.
+-- @return Table containing all associated luci.uvl.option instances
+function section.variables(self)
+ local v = { }
+ if self.s.packages[self.sref[1]].variables[self.sref[2]] then
+ for o, _ in pairs(
+ self.s.packages[self.sref[1]].variables[self.sref[2]]
+ ) do
+ v[#v+1] = option(
+ self.s, self.c, self.cref[1], self.cref[2], o
+ )
+ end
+ end
+ return v
+end
+
+--- Get an associated option object.
+-- @param o Option to select
+-- @return Option instance
+function section.option(self, o)
+ local oo = option( self.s, self.c, self.cref[1], self.cref[2], o )
+ oo.p = self
+
+ return oo
+end
+
+
+--- Object representation of a scheme/config option.
+-- @class module
+-- @cstyle instance
+-- @name luci.uvl.option
+
+--- Section instance constructor.
+-- @class function
+-- @name option
+-- @param scheme Scheme instance
+-- @param co Configuration data
+-- @param c Configuration name
+-- @param s Section name
+-- @param o Option name
+-- @return Option instance
+option = util.class(uvlitem)
+
+function option.__init__(self, scheme, co, c, s, o)
+ self.cref = { c, s, o }
+ self.sref = { c, co and co[s] and co[s]['.type'] or s, o }
+ self.c = self:_loadconf(co, c, scheme.configdir)
+ self.s = scheme
+ self.t = TYPE_OPTION
+end
+
+--- Get the value of this option.
+-- @return The associated configuration value
+function option.value(self)
+ local v = self:config() or self:scheme('default')
+ if v and self:scheme('multival') then
+ v = util.split( v, "%s+", nil, true )
+ end
+ return v
+end
+
+--- Get the associated section information in scheme.
+-- @return Table containing the scheme properties
+function option.section(self)
+ return self.s.packages[self.sref[1]].sections[self.sref[2]]
+end
+
+--- Construct an enum object instance from given or default value.
+-- @param v Value to select
+-- @return Enum instance for selected value
+function option.enum(self, val)
+ return enum(
+ self.s, self.c,
+ self.cref[1], self.cref[2], self.cref[3],
+ val or self:value()
+ )
+end
+
+
+--- Object representation of a enum value.
+-- @class module
+-- @cstyle instance
+-- @name luci.uvl.enum
+
+--- Section instance constructor.
+-- @class function
+-- @name enum
+-- @param scheme Scheme instance
+-- @param co Configuration data
+-- @param c Configuration name
+-- @param s Section name
+-- @param o Enum name
+-- @param v Enum value
+-- @return Enum value instance
+enum = util.class(option)
+
+function enum.__init__(self, scheme, co, c, s, o, v)
+ self.cref = { c, s, o, v }
+ self.sref = { c, co and co[s] and co[s]['.type'] or s, o, v }
+ self.c = self:_loadconf(co, c, scheme.configdir)
+ self.s = scheme
+ self.t = TYPE_ENUM
+end