class Phonelib::DataImporter::Importer

@private class with functionality for importing data

Constants

CARRIER_DIR

carrier data dir in repo

DOUBLE_COUNTRY_CODES_COUNTRIES

countries that can have double country prefix in number

FORMATS_FILE

alternate formats data file in repo

GEOCODING_DIR

geocoding data dir in repo

MAIN_FILE

main data file in repo

SHORT_DATA_FILE

short number metadata

TIMEZONES_DIR

timezones data dir in repo

Public Class Methods

new() click to toggle source

class initialization method

# File lib/phonelib/data_importer.rb, line 37
def initialize
  @destination = File.path(
    "#{File.dirname(__FILE__)}/../../data/libphonenumber/")
  @data = {}
  @prefixes = {}
  @geo_names = []
  @timezones = []
  @carriers = []
  @countries = {}

  run_import
end

Private Instance Methods

add_double_country_flag(country) click to toggle source

adds double country code flag in case country allows

# File lib/phonelib/data_importer.rb, line 158
def add_double_country_flag(country)
  if DOUBLE_COUNTRY_CODES_COUNTRIES.include?(country[:id])
    country[:double_prefix] = true
  end
  country
end
clone_repo() click to toggle source

method clones libphonenumber repo to local dir

# File lib/phonelib/data_importer.rb, line 67
def clone_repo
  repo = Phonelib::DataImporter::REPO

  system("rm -rf #{@destination}")
  cloned = system("git clone #{repo} #{@destination} --depth 1 -b master")
  fail 'Could not clone repo' unless cloned
end
country_by_code(country_code) click to toggle source

method finds country by country prefix

# File lib/phonelib/data_importer.rb, line 247
def country_by_code(country_code)
  match = @data.select { |_k, v| v[:country_code] == country_code }
  if match.size > 1
    match = match.select { |_k, v| v[:main_country_for_code] == 'true' }
  end

  match.keys.first
end
fill_possible_to_types_if_nil(result) click to toggle source

adds possible pattern in case it doesn't exists

# File lib/phonelib/data_importer.rb, line 197
def fill_possible_to_types_if_nil(result)
  result[:types].each do |type, data|
    if data[Core::VALID_PATTERN] && !data[Core::POSSIBLE_PATTERN]
      result[:types][type][Core::POSSIBLE_PATTERN] = case type
            when Core::GENERAL
              national_possible result[:types]
            else
              data[Core::VALID_PATTERN]
            end
    end
  end
  result
end
import_alternate_formats() click to toggle source

method parses alternate formats file

# File lib/phonelib/data_importer.rb, line 105
def import_alternate_formats
  puts 'IMPORTING ALTERNATE FORMATS'

  main_from_xml("#{@destination}#{FORMATS_FILE}").elements.each do |el|
    el.children.each do |phone_type|
      next unless phone_type.name == 'availableFormats'

      country_code = country_by_code(el.attribute('countryCode').value)
      @data[country_code][:formats] += parse_formats(phone_type.children)
    end
  end
end
import_carrier_data() click to toggle source

method parses carriers data dir

# File lib/phonelib/data_importer.rb, line 135
def import_carrier_data
  puts 'IMPORTING CARRIER DATA'
  import_raw_files_data("#{@destination}#{CARRIER_DIR}*",
                        @carriers,
                        :c)
end
import_country_names() click to toggle source

import country names

# File lib/phonelib/data_importer.rb, line 143
def import_country_names
  puts 'IMPORTING COUNTRY NAMES'

  require 'open-uri'
  require 'csv'
  io = open('http://api.geonames.org/countryInfoCSV?username=demo&style=full')
  csv = CSV.new(io, {col_sep: "\t"})
  csv.each do |row|
    next if row[0].nil? || row[0].start_with?('#') || row[0].empty? || row[0].size != 2

    @countries[row[0]] = row[4]
  end
end
import_geocoding_data() click to toggle source

method parses geocoding data dir

# File lib/phonelib/data_importer.rb, line 119
def import_geocoding_data
  puts 'IMPORTING GEOCODING DATA'
  import_raw_files_data("#{@destination}#{GEOCODING_DIR}*",
                        @geo_names,
                        :g)
