forked from organicmaps/organicmaps
Do not create node features from xml for now. Patch everything.
This commit is contained in:
parent
ef1e40d052
commit
cf2302d034
10 changed files with 320 additions and 360 deletions
|
@ -15,7 +15,7 @@ using namespace editor;
|
|||
|
||||
UNIT_TEST(XMLFeature_RawGetSet)
|
||||
{
|
||||
XMLFeature feature;
|
||||
XMLFeature feature(XMLFeature::Type::Node);
|
||||
TEST(!feature.HasTag("opening_hours"), ());
|
||||
TEST(!feature.HasAttribute("center"), ());
|
||||
|
||||
|
@ -48,7 +48,7 @@ UNIT_TEST(XMLFeature_RawGetSet)
|
|||
|
||||
UNIT_TEST(XMLFeature_Setters)
|
||||
{
|
||||
XMLFeature feature;
|
||||
XMLFeature feature(XMLFeature::Type::Node);
|
||||
|
||||
feature.SetCenter(MercatorBounds::FromLatLon(55.7978998, 37.4745280));
|
||||
feature.SetModificationTime(my::StringToTimestamp("2015-11-27T21:13:32Z"));
|
||||
|
@ -93,57 +93,57 @@ UNIT_TEST(XMLFeature_Setters)
|
|||
TEST_EQUAL(sstr.str(), expectedString, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(XMLFeature_FromXml)
|
||||
{
|
||||
auto const srcString = R"(<?xml version="1.0"?>
|
||||
<node
|
||||
lat="55.7978998"
|
||||
lon="37.474528"
|
||||
timestamp="2015-11-27T21:13:32Z">
|
||||
<tag
|
||||
k="name"
|
||||
v="Gorki Park" />
|
||||
<tag
|
||||
k="name:en"
|
||||
v="Gorki Park" />
|
||||
<tag
|
||||
k="name:ru"
|
||||
v="Парк Горького" />
|
||||
<tag
|
||||
k="addr:housenumber"
|
||||
v="10" />
|
||||
<tag
|
||||
k="opening_hours"
|
||||
v="Mo-Fr 08:15-17:30" />
|
||||
<tag
|
||||
k="amenity"
|
||||
v="atm" />
|
||||
</node>
|
||||
)";
|
||||
// UNIT_TEST(XMLFeature_FromXml)
|
||||
// {
|
||||
// auto const srcString = R"(<?xml version="1.0"?>
|
||||
// <node
|
||||
// lat="55.7978998"
|
||||
// lon="37.474528"
|
||||
// timestamp="2015-11-27T21:13:32Z">
|
||||
// <tag
|
||||
// k="name"
|
||||
// v="Gorki Park" />
|
||||
// <tag
|
||||
// k="name:en"
|
||||
// v="Gorki Park" />
|
||||
// <tag
|
||||
// k="name:ru"
|
||||
// v="Парк Горького" />
|
||||
// <tag
|
||||
// k="addr:housenumber"
|
||||
// v="10" />
|
||||
// <tag
|
||||
// k="opening_hours"
|
||||
// v="Mo-Fr 08:15-17:30" />
|
||||
// <tag
|
||||
// k="amenity"
|
||||
// v="atm" />
|
||||
// </node>
|
||||
// )";
|
||||
|
||||
XMLFeature feature(srcString);
|
||||
// XMLFeature feature(srcString);
|
||||
|
||||
stringstream sstr;
|
||||
feature.Save(sstr);
|
||||
TEST_EQUAL(srcString, sstr.str(), ());
|
||||
// stringstream sstr;
|
||||
// feature.Save(sstr);
|
||||
// TEST_EQUAL(srcString, sstr.str(), ());
|
||||
|
||||
TEST(feature.HasKey("opening_hours"), ());
|
||||
TEST(feature.HasKey("lat"), ());
|
||||
TEST(feature.HasKey("lon"), ());
|
||||
TEST(!feature.HasKey("FooBarBaz"), ());
|
||||
// TEST(feature.HasKey("opening_hours"), ());
|
||||
// TEST(feature.HasKey("lat"), ());
|
||||
// TEST(feature.HasKey("lon"), ());
|
||||
// TEST(!feature.HasKey("FooBarBaz"), ());
|
||||
|
||||
TEST_EQUAL(feature.GetHouse(), "10", ());
|
||||
TEST_EQUAL(feature.GetCenter(), MercatorBounds::FromLatLon(55.7978998, 37.4745280), ());
|
||||
TEST_EQUAL(feature.GetName(), "Gorki Park", ());
|
||||
TEST_EQUAL(feature.GetName("default"), "Gorki Park", ());
|
||||
TEST_EQUAL(feature.GetName("en"), "Gorki Park", ());
|
||||
TEST_EQUAL(feature.GetName("ru"), "Парк Горького", ());
|
||||
TEST_EQUAL(feature.GetName("No such language"), "", ());
|
||||
// TEST_EQUAL(feature.GetHouse(), "10", ());
|
||||
// TEST_EQUAL(feature.GetCenter(), MercatorBounds::FromLatLon(55.7978998, 37.4745280), ());
|
||||
// TEST_EQUAL(feature.GetName(), "Gorki Park", ());
|
||||
// TEST_EQUAL(feature.GetName("default"), "Gorki Park", ());
|
||||
// TEST_EQUAL(feature.GetName("en"), "Gorki Park", ());
|
||||
// TEST_EQUAL(feature.GetName("ru"), "Парк Горького", ());
|
||||
// TEST_EQUAL(feature.GetName("No such language"), "", ());
|
||||
|
||||
TEST_EQUAL(feature.GetTagValue("opening_hours"), "Mo-Fr 08:15-17:30", ());
|
||||
TEST_EQUAL(feature.GetTagValue("amenity"), "atm", ());
|
||||
TEST_EQUAL(my::TimestampToString(feature.GetModificationTime()), "2015-11-27T21:13:32Z", ());
|
||||
}
|
||||
// TEST_EQUAL(feature.GetTagValue("opening_hours"), "Mo-Fr 08:15-17:30", ());
|
||||
// TEST_EQUAL(feature.GetTagValue("amenity"), "atm", ());
|
||||
// TEST_EQUAL(my::TimestampToString(feature.GetModificationTime()), "2015-11-27T21:13:32Z", ());
|
||||
// }
|
||||
|
||||
UNIT_TEST(XMLFeature_ForEachName)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,9 @@ constexpr char const * kUploadTimestamp = "upload_timestamp";
|
|||
constexpr char const * kUploadStatus = "upload_status";
|
||||
constexpr char const * kUploadError = "upload_error";
|
||||
constexpr char const * kHouseNumber = "addr:housenumber";
|
||||
constexpr char const * kGeomType = "mapswithme:geom_type";
|
||||
|
||||
constexpr char const * kNodeType = "node";
|
||||
constexpr char const * kWayType = "way";
|
||||
|
||||
pugi::xml_node FindTag(pugi::xml_document const & document, string const & key)
|
||||
{
|
||||
|
@ -65,9 +67,9 @@ namespace editor
|
|||
char const * const XMLFeature::kDefaultLang =
|
||||
StringUtf8Multilang::GetLangByCode(StringUtf8Multilang::DEFAULT_CODE);
|
||||
|
||||
XMLFeature::XMLFeature()
|
||||
XMLFeature::XMLFeature(Type const type)
|
||||
{
|
||||
m_document.append_child("node");
|
||||
m_document.append_child(type == Type::Node ? kNodeType : kWayType);
|
||||
}
|
||||
|
||||
XMLFeature::XMLFeature(string const & xml)
|
||||
|
@ -89,14 +91,9 @@ XMLFeature::XMLFeature(pugi::xml_node const & xml)
|
|||
ValidateNode(GetRootNode());
|
||||
}
|
||||
|
||||
string XMLFeature::GetGeomType() const
|
||||
XMLFeature::Type XMLFeature::GetType() const
|
||||
{
|
||||
return GetTagValue(kGeomType);
|
||||
}
|
||||
|
||||
void XMLFeature::SetGeomType(string const & type)
|
||||
{
|
||||
SetTagValue(kGeomType, type);
|
||||
return strcmp(GetRootNode().name(), "node") == 0 ? Type::Node : Type::Way;
|
||||
}
|
||||
|
||||
void XMLFeature::Save(ostream & ost) const
|
||||
|
@ -257,12 +254,12 @@ void XMLFeature::SetAttribute(string const & key, string const & value)
|
|||
|
||||
pugi::xml_node const XMLFeature::GetRootNode() const
|
||||
{
|
||||
return m_document.child("node");
|
||||
return m_document.first_child();
|
||||
}
|
||||
|
||||
pugi::xml_node XMLFeature::GetRootNode()
|
||||
{
|
||||
return m_document.child("node");
|
||||
return m_document.first_child();
|
||||
}
|
||||
|
||||
bool XMLFeature::AttachToParentNode(pugi::xml_node parent) const
|
||||
|
|
|
@ -26,15 +26,20 @@ class XMLFeature
|
|||
static char const * const kDefaultLang;
|
||||
|
||||
public:
|
||||
XMLFeature();
|
||||
enum class Type
|
||||
{
|
||||
Node,
|
||||
Way
|
||||
};
|
||||
|
||||
XMLFeature(Type const type);
|
||||
XMLFeature(string const & xml);
|
||||
XMLFeature(pugi::xml_document const & xml);
|
||||
XMLFeature(pugi::xml_node const & xml);
|
||||
XMLFeature(XMLFeature const & feature) : XMLFeature(feature.m_document) {}
|
||||
void Save(ostream & ost) const;
|
||||
|
||||
string GetGeomType() const;
|
||||
void SetGeomType(string const & type);
|
||||
Type GetType() const;
|
||||
|
||||
m2::PointD GetCenter() const;
|
||||
void SetCenter(m2::PointD const & mercatorCenter);
|
||||
|
|
|
@ -32,28 +32,34 @@ void FeatureBase::Deserialize(feature::LoaderBase * pLoader, TBuffer buffer)
|
|||
m_header = m_pLoader->GetHeader();
|
||||
}
|
||||
|
||||
FeatureType FeatureType::FromXML(string const & xml)
|
||||
{
|
||||
pugi::xml_document document;
|
||||
document.load(xml.data());
|
||||
return FromXML(document);
|
||||
}
|
||||
// TODO(mgsergio): No need to create feature from xml, can go with patchig for now.
|
||||
//@{
|
||||
// FeatureType FeatureType::FromXML(string const & xml)
|
||||
// {
|
||||
// pugi::xml_document document;
|
||||
// document.load(xml.data());
|
||||
// return FromXML(document);
|
||||
// }
|
||||
|
||||
FeatureType FeatureType::FromXML(editor::XMLFeature const & xml)
|
||||
{
|
||||
FeatureType feature;
|
||||
// Should be set to true. Or later call to ParseGeometry will lead to crash.
|
||||
feature.m_bTrianglesParsed = feature.m_bPointsParsed = true;
|
||||
feature.m_center = xml.GetCenter();
|
||||
// FeatureType FeatureType::FromXML(editor::XMLFeature const & xml)
|
||||
// {
|
||||
// FeatureType feature;
|
||||
// // Should be set to true. Or later call to ParseGeometry will lead to crash.
|
||||
// feature.m_bTrianglesParsed = feature.m_bPointsParsed = true;
|
||||
// feature.m_center = xml.GetCenter();
|
||||
|
||||
// Preset type for header calculation later in ApplyPatch.
|
||||
feature.m_header = HEADER_GEOM_POINT;
|
||||
// // Preset type for header calculation later in ApplyPatch.
|
||||
// feature.m_header = HEADER_GEOM_POINT;
|
||||
|
||||
feature.ApplyPatch(xml);
|
||||
// auto const & types = osm::Editor::Instance().GetTypesOfFeature(xml);
|
||||
// copy(begin(types), end(types), begin(feature.m_types));
|
||||
// feature.m_bTypesParsed = true;
|
||||
|
||||
return feature;
|
||||
}
|
||||
// feature.ApplyPatch(xml);
|
||||
|
||||
// return feature;
|
||||
// }
|
||||
//@}
|
||||
void FeatureType::ApplyPatch(editor::XMLFeature const & xml)
|
||||
{
|
||||
xml.ForEachName([this](string const & lang, string const & name)
|
||||
|
@ -71,10 +77,6 @@ void FeatureType::ApplyPatch(editor::XMLFeature const & xml)
|
|||
// m_params.rank =
|
||||
m_bCommonParsed = true;
|
||||
|
||||
auto const & types = osm::Editor::Instance().GetTypesOfFeature(xml);
|
||||
copy(begin(types), end(types), begin(m_types));
|
||||
m_bTypesParsed = true;
|
||||
|
||||
for (auto const i : my::Range(1u, static_cast<uint32_t>(feature::Metadata::FMD_COUNT)))
|
||||
{
|
||||
auto const type = static_cast<feature::Metadata::EType>(i);
|
||||
|
@ -92,11 +94,9 @@ void FeatureType::ApplyPatch(editor::XMLFeature const & xml)
|
|||
|
||||
editor::XMLFeature FeatureType::ToXML() const
|
||||
{
|
||||
editor::XMLFeature feature;
|
||||
|
||||
// Save geom type to choose what to do later:
|
||||
// deserialize or patch.
|
||||
feature.SetGeomType(DebugPrint(GetFeatureType()));
|
||||
editor::XMLFeature feature(GetFeatureType() == feature::GEOM_POINT
|
||||
? editor::XMLFeature::Type::Node
|
||||
: editor::XMLFeature::Type::Way);
|
||||
|
||||
// Only Poins are completely serialized and deserialized.
|
||||
// Other types could only be patched.
|
||||
|
@ -118,12 +118,13 @@ editor::XMLFeature FeatureType::ToXML() const
|
|||
// feature.m_params.layer =
|
||||
// feature.m_params.rank =
|
||||
|
||||
ParseTypes();
|
||||
for (auto const i : my::Range(GetTypesCount()))
|
||||
{
|
||||
for (auto const & tag : osm::Editor::Instance().GetTagsForType(m_types[i]))
|
||||
feature.SetTagValue(tag.first, tag.second);
|
||||
}
|
||||
// TODO(mgsergio): Save/Load types when required by feature creation or type modification.
|
||||
// ParseTypes();
|
||||
// for (auto const i : my::Range(GetTypesCount()))
|
||||
// {
|
||||
// for (auto const & tag : osm::Editor::Instance().GetTagsForType(m_types[i]))
|
||||
// feature.SetTagValue(tag.first, tag.second);
|
||||
// }
|
||||
|
||||
for (auto const type : m_metadata.GetPresentTypes())
|
||||
{
|
||||
|
|
|
@ -2,20 +2,6 @@
|
|||
|
||||
#include "std/sstream.hpp"
|
||||
|
||||
namespace feature
|
||||
{
|
||||
string DebugPrint(feature::EGeomType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case feature::GEOM_UNDEFINED: return "GEOM_UNDEFINED";
|
||||
case feature::GEOM_POINT: return "GEOM_POINT";
|
||||
case feature::GEOM_LINE: return "GEOM_LINE";
|
||||
case feature::GEOM_AREA: return "GEOM_AREA";
|
||||
}
|
||||
}
|
||||
} // namespace feature
|
||||
|
||||
string DebugPrint(FeatureID const & id)
|
||||
{
|
||||
ostringstream ss;
|
||||
|
|
|
@ -15,8 +15,6 @@ enum EGeomType
|
|||
GEOM_LINE = 1,
|
||||
GEOM_AREA = 2
|
||||
};
|
||||
|
||||
string DebugPrint(EGeomType type);
|
||||
}
|
||||
|
||||
struct FeatureID
|
||||
|
|
|
@ -137,14 +137,14 @@ private:
|
|||
FeatureType feature;
|
||||
switch (m_editor.GetFeatureStatus(mwmID, index))
|
||||
{
|
||||
case osm::Editor::FeatureStatus::Deleted: return;
|
||||
case osm::Editor::FeatureStatus::Modified:
|
||||
VERIFY(m_editor.GetEditedFeature(mwmID, index, feature), ());
|
||||
m_f(feature);
|
||||
return;
|
||||
case osm::Editor::FeatureStatus::Created:
|
||||
CHECK(false, ("Created features index should be generated."));
|
||||
case osm::Editor::FeatureStatus::Untouched: break;
|
||||
case osm::Editor::FeatureStatus::Deleted: return;
|
||||
case osm::Editor::FeatureStatus::Modified:
|
||||
VERIFY(m_editor.GetEditedFeature(mwmID, index, feature), ());
|
||||
m_f(feature);
|
||||
return;
|
||||
case osm::Editor::FeatureStatus::Created:
|
||||
CHECK(false, ("Created features index should be generated."));
|
||||
case osm::Editor::FeatureStatus::Untouched: break;
|
||||
}
|
||||
if (checkUnique(index))
|
||||
{
|
||||
|
@ -196,12 +196,15 @@ private:
|
|||
|
||||
for (auto const & i : interval)
|
||||
{
|
||||
index.ForEachInIntervalAndScale([&] (uint32_t index)
|
||||
{
|
||||
if (osm::Editor::FeatureStatus::Deleted != m_editor.GetFeatureStatus(mwmID, index) &&
|
||||
checkUnique(index))
|
||||
m_f(FeatureID(mwmID, index));
|
||||
}, i.first, i.second, scale);
|
||||
index.ForEachInIntervalAndScale(
|
||||
[&](uint32_t index)
|
||||
{
|
||||
if (osm::Editor::FeatureStatus::Deleted !=
|
||||
m_editor.GetFeatureStatus(mwmID, index) &&
|
||||
checkUnique(index))
|
||||
m_f(FeatureID(mwmID, index));
|
||||
},
|
||||
i.first, i.second, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +251,8 @@ public:
|
|||
do
|
||||
{
|
||||
osm::Editor::FeatureStatus const fts = editor.GetFeatureStatus(id, fidIter->m_index);
|
||||
ASSERT_NOT_EQUAL(osm::Editor::FeatureStatus::Deleted, fts, ("Deleted feature was cached. Please review your code."));
|
||||
ASSERT_NOT_EQUAL(osm::Editor::FeatureStatus::Deleted, fts,
|
||||
("Deleted feature was cached. Please review your code."));
|
||||
FeatureType featureType;
|
||||
if (fts == osm::Editor::FeatureStatus::Modified)
|
||||
{
|
||||
|
|
|
@ -48,42 +48,43 @@ void CompareFeatureXML(string const & d1, string const & d2)
|
|||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(FeatureType_FromXMLAndBackToXML)
|
||||
{
|
||||
auto const xml = R"(<?xml version="1.0"?>
|
||||
<node
|
||||
lat="55.7978998"
|
||||
lon="37.474528"
|
||||
timestamp="2015-11-27T21:13:32Z">
|
||||
<tag
|
||||
k="name"
|
||||
v="Gorki Park" />
|
||||
<tag
|
||||
k="name:en"
|
||||
v="Gorki Park" />
|
||||
<tag
|
||||
k="name:ru"
|
||||
v="Парк Горького" />
|
||||
<tag
|
||||
k="addr:housenumber"
|
||||
v="10" />
|
||||
<tag
|
||||
k="opening_hours"
|
||||
v="Mo-Fr 08:15-17:30" />
|
||||
<tag
|
||||
k="amenity"
|
||||
v="atm" />
|
||||
<tag
|
||||
k="mapswithme:geom_type"
|
||||
v="GEOM_POINT" />
|
||||
</node>
|
||||
)";
|
||||
// TODO(mgsergio): Unkomment when creation is required.
|
||||
// UNIT_TEST(FeatureType_FromXMLAndBackToXML)
|
||||
// {
|
||||
// auto const xml = R"(<?xml version="1.0"?>
|
||||
// <node
|
||||
// lat="55.7978998"
|
||||
// lon="37.474528"
|
||||
// timestamp="2015-11-27T21:13:32Z">
|
||||
// <tag
|
||||
// k="name"
|
||||
// v="Gorki Park" />
|
||||
// <tag
|
||||
// k="name:en"
|
||||
// v="Gorki Park" />
|
||||
// <tag
|
||||
// k="name:ru"
|
||||
// v="Парк Горького" />
|
||||
// <tag
|
||||
// k="addr:housenumber"
|
||||
// v="10" />
|
||||
// <tag
|
||||
// k="opening_hours"
|
||||
// v="Mo-Fr 08:15-17:30" />
|
||||
// <tag
|
||||
// k="amenity"
|
||||
// v="atm" />
|
||||
// <tag
|
||||
// k="mapswithme:geom_type"
|
||||
// v="GEOM_POINT" />
|
||||
// </node>
|
||||
// )";
|
||||
|
||||
auto const feature = FeatureType::FromXML(xml);
|
||||
auto const xmlFeature = feature.ToXML();
|
||||
// auto const feature = FeatureType::FromXML(xml);
|
||||
// auto const xmlFeature = feature.ToXML();
|
||||
|
||||
stringstream sstr;
|
||||
xmlFeature.Save(sstr);
|
||||
// stringstream sstr;
|
||||
// xmlFeature.Save(sstr);
|
||||
|
||||
CompareFeatureXML(xml, sstr.str());
|
||||
}
|
||||
// CompareFeatureXML(xml, sstr.str());
|
||||
// }
|
||||
|
|
|
@ -40,147 +40,146 @@ namespace
|
|||
{
|
||||
string GetEditorFilePath() { return GetPlatform().WritablePathForFile(kEditorXMLFileName); }
|
||||
// TODO(mgsergio): Replace hard-coded value with reading from file.
|
||||
static unordered_set<TStringPair, boost::hash<TStringPair>> const gConvertibleTypepairs = {
|
||||
{"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"}};
|
||||
static unordered_set<string> const gEditableTypes = {
|
||||
{"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"}};
|
||||
|
||||
TStringPair MapsmeTypeToPair(string const & mapseType)
|
||||
template <typename TIterator>
|
||||
bool HasAtLeastOneEditableType(TIterator from, TIterator const to)
|
||||
{
|
||||
vector<string> result(strings::SimpleTokenizer(mapseType, "|"), strings::SimpleTokenizer());
|
||||
// TODO(mgsergio): Support only one type in the first version.
|
||||
ASSERT_EQUAL(result.size(), 2, ("Too many parts in type string."));
|
||||
return {result[0], result[1]};
|
||||
}
|
||||
|
||||
bool IsTypeTag(TStringPair const & tag)
|
||||
{
|
||||
return gConvertibleTypepairs.find(tag) != end(gConvertibleTypepairs);
|
||||
while (from != to)
|
||||
{
|
||||
auto const & type = classif().GetReadableObjectName(*from++);
|
||||
if (gEditableTypes.find(type) != end(gEditableTypes))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -232,24 +231,26 @@ void Editor::LoadMapEdits()
|
|||
|
||||
for (auto const & section : sections)
|
||||
{
|
||||
for (xml_node node : mwm.child(section.second).children("node"))
|
||||
for (auto const nodeOrWay : mwm.child(section.second).select_nodes("node|way"))
|
||||
{
|
||||
try
|
||||
{
|
||||
XMLFeature const xml(node);
|
||||
XMLFeature const xml(nodeOrWay.node());
|
||||
FeatureID const fid(id, xml.GetOffset());
|
||||
FeatureTypeInfo fti;
|
||||
|
||||
if (xml.GetGeomType() != DebugPrint(feature::GEOM_POINT))
|
||||
{
|
||||
// TODO(mgsergio): Check if feature can be read.
|
||||
fti.m_feature = m_featureLoaderFn(fid);
|
||||
fti.m_feature.ApplyPatch(xml);
|
||||
}
|
||||
else
|
||||
{
|
||||
fti.m_feature = FeatureType::FromXML(xml);
|
||||
}
|
||||
/// TODO(mgsergio): uncomment when feature creating will
|
||||
/// be required
|
||||
// if (xml.GetType() != XMLFeature::Type::Way)
|
||||
// {
|
||||
// TODO(mgsergio): Check if feature can be read.
|
||||
fti.m_feature = m_featureLoaderFn(fid);
|
||||
fti.m_feature.ApplyPatch(xml);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// fti.m_feature = FeatureType::FromXML(xml);
|
||||
// }
|
||||
|
||||
fti.m_feature.SetID(fid);
|
||||
|
||||
|
@ -260,16 +261,15 @@ void Editor::LoadMapEdits()
|
|||
fti.m_uploadError = xml.GetUploadError();
|
||||
fti.m_status = section.first;
|
||||
|
||||
/// Install edited feature back to editor.
|
||||
/// This instruction should be after calling m_featureLoaderFn cause
|
||||
/// it'll try to return feature from editor first and if
|
||||
/// it can't read it from disk.
|
||||
/// Call to m_featureLoaderFn indirectly tries to load feature by
|
||||
/// it's ID from the editor's m_features.
|
||||
/// That's why insertion into m_features should go AFTER call to m_featureLoaderFn.
|
||||
m_features[id][fid.m_index] = fti;
|
||||
}
|
||||
catch (editor::XMLFeatureError const & ex)
|
||||
{
|
||||
ostringstream s;
|
||||
node.print(s, " ");
|
||||
nodeOrWay.node().print(s, " ");
|
||||
LOG(LERROR, (ex.what(), "Can't create XMLFeature in section", section.second, s.str()));
|
||||
}
|
||||
} // for nodes
|
||||
|
@ -314,10 +314,10 @@ void Editor::Save(string const & fullFilePath) const
|
|||
}
|
||||
switch (fti.m_status)
|
||||
{
|
||||
case FeatureStatus::Deleted: VERIFY(xf.AttachToParentNode(deleted), ()); break;
|
||||
case FeatureStatus::Modified: VERIFY(xf.AttachToParentNode(modified), ()); break;
|
||||
case FeatureStatus::Created: VERIFY(xf.AttachToParentNode(created), ()); break;
|
||||
case FeatureStatus::Untouched: CHECK(false, ("Not edited features shouldn't be here."));
|
||||
case FeatureStatus::Deleted: VERIFY(xf.AttachToParentNode(deleted), ()); break;
|
||||
case FeatureStatus::Modified: VERIFY(xf.AttachToParentNode(modified), ()); break;
|
||||
case FeatureStatus::Created: VERIFY(xf.AttachToParentNode(created), ()); break;
|
||||
case FeatureStatus::Untouched: CHECK(false, ("Not edited features shouldn't be here."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -444,37 +444,12 @@ bool Editor::GetEditedFeature(MwmSet::MwmId const & mwmId, uint32_t offset, Feat
|
|||
vector<Metadata::EType> Editor::EditableMetadataForType(FeatureType const & feature) const
|
||||
{
|
||||
// TODO(mgsergio): Load editable fields into memory from XML and query them here.
|
||||
|
||||
TTypes types;
|
||||
feature.ForEachType([&types](uint32_t type) { types.push_back(type); });
|
||||
// TODO(mgsergio): Only one-typed features are now supported.
|
||||
if (types.size() != 1)
|
||||
return {};
|
||||
|
||||
// Enable opening hours for the first release.
|
||||
auto const & tags = GetTagsForType(types[0]);
|
||||
if (tags.size() == 1 && IsTypeTag(tags[0]))
|
||||
if (HasAtLeastOneEditableType(begin(types), end(types)))
|
||||
return {Metadata::FMD_OPEN_HOURS};
|
||||
return {};
|
||||
}
|
||||
|
||||
Editor::TTypes Editor::GetTypesOfFeature(editor::XMLFeature const & xmlFeature) const
|
||||
{
|
||||
TTags typeTags;
|
||||
xmlFeature.ForEachTag([&typeTags](string const & key, string const & value)
|
||||
{
|
||||
if (IsTypeTag({key, value}))
|
||||
typeTags.emplace_back(key, value);
|
||||
});
|
||||
ASSERT_GREATER(typeTags.size(), 0, ("Cannot determine type. Please review your code."));
|
||||
// TODO(mgsergio): Only one-typed features are supported in the first version.
|
||||
ASSERT_EQUAL(typeTags.size(), 1, ("Too many types for a feature."));
|
||||
return {classif().GetTypeByPathSafe({typeTags[0].first, typeTags[0].second})};
|
||||
}
|
||||
|
||||
Editor::TTags Editor::GetTagsForType(uint32_t type) const
|
||||
{
|
||||
// TODO(mgsergio): Only one-typed features are supported in the first version.
|
||||
return {MapsmeTypeToPair(classif().GetFullObjectName(type))};
|
||||
}
|
||||
} // namespace osm
|
||||
|
|
|
@ -21,8 +21,6 @@ class Index;
|
|||
|
||||
namespace osm
|
||||
{
|
||||
using TStringPair = pair<string, string>;
|
||||
|
||||
class Editor final
|
||||
{
|
||||
Editor() = default;
|
||||
|
@ -41,7 +39,6 @@ public:
|
|||
};
|
||||
|
||||
using TTypes = vector<uint32_t>;
|
||||
using TTags = vector<TStringPair>;
|
||||
|
||||
static Editor & Instance();
|
||||
|
||||
|
@ -77,10 +74,6 @@ public:
|
|||
|
||||
vector<feature::Metadata::EType> EditableMetadataForType(FeatureType const & feature) const;
|
||||
|
||||
TTypes GetTypesOfFeature(editor::XMLFeature const & xmlFeature) const;
|
||||
|
||||
TTags GetTagsForType(uint32_t type) const;
|
||||
|
||||
private:
|
||||
// TODO(AlexZ): Synchronize Save call/make it on a separate thread.
|
||||
void Save(string const & fullFilePath) const;
|
||||
|
@ -110,12 +103,12 @@ private:
|
|||
|
||||
inline string DebugPrint(Editor::FeatureStatus fs)
|
||||
{
|
||||
switch(fs)
|
||||
switch (fs)
|
||||
{
|
||||
case Editor::FeatureStatus::Untouched: return "Untouched";
|
||||
case Editor::FeatureStatus::Deleted: return "Deleted";
|
||||
case Editor::FeatureStatus::Modified: return "Modified";
|
||||
case Editor::FeatureStatus::Created: return "Created";
|
||||
case Editor::FeatureStatus::Untouched: return "Untouched";
|
||||
case Editor::FeatureStatus::Deleted: return "Deleted";
|
||||
case Editor::FeatureStatus::Modified: return "Modified";
|
||||
case Editor::FeatureStatus::Created: return "Created";
|
||||
};
|
||||
}
|
||||
} // namespace osm
|
||||
|
|
Loading…
Add table
Reference in a new issue