Module: OvertureMaps::Attribution

Defined in:
lib/overture_maps/attribution.rb

Overview

Builds license-correct attribution from the data actually imported. The sources column preserved on every row records which upstream datasets contributed, which is what determines the required notices:

OvertureMaps::Attribution.notices  # => array of notice strings
OvertureMaps::Attribution.text     # => single line for a map corner

Overture licensing: ODbL for OSM-derived themes (base, buildings, divisions, transportation), CDLA-Permissive-2.0 for places (Foursquare requires referencing their NOTICE), per-source terms for addresses. See https://docs.overturemaps.org/attribution/

Constant Summary collapse

FOURSQUARE_NOTICE_URL =
"https://opensource.foursquare.com/places-notice-txt/"

Class Method Summary collapse

Class Method Details

.dataset_names(models: default_models) ⇒ Object

Distinct upstream dataset names across the given models' sources columns.



39
40
41
# File 'lib/overture_maps/attribution.rb', line 39

def dataset_names(models: default_models)
  models.flat_map { |model| datasets_for(model) }.uniq
end

.datasets_for(model) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/overture_maps/attribution.rb', line 43

def datasets_for(model)
  return [] unless model.table_exists? && model.column_names.include?("sources")

  model.connection.select_values(<<~SQL).compact
    SELECT DISTINCT elem->>'dataset'
    FROM #{model.quoted_table_name},
         LATERAL jsonb_array_elements(sources) AS elem
    WHERE sources IS NOT NULL AND jsonb_typeof(sources) = 'array'
  SQL
rescue StandardError
  []
end

.notices(models: default_models) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/overture_maps/attribution.rb', line 19

def notices(models: default_models)
  datasets = dataset_names(models: models)

  notices = ["Overture Maps Foundation — overturemaps.org"]
  notices << "© OpenStreetMap contributors (ODbL)" if datasets.any? { |d| d.match?(/openstreetmap|\bosm\b/i) }
  if datasets.any? { |d| d.match?(/foursquare/i) }
    notices << "Includes Foursquare data (CDLA-Permissive-2.0) — see #{FOURSQUARE_NOTICE_URL}"
  end

  remaining = datasets.reject { |d| d.match?(/openstreetmap|\bosm\b|foursquare/i) }
  notices << "Data sources: #{remaining.sort.join(", ")}" if remaining.any?
  notices
end

.text(models: default_models) ⇒ Object



33
34
35
# File 'lib/overture_maps/attribution.rb', line 33

def text(models: default_models)
  notices(models: models).join(" · ")
end