* CBI updates
[project/luci.git] / src / ffluci / cbi.lua
index de02699..149c1d7 100644 (file)
@@ -25,8 +25,13 @@ limitations under the License.
 
 ]]--
 module("ffluci.cbi", package.seeall)
+require("ffluci.template")
 require("ffluci.util")
+require("ffluci.http")
+require("ffluci.model.uci")
+local Template = ffluci.template.Template
 local class = ffluci.util.class
+local instanceof = ffluci.util.instanceof
 
 
 -- Node pseudo abstract class
@@ -36,20 +41,181 @@ function Node.__init__(self, title, description)
        self.children = {}
        self.title = title
        self.description = description
+       self.template = "cbi/node"
 end
 
 function Node.append(self, obj)
        table.insert(self.children, obj)
 end
 
+function Node.parse(self)
+       for k, child in ipairs(self.children) do
+               child:parse()
+       end
+end
+
+function Node.render(self)
+       ffluci.template.render(self.template)
+end
+
 
--- CBI Map
+--[[
+Map - A map describing a configuration file 
+]]--
 Map = class(Node)
 
-function Map.__init__(self, ...)
+function Map.__init__(self, config, ...)
+       Node.__init__(self, ...)
+       self.config = config
+       self.template = "cbi/map"
+end
+
+function Map.section(self, class, ...)
+       if instanceof(class, AbstractSection) then
+               local obj  = class(...)
+               obj.map    = self
+               obj.config = self.config
+               self:append(obj)
+               return obj
+       else
+               error("class must be a descendent of AbstractSection")
+       end
+end
+
+function Map.read(self)
+       self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)
+       return self.ucidata
+end
+
+--[[
+AbstractSection
+]]--
+AbstractSection = class(Node)
+
+function AbstractSection.__init__(self, sectiontype, ...)
        Node.__init__(self, ...)
+       self.sectiontype = sectiontype
+end
+
+function AbstractSection.option(self, class, ...)
+       if instanceof(class, AbstractValue) then
+               local obj  = class(...)
+               obj.map    = self.map
+               obj.config = self.config
+               self:append(obj)
+               return obj
+       else
+               error("class must be a descendent of AbstractValue")
+       end     
 end
+       
+
+
+--[[
+NamedSection - A fixed configuration section defined by its name
+]]--
+NamedSection = class(AbstractSection)
+
+function NamedSection.__init__(self, section, ...)
+       AbstractSection.__init__(self, ...)
+       self.template = "cbi/nsection"
+       
+       self.section = section
+end
+
+function NamedSection.option(self, ...)
+       local obj = AbstractSection.option(self, ...)
+       obj.section = self.section
+       return obj
+end
+
+
+--[[
+TypedSection - A (set of) configuration section(s) defined by the type
+       addremove:      Defines whether the user can add/remove sections of this type
+       anonymous:  Allow creating anonymous sections
+       valid:          a table with valid names or a function returning nil if invalid
+]]--
+TypedSection = class(AbstractSection)
 
-function Map.render(self, template)
-       -- ToDo
+function TypedSection.__init__(self, ...)
+       AbstractSection.__init__(self, ...)
+       self.template  = "cbi/tsection"
+       
+       self.addremove = true
+       self.anonymous = false
+       self.valid     = nil
 end
+
+
+--[[
+AbstractValue - An abstract Value Type
+       null:           Value can be empty
+       valid:          A function returning the value if it is valid otherwise nil 
+       depends:        A table of option => value pairs of which one must be true
+       default:        The default value
+]]--
+AbstractValue = class(Node)
+
+function AbstractValue.__init__(self, option, ...)
+       Node.__init__(self, ...)
+       self.option  = option
+       
+       self.valid   = nil
+       self.depends = nil
+       self.default = nil
+end
+
+
+function AbstractValue.formvalue(self)
+       local key = "uci."..self.map.config.."."..self.section.."."..self.option
+       return ffluci.http.formvalue(key)
+end
+
+function AbstractValue.ucivalue(self)
+       return self.map.read()[self.section][self.option]
+end
+
+function AbstractValue.validate(self, value)
+       return ffluci.util.validate(value, nil, nil, self.valid)
+end
+
+function AbstractValue.write(self, value)
+       ffluci.model.uci.set(self.config, self.section, self.option, value)
+end
+
+
+--[[
+Value - A one-line value
+       maxlength:      The maximum length
+       isnumber:       The value must be a valid (floating point) number
+       isinteger:  The value must be a valid integer
+]]--
+Value = class(AbstractValue)
+
+function Value.__init__(self, ...)
+       AbstractValue.__init__(self, ...)
+       self.template  = "cbi/value"
+       
+       self.maxlength = nil
+       self.isnumber  = false
+       self.isinteger = false
+end
+
+
+--[[
+ListValue - A one-line value predefined in a list
+]]--
+ListValue = class(AbstractValue)
+
+function ListValue.__init__(self, ...)
+       AbstractValue.__init__(self, ...)
+       self.template  = "cbi/lvalue"
+       
+       self.list = {}
+end
+
+function ListValue.addValue(self, key, val)
+       val = val or key
+       self.list[key] = val
+end
\ No newline at end of file