diff --git a/docs/mapping.rst b/docs/mapping.rst
index 93c759d..7b1670e 100644
--- a/docs/mapping.rst
+++ b/docs/mapping.rst
@@ -205,6 +205,32 @@ Convert ``true``, ``yes`` and ``1`` to the numeric ``1``, ``-1`` values to ``-1`
Convert values to an integer number. Other values will not be inserted. Useful for ``admin_levels`` for example.
+``enumerate``
+^^^^^^^^^^^^^
+
+Enumerates a list of values and stores tag values as an integer.
+
+The following `enum` column will contain ``1`` for ``landuse=forest``, ``4`` for ``landuse=grass`` and ``0`` for undefined values.
+
+.. code-block:: javascript
+
+ {
+ "args": {
+ "values": [
+ "forest",
+ "park",
+ "cemetery",
+ "grass"
+ ]
+ },
+ "type": "enumerate",
+ "name": "enum",
+ "key": "landuse"
+ }
+
+``mapping_value`` will be used when ``key`` is not set or ``null``.
+
+
Element types
~~~~~~~~~~~~~
@@ -255,7 +281,6 @@ Area of polygon geometries in square meters. This area is calculated in the webm
Calculate the z-order of an OSM highway or railway. Returns a numeric value that represents the importance of a way where ``motorway`` is the most important (9), and ``path`` or ``track`` are least important (0). ``bridge`` and ``tunnel`` will modify the value by -10/+10. ``layer`` will be multiplied by ten and added to the value. E.g. ``highway=motorway``, ``bridge=yes`` and ``layer=2`` will return 39 (9+10+2*10).
-
``hstore_tags``
^^^^^^^^^^^^^^^
diff --git a/example-mapping.json b/example-mapping.json
index 9a7d604..cc5d876 100644
--- a/example-mapping.json
+++ b/example-mapping.json
@@ -71,58 +71,57 @@
},
{
"args": {
- "ranks": [
- "pedestrian",
- "footway",
- "playground",
- "park",
- "forest",
- "cemetery",
- "farmyard",
- "farm",
- "farmland",
- "wood",
- "meadow",
- "grass",
- "wetland",
- "village_green",
- "recreation_ground",
- "garden",
- "sports_centre",
- "pitch",
- "common",
- "allotments",
- "golf_course",
- "university",
- "school",
- "college",
- "library",
- "baracks",
- "fuel",
- "parking",
- "nature_reserve",
- "cinema",
- "theatre",
- "place_of_worship",
- "hospital",
- "scrub",
- "orchard",
- "vineyard",
- "zoo",
- "quarry",
- "residential",
- "retail",
- "commercial",
- "industrial",
- "railway",
- "heath",
+ "values": [
+ "land",
"island",
- "land"
+ "heath",
+ "railway",
+ "industrial",
+ "commercial",
+ "retail",
+ "residential",
+ "quarry",
+ "zoo",
+ "vineyard",
+ "orchard",
+ "scrub",
+ "hospital",
+ "place_of_worship",
+ "theatre",
+ "cinema",
+ "nature_reserve",
+ "parking",
+ "fuel",
+ "baracks",
+ "library",
+ "college",
+ "school",
+ "university",
+ "golf_course",
+ "allotments",
+ "common",
+ "pitch",
+ "sports_centre",
+ "garden",
+ "recreation_ground",
+ "village_green",
+ "wetland",
+ "grass",
+ "meadow",
+ "wood",
+ "farmland",
+ "farm",
+ "farmyard",
+ "cemetery",
+ "forest",
+ "park",
+ "playground",
+ "footway",
+ "pedestrian"
]
},
- "type": "zorder",
- "name": "z_order",
- "key": "z_order"
+ "type": "enumerate",
+ "name": "z_order"
}
],
"type": "polygon",
@@ -258,22 +257,21 @@
},
{
"args": {
- "ranks": [
- "country",
- "state",
- "region",
- "county",
- "city",
- "town",
- "village",
- "hamlet",
+ "values": [
+ "locality",
"suburb",
- "locality"
+ "hamlet",
+ "village",
+ "town",
+ "city",
+ "county",
+ "region",
+ "state",
+ "country"
]
},
- "type": "zorder",
- "name": "z_order",
- "key": "z_order"
+ "type": "enumerate",
+ "name": "z_order"
},
{
"type": "integer",
diff --git a/mapping/fields.go b/mapping/fields.go
index 21436a7..7407797 100644
--- a/mapping/fields.go
+++ b/mapping/fields.go
@@ -31,6 +31,7 @@ func init() {
"wayzorder": {"wayzorder", "int32", WayZOrder, nil},
"pseudoarea": {"pseudoarea", "float32", PseudoArea, nil},
"zorder": {"zorder", "int32", nil, MakeZOrder},
+ "enumerate": {"enumerate", "int32", nil, MakeEnumerate},
"string_suffixreplace": {"string_suffixreplace", "string", nil, MakeSuffixReplace},
}
}
@@ -224,6 +225,7 @@ func WayZOrder(val string, elem *element.OSMElem, geom *geom.Geometry, match Mat
}
func MakeZOrder(fieldName string, fieldType FieldType, field Field) (MakeValue, error) {
+ log.Print("warn: zorder type is deprecated and will be removed. See enumerate type.")
_rankList, ok := field.Args["ranks"]
if !ok {
return nil, errors.New("missing ranks in args for zorder")
@@ -269,6 +271,42 @@ func MakeZOrder(fieldName string, fieldType FieldType, field Field) (MakeValue,
return zOrder, nil
}
+func MakeEnumerate(fieldName string, fieldType FieldType, field Field) (MakeValue, error) {
+ _valuesList, ok := field.Args["values"]
+ if !ok {
+ return nil, errors.New("missing values in args for enumerate")
+ }
+
+ valuesList, ok := _valuesList.([]interface{})
+ if !ok {
+ return nil, errors.New("values in args for enumerate not a list")
+ }
+
+ values := make(map[string]int)
+ for i, value := range valuesList {
+ valueName, ok := value.(string)
+ if !ok {
+ return nil, errors.New("value in values not a string")
+ }
+
+ values[valueName] = i + 1
+ }
+ enumerate := func(val string, elem *element.OSMElem, geom *geom.Geometry, match Match) interface{} {
+ if field.Key != "" {
+ if r, ok := values[val]; ok {
+ return r
+ }
+ return 0
+ }
+ if r, ok := values[match.Value]; ok {
+ return r
+ }
+ return 0
+ }
+
+ return enumerate, nil
+}
+
func MakeSuffixReplace(fieldName string, fieldType FieldType, field Field) (MakeValue, error) {
_changes, ok := field.Args["suffixes"]
if !ok {
diff --git a/mapping/fields_test.go b/mapping/fields_test.go
index aff33ed..b29b50a 100644
--- a/mapping/fields_test.go
+++ b/mapping/fields_test.go
@@ -107,6 +107,80 @@ func TestZOrder(t *testing.T) {
}
}
+func TestEnumerate_Match(t *testing.T) {
+ // test enumerate by matched mapping key
+ match := Match{}
+
+ zOrder, err := MakeEnumerate("enumerate",
+ AvailableFieldTypes["enumerate"],
+ Field{
+ Name: "enumerate",
+ Key: "",
+ Type: "enumerate",
+ Args: map[string]interface{}{"values": []interface{}{"AA", "CC", "FF", "ZZ"}},
+ },
+ )
+ if err != nil {
+ t.Fatal(err)
+ }
+ elem := &element.OSMElem{}
+
+ elem.Tags = element.Tags{} // missing
+ if v := zOrder("", elem, nil, match); v != 0 {
+ t.Errorf(" -> %v", v)
+ }
+ match.Value = "ABCD" // unknown
+ if v := zOrder("", elem, nil, match); v != 0 {
+ t.Errorf(" -> %v", v)
+ }
+ match.Value = "AA"
+ if v := zOrder("", elem, nil, match); v != 1 {
+ t.Errorf(" -> %v", v)
+ }
+ match.Value = "CC"
+ if v := zOrder("", elem, nil, match); v != 2 {
+ t.Errorf(" -> %v", v)
+ }
+ match.Value = "ZZ"
+ if v := zOrder("", elem, nil, match); v != 4 {
+ t.Errorf(" -> %v", v)
+ }
+}
+
+func TestEnumerate_Key(t *testing.T) {
+ // test enumerate by key
+ match := Match{}
+
+ zOrder, err := MakeEnumerate("enumerate",
+ AvailableFieldTypes["enumerate"],
+ Field{
+ Name: "enumerate",
+ Key: "fips",
+ Type: "enumerate",
+ Args: map[string]interface{}{"values": []interface{}{"AA", "CC", "FF", "ZZ"}},
+ },
+ )
+ if err != nil {
+ t.Fatal(err)
+ }
+ elem := &element.OSMElem{}
+ if v := zOrder("", elem, nil, match); v != 0 {
+ t.Errorf(" -> %v", v)
+ }
+ if v := zOrder("ABCD", elem, nil, match); v != 0 {
+ t.Errorf(" -> %v", v)
+ }
+ if v := zOrder("AA", elem, nil, match); v != 1 {
+ t.Errorf(" -> %v", v)
+ }
+ if v := zOrder("CC", elem, nil, match); v != 2 {
+ t.Errorf(" -> %v", v)
+ }
+ if v := zOrder("ZZ", elem, nil, match); v != 4 {
+ t.Errorf(" -> %v", v)
+ }
+}
+
func TestMakeSuffixReplace(t *testing.T) {
field := Field{
Name: "name", Key: "name", Type: "string_suffixreplace",
diff --git a/test/complete_db.osm b/test/complete_db.osm
index ce3c6eb..6327832 100644
--- a/test/complete_db.osm
+++ b/test/complete_db.osm
@@ -1021,4 +1021,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/complete_db_mapping.json b/test/complete_db_mapping.json
index 201ff38..637b06c 100644
--- a/test/complete_db_mapping.json
+++ b/test/complete_db_mapping.json
@@ -71,58 +71,32 @@
},
{
"args": {
- "ranks": [
- "pedestrian",
- "footway",
- "playground",
+ "values": [
"park",
"forest",
- "cemetery",
- "farmyard",
- "farm",
- "farmland",
- "wood",
- "meadow",
- "grass",
- "wetland",
- "village_green",
- "recreation_ground",
- "garden",
- "sports_centre",
- "pitch",
- "common",
- "allotments",
- "golf_course",
- "university",
- "school",
- "college",
- "library",
- "baracks",
- "fuel",
- "parking",
- "nature_reserve",
- "cinema",
- "theatre",
- "place_of_worship",
- "hospital",
- "scrub",
- "orchard",
- "vineyard",
- "zoo",
- "quarry",
"residential",
"retail",
"commercial",
"industrial",
"railway",
- "heath",
- "island",
- "land"
+ "cemetery",
+ "grass",
+ "farmyard",
+ "farm",
+ "farmland",
+ "orchard",
+ "vineyard",
+ "wood",
+ "meadow",
+ "village_green",
+ "recreation_ground",
+ "allotments",
+ "quarry"
]
},
- "type": "zorder",
- "name": "z_order",
- "key": "z_order"
+ "type": "enumerate",
+ "name": "enum",
+ "key": "enum_test"
}
],
"type": "polygon",
@@ -258,22 +232,21 @@
},
{
"args": {
- "ranks": [
- "country",
- "state",
- "region",
- "county",
- "city",
- "town",
- "village",
- "hamlet",
+ "values": [
+ "locality",
"suburb",
- "locality"
+ "hamlet",
+ "village",
+ "town",
+ "city",
+ "county",
+ "region",
+ "state",
+ "country"
]
},
- "type": "zorder",
- "name": "z_order",
- "key": "z_order"
+ "type": "enumerate",
+ "name": "z_order"
},
{
"type": "integer",
diff --git a/test/complete_db_test.py b/test/complete_db_test.py
index 0129982..6ab1e9f 100644
--- a/test/complete_db_test.py
+++ b/test/complete_db_test.py
@@ -298,6 +298,13 @@ def test_update_node_to_coord_1():
assert t.query_row(t.db_conf, 'osm_amenities', 70001)
assert not t.query_row(t.db_conf, 'osm_amenities', 70002)
+def test_enumerate_key():
+ """Enumerate from key."""
+ assert t.query_row(t.db_conf, 'osm_landusages', 100001)['enum'] == 1
+ assert t.query_row(t.db_conf, 'osm_landusages', 100002)['enum'] == 0
+ assert t.query_row(t.db_conf, 'osm_landusages', 100003)['enum'] == 15
+
+
#######################################################################
def test_update():
"""Diff import applies"""