Module: Eco::Data::Locations::NodeLevel::Parsing

Includes:
Convert, Cleaner
Included in:
Builder
Defined in:
lib/eco/data/locations/node_level/parsing.rb

Instance Attribute Summary collapse

Attributes included from Language::AuxiliarLogger

#logger

Instance Method Summary collapse

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

Methods included from Language::AuxiliarLogger

#log

Methods included from Cleaner

#done_ids, #fill_in_parents, #repeated_ids, #reset_trackers!, #tidy_nodes

Instance Attribute Details

#node_classObject



8
9
10
# File 'lib/eco/data/locations/node_level/parsing.rb', line 8

def node_class
  @node_class ||= Eco::Data::Locations::NodeLevel
end

Instance Method Details

#csv_matches_format?(csv) ⇒ Boolean

Note:

there are only two accepted input csv formats. The expected header of NodePlain is predictable, but the header of NodeLevel is not.

It evaluates as an opposite to NodePlain

Parameters:

Returns:

  • (Boolean)

    whether or not it's worthy trying to parse with NodeLevel.



18
19
20
21
# File 'lib/eco/data/locations/node_level/parsing.rb', line 18

def csv_matches_format?(csv)
  return false unless csv.is_a?(::CSV::Table)
  !Eco::Data::Locations::NodePlain.csv_matches_format?(csv)
end

#nodes_from_csv(csv) ⇒ Array<NodeLevel>

Note:
  1. It ensures basic data integrity when builing the nodes in the first screening
  2. It then delegates the tidy up to a cleaner function (see tidy_nodes)

Parameters:

Returns:

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/eco/data/locations/node_level/parsing.rb', line 28

def nodes_from_csv(csv)
  raise ArgumentError, "Expecting CSV::Table. Given: #{csv.class}" unless csv.is_a?(::CSV::Table)

  prev_level = nil
  prev_node  = nil

  # Convert to Eco::CSV::Table for a fresh start
  csv = Eco::CSV.parse(csv.to_csv).nil_blank_cells.add_index_column(:row_num)

  first = true
  nodes = csv.each_with_object([]) do |row, out|
    row_num, *values = row.fields
    node = node_class.new(row_num, *values)
    prev_node ||= node

    # If node is nested in prev_node or is a sibling thereof
    if prev_node.raw_level <= node.raw_level
      # Make sure upper level tags are there (including parent)
      # This normalizes input to all upper level tags always filled in
      # which allows to node#actual_level to work
      node.set_high_levels(prev_node)
    else
      if node.raw_level == 1
        # It is expected not to have parent (as it's top level tag)
      elsif prev_node
        node.set_high_levels(prev_node)
      else
        raise "Node '#{node.raw_tag}' (#{node.row_num} row) doesn't have parent"
      end
    end
    out << node
    prev_node = node
  end
  tidy_nodes(nodes)
end