* luci/libs/uvl: prepare support for @type[n] notation in luci.uvl.uvlitem.cid()
[project/luci.git] / libs / uvl / luasrc / uvl.lua
index 908cfd7..98e7dfb 100644 (file)
@@ -296,14 +296,16 @@ function UVL._validate_option( self, option, nodeps )
                        if option:scheme('type') == "reference" or
                           option:scheme('type') == "enum"
                        then
-                               if not option:scheme('values') or
-                                  not option:scheme('values')[val]
-                               then
-                                       return false, option:error( ERR.OPT_BADVALUE(
-                                               option, luci.util.serialize_data(
-                                                       luci.util.keys(option:scheme('values') or {})
-                                               )
-                                       ) )
+                               local scheme_values = option:scheme('values') or { }
+                               local config_values = ( type(val) == "table" and val or { val } )
+                               for _, v in ipairs(config_values) do
+                                       if not scheme_values[v] then
+                                               return false, option:error( ERR.OPT_BADVALUE(
+                                                       option, { v, luci.util.serialize_data(
+                                                               luci.util.keys(scheme_values)
+                                                       ) }
+                                               ) )
+                                       end
                                end
                        elseif option:scheme('type') == "list" then
                                if type(val) ~= "table" and STRICT_LIST_TYPE then
@@ -319,7 +321,7 @@ function UVL._validate_option( self, option, nodeps )
                                        for i, v in ipairs(val) do
                                                if not self.datatypes[dt]( v ) then
                                                        return false, option:error(
-                                                               ERR.OPT_INVVALUE(option, dt)
+                                                               ERR.OPT_INVVALUE(option, { v, dt })
                                                        )
                                                end
                                        end
@@ -349,33 +351,47 @@ end
 -- This is normally done on demand, so you don't have to call this function
 -- by yourself.
 -- @param scheme       Name of the scheme to parse
-function UVL.read_scheme( self, scheme )
+-- @param alias                Create an alias for the loaded scheme
+function UVL.read_scheme( self, scheme, alias )
 
        local so = luci.uvl.scheme( self, scheme )
+       local bc = "%s/bytecode/%s.lua" %{ self.schemedir, scheme }
 
-       local schemes = { }
-       local files = luci.fs.glob(self.schemedir .. '/*/' .. scheme)
+       if not luci.fs.access(bc) then
+               local schemes = { }
+               local files = luci.fs.glob(self.schemedir .. '/*/' .. scheme)
 
-       if files then
-               for i, file in ipairs( files ) do
-                       if not luci.fs.access(file) then
-                               return so:error(ERR.SME_READ(so,file))
-                       end
+               if files then
+                       for i, file in ipairs( files ) do
+                               if not luci.fs.access(file) then
+                                       return false, so:error(ERR.SME_READ(so,file))
+                               end
+
+                               local uci = luci.model.uci.cursor( luci.fs.dirname(file), default_savedir )
 
-                       local uci = luci.model.uci.cursor( luci.fs.dirname(file), default_savedir )
+                               local sd, err = uci:get_all( luci.fs.basename(file) )
 
-                       local sd, err = uci:get_all( luci.fs.basename(file) )
+                               if not sd then
+                                       return false, ERR.UCILOAD(so, err)
+                               end
 
-                       if not sd then
-                               return false, ERR.UCILOAD(so, err)
+                               table.insert( schemes, sd )
                        end
 
-                       table.insert( schemes, sd )
+                       local ok, err = self:_read_scheme_parts( so, schemes )
+                       if ok and alias then self.packages[alias] = self.packages[scheme] end
+                       return ok, err
+               else
+                       return false, so:error(ERR.SME_FIND(so, self.schemedir))
                end
-
-               return self:_read_scheme_parts( so, schemes )
        else
-               return false, so:error(ERR.SME_FIND(so, self.schemedir))
+               local sc = loadfile(bc)
+               if sc then
+                       self.packages[scheme] = sc()
+                       return true
+               else
+                       return false, so:error(ERR.SME_READ(so,bc))
+               end
        end
 end
 
@@ -614,7 +630,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
                                local oo = so:option(r[3])
                                local eo = oo:enum(v.value)
 
-                               if t.type ~= "enum" then
+                               if t.type ~= "enum" and t.type ~= "reference" then
                                        return false, scheme:error(ERR.SME_EBADTYPE(eo))
                                end
 
@@ -797,7 +813,17 @@ end
 uvlitem = luci.util.class()
 
 function uvlitem.cid(self)
-       return table.concat( self.cref, '.' )
+       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)
@@ -1103,7 +1129,11 @@ end
 --- Get the value of this option.
 -- @return     The associated configuration value
 function option.value(self)
-       return self:config()
+       local v = self:config() or self:scheme('default')
+       if v and self:scheme('multival') then
+               v = luci.util.split( v, "%s+", nil, true )
+       end
+       return v
 end
 
 --- Get the associated section information in scheme.