89ad3284c8ce55d309e058e30d4145f1b60e837a
[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                 stat = self:uciop("set", c, k, v)
130         else
131                 self:uciop("foreach", self.stype,
132                         function(s)
133                                 if type(c) == "table" then
134                                         local ck, cv
135                                         for ck, cv in pairs(c) do
136                                                 if s[ck] ~= cv then return true end
137                                         end
138                                 end
139                                 stat = self:uciop("set", c, k, v)
140                                 return false
141                         end)
142         end
143         return stat or false
144 end
145
146 function bsection.property(self, k, n)
147         self[n or k] = function(c, val)
148                 if val == nil then
149                         return c:get(k, c.sid)
150                 else
151                         return c:set(k, val, c.sid)
152                 end
153         end
154 end
155
156 function bsection.property_bool(self, k, n)
157         self[n or k] = function(c, val)
158                 if val == nil then
159                         return self.bind:bool(c:get(k, c.sid))
160                 else
161                         return c:set(k, self.bind:bool(val) and "1" or "0", c.sid)
162                 end
163         end
164 end
165