1 # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4
3 class tlc
::Hconfig_ext {
11 method register_backend
{obj args
}
13 method
load {path
{inherited
{}} {datatypes
{}} {inh_info
{}}}
14 method load_only
{path
}
16 method listsub
{path
{immediate
0}}
17 method save
{path configlist
{datatype_list
""}}
19 method
rename {frompath topath
}
24 variable backend_pathlist
{}
26 method find_handler
{path
}
27 method normalize
{path
}
32 body tlc
::Hconfig_ext::constructor {backend
info args
} { #<<<1
41 body tlc
::Hconfig_ext::load {path
{inherited
{}} {datatypes
{}} {inh_info
{}}} { #<<<1
43 set path
[string trim
$path "/ "]
45 if {$inherited != {}} {
48 if {$datatypes != {}} {
52 if {$inh_info != {}} {
53 upvar $inh_info inh_inf
63 # Initialize from root "" <<<
64 set rows
[$sql_obj getlist
"
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)"
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
86 foreach {idx val
} $last {
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 /] {
99 set rows
[$sql_obj getlist
"
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
121 foreach {key val
} $last {
122 if {![info exists dt
($key)]} {
125 switch -- $dt($key) {
127 log debug
"Compositing mergelist: $p, $key, $val"
131 if {![info exists build
($key)]} {
136 switch -- [string index
$item 0] {
138 lappend chopitems
[string range
$item 1 end
]
142 lappend newitems
[string range
$item 1 end
]
146 lappend newitems
$item
152 [lindex [tlc
::intersect3 $build($key) $chopitems] 0]
154 [lsort -unique [concat $chopped $newitems]]
159 log debug
"Compositing mergelist: $p, $key, $val"
164 if {![info exists build
($key)]} {
167 array set tmparr
$build($key)
170 foreach {skey sval
} $val {
171 switch -- [string index
$skey 0] {
173 lappend chopitems
[string range
$skey 1 end
]
178 [string range
$skey 1 end
] \
183 lappend newitems
$skey $sval
188 foreach chopitem
$chopitems {
189 array unset tmparr
$chopitem
191 foreach {skey sval
} $newitems {
192 set tmparr
($skey) $sval
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
] {
218 foreach {name value
} $last {
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
240 set path
[string trim
$path "/ "]
242 if {[catch {array set test
$configlist}]} {
243 error "Badly formatted configlist. Should be result of array get" "" \
247 set id
[lindex [lindex [$sql_obj getlist
"
253 path = '[sql quote $path]'
264 '[sql quote $configlist]',
265 '[sql quote $datatype_list]'
269 set row
[lindex [$sql_obj getlist
"
276 path = '[sql quote $path]'
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
286 data = '[sql quote [array get build]]',
287 datatypes = '[sql quote [array get datatypes]]'
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
303 set frompath
[string trim
$frompath "/ "]
304 set topath
[string trim
$topath "/ "]
311 path = '[sql quote $topath]'
313 path = '[sql quote $frompath]'
316 set subs
[listsub
$frompath 0]
317 $sql_obj getlist
"begin"
319 set from
[join [list $frompath $sub] /]
320 set to
[join [list $topath $sub] /]
325 path = '[sql quote $to]'
327 path = '[sql quote $from]'
335 path = '[sql quote $topath]'
337 path = '[sql quote $frompath]'
339 $sql_obj getlist
"commit"
344 body tlc
::Hconfig_ext::listsub {path
{immediate
0}} { #<<<1
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
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 "/ "]