imposm3/mapping/config.go

237 lines
5.4 KiB
Go
Raw Normal View History

package mapping
2013-05-13 15:58:44 +04:00
import (
2013-05-29 10:47:26 +04:00
"errors"
2015-08-11 20:22:01 +03:00
"io/ioutil"
"github.com/omniscale/imposm3/element"
2015-08-11 20:22:01 +03:00
"gopkg.in/yaml.v2"
2013-05-13 15:58:44 +04:00
)
type Field struct {
2015-08-11 20:22:01 +03:00
Name string `yaml:"name"`
Key Key `yaml:"key"`
Keys []Key `yaml:"keys"`
Type string `yaml:"type"`
Args map[string]interface{} `yaml:"args"`
2013-05-13 15:58:44 +04:00
}
type Table struct {
Name string
2015-08-11 20:22:01 +03:00
Type TableType `yaml:"type"`
Mapping map[Key][]Value `yaml:"mapping"`
Mappings map[string]SubMapping `yaml:"mappings"`
TypeMappings TypeMappings `yaml:"type_mappings"`
Fields []*Field `yaml:"columns"` // TODO rename Fields internaly to Columns
OldFields []*Field `yaml:"fields"`
Filters *Filters `yaml:"filters"`
2013-05-17 17:07:03 +04:00
}
2013-05-22 13:48:34 +04:00
type GeneralizedTable struct {
Name string
2015-08-11 20:22:01 +03:00
SourceTableName string `yaml:"source"`
Tolerance float64 `yaml:"tolerance"`
SqlFilter string `yaml:"sql_filter"`
2013-05-22 13:48:34 +04:00
}
2013-05-17 17:07:03 +04:00
type Filters struct {
2015-08-11 20:22:01 +03:00
ExcludeTags *[][]string `yaml:"exclude_tags"`
2013-05-13 15:58:44 +04:00
}
2013-05-14 18:15:35 +04:00
type Tables map[string]*Table
2013-05-13 15:58:44 +04:00
2013-05-22 13:48:34 +04:00
type GeneralizedTables map[string]*GeneralizedTable
2013-05-13 15:58:44 +04:00
type Mapping struct {
2015-08-11 20:22:01 +03:00
Tables Tables `yaml:"tables"`
GeneralizedTables GeneralizedTables `yaml:"generalized_tables"`
Tags Tags `yaml:"tags"`
// SingleIdSpace mangles the overlapping node/way/relation IDs
// to be unique (nodes positive, ways negative, relations negative -1e17)
2015-08-11 20:22:01 +03:00
SingleIdSpace bool `yaml:"use_single_id_space"`
}
type Tags struct {
2015-08-11 20:22:01 +03:00
LoadAll bool `yaml:"load_all"`
Exclude []Key `yaml:"exclude"`
}
type SubMapping struct {
Mapping map[Key][]Value
}
type TypeMappings struct {
2015-08-11 20:22:01 +03:00
Points map[Key][]Value `yaml:"points"`
LineStrings map[Key][]Value `yaml:"linestrings"`
Polygons map[Key][]Value `yaml:"polygons"`
2013-05-13 15:58:44 +04:00
}
2013-05-23 15:09:47 +04:00
type ElementFilter func(tags *element.Tags) bool
2013-05-17 17:44:50 +04:00
2014-04-30 18:33:07 +04:00
type TagTables map[Key]map[Value][]DestTable
2013-05-27 13:24:22 +04:00
type DestTable struct {
Name string
SubMapping string
}
2013-05-17 17:44:50 +04:00
2013-10-28 11:41:24 +04:00
type TableType string
func (tt *TableType) UnmarshalJSON(data []byte) error {
switch string(data) {
case "":
return errors.New("missing table type")
case `"point"`:
*tt = PointTable
case `"linestring"`:
*tt = LineStringTable
case `"polygon"`:
*tt = PolygonTable
case `"geometry"`:
*tt = GeometryTable
default:
return errors.New("unknown type " + string(data))
}
return nil
}
2013-10-28 11:41:24 +04:00
const (
PolygonTable TableType = "polygon"
LineStringTable TableType = "linestring"
PointTable TableType = "point"
GeometryTable TableType = "geometry"
2013-10-28 11:41:24 +04:00
)
2013-05-17 17:44:50 +04:00
func NewMapping(filename string) (*Mapping, error) {
2015-08-11 20:22:01 +03:00
f, err := ioutil.ReadFile(filename)
2013-05-17 17:44:50 +04:00
if err != nil {
return nil, err
}
mapping := Mapping{}
2015-08-11 20:22:01 +03:00
err = yaml.Unmarshal(f, &mapping)
2013-05-17 17:44:50 +04:00
if err != nil {
return nil, err
}
2013-05-29 10:47:26 +04:00
err = mapping.prepare()
if err != nil {
return nil, err
}
2013-05-17 17:44:50 +04:00
return &mapping, nil
2013-05-13 15:58:44 +04:00
}
2014-04-30 18:33:07 +04:00
func (t *Table) ExtraTags() map[Key]bool {
tags := make(map[Key]bool)
2013-05-13 15:58:44 +04:00
for _, field := range t.Fields {
2013-05-15 10:15:33 +04:00
if field.Key != "" {
tags[field.Key] = true
}
for _, k := range field.Keys {
tags[k] = true
}
2013-05-13 15:58:44 +04:00
}
return tags
}
2013-05-29 10:47:26 +04:00
func (m *Mapping) prepare() error {
2013-05-14 18:15:35 +04:00
for name, t := range m.Tables {
t.Name = name
if t.OldFields != nil {
// todo deprecate 'fields'
t.Fields = t.OldFields
}
2013-05-13 15:58:44 +04:00
}
2013-05-22 13:48:34 +04:00
for name, t := range m.GeneralizedTables {
t.Name = name
}
2013-05-29 10:47:26 +04:00
return nil
2013-05-13 15:58:44 +04:00
}
2014-04-30 18:33:07 +04:00
func (tt TagTables) addFromMapping(mapping map[Key][]Value, table DestTable) {
2013-05-27 13:24:22 +04:00
for key, vals := range mapping {
for _, v := range vals {
vals, ok := tt[key]
if ok {
vals[v] = append(vals[v], table)
} else {
2014-04-30 18:33:07 +04:00
tt[key] = make(map[Value][]DestTable)
2013-05-27 13:24:22 +04:00
tt[key][v] = append(tt[key][v], table)
}
}
}
}
2013-10-28 11:41:24 +04:00
func (m *Mapping) mappings(tableType TableType, mappings TagTables) {
2013-05-13 15:58:44 +04:00
for name, t := range m.Tables {
if t.Type != GeometryTable && t.Type != tableType {
2013-05-13 15:58:44 +04:00
continue
}
2013-05-27 13:24:22 +04:00
mappings.addFromMapping(t.Mapping, DestTable{name, ""})
for subMappingName, subMapping := range t.Mappings {
mappings.addFromMapping(subMapping.Mapping, DestTable{name, subMappingName})
2013-05-13 15:58:44 +04:00
}
switch tableType {
case PointTable:
mappings.addFromMapping(t.TypeMappings.Points, DestTable{name, ""})
case LineStringTable:
mappings.addFromMapping(t.TypeMappings.LineStrings, DestTable{name, ""})
case PolygonTable:
mappings.addFromMapping(t.TypeMappings.Polygons, DestTable{name, ""})
}
2013-05-13 15:58:44 +04:00
}
}
2013-10-28 11:41:24 +04:00
func (m *Mapping) tables(tableType TableType) map[string]*TableFields {
2013-05-14 18:15:35 +04:00
result := make(map[string]*TableFields)
for name, t := range m.Tables {
if t.Type == tableType || t.Type == "geometry" {
2013-05-14 18:15:35 +04:00
result[name] = t.TableFields()
}
}
return result
}
2014-04-30 18:33:07 +04:00
func (m *Mapping) extraTags(tableType TableType, tags map[Key]bool) {
2013-05-13 15:58:44 +04:00
for _, t := range m.Tables {
if t.Type != tableType {
continue
}
for key, _ := range t.ExtraTags() {
tags[key] = true
}
2013-05-17 17:07:03 +04:00
if t.Filters != nil && t.Filters.ExcludeTags != nil {
2013-05-27 13:24:22 +04:00
for _, keyVal := range *t.Filters.ExcludeTags {
2014-04-30 18:33:07 +04:00
tags[Key(keyVal[0])] = true
2013-05-17 17:07:03 +04:00
}
}
}
}
2013-05-17 17:44:50 +04:00
func (m *Mapping) ElementFilters() map[string][]ElementFilter {
result := make(map[string][]ElementFilter)
2013-05-17 17:07:03 +04:00
for name, t := range m.Tables {
if t.Filters == nil {
continue
}
if t.Filters.ExcludeTags != nil {
2013-05-27 13:24:22 +04:00
for _, filterKeyVal := range *t.Filters.ExcludeTags {
2013-05-23 15:09:47 +04:00
f := func(tags *element.Tags) bool {
2013-05-27 13:24:22 +04:00
if v, ok := (*tags)[filterKeyVal[0]]; ok {
if filterKeyVal[1] == "__any__" || v == filterKeyVal[1] {
2013-05-17 17:07:03 +04:00
return false
}
}
return true
}
result[name] = append(result[name], f)
}
}
2013-05-13 15:58:44 +04:00
}
2013-05-17 17:07:03 +04:00
return result
2013-05-13 15:58:44 +04:00
}