6f9060d22402d282dde49fcf5783a1307dac66c5
[project/luci.git] / libs / uci / luasrc / model / uci / bind.lua
1 --[[
2 LuCI - UCI utilities for model classes
3
4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17
18 ]]--
19
20 local assert, pairs, type = assert, pairs, type
21 local utl = require "luci.util"
22
23 module "luci.model.uci.bind"
24
25 bind = utl.class()
26
27 function bind.__init__(self, config, cursor)
28         assert(config, "call to bind() without config file")
29         self.cfg = config
30         self.uci = cursor
31 end
32
33 function bind.init(self, cursor)
34         assert(cursor, "call to init() without uci cursor")
35         self.uci = cursor
36 end
37
38 function bind.section(self, stype)
39         local x = utl.class(bsection)
40         x.__init__ = function(inst, sid)
41                 assert(self.uci:get(self.cfg, sid) == stype,
42                         "attempt to instantiate bsection(%q) of wrong type, expected %q"
43                         % { sid, stype })
44
45                 inst.bind  = self
46                 inst.stype = stype
47                 inst.sid   = sid
48         end
49         return x
50 end
51
52 function bind.usection(self, stype)
53         local x = utl.class(bsection)
54         x.__init__ = function(inst)
55                 inst.bind  = self
56                 inst.stype = stype
57                 inst.sid   = true
58         end
59         return x()
60 end
61
62 function bind.list(self, list, add, rem)
63         local lookup = { }
64
65         if type(list) == "string" then
66                 local item
67                 for item in list:gmatch("%S+") do
68                         lookup[item] = true
69                 end
70
71         elseif type(list) == "table" then
72                 local item
73                 for _, item in pairs(list) do
74                         lookup[item] = true
75                 end
76         end
77
78         if add then lookup[add] = true end
79         if rem then lookup[rem] = nil  end
80
81         return utl.keys(lookup)
82 end
83
84 function bind.bool(self, v)
85         return ( v == "1" or v == "true" or v == "yes" or v == "on" )
86 end
87
88
89 bsection = utl.class()
90
91 function bsection.uciop(self, op, ...)
92         assert(self.bind and self.bind.uci,
93                 "attempt to use unitialized binding")
94
95         if op then
96                 return self.bind.uci[op](self.bind.uci, self.bind.cfg, ...)
97         else
98                 return self.bind.uci
99         end
100 end
101
102 function bsection.get(self, k, c)
103         local v
104         if type(c) == "string" then
105                 v = self:uciop("get", c, k)
106         else
107                 self:uciop("foreach", self.stype,
108                         function(s)
109                                 if type(c) == "table" then
110                                         local ck, cv
111                                         for ck, cv in pairs(c) do
112                                                 if s[ck] ~= cv then return true end
113                                         end
114                                 end
115                                 if k ~= nil then
116                                         v = s[k]
117                                 else
118                                         v = s
119                                 end
120                                 return false
121                         end)
122         end
123         return v
124 end
125
126 function bsection.set(self, k, v, c)
127         local stat
128         if type(c) == "string" then
129                 if type(v) == "table" and #v == 0 then
130                         stat = self:uciop("delete", c, k)
131                 else
132                         stat = self:uciop("set", c, k, v)
133                 end
134         else
135                 self:uciop("foreach", self.stype,
136                         function(s)
137                                 if type(c) == "table" then
138                                         local ck, cv
139                                         for ck, cv in pairs(c) do
140                                                 if s[ck] ~= cv then return true end
141                                         end
142                                 end
143                                 stat = self:uciop("set", c, k, v)
144                                 return false
145                         end)
146         end
147         return stat or false
148 end
149
150 function bsection.property(self, k, n)
151         self[n or k] = function(c, val)
152                 if val == nil then
153                         return c:get(k, c.sid)
154                 else
155                         return c:set(k, val, c.sid)
156                 end
157         end
158 end
159
160 function bsection.property_bool(self, k, n)
161         self[n or k] = function(c, val)
162                 if val == nil then
163                         return self.bind:bool(c:get(k, c.sid))
164                 else
165                         return c:set(k, self.bind:bool(val) and "1" or "0", c.sid)
166                 end
167         end
168 end
169