9472dabebb53dfae0dba469fa5398da3a78d5755
[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
49                 if inst._init then
50                         inst:_init(sid)
51                 end
52         end
53         return x
54 end
55
56 function bind.usection(self, stype)
57         local x = utl.class(bsection)
58         x.__init__ = function(inst)
59                 inst.bind  = self
60                 inst.stype = stype
61                 inst.sid   = true
62         end
63         return x()
64 end
65
66 function bind.list(self, list, add, rem)
67         local lookup = { }
68
69         if type(list) == "string" then
70                 local item
71                 for item in list:gmatch("%S+") do
72                         lookup[item] = true
73                 end
74
75         elseif type(list) == "table" then
76                 local item
77                 for _, item in pairs(list) do
78                         lookup[item] = true
79                 end
80         end
81
82         if add then lookup[add] = true end
83         if rem then lookup[rem] = nil  end
84
85         return utl.keys(lookup)
86 end
87
88 function bind.bool(self, v)
89         return ( v == "1" or v == "true" or v == "yes" or v == "on" )
90 end
91
92
93 bsection = utl.class()
94
95 function bsection.uciop(self, op, ...)
96         assert(self.bind and self.bind.uci,
97                 "attempt to use unitialized binding")
98
99         if op then
100                 return self.bind.uci[op](self.bind.uci, self.bind.cfg, ...)
101         else
102                 return self.bind.uci
103         end
104 end
105
106 function bsection.get(self, k, c)
107         local v
108         if type(c) == "string" then
109                 v = self:uciop("get", c, k)
110         else
111                 self:uciop("foreach", self.stype,
112                         function(s)
113                                 if type(c) == "table" then
114                                         local ck, cv
115                                         for ck, cv in pairs(c) do
116                                                 if s[ck] ~= cv then return true end
117                                         end
118                                 end
119                                 if k ~= nil then
120                                         v = s[k]
121                                 else
122                                         v = s
123                                 end
124                                 return false
125                         end)
126         end
127         return v
128 end
129
130 function bsection.set(self, k, v, c)
131         local stat
132         if type(c) == "string" then
133                 if type(v) == "table" and #v == 0 then
134                         stat = self:uciop("delete", c, k)
135                 else
136                         stat = self:uciop("set", c, k, v)
137                 end
138         else
139                 self:uciop("foreach", self.stype,
140                         function(s)
141                                 if type(c) == "table" then
142                                         local ck, cv
143                                         for ck, cv in pairs(c) do
144                                                 if s[ck] ~= cv then return true end
145                                         end
146                                 end
147                                 stat = self:uciop("set", c, k, v)
148                                 return false
149                         end)
150         end
151         return stat or false
152 end
153
154 function bsection.property(self, k, n)
155         self[n or k] = function(c, val)
156                 if val == nil then
157                         return c:get(k, c.sid)
158                 else
159                         return c:set(k, val, c.sid)
160                 end
161         end
162 end
163
164 function bsection.property_bool(self, k, n)
165         self[n or k] = function(c, val)
166                 if val == nil then
167                         return bind:bool(c:get(k, c.sid))
168                 else
169                         return c:set(k, bind:bool(val) and "1" or "0", c.sid)
170                 end
171         end
172 end
173