Class: I18n::Processes::Data::Tree::Siblings
Overview
Siblings represents a subtree sharing a common parent in case of an empty parent (nil) it represents a forest【也就是整棵树】siblings’ keys are unique
Instance Attribute Summary collapse
Attributes inherited from Nodes
#list
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from SplitKey
key_parts, last_key_part, split_key
Methods inherited from Nodes
#children, #derive, #inspect, #to_hash, #to_nodes
Methods included from Traversal
#breadth_first, #depth_first, #get_nodes_by_key_filter, #grep_keys, #intersect_keys, #key_names, #key_values, #keys, #leaves, #levels, #nodes, #root_key_value_data, #root_key_values, #select_keys, #select_keys!, #select_nodes, #select_nodes!, #set_each_value!
Constructor Details
#initialize(opts = {}) ⇒ Siblings
Returns a new instance of Siblings.
17
18
19
20
21
22
23
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 17
def initialize(opts = {})
super(nodes: opts[:nodes])
@parent = opts[:parent] || first.try(:parent)
@list.map! { |node| node.parent == @parent ? node : node.derive(parent: @parent) }
@key_to_node = @list.each_with_object({}) { |node, h| h[node.key] = node }
@warn_about_add_children_to_leaf = opts.fetch(:warn_about_add_children_to_leaf, true)
end
|
Instance Attribute Details
#key_to_node ⇒ Object
Returns the value of attribute key_to_node.
15
16
17
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 15
def key_to_node
@key_to_node
end
|
#parent ⇒ Object
Returns the value of attribute parent.
15
16
17
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 15
def parent
@parent
end
|
Class Method Details
.build_forest(opts = {}) {|forest| ... } ⇒ Object
256
257
258
259
260
261
262
263
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 256
def build_forest(opts = {}, &block)
opts[:nodes] ||= []
parse_parent_opt!(opts)
forest = Siblings.new(opts)
yield(forest) if block
forest
end
|
.from_flat_pairs(pairs) ⇒ Object
build forest from [[Full Key, Value]]
311
312
313
314
315
316
317
318
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 311
def from_flat_pairs(pairs)
Siblings.new.tap do |siblings|
pairs.each do |full_key, value|
value.gsub!(/'|\n/, '') if value.include?("\n")
siblings[full_key] = ::I18n::Processes::Data::Tree::Node.new(key: split_key(full_key).last, value: value)
end
end
end
|
.from_key_attr(key_attrs, opts = {}, &block) ⇒ Object
278
279
280
281
282
283
284
285
286
287
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 278
def from_key_attr(key_attrs, opts = {}, &block)
build_forest(opts) do |forest|
key_attrs.each do |(full_key, attr)|
fail "Invalid key #{full_key.inspect}" if full_key.end_with?('.')
node = ::I18n::Processes::Data::Tree::Node.new(attr.merge(key: split_key(full_key).last))
yield(full_key, node) if block
forest[full_key] = node
end
end
end
|
.from_key_names(keys, opts = {}, &block) ⇒ Object
289
290
291
292
293
294
295
296
297
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 289
def from_key_names(keys, opts = {}, &block)
build_forest(opts) do |forest|
keys.each do |full_key|
node = ::I18n::Processes::Data::Tree::Node.new(key: split_key(full_key).last)
yield(full_key, node) if block
forest[full_key] = node
end
end
end
|
.from_key_occurrences(key_occurrences) ⇒ Siblings
267
268
269
270
271
272
273
274
275
276
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 267
def from_key_occurrences(key_occurrences)
build_forest(warn_about_add_children_to_leaf: false) do |forest|
key_occurrences.each do |key_occurrence|
forest[key_occurrence.key] = ::I18n::Processes::Data::Tree::Node.new(
key: split_key(key_occurrence.key).last,
data: { occurrences: key_occurrence.occurrences }
)
end
end
end
|
.from_nested_hash(hash, opts = {}) ⇒ Object
Also known as:
[]
build forest from nested hash, e.g. {‘es’ => { ‘common’ => { name => ‘Nombre’, ‘age’ => ‘Edad’ } } } this is the native i18n gem format
301
302
303
304
305
306
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 301
def from_nested_hash(hash, opts = {})
parse_parent_opt!(opts)
fail I18n::Processes::CommandError, "invalid tree #{hash.inspect}" unless hash.respond_to?(:map)
opts[:nodes] = hash.map { |key, value| Node.from_key_value key, value }
Siblings.new(opts)
end
|
.null ⇒ Object
252
253
254
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 252
def null
new
end
|
Instance Method Details
#append(nodes) ⇒ Object
153
154
155
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 153
def append(nodes)
derive.append!(nodes)
end
|
#append!(nodes) ⇒ Object
144
145
146
147
148
149
150
151
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 144
def append!(nodes)
nodes = nodes.map do |node|
fail "already has a child with key '#{node.key}'" if key_to_node.key?(node.key)
key_to_node[node.key] = (node.parent == parent ? node : node.derive(parent: parent))
end
super(nodes)
self
end
|
#attributes ⇒ Object
25
26
27
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 25
def attributes
super.merge(parent: @parent)
end
|
#get(full_key) ⇒ Node
Also known as:
[]
96
97
98
99
100
101
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 96
def get(full_key)
first_key, rest = split_key(full_key.to_s, 2)
node = key_to_node[first_key]
node = node.children.try(:get, rest) if rest && node
node
end
|
#merge(nodes) ⇒ Object
166
167
168
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 166
def merge(nodes)
derive.merge!(nodes)
end
|
#merge!(nodes, on_leaves_merge: nil) ⇒ Object
158
159
160
161
162
163
164
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 158
def merge!(nodes, on_leaves_merge: nil)
nodes = Siblings.from_nested_hash(nodes) if nodes.is_a?(Hash)
nodes.each do |node|
merge_node! node, on_leaves_merge: on_leaves_merge
end
self
end
|
#merge_node!(node, on_leaves_merge: nil) ⇒ Object
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 194
def merge_node!(node, on_leaves_merge: nil)
if key_to_node.key?(node.key)
our = key_to_node[node.key]
return if our == node
our.value = node.value if node.leaf?
our.data.merge!(node.data) if node.data?
if node.children?
if our.children
our.children.merge!(node.children)
else
warn_add_children_to_leaf our
our.children = node.children
end
elsif on_leaves_merge
on_leaves_merge.call(our, node)
end
else
@list << (key_to_node[node.key] = node.derive(parent: parent))
dirty!
end
end
|
#mv_key!(from_pattern, to_pattern, root: false) ⇒ old key => new key
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 53
def mv_key!(from_pattern, to_pattern, root: false)
moved_forest = Siblings.new
moved_nodes = []
old_key_to_new_key = {}
nodes do |node|
full_key = node.full_key(root: root)
if from_pattern =~ full_key
moved_nodes << node
if to_pattern.empty?
old_key_to_new_key[full_key] = nil
next
end
match = $~
new_key = to_pattern.gsub(/\\\d+/) { |m| match[m[1..-1].to_i] }
old_key_to_new_key[full_key] = new_key
moved_forest.merge!(Siblings.new.tap do |forest|
forest[[(node.root.try(:key) unless root), new_key].compact.join('.')] =
node.derive(key: split_key(new_key).last)
end)
end
end
nodes do |node|
next unless node.reference?
old_target = [(node.root.key if root), node.value.to_s].compact.join('.')
new_target = old_key_to_new_key[old_target]
if new_target
new_target = new_target.sub(/\A[^.]*\./, '') if root
node.value = new_target.to_sym
end
end
remove_nodes_and_emptied_ancestors! moved_nodes
merge! moved_forest
old_key_to_new_key
end
|
#remove!(node) ⇒ Object
methods below change state
138
139
140
141
142
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 138
def remove!(node)
super
key_to_node.delete(node.key)
self
end
|
#remove_nodes_and_emptied_ancestors(nodes) ⇒ Object
217
218
219
220
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 217
def remove_nodes_and_emptied_ancestors(nodes)
add_ancestors_that_only_contain_nodes! nodes
select_nodes { |node| !nodes.include?(node) }
end
|
#remove_nodes_and_emptied_ancestors!(nodes) ⇒ Object
223
224
225
226
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 223
def remove_nodes_and_emptied_ancestors!(nodes)
add_ancestors_that_only_contain_nodes! nodes
select_nodes! { |node| !nodes.include?(node) }
end
|
#rename_each_key!(full_key_pattern, new_key_tpl) ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 35
def rename_each_key!(full_key_pattern, new_key_tpl)
pattern_re = I18n::Processes::KeyPatternMatching.compile_key_pattern(full_key_pattern)
nodes do |node|
next if node.full_key(root: true) !~ pattern_re
new_key = new_key_tpl.gsub('%{key}', node.key)
if node.parent == parent
rename_key(node.key, new_key)
else
node.parent.children.rename_key(node.key, new_key)
end
end
self
end
|
#rename_key(key, new_key) ⇒ Object
29
30
31
32
33
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 29
def rename_key(key, new_key)
node = key_to_node.delete(key)
replace_node! node, node.derive(key: new_key)
self
end
|
#replace_node!(node, new_node) ⇒ Object
90
91
92
93
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 90
def replace_node!(node, new_node)
@list[@list.index(node)] = new_node
key_to_node[new_node.key] = new_node
end
|
#set(full_key, node) ⇒ Object
Also known as:
[]=
add or replace node by full key
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 106
def set(full_key, node)
fail 'value should be a I18n::Processes::Data::Tree::Node' unless node.is_a?(Node)
key_part, rest = split_key(full_key, 2)
child = key_to_node[key_part]
if rest
unless child
child = Node.new(
key: key_part,
parent: parent,
children: [],
warn_about_add_children_to_leaf: @warn_add_children_to_leaf
)
append! child
end
unless child.children
warn_add_children_to_leaf child if @warn_about_add_children_to_leaf
child.children = []
end
child.children.set rest, node
else
remove! child if child
append! node
end
dirty!
node
end
|
#set_root_key!(new_key, data = nil) ⇒ Object
186
187
188
189
190
191
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 186
def set_root_key!(new_key, data = nil)
return self if empty?
rename_key first.key, new_key
leaves { |node| node.data.merge! data } if data
self
end
|
#subtract_by_key(other) ⇒ Object
178
179
180
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 178
def subtract_by_key(other)
subtract_keys other.key_names(root: true)
end
|
#subtract_by_key!(other) ⇒ Object
182
183
184
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 182
def subtract_by_key!(other)
subtract_keys! other.key_names(root: true)
end
|
#subtract_keys(keys) ⇒ Object
170
171
172
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 170
def subtract_keys(keys)
remove_nodes_and_emptied_ancestors(find_nodes(keys))
end
|
#subtract_keys!(keys) ⇒ Object
174
175
176
|
# File 'lib/i18n/processes/data/tree/siblings.rb', line 174
def subtract_keys!(keys)
remove_nodes_and_emptied_ancestors!(find_nodes(keys))
end
|