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
63
64
65
|
# File 'lib/eco/data/locations/node_level.rb', line 63
def
@original_headers ||= []
end
|
#parentId ⇒ Object
Also known as:
parent_id
In node level the parent id is set via parsing
39
40
41
|
# File 'lib/eco/data/locations/node_level.rb', line 39
def parentId
@parentId
end
|
Instance Method Details
#actual_level ⇒ Object
85
86
87
|
# File 'lib/eco/data/locations/node_level.rb', line 85
def actual_level
tags_array.compact.length
end
|
#blanks_between? ⇒ Boolean
246
247
248
|
# File 'lib/eco/data/locations/node_level.rb', line 246
def blanks_between?
actual_level > empty_idx
end
|
#classification_names ⇒ Object
77
78
79
|
# File 'lib/eco/data/locations/node_level.rb', line 77
def classification_names
classifications.dup
end
|
#classifications ⇒ Object
71
72
73
74
75
|
# File 'lib/eco/data/locations/node_level.rb', line 71
def classifications
return [] unless (al = actual_level).positive?
[al - 1]
end
|
#clean_parent_id ⇒ Object
135
136
137
|
# File 'lib/eco/data/locations/node_level.rb', line 135
def clean_parent_id
clean_tags_array.compact[-2]
end
|
250
251
252
253
254
|
# File 'lib/eco/data/locations/node_level.rb', line 250
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/eco/data/locations/node_level.rb', line 195
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/eco/data/locations/node_level.rb', line 113
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
# File 'lib/eco/data/locations/node_level.rb', line 158
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
148
149
150
151
|
# File 'lib/eco/data/locations/node_level.rb', line 148
def empty_idx
tary = tags_array
tary.index(nil) || (tary.length + 1)
end
|
#filled_idxs ⇒ Object
240
241
242
243
244
|
# File 'lib/eco/data/locations/node_level.rb', line 240
def filled_idxs
tags_array.each_with_index.with_object([]) do |(tg, ix), out|
out << ix if tg
end
end
|
#highest_levels_set! ⇒ Object
184
185
186
|
# File 'lib/eco/data/locations/node_level.rb', line 184
def highest_levels_set!
@highest_levels_set = true
end
|
#highest_levels_set? ⇒ Boolean
177
178
179
180
181
182
|
# File 'lib/eco/data/locations/node_level.rb', line 177
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:
nodeId
43
44
45
|
# File 'lib/eco/data/locations/node_level.rb', line 43
def id
tag.upcase
end
|
#idx_to_level(x) ⇒ Object
232
233
234
|
# File 'lib/eco/data/locations/node_level.rb', line 232
def idx_to_level(x)
x + 1
end
|
81
82
83
|
# File 'lib/eco/data/locations/node_level.rb', line 81
def level
actual_level
end
|
#level_to_idx(x) ⇒ Object
236
237
238
|
# File 'lib/eco/data/locations/node_level.rb', line 236
def level_to_idx(x)
x - 1
end
|
49
50
51
|
# File 'lib/eco/data/locations/node_level.rb', line 49
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
|
67
68
69
|
# File 'lib/eco/data/locations/node_level.rb', line 67
def
.any?
end
|
#previous_idx ⇒ Object
143
144
145
146
|
# File 'lib/eco/data/locations/node_level.rb', line 143
def previous_idx
idx = tag_idx - 1
idx&.negative?? nil : idx
end
|
#raw_latest_consecutive_top_empty_level ⇒ Object
105
106
107
108
109
110
|
# File 'lib/eco/data/locations/node_level.rb', line 105
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
89
90
91
|
# File 'lib/eco/data/locations/node_level.rb', line 89
def raw_level
tags_array.index(raw_tag) + 1
end
|
#raw_parent_id ⇒ Object
Second last id in tags_array
131
132
133
|
# File 'lib/eco/data/locations/node_level.rb', line 131
def raw_parent_id
tags_array.compact[-2]
end
|
#raw_prev_empty_level ⇒ Object
93
94
95
96
97
98
|
# File 'lib/eco/data/locations/node_level.rb', line 93
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
100
101
102
103
|
# File 'lib/eco/data/locations/node_level.rb', line 100
def raw_prev_empty_level?
lev = raw_prev_empty_level
lev&.positive?
end
|
57
58
59
|
# File 'lib/eco/data/locations/node_level.rb', line 57
def raw_tag
values_at(*TAGS_ATTRS.reverse).compact.first
end
|
#set_high_levels(node) ⇒ Object
189
190
191
192
|
# File 'lib/eco/data/locations/node_level.rb', line 189
def set_high_levels(node)
update_lower_levels(node.tags_array)
self
end
|
53
54
55
|
# File 'lib/eco/data/locations/node_level.rb', line 53
def tag
clean_id(raw_tag, ref: "(Row: #{row_num}) ")
end
|
#tag_attrs_count ⇒ Object
260
261
262
|
# File 'lib/eco/data/locations/node_level.rb', line 260
def tag_attrs_count
TAGS_ATTRS.length
end
|
139
140
141
|
# File 'lib/eco/data/locations/node_level.rb', line 139
def tag_idx
tags_array.index(raw_tag)
end
|
256
257
258
|
# File 'lib/eco/data/locations/node_level.rb', line 256
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
219
220
221
222
223
224
225
226
227
228
229
230
|
# File 'lib/eco/data/locations/node_level.rb', line 219
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
|