Fix too many ]s in try
[tcl-tlc-base.git] / scripts / hconfig_ext.itcl
blob62aaae11b732234d58dfc0213aacb8fa6657d228
1 # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4
3 class tlc::Hconfig_ext {
4 inherit tlc::Baselog
6 constructor {args} {}
8 public {
9 variable exact 1
11 method register_backend {obj args}
13 method load {path {inherited {}} {datatypes {}} {inh_info {}}}
14 method load_only {path}
15 method exists {path}
16 method listsub {path {immediate 0}}
17 method save {path configlist {datatype_list ""}}
18 method trash {path}
19 method rename {frompath topath}
22 private {
23 variable backends
24 variable backend_pathlist {}
26 method find_handler {path}
27 method normalize {path}
32 body tlc::Hconfig_ext::constructor {backend info args} { #<<<1
33 log debug $this
35 array set backends {}
37 eval configure $args
41 body tlc::Hconfig_ext::load {path {inherited {}} {datatypes {}} {inh_info {}}} { #<<<1
42 log debug
43 set path [string trim $path "/ "]
45 if {$inherited != {}} {
46 upvar $inherited inh
48 if {$datatypes != {}} {
49 upvar $datatypes dt
52 if {$inh_info != {}} {
53 upvar $inh_info inh_inf
56 array set build {}
58 set p ""
59 set sep ""
60 set leaf 0
61 set real 0
62 set last {}
63 # Initialize from root "" <<<
64 set rows [$sql_obj getlist "
65 select
66 data,
67 leaf,
68 datatypes
69 from
70 $table
71 where
72 path = ''
74 set real [expr {[llength $rows] == 1}]
75 set raw [lindex $rows 0]
76 set last [lindex $raw 0]
77 set leaf [lindex $raw 1]
78 set types [lindex $raw 2]
80 #log debug "path: ($p) data: ($last)"
81 array set build $last
83 # look for this variable's data type in the (should be a list) types var
84 # the default type is text, so if the variable is not found in the types list
85 # then we set to that
86 foreach {idx val} $last {
87 set dt($idx) "text"
89 array set dt $types
91 set inh_inf(parent) [array get build]
92 set inh_inf(this) $last
93 set inh_inf(parent_dt) [array get dt]
94 set inh_inf(this_dt) $types
95 # Initialize from root "" >>>
97 foreach elem [split $path /] {
98 append p $sep $elem
99 set rows [$sql_obj getlist "
100 select
101 data,
102 leaf,
103 datatypes
104 from
105 $table
106 where
107 path = '[sql quote $p]'
109 set real [expr {[llength $rows] == 1}]
110 set raw [lindex $rows 0]
111 set last [lindex $raw 0]
112 set leaf [lindex $raw 1]
113 set types [lindex $raw 2]
115 set inh_inf(parent) [array get build]
116 set inh_inf(this) $last
117 set inh_inf(parent_dt) [array get dt]
118 set inh_inf(this_dt) $types
120 array set dt $types
121 foreach {key val} $last {
122 if {![info exists dt($key)]} {
123 set dt($key) "text"
125 switch -- $dt($key) {
126 "mergelist" { #<<<
127 log debug "Compositing mergelist: $p, $key, $val"
128 set chopitems {}
129 set newitems {}
131 if {![info exists build($key)]} {
132 set build($key) {}
135 foreach item $val {
136 switch -- [string index $item 0] {
137 "-" {
138 lappend chopitems [string range $item 1 end]
141 "+" {
142 lappend newitems [string range $item 1 end]
145 default {
146 lappend newitems $item
151 set chopped \
152 [lindex [tlc::intersect3 $build($key) $chopitems] 0]
153 set build($key) \
154 [lsort -unique [concat $chopped $newitems]]
155 #>>>
158 "mergearray" { #<<<
159 log debug "Compositing mergelist: $p, $key, $val"
160 set chopitems {}
161 set newitems {}
163 catch {unset tmparr}
164 if {![info exists build($key)]} {
165 array set tmparr {}
166 } else {
167 array set tmparr $build($key)
170 foreach {skey sval} $val {
171 switch -- [string index $skey 0] {
172 "-" {
173 lappend chopitems [string range $skey 1 end]
176 "+" {
177 lappend newitems \
178 [string range $skey 1 end] \
179 $sval
182 default {
183 lappend newitems $skey $sval
188 foreach chopitem $chopitems {
189 array unset tmparr $chopitem
191 foreach {skey sval} $newitems {
192 set tmparr($skey) $sval
194 set build($key) \
195 [array get tmparr]
196 #>>>
199 default -
200 "text" { #<<<
201 set build($key) $val
202 #>>>
207 set sep "/"
208 if {$leaf == 1} break
210 if {$exact && (($p != $path) || !$real)} {
211 error "path not found: ($path) exact: ($exact)" "" \
212 [list not_found $path]
215 foreach name [array names build] {
216 set inh($name) 1
218 foreach {name value} $last {
219 set inh($name) 0
222 return [array get build]
226 body tlc::Hconfig_ext::load_only {path} { #<<<1
227 set path [normalize $path]
228 return [[find_handler $path] retrieve $path]
232 body tlc::Hconfig_ext::exists {path} { #<<<1
233 set path [normalize $path]
234 return [[find_handler $path] exists $path]
238 body tlc::Hconfig_ext::save {path configlist {datatype_list ""}} { #<<<1
239 log debug
240 set path [string trim $path "/ "]
242 if {[catch {array set test $configlist}]} {
243 error "Badly formatted configlist. Should be result of array get" "" \
244 [list bad_format]
247 set id [lindex [lindex [$sql_obj getlist "
248 select
249 count(*)
250 from
251 $table
252 where
253 path = '[sql quote $path]'
254 "] 0] 0]
256 if {$id == 0} {
257 $sql_obj getlist "
258 insert into $table (
259 path,
260 data,
261 datatypes
262 ) values (
263 '[sql quote $path]',
264 '[sql quote $configlist]',
265 '[sql quote $datatype_list]'
268 } else {
269 set row [lindex [$sql_obj getlist "
270 select
271 data,
272 datatypes
273 from
274 $table
275 where
276 path = '[sql quote $path]'
277 "] 0]
278 array set build [lindex $row 0]
279 array set datatypes [lindex $row 1]
280 array set build $configlist
281 array set datatypes $datatype_list
282 $sql_obj getlist "
283 update
284 $table
286 data = '[sql quote [array get build]]',
287 datatypes = '[sql quote [array get datatypes]]'
288 where
289 path = '[sql quote $path]'
295 body tlc::Hconfig_ext::trash {path} { #<<<1
296 set path [normalize $path]
297 return [[find_handler $path] trash $path]
301 body tlc::Hconfig_ext::rename {frompath topath {allsub 0}} { #<<<1
302 log debug
303 set frompath [string trim $frompath "/ "]
304 set topath [string trim $topath "/ "]
306 if {$allsub != 1} {
307 $sql_obj getlist "
308 update
309 $table
311 path = '[sql quote $topath]'
312 where
313 path = '[sql quote $frompath]'
315 } else {
316 set subs [listsub $frompath 0]
317 $sql_obj getlist "begin"
318 foreach sub $subs {
319 set from [join [list $frompath $sub] /]
320 set to [join [list $topath $sub] /]
321 $sql_obj getlist "
322 update
323 $table
325 path = '[sql quote $to]'
326 where
327 path = '[sql quote $from]'
331 $sql_obj getlist "
332 update
333 $table
335 path = '[sql quote $topath]'
336 where
337 path = '[sql quote $frompath]'
339 $sql_obj getlist "commit"
344 body tlc::Hconfig_ext::listsub {path {immediate 0}} { #<<<1
345 log debug
346 #log debug "listsub of ($path) ($immediate)"
347 set path [normalize $path]
348 return [[find_handler $path] listsub $path $immediate]
352 body Hconfig_ext::register_backend {obj args} { #<<<1
353 set paths $args
355 if {![itcl::is object $obj] || [$obj isa tlc::Hconfig_backend]} {
356 error "obj must implement tlc::Hconfig_backend" "" [list invalid_type]
359 if {[llength $paths] == 0} {
360 error "Must provide at least one path" "" [list invalid_paths]
363 foreach path $paths {
364 set path [string trim $path /]
365 if {[info exists backends($path)]} {
366 error "Path \"$path\" is already handled by \"$backends($path)\"" \
367 "" [list duplicate_path $path $backends($path)]
371 foreach path $paths {
372 set backends($path) $obj
375 # Get a list of paths sorted longest to shortest
376 set backend_pathlist \
377 [lsort -command [code $this pathsort] [array names backends]]
381 body Hconfig_ext::pathsort {p1 p2} { #<<<1
382 return [expr {[string length $p2] - [string length $p1]}]
386 body Hconfig_ext::find_handler {path} { #<<<1
387 foreach rootpath $backend_pathlist {
388 if {[string match "${rootpath}*" $path]} {
389 return $backends($path)
392 error "No backends" "" [list no_backends]
396 body Hconfig_ext::normalize {path} { #<<<1
397 return [string trim $path "/ "]