Class: Eco::Data::Locations::NodeLevel
- Inherits:
-
NodeLevelStruct
show all
- Extended by:
- Builder
- Includes:
- NodeBase
- Defined in:
- lib/eco/data/locations/node_level.rb,
lib/eco/data/locations/node_level/serial.rb,
lib/eco/data/locations/node_level/builder.rb,
lib/eco/data/locations/node_level/cleaner.rb,
lib/eco/data/locations/node_level/parsing.rb
Overview
Class to treat input csv in a form of levels, where each column is one level,
and children are placed in higher columns right below the parent.
Defined Under Namespace
Modules: Builder, Cleaner, Parsing, Serial
Constant Summary
collapse
- ALL_ATTRS =
NODE_LEVEL_ATTRS
- ADDITIONAL_ATTRS =
i[row_num].freeze
- TAGS_ATTRS =
(ALL_ATTRS - ADDITIONAL_ATTRS).freeze
Eco::Data::Locations::NodeBase::TagValidations::ALLOWED_CHARACTERS, Eco::Data::Locations::NodeBase::TagValidations::DOUBLE_BLANKS, Eco::Data::Locations::NodeBase::TagValidations::INVALID_TAG_REGEX, Eco::Data::Locations::NodeBase::TagValidations::VALID_TAG_CHARS, Eco::Data::Locations::NodeBase::TagValidations::VALID_TAG_REGEX
Instance Attribute Summary collapse
Attributes included from Serial
#serializer
#logger
Attributes included from Parsing
#node_class
Attributes included from NodeBase
#parent, #tracked_level
Instance Method Summary
collapse
Methods included from Serial
#nodes_to_csv_tree
Methods included from Convert
#csv_from, #empty_array, #empty_level_tracker_hash, #hash_tree_to_tree_csv, #log_pretty_inspect, #normalize_arrays, #report_repeated_node_ids
#log
Methods included from Cleaner
#done_ids, #fill_in_parents, #repeated_ids, #reset_trackers!, #tidy_nodes
Methods included from Parsing
#csv_matches_format?, #nodes_from_csv
Methods included from NodeBase
#attr, #attr?, #set_attr, #set_attrs, #slice, #to_h, #values_at
#node_class
#serialize_node, #treeify
#csv_list, #csv_tree, #hash_list, #hash_tree, #org_tree, #tree_class
#csv_nodes_from, #hash_tree_from_csv, #nodes_from_csv
#nodes_to_csv_list, #nodes_to_csv_tree, #serializer
#clean_id, #has_double_blanks?, #identify_invalid_characters, #invalid_warned, #invalid_warned!, #invalid_warned?, #remove_double_blanks, #replace_not_allowed
Instance Attribute Details
71
72
73
|
# File 'lib/eco/data/locations/node_level.rb', line 71
def
||= []
end
|
#parent_id ⇒ Object
Also known as:
parentId
42
43
44
|
# File 'lib/eco/data/locations/node_level.rb', line 42
def parent_id
@parent_id&.upcase
end
|
Instance Method Details
#actual_level ⇒ Object
93
94
95
|
# File 'lib/eco/data/locations/node_level.rb', line 93
def actual_level
tags_array.compact.length
end
|
#blanks_between? ⇒ Boolean
254
255
256
|
# File 'lib/eco/data/locations/node_level.rb', line 254
def blanks_between?
actual_level > empty_idx
end
|
#classification_names ⇒ Object
85
86
87
|
# File 'lib/eco/data/locations/node_level.rb', line 85
def classification_names
classifications.dup
end
|
#classifications ⇒ Object
79
80
81
82
83
|
# File 'lib/eco/data/locations/node_level.rb', line 79
def classifications
return [] unless (al = actual_level).positive?
[al - 1]
end
|
#clean_parent_id ⇒ Object
143
144
145
|
# File 'lib/eco/data/locations/node_level.rb', line 143
def clean_parent_id
clean_tags_array.compact[-2]
end
|
258
259
260
261
262
|
# File 'lib/eco/data/locations/node_level.rb', line 258
def clean_tags_array
tags_array.map do |tg|
clean_id(tg, notify: false)
end
end
|
#clear_level(i) ⇒ Object
Clears the deepest levels, from level i onwards
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
# File 'lib/eco/data/locations/node_level.rb', line 203
def clear_level(i)
case i
when Enumerable
target = i.to_a
when Integer
return false unless i >= 1 && i <= tag_attrs_count
target = Array(i..tag_attrs_count)
else
return false
end
return false if target.empty?
target.each do |n|
set_attr("l#{n}", nil)
end
true
end
|
#common_level_with(other) ⇒ Object
Requires that all upper levels (lower positions) are filled-in
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/eco/data/locations/node_level.rb', line 121
def common_level_with(other)
return nil unless other
otags_array = other.tags_array.compact
stags_array = tags_array.compact
raise "Missing lower levels for #{other.id}: #{other.tags_array.pretty_inspect}" unless other.highest_levels_set?
raise "Missing lower levels for #{id}: #{tags_array.pretty_inspect}" unless highest_levels_set?
otags_array.zip(stags_array).each_with_index do |(otag, stag), idx|
next if otag&.upcase&.strip == stag&.upcase&.strip
return nil if idx&.zero?
return idx
end
actual_level
end
|
31
32
33
34
35
36
|
# File 'lib/eco/data/locations/node_level.rb', line 31
def copy
super.tap do |cp|
cp.highest_levels_set!
cp. =
end
end
|
#decouple(num = 1) ⇒ Object
Note:
for each one in the gap, creates a copy and clears deepest levels thereof
We got a missing level that is compacted in one row
Here we get the missing intermediate levels
This is done from upper to lower level to ensure processing order
It skips last one, as that is this object already
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/eco/data/locations/node_level.rb', line 166
def decouple(num = 1)
with_info = filled_idxs
unless with_info.last == tag_idx
msg = "Review this (row #{row_num}; '#{raw_tag}'): "
msg << "tag_idx is #{tag_idx}, while last filled idx is #{with_info.last}"
raise msg
end
len = with_info.length
target_idxs = with_info[len-(num+1)..-2]
target_idxs.map do |idx|
copy.tap do |dup|
dup.clear_level(idx_to_level(idx + 1))
end
end
end
|
#empty_idx ⇒ Object
156
157
158
159
|
# File 'lib/eco/data/locations/node_level.rb', line 156
def empty_idx
tary = tags_array
tary.index(nil) || (tary.length + 1)
end
|
#filled_idxs ⇒ Object
248
249
250
251
252
|
# File 'lib/eco/data/locations/node_level.rb', line 248
def filled_idxs
tags_array.each_with_index.with_object([]) do |(tg, ix), out|
out << ix if tg
end
end
|
#highest_levels_set! ⇒ Object
192
193
194
|
# File 'lib/eco/data/locations/node_level.rb', line 192
def highest_levels_set!
@highest_levels_set = true
end
|
#highest_levels_set? ⇒ Boolean
185
186
187
188
189
190
|
# File 'lib/eco/data/locations/node_level.rb', line 185
def highest_levels_set?
return true if raw_level == 1
return true unless raw_prev_empty_level?
!!@highest_levels_set
end
|
#id ⇒ Object
Also known as:
node_id, nodeId
47
48
49
|
# File 'lib/eco/data/locations/node_level.rb', line 47
def id
tag.upcase
end
|
#idx_to_level(x) ⇒ Object
240
241
242
|
# File 'lib/eco/data/locations/node_level.rb', line 240
def idx_to_level(x)
x + 1
end
|
89
90
91
|
# File 'lib/eco/data/locations/node_level.rb', line 89
def level
actual_level
end
|
#level_to_idx(x) ⇒ Object
244
245
246
|
# File 'lib/eco/data/locations/node_level.rb', line 244
def level_to_idx(x)
x - 1
end
|
57
58
59
|
# File 'lib/eco/data/locations/node_level.rb', line 57
def name
tag
end
|
#node_hash(stringify_keys: true) {|node, json| ... } ⇒ Object
24
25
26
27
28
29
|
# File 'lib/eco/data/locations/node_level.rb', line 24
def node_hash(stringify_keys: true)
json = to_h(:id, :name, :parent_id, :classifications, :classification_names)
json.transform_keys!(&:to_s) if stringify_keys
json.merge!(yield(self, json)) if block_given?
json
end
|
75
76
77
|
# File 'lib/eco/data/locations/node_level.rb', line 75
def
.any?
end
|
#previous_idx ⇒ Object
151
152
153
154
|
# File 'lib/eco/data/locations/node_level.rb', line 151
def previous_idx
idx = tag_idx - 1
idx&.negative?? nil : idx
end
|
#raw_latest_consecutive_top_empty_level ⇒ Object
113
114
115
116
117
118
|
# File 'lib/eco/data/locations/node_level.rb', line 113
def raw_latest_consecutive_top_empty_level
tags_array[0..raw_level-1].each_with_index do |value, idx|
return idx if value
end
nil
end
|
#raw_level ⇒ Object
97
98
99
|
# File 'lib/eco/data/locations/node_level.rb', line 97
def raw_level
tags_array.index(raw_tag) + 1
end
|
#raw_parent_id ⇒ Object
Second last id in tags_array
139
140
141
|
# File 'lib/eco/data/locations/node_level.rb', line 139
def raw_parent_id
tags_array.compact[-2]
end
|
#raw_prev_empty_level ⇒ Object
101
102
103
104
105
106
|
# File 'lib/eco/data/locations/node_level.rb', line 101
def raw_prev_empty_level
tags_array[0..raw_level-1].each_with_index.reverse_each do |value, idx|
return idx + 1 unless value
end
nil
end
|
#raw_prev_empty_level? ⇒ Boolean
108
109
110
111
|
# File 'lib/eco/data/locations/node_level.rb', line 108
def raw_prev_empty_level?
lev = raw_prev_empty_level
lev&.positive?
end
|
65
66
67
|
# File 'lib/eco/data/locations/node_level.rb', line 65
def raw_tag
values_at(*TAGS_ATTRS.reverse).compact.first
end
|
#self_parented? ⇒ Boolean
53
54
55
|
# File 'lib/eco/data/locations/node_level.rb', line 53
def self_parented?
id == parent_id
end
|
#set_high_levels(node) ⇒ Object
197
198
199
200
|
# File 'lib/eco/data/locations/node_level.rb', line 197
def set_high_levels(node)
update_lower_levels(node.tags_array)
self
end
|
61
62
63
|
# File 'lib/eco/data/locations/node_level.rb', line 61
def tag
clean_id(raw_tag, ref: "(Row: #{row_num}) ")
end
|
#tag_attrs_count ⇒ Object
268
269
270
|
# File 'lib/eco/data/locations/node_level.rb', line 268
def tag_attrs_count
TAGS_ATTRS.length
end
|
147
148
149
|
# File 'lib/eco/data/locations/node_level.rb', line 147
def tag_idx
tags_array.index(raw_tag)
end
|
264
265
266
|
# File 'lib/eco/data/locations/node_level.rb', line 264
def tags_array
values_at(*TAGS_ATTRS)
end
|
#update_lower_levels(src_tags_array, to_level: raw_latest_consecutive_top_empty_level) ⇒ Object
Ensures parent is among the upper level tags
It actually ensures all ancestors are there
227
228
229
230
231
232
233
234
235
236
237
238
|
# File 'lib/eco/data/locations/node_level.rb', line 227
def update_lower_levels(src_tags_array, to_level: raw_latest_consecutive_top_empty_level)
highest_levels_set!
return self unless to_level
target_lev = Array(1..to_level)
target_tags = src_tags_array[level_to_idx(1)..level_to_idx(to_level)]
target_lev.zip(target_tags).each do |(n, tag)|
attr_lev = "l#{n}"
set_attr(attr_lev, tag)
end
self
end
|