source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/basenode.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 6.0 KB
Line 
1#
2# YAML::BaseNode class
3#
4require 'yaml/ypath'
5
6module YAML
7
8 #
9 # YAML Generic Model container
10 #
11 module BaseNode
12
13 #
14 # Search for YPath entry and return
15 # qualified nodes.
16 #
17 def select( ypath_str )
18 matches = match_path( ypath_str )
19
20 #
21 # Create a new generic view of the elements selected
22 #
23 if matches
24 result = []
25 matches.each { |m|
26 result.push m.last
27 }
28 YAML.transfer( 'seq', result )
29 end
30 end
31
32 #
33 # Search for YPath entry and return
34 # transformed nodes.
35 #
36 def select!( ypath_str )
37 matches = match_path( ypath_str )
38
39 #
40 # Create a new generic view of the elements selected
41 #
42 if matches
43 result = []
44 matches.each { |m|
45 result.push m.last.transform
46 }
47 result
48 end
49 end
50
51 #
52 # Search for YPath entry and return a list of
53 # qualified paths.
54 #
55 def search( ypath_str )
56 matches = match_path( ypath_str )
57
58 if matches
59 matches.collect { |m|
60 path = []
61 m.each_index { |i|
62 path.push m[i] if ( i % 2 ).zero?
63 }
64 "/" + path.compact.join( "/" )
65 }
66 end
67 end
68
69 def at( seg )
70 if Hash === @value
71 self[seg]
72 elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i]
73 @value[seg.to_i]
74 end
75 end
76
77 #
78 # YPath search returning a complete depth array
79 #
80 def match_path( ypath_str )
81 depth = 0
82 matches = []
83 YPath.each_path( ypath_str ) do |ypath|
84 seg = match_segment( ypath, 0 )
85 matches += seg if seg
86 end
87 matches.uniq
88 end
89
90 #
91 # Search a node for a single YPath segment
92 #
93 def match_segment( ypath, depth )
94 deep_nodes = []
95 seg = ypath.segments[ depth ]
96 if seg == "/"
97 unless String === @value
98 idx = -1
99 @value.collect { |v|
100 idx += 1
101 if Hash === @value
102 match_init = [v[0].transform, v[1]]
103 match_deep = v[1].match_segment( ypath, depth )
104 else
105 match_init = [idx, v]
106 match_deep = v.match_segment( ypath, depth )
107 end
108 if match_deep
109 match_deep.each { |m|
110 deep_nodes.push( match_init + m )
111 }
112 end
113 }
114 end
115 depth += 1
116 seg = ypath.segments[ depth ]
117 end
118 match_nodes =
119 case seg
120 when "."
121 [[nil, self]]
122 when ".."
123 [["..", nil]]
124 when "*"
125 if @value.is_a? Enumerable
126 idx = -1
127 @value.collect { |h|
128 idx += 1
129 if Hash === @value
130 [h[0].transform, h[1]]
131 else
132 [idx, h]
133 end
134 }
135 end
136 else
137 if seg =~ /^"(.*)"$/
138 seg = $1
139 elsif seg =~ /^'(.*)'$/
140 seg = $1
141 end
142 if ( v = at( seg ) )
143 [[ seg, v ]]
144 end
145 end
146 return deep_nodes unless match_nodes
147 pred = ypath.predicates[ depth ]
148 if pred
149 case pred
150 when /^\.=/
151 pred = $' # '
152 match_nodes.reject! { |n|
153 n.last.value != pred
154 }
155 else
156 match_nodes.reject! { |n|
157 n.last.at( pred ).nil?
158 }
159 end
160 end
161 return match_nodes + deep_nodes unless ypath.segments.length > depth + 1
162
163 #puts "DEPTH: #{depth + 1}"
164 deep_nodes = []
165 match_nodes.each { |n|
166 if n[1].is_a? BaseNode
167 match_deep = n[1].match_segment( ypath, depth + 1 )
168 if match_deep
169 match_deep.each { |m|
170 deep_nodes.push( n + m )
171 }
172 end
173 else
174 deep_nodes = []
175 end
176 }
177 deep_nodes = nil if deep_nodes.length == 0
178 deep_nodes
179 end
180
181 #
182 # We want the node to act like as Hash
183 # if it is.
184 #
185 def []( *key )
186 if Hash === @value
187 v = @value.detect { |k,v| k.transform == key.first }
188 v[1] if v
189 elsif Array === @value
190 @value.[]( *key )
191 end
192 end
193
194 def children
195 if Hash === @value
196 @value.values.collect { |c| c[1] }
197 elsif Array === @value
198 @value
199 end
200 end
201
202 def children_with_index
203 if Hash === @value
204 @value.keys.collect { |i| [self[i], i] }
205 elsif Array === @value
206 i = -1; @value.collect { |v| i += 1; [v, i] }
207 end
208 end
209
210 def emit
211 transform.to_yaml
212 end
213 end
214
215end
216
Note: See TracBrowser for help on using the repository browser.