diff --git a/editor/editor_tests/xml_feature_test.cpp b/editor/editor_tests/xml_feature_test.cpp
index 592de5b514..6f76e4e2f7 100644
--- a/editor/editor_tests/xml_feature_test.cpp
+++ b/editor/editor_tests/xml_feature_test.cpp
@@ -59,6 +59,8 @@ UNIT_TEST(XMLFeature_Setters)
feature.SetHouse("10");
feature.SetTagValue("opening_hours", "Mo-Fr 08:15-17:30");
+ feature.SetType("amenity|atm");
+
stringstream sstr;
feature.Save(sstr);
@@ -82,6 +84,9 @@ UNIT_TEST(XMLFeature_Setters)
+
)";
@@ -110,6 +115,9 @@ UNIT_TEST(XMLFeatureFromXml)
+
)";
@@ -134,4 +142,6 @@ UNIT_TEST(XMLFeatureFromXml)
TEST_EQUAL(feature.GetTagValue("opening_hours"), "Mo-Fr 08:15-17:30", ());
TEST_EQUAL(my::TimestampToString(feature.GetModificationTime()), "2015-11-27T21:13:32Z", ());
+
+ TEST_EQUAL(feature.GetType(), "amenity|atm", ());
}
diff --git a/editor/xml_feature.cpp b/editor/xml_feature.cpp
index 46ffc9037a..24b5f714d2 100644
--- a/editor/xml_feature.cpp
+++ b/editor/xml_feature.cpp
@@ -1,11 +1,17 @@
#include "editor/xml_feature.hpp"
+#include "base/assert.hpp"
#include "base/string_utils.hpp"
#include "base/timer.hpp"
#include "geometry/mercator.hpp"
-#include "std/cstring.hpp"
+#include "std/set.hpp"
+#include "std/unordered_set.hpp"
+
+#include
+#include
+#include
#include "3party/pugixml/src/pugixml.hpp"
@@ -47,6 +53,153 @@ void ValidateNode(pugi::xml_node const & node)
if (!node.attribute("timestamp"))
MYTHROW(editor::XMLFeatureNoTimestampError, ("Node has no timestamp attribute"));
}
+
+bool IsConvertable(string const & k, string const & v)
+{
+ static unordered_set, boost::hash>> const
+ convertableTypePairs =
+ {
+ { "aeroway", "aerodrome" },
+ { "aeroway", "airport" },
+ { "amenity", "atm" },
+ { "amenity", "bank" },
+ { "amenity", "bar" },
+ { "amenity", "bbq" },
+ { "amenity", "bench" },
+ { "amenity", "bicycle_rental" },
+ { "amenity", "bureau_de_change" },
+ { "amenity", "bus_station" },
+ { "amenity", "cafe" },
+ { "amenity", "car_rental" },
+ { "amenity", "car_sharing" },
+ { "amenity", "casino" },
+ { "amenity", "cinema" },
+ { "amenity", "college" },
+ { "amenity", "doctors" },
+ { "amenity", "drinking_water" },
+ { "amenity", "embassy" },
+ { "amenity", "fast_food" },
+ { "amenity", "ferry_terminal" },
+ { "amenity", "fire_station" },
+ { "amenity", "fountain" },
+ { "amenity", "fuel" },
+ { "amenity", "grave_yard" },
+ { "amenity", "hospital" },
+ { "amenity", "hunting_stand" },
+ { "amenity", "kindergarten" },
+ { "amenity", "library" },
+ { "amenity", "marketplace" },
+ { "amenity", "nightclub" },
+ { "amenity", "parking" },
+ { "amenity", "pharmacy" },
+ { "amenity", "place_of_worship" },
+ { "amenity", "police" },
+ { "amenity", "post_box" },
+ { "amenity", "post_office" },
+ { "amenity", "pub" },
+ { "amenity", "recycling" },
+ { "amenity", "restaurant" },
+ { "amenity", "school" },
+ { "amenity", "shelter" },
+ { "amenity", "taxi" },
+ { "amenity", "telephone" },
+ { "amenity", "theatre" },
+ { "amenity", "toilets" },
+ { "amenity", "townhall" },
+ { "amenity", "university" },
+ { "amenity", "waste_disposal" },
+ { "highway", "bus_stop" },
+ { "highway", "speed_camera" },
+ { "historic", "archaeological_site" },
+ { "historic", "castle" },
+ { "historic", "memorial" },
+ { "historic", "monument" },
+ { "historic", "ruins" },
+ { "internet", "access" },
+ { "internet", "access|wlan" },
+ { "landuse", "cemetery" },
+ { "leisure", "garden" },
+ { "leisure", "pitch" },
+ { "leisure", "playground" },
+ { "leisure", "sports_centre" },
+ { "leisure", "stadium" },
+ { "leisure", "swimming_pool" },
+ { "natural", "peak" },
+ { "natural", "spring" },
+ { "natural", "waterfall" },
+ { "office", "company" },
+ { "office", "estate_agent" },
+ { "office", "government" },
+ { "office", "lawyer" },
+ { "office", "telecommunication" },
+ { "place", "farm" },
+ { "place", "hamlet" },
+ { "place", "village" },
+ { "railway", "halt" },
+ { "railway", "station" },
+ { "railway", "subway_entrance" },
+ { "railway", "tram_stop" },
+ { "shop", "alcohol" },
+ { "shop", "bakery" },
+ { "shop", "beauty" },
+ { "shop", "beverages" },
+ { "shop", "bicycle" },
+ { "shop", "books" },
+ { "shop", "butcher" },
+ { "shop", "car" },
+ { "shop", "car_repair" },
+ { "shop", "chemist" },
+ { "shop", "clothes" },
+ { "shop", "computer" },
+ { "shop", "confectionery" },
+ { "shop", "convenience" },
+ { "shop", "department_store" },
+ { "shop", "doityourself" },
+ { "shop", "electronics" },
+ { "shop", "florist" },
+ { "shop", "furniture" },
+ { "shop", "garden_centre" },
+ { "shop", "gift" },
+ { "shop", "greengrocer" },
+ { "shop", "hairdresser" },
+ { "shop", "hardware" },
+ { "shop", "jewelry" },
+ { "shop", "kiosk" },
+ { "shop", "laundry" },
+ { "shop", "mall" },
+ { "shop", "mobile_phone" },
+ { "shop", "optician" },
+ { "shop", "shoes" },
+ { "shop", "sports" },
+ { "shop", "supermarket" },
+ { "shop", "toys" },
+ { "tourism", "alpine_hut" },
+ { "tourism", "artwork" },
+ { "tourism", "attraction" },
+ { "tourism", "camp_site" },
+ { "tourism", "caravan_site" },
+ { "tourism", "guest_house" },
+ { "tourism", "hostel" },
+ { "tourism", "hotel" },
+ { "tourism", "information" },
+ { "tourism", "motel" },
+ { "tourism", "museum" },
+ { "tourism", "picnic_site" },
+ { "tourism", "viewpoint" },
+ { "waterway", "waterfall" }
+ };
+
+ return convertableTypePairs.find(make_pair(k, v)) != end(convertableTypePairs);
+}
+
+pair SplitMapsmeType(string const & type)
+{
+ vector parts;
+ boost::split(parts, type, boost::is_any_of("|"));
+ // Current implementations supports only types with one pipe
+ ASSERT(parts.size() == 2, ("Too many parts in type: " + type));
+ return make_pair(parts[0], parts[1]);
+}
} // namespace
namespace editor
@@ -80,6 +233,27 @@ void XMLFeature::Save(ostream & ost) const
m_document.save(ost, " ", pugi::format_indent_attributes);
}
+string XMLFeature::GetType() const
+{
+ for (auto const tag : GetRootNode().select_nodes("tag"))
+ {
+ string const key = tag.node().attribute("k").value();
+ string const val = tag.node().attribute("v").value();
+ // Handle only the first appropriate tag in first version
+ if (IsConvertable(key, val))
+ return key + '|' + val;
+ }
+
+ return "";
+}
+
+void XMLFeature::SetType(string const & type)
+{
+ auto const p = SplitMapsmeType(type);
+ if (IsConvertable(p.first, p.second))
+ SetTagValue(p.first, p.second);
+}
+
m2::PointD XMLFeature::GetCenter() const
{
return PointFromLatLon(GetRootNode());
@@ -191,7 +365,12 @@ void XMLFeature::SetAttribute(string const & key, string const & value)
node = value.data();
}
-pugi::xml_node XMLFeature::GetRootNode() const
+pugi::xml_node const XMLFeature::GetRootNode() const
+{
+ return m_document.child("node");
+}
+
+pugi::xml_node XMLFeature::GetRootNode()
{
return m_document.child("node");
}
diff --git a/editor/xml_feature.hpp b/editor/xml_feature.hpp
index ab13b96801..58fc76ef6e 100644
--- a/editor/xml_feature.hpp
+++ b/editor/xml_feature.hpp
@@ -5,7 +5,6 @@
#include "std/ctime.hpp"
#include "std/iostream.hpp"
#include "std/map.hpp"
-#include "std/unique_ptr.hpp"
#include "coding/multilang_utf8_string.hpp"
@@ -60,7 +59,8 @@ public:
void SetAttribute(string const & key, string const & value);
private:
- pugi::xml_node GetRootNode() const;
+ pugi::xml_node const GetRootNode() const;
+ pugi::xml_node GetRootNode();
pugi::xml_document m_document;
};