Class: WorldDb::StateTreeReader

Inherits:
ReaderBaseWithMoreAttribs show all
Defined in:
lib/worlddb/readers/state_tree.rb

Instance Method Summary collapse

Methods inherited from ReaderBaseWithMoreAttribs

from_file, from_string, from_zip, #initialize, #skip_tags?, #strict?

Methods included from TextUtils::ValueHelper

#is_state?, #match_city, #match_country, #match_metro, #match_metro_flag, #match_metro_pop, #match_state_for_country, #match_supra, #match_supra_flag

Constructor Details

This class inherits a constructor from WorldDb::ReaderBaseWithMoreAttribs

Instance Method Details

#readObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/worlddb/readers/state_tree.rb', line 7

def read
  ## for now requires country_id !!
  country = Country.find( @more_attribs[ :country_id ] )
  puts "[StateTreeReader] country key: #{country.key}, name: #{country.name}"

  reader = TreeReader.from_string( @text )

  stack = []    # note: last_level  => stack.size; starts w/ 0

  if country.key == 'de'
    ## use state (1) > part (2) > county (3) > muni (4) > city (5)
    state_level  = 1   # Land
    part_level   = 2   # Regierungsbezirk
    county_level = 3   # Landkreis, Kreisfreie Stadt
    muni_level   = 4   # Gemeinde
    city_level   = 5   # Stadt, Ort, etc.
  else
    ## use state (1) > county (2) > muni (3) > city (4)
    state_level  = 1
    part_level   = -1    ## note: not in use (-1)
    county_level = 2
    muni_level   = 3
    city_level   = 4
  end

  reader.each_line do |nodes|
    names = nodes.map { |item| "(#{item.level}) #{item.value}" }
    node = nodes.last

    puts "    #{names.join( '' )}:"
    puts "      key: >#{node.key}<, level: >#{node.level}<, value: >#{node.value}<"

    if node.level == state_level  # 1
      recs = Name.find_states( node.value, country.id )
    elsif node.level == part_level # 2 
      state = stack[0]
      recs = Name.find_parts( node.value, state.id )
    elsif node.level == county_level  # 2 or 3
      state = stack[0]
      recs = Name.find_counties( node.value, state.id )
    elsif node.level == muni_level   # 3 or 4
      state = stack[0]
      recs = Name.find_munis( node.value, state.id )
    elsif node.level == city_level  # 4 or 5
      ## note: city requires country scope for lookup
      ## todo/fix: how to deal with cities with the same name
      ##   in the same country (and same state and same county etc.) ??? - add some examples here
      recs = Name.find_cities( node.value, country.id )
    else
      puts "*** (fatal) error: unknown level for tree node: #{node.inspect}"
      fail "[StateTreeReader] unknown level for tree node: #{node.inspect}"
    end


    if recs.size > 0
      if recs.size == 1
        puts "ok - record match found: #{recs.inspect}"      
        rec = recs[0].place_object  # e.g. state,part,county,muni,city,etc.
      else
        puts "** ok - #{recs.size} record(s) match found: #{recs.inspect}"
        ## fix/todo: note - uses always first entry for now;
        ##   make lookup/matching more intelligent/usable!!
        rec = recs[0].place_object  # e.g. state,part,county,muni,city,etc.
      end
    else
      ## note: for now only auto-adds munis n cities
      if node.level == muni_level  # 3 or 4
        ## add muni
        key    = TextUtils.title_to_key( node.value )
        name   = node.value
        level  = node.level
        state  = stack[0]
        county = stack[county_level-1]  # note: stack is zero-based (thus, -1)
        puts "*** adding muni record:"
        rec = Muni.create!( key:       key,
                            name:      name,
                            level:     level,
                            state_id:  state.id,
                            county_id: county.id )
      elsif node.level == city_level # 4 or 5
        ## add city
        key    = TextUtils.title_to_key( node.value )
        name   = node.value
        state  = stack[0]
        county = stack[county_level-1]  # note: stack is zero-based (thus, -1)
        muni   = stack[muni_level-1]    # note: stack is zero-based (thus, -1)
        puts "*** adding city record:"
        rec = City.create!( key:        key,
                            name:       name,
                            state_id:   state.id,
                            ## add county_id too ???
                            muni_id:    muni.id,
                            country_id: country.id )
      else
        puts "*** (fatal) error: record not found for tree node: #{node.inspect}"
        fail "[StateTreeReader] record not found for tree node: #{node.inspect}"
      end
    end

    level_diff = node.level - stack.size

    if level_diff > 0
      logger.debug "[StateTreeReader]    up  +#{level_diff}"
      if level_diff > 1
        fail "[StateTreeReader] level diff MUST be +1 is +#{level_diff}"
      end
    elsif level_diff < 0
      logger.debug "[StateTreeReader]    down #{level_diff}"
      level_diff.abs.times { stack.pop }
      stack.pop
    else
      ## same level
      stack.pop
    end
    stack.push( rec )   ## hierarchy of records  (mirrors hierarchy of read-in text)

  end # each_line
end