end
import_main_data() click to toggle source

method parses main data file

# File lib/phonelib/data_importer.rb, line 76
def import_main_data
  puts 'IMPORTING MAIN DATA'
  main_from_xml("#{@destination}#{MAIN_FILE}").elements.each do |el|
    # each country
    country = hash_from_xml(el, :attributes)
    country.merge! types_and_formats(el.children)
    country = add_double_country_flag country
    if country[Core::NATIONAL_PREFIX_TRANSFORM_RULE]
      country[Core::NATIONAL_PREFIX_TRANSFORM_RULE].gsub!('$', '\\')
    end
    @data[country[:id]] = country
  end
end
import_raw_files_data(dir, var, key) click to toggle source

method updates data from raw files

# File lib/phonelib/data_importer.rb, line 232
def import_raw_files_data(dir, var, key)
  name2index = {}
  Dir["#{dir}"].each do |file|
    parse_raw_file(file).each do |prefix, name|
      unless name2index[name]
        var.push name
        name2index[name] = var.size - 1
      end

      @prefixes = fill_prefixes(key, name2index[name], prefix, @prefixes)
    end
  end
end
import_short_data() click to toggle source

method parses main data file

# File lib/phonelib/data_importer.rb, line 91
def import_short_data
  puts 'IMPORTING SHORT NUMBER DATA'
  main_from_xml("#{@destination}#{SHORT_DATA_FILE}").elements.each do |el|
    # each country
    country = hash_from_xml(el, :attributes)
    country.merge! types_and_formats(el.children)

    country[:types].each do |type, data|
      merge_short_with_main_type(country[:id], type, data)
    end
  end
end
import_timezone_data() click to toggle source

method parses timezones data dir

# File lib/phonelib/data_importer.rb, line 127
def import_timezone_data
  puts 'IMPORTING TIMEZONES DATA'
  import_raw_files_data("#{@destination}#{TIMEZONES_DIR}*",
                        @timezones,
                        :t)
end
merge_short_with_main_type(country_id, type, data) click to toggle source

method adds short number patterns to main data parsed from main xml

# File lib/phonelib/data_importer.rb, line 184
def merge_short_with_main_type(country_id, type, data)
  @data[country_id][:types][type] ||= {}
  @data[country_id][:types][type][Core::SHORT] ||= {}
  data.each do |k, v|
    if @data[country_id][:types][type][Core::SHORT][k]
      @data[country_id][:types][type][Core::SHORT][k] += "|#{v}"
    else
      @data[country_id][:types][type][Core::SHORT][k] = v
    end
  end
end
national_possible(types) click to toggle source

take all possible patters from all types

# File lib/phonelib/data_importer.rb, line 212
def national_possible(types)
  types.map { |k, v| v[:possible_number_pattern] }.
      compact.map { |e| e.split('|') }.flatten.uniq.join('|')
end
parse_formats(formats_children) click to toggle source

method parses xml for formats data

# File lib/phonelib/data_importer.rb, line 218
def parse_formats(formats_children)
  without_comments(formats_children).map do |format|
    current_format = hash_from_xml(format, :children)

    without_comments(format.children).each do |f|
      current_format[name2sym(f.name)] =
          str_clean(f.children.first, not_format?(f.name))
    end

    current_format
  end
end
run_import() click to toggle source

running import method

# File lib/phonelib/data_importer.rb, line 53
def run_import
  clone_repo
  import_main_data
  import_short_data
  import_alternate_formats
  import_geocoding_data
  import_timezone_data
  import_carrier_data
  import_country_names
  save_data_file
  save_extended_data_file
end
types_and_formats(children) click to toggle source

method extracts formats and types from xml data

# File lib/phonelib/data_importer.rb, line 166
def types_and_formats(children)
  result = { types: {}, formats: [] }

  without_comments(children).each do |phone_type|
    if phone_type.name == 'references'
      next
    elsif phone_type.name == 'availableFormats'
      result[:formats] = parse_formats(phone_type.children)
    else
      result[:types][name2sym(phone_type.name)] =
          hash_from_xml(phone_type, :element)
    end
  end

  fill_possible_to_types_if_nil(result)
end