diff --git a/data/osm_test_data/building_address.osm b/data/osm_test_data/building_address.osm
new file mode 100644
index 0000000000..b2741b3eef
--- /dev/null
+++ b/data/osm_test_data/building_address.osm
@@ -0,0 +1,232 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/generator/addresses_collector.cpp b/generator/addresses_collector.cpp
index 911b9544d4..54ba1cf34d 100644
--- a/generator/addresses_collector.cpp
+++ b/generator/addresses_collector.cpp
@@ -22,12 +22,8 @@ uint64_t GetOsmID(FeatureBuilder const & fb)
AddressesHolder::AddressInfo FromFB(FeatureBuilder const & fb)
{
- return {
- fb.GetParams().house.Get(),
- std::string(fb.GetAddressData().Get(AddressData::Type::Street)),
- std::string(fb.GetAddressData().Get(AddressData::Type::Postcode)),
- {}
- };
+ auto const & params = fb.GetParams();
+ return { params.house.Get(), std::string(params.GetStreet()), std::string(params.GetPostcode()), {} };
}
void LogWarning(std::string const & msg, uint64_t id)
@@ -114,7 +110,7 @@ bool AddressesHolder::Update(feature::FeatureBuilder & fb) const
if (!info.m_street.empty())
LogWarning("Different streets", id);
else
- params.AddStreet(i->second.m_street);
+ params.SetStreet(i->second.m_street);
}
if (!i->second.m_postcode.empty() && i->second.m_postcode != info.m_postcode)
@@ -122,7 +118,7 @@ bool AddressesHolder::Update(feature::FeatureBuilder & fb) const
if (!info.m_postcode.empty())
LogWarning("Different postcodes", id);
else
- params.AddPostcode(i->second.m_postcode);
+ params.SetPostcode(i->second.m_postcode);
}
return true;
diff --git a/generator/boundary_postcodes_enricher.cpp b/generator/boundary_postcodes_enricher.cpp
index a5851ad6b2..25d93b542a 100644
--- a/generator/boundary_postcodes_enricher.cpp
+++ b/generator/boundary_postcodes_enricher.cpp
@@ -33,11 +33,12 @@ BoundaryPostcodesEnricher::BoundaryPostcodesEnricher(std::string const & boundar
void BoundaryPostcodesEnricher::Enrich(feature::FeatureBuilder & fb) const
{
- if (fb.HasPostcode() || !ftypes::IsAddressObjectChecker::Instance()(fb.GetTypes()))
+ auto & params = fb.GetParams();
+ if (!params.GetPostcode().empty() || !ftypes::IsAddressObjectChecker::Instance()(fb.GetTypes()))
return;
auto const hasName = !fb.GetMultilangName().IsEmpty();
- auto const hasHouseNumber = !fb.GetParams().house.IsEmpty();
+ auto const hasHouseNumber = !params.house.IsEmpty();
// We do not save postcodes for unnamed features without house number to reduce amount of data.
// For example with this filter we have +100Kb for Turkey_Marmara Region_Istanbul.mwm, without
@@ -52,7 +53,7 @@ void BoundaryPostcodesEnricher::Enrich(feature::FeatureBuilder & fb) const
if (!m_boundaryPostcodes[i].second.Contains(center))
return false;
- fb.SetPostcode(m_boundaryPostcodes[i].first);
+ params.SetPostcode(m_boundaryPostcodes[i].first);
return true;
});
}
diff --git a/generator/feature_builder.cpp b/generator/feature_builder.cpp
index 3d0842ff7c..b23b5961d6 100644
--- a/generator/feature_builder.cpp
+++ b/generator/feature_builder.cpp
@@ -161,17 +161,6 @@ void FeatureBuilder::ResetGeometry()
m_limitRect.MakeEmpty();
}
-bool FeatureBuilder::HasPostcode() const
-{
- return m_params.GetMetadata().Has(Metadata::FMD_POSTCODE);
-}
-
-void FeatureBuilder::SetPostcode(std::string const & postcode)
-{
- m_params.GetMetadata().Set(Metadata::FMD_POSTCODE, postcode);
- m_params.AddPostcode(postcode);
-}
-
bool FeatureBuilder::RemoveInvalidTypes()
{
if (!m_params.FinishAddingTypes())
diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp
index 0cef136ae7..3df2005b8d 100644
--- a/generator/feature_builder.hpp
+++ b/generator/feature_builder.hpp
@@ -157,14 +157,10 @@ public:
std::string_view GetName(int8_t lang = StringUtf8Multilang::kDefaultCode) const;
StringUtf8Multilang const & GetMultilangName() const { return m_params.name; }
uint8_t GetRank() const { return m_params.rank; }
- AddressData const & GetAddressData() const { return m_params.GetAddressData(); }
Metadata const & GetMetadata() const { return m_params.GetMetadata(); }
Metadata & GetMetadata() { return m_params.GetMetadata(); }
- bool HasPostcode() const;
- void SetPostcode(std::string const & postcode);
-
// To work with types and names based on drawing.
// Check classificator types for their compatibility with feature geometry type.
// Need to call when using any classificator types manipulating.
diff --git a/generator/feature_sorter.cpp b/generator/feature_sorter.cpp
index 2950aae8ff..aea8bae70a 100644
--- a/generator/feature_sorter.cpp
+++ b/generator/feature_sorter.cpp
@@ -292,7 +292,7 @@ public:
m_boundaryPostcodesEnricher.Enrich(fb);
// 2. Write address to a file (with possible updated postcode above).
- fb.GetAddressData().SerializeForMwmTmp(*m_addrFile);
+ fb.GetParams().SerializeAddress(*m_addrFile);
// 3. Save metadata.
if (!fb.GetMetadata().Empty())
diff --git a/generator/generator_tests/osm_type_test.cpp b/generator/generator_tests/osm_type_test.cpp
index 308501a785..bed19d7486 100644
--- a/generator/generator_tests/osm_type_test.cpp
+++ b/generator/generator_tests/osm_type_test.cpp
@@ -196,8 +196,6 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Address)
TEST_EQUAL(params.house.Get(), "42", ());
}
- using AddrType = feature::AddressData::Type;
-
{
Tags const tags = {
{ "addr:conscriptionnumber", "223" },
@@ -215,8 +213,8 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Address)
TEST(params.IsTypeExist(addrType), ());
TEST_EQUAL(params.house.Get(), "223/5", ());
- TEST_EQUAL(params.GetAddressData().Get(AddrType::Street), "Řetězová", ());
- TEST_EQUAL(params.GetAddressData().Get(AddrType::Postcode), "11000", ());
+ TEST_EQUAL(params.GetStreet(), "Řetězová", ());
+ TEST_EQUAL(params.GetPostcode(), "11000", ());
}
{
@@ -240,8 +238,8 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Address)
TEST(params.IsTypeExist(GetType({"internet_access", "wlan"})), ());
TEST_EQUAL(params.house.Get(), "41", ());
- TEST_EQUAL(params.GetAddressData().Get(AddrType::Street), "Leutschenbachstrasse", ());
- TEST_EQUAL(params.GetAddressData().Get(AddrType::Postcode), "8050", ());
+ TEST_EQUAL(params.GetStreet(), "Leutschenbachstrasse", ());
+ TEST_EQUAL(params.GetPostcode(), "8050", ());
}
{
@@ -261,8 +259,8 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Address)
TEST(params.IsTypeExist(addrType), ());
TEST_EQUAL(params.house.Get(), "Rozemnieki", ());
- TEST(params.GetAddressData().Get(AddrType::Street).empty(), ());
- TEST_EQUAL(params.GetAddressData().Get(AddrType::Postcode), "LV-5695", ());
+ TEST(params.GetStreet().empty(), ());
+ TEST_EQUAL(params.GetPostcode(), "LV-5695", ());
}
}
diff --git a/generator/generator_tests/raw_generator_test.cpp b/generator/generator_tests/raw_generator_test.cpp
index 33831544a2..4039066f34 100644
--- a/generator/generator_tests/raw_generator_test.cpp
+++ b/generator/generator_tests/raw_generator_test.cpp
@@ -4,6 +4,7 @@
#include "generator/descriptions_section_builder.hpp"
#include "search/cities_boundaries_table.hpp"
+#include "search/house_to_street_table.hpp"
#include "routing/index_graph_loader.hpp"
#include "routing/maxspeeds.hpp"
@@ -415,6 +416,59 @@ UNIT_CLASS_TEST(TestRawGenerator, Postcode_Relations)
TEST_EQUAL(count, 2, ());
}
+UNIT_CLASS_TEST(TestRawGenerator, Building_Address)
+{
+ std::string const mwmName = "Address";
+ BuildFB("./data/osm_test_data/building_address.osm", mwmName, false /* makeWorld */);
+
+ size_t count = 0;
+ ForEachFB(mwmName, [&](feature::FeatureBuilder const & fb)
+ {
+ if (ftypes::IsBuildingChecker::Instance()(fb.GetTypes()))
+ {
+ auto const & params = fb.GetParams();
+ TEST_EQUAL(params.GetStreet(), "Airport Boulevard", ());
+ TEST_EQUAL(params.GetPostcode(), "819666", ());
+ ++count;
+ }
+ });
+ TEST_EQUAL(count, 1, ());
+
+ BuildFeatures(mwmName);
+ BuildSearch(mwmName);
+
+ FrozenDataSource dataSource;
+ auto const res = dataSource.RegisterMap(platform::LocalCountryFile::MakeTemporary(GetMwmPath(mwmName)));
+ CHECK_EQUAL(res.second, MwmSet::RegResult::Success, ());
+
+ FeaturesLoaderGuard guard(dataSource, res.first);
+
+ count = 0;
+ size_t const numFeatures = guard.GetNumFeatures();
+ for (size_t id = 0; id < numFeatures; ++id)
+ {
+ auto ft = guard.GetFeatureByIndex(id);
+ if (ftypes::IsBuildingChecker::Instance()(*ft))
+ {
+ TEST_EQUAL(ft->GetHouseNumber(), "78", ());
+ TEST_EQUAL(GetPostcode(*ft), "819666", ());
+ ++count;
+
+ auto value = guard.GetHandle().GetValue();
+ if (!value->m_house2street)
+ value->m_house2street = search::LoadHouseToStreetTable(*value);
+
+ auto res = value->m_house2street->Get(id);
+ TEST(res, ());
+
+ auto street = guard.GetFeatureByIndex(res->m_streetId);
+ TEST_EQUAL(street->GetName(StringUtf8Multilang::kDefaultCode), "Airport Boulevard", ());
+ }
+ }
+
+ TEST_EQUAL(count, 1, ());
+}
+
// https://github.com/organicmaps/organicmaps/issues/4974
UNIT_TEST(Relation_Wiki)
{
@@ -896,8 +950,9 @@ UNIT_CLASS_TEST(TestRawGenerator, Addr_Interpolation)
if (fb.GetGeomType() == feature::GeomType::Line && fb.HasType(addrType))
{
++count;
- TEST_EQUAL(fb.GetParams().ref, "3602:3800", ());
- TEST_EQUAL(fb.GetAddressData().Get(feature::AddressData::Type::Street), "Juncal", ());
+ auto const & params = fb.GetParams();
+ TEST_EQUAL(params.ref, "3602:3800", ());
+ TEST_EQUAL(params.GetStreet(), "Juncal", ());
}
});
@@ -919,14 +974,15 @@ UNIT_CLASS_TEST(TestRawGenerator, NamedAddress)
TEST_EQUAL(fb.GetGeomType(), feature::GeomType::Point, ());
TEST(fb.HasType(addrType), ());
- TEST(fb.GetParams().house.IsEmpty() != fb.GetName().empty(), ());
- if (fb.GetParams().house.IsEmpty())
+ auto const & params = fb.GetParams();
+ TEST(params.house.IsEmpty() != fb.GetName().empty(), ());
+ if (params.house.IsEmpty())
++withName;
else
++withNumber;
- TEST(fb.GetAddressData().Get(feature::AddressData::Type::Street).empty(), ());
- TEST_EQUAL(fb.GetAddressData().Get(feature::AddressData::Type::Postcode), "LV-5695", ());
+ TEST(params.GetStreet().empty(), ());
+ TEST_EQUAL(params.GetPostcode(), "LV-5695", ());
});
TEST_EQUAL(withName, 3, ());
diff --git a/generator/generator_tests_support/test_feature.cpp b/generator/generator_tests_support/test_feature.cpp
index 7e5495a864..085ab50e29 100644
--- a/generator/generator_tests_support/test_feature.cpp
+++ b/generator/generator_tests_support/test_feature.cpp
@@ -141,7 +141,7 @@ void TestFeature::Serialize(FeatureBuilder & fb) const
});
if (!m_postcode.empty())
- fb.SetPostcode(m_postcode);
+ fb.GetParams().SetPostcode(m_postcode);
}
// TestPlace -------------------------------------------------------------------------------------
@@ -309,7 +309,7 @@ void TestPOI::Serialize(FeatureBuilder & fb) const
params.AddHouseNumber(m_houseNumber);
if (!m_streetName.empty())
- params.AddStreet(m_streetName);
+ params.SetStreet(m_streetName);
}
string TestPOI::ToDebugString() const
@@ -398,7 +398,7 @@ void TestBuilding::Serialize(FeatureBuilder & fb) const
if (!m_houseNumber.empty())
params.AddHouseNumber(m_houseNumber);
if (!m_streetName.empty())
- params.AddStreet(m_streetName);
+ params.SetStreet(m_streetName);
if (m_type == 0)
fb.AddType(classif().GetTypeByPath({"building"}));
diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp
index 685a2f6494..b6552512fa 100644
--- a/generator/osm2type.cpp
+++ b/generator/osm2type.cpp
@@ -1069,8 +1069,9 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params,
namesExtractor.Finish();
// Stage3: Process base feature tags.
- std::string houseName, houseNumber;
- TagProcessor(p).ApplyRules({
+ std::string houseName, houseNumber, addrPostcode;
+ TagProcessor(p).ApplyRules(
+ {
{"addr:housenumber", "*",
[&houseNumber](string & k, string & v) {
houseNumber = std::move(v);
@@ -1085,13 +1086,21 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params,
}},
{"addr:street", "*",
[¶ms](string & k, string & v) {
- params.AddStreet(v);
+ params.SetStreet(std::move(v));
k.clear();
v.clear();
}},
- {"addr:postcode", "*",
- [¶ms](string & k, string & v) {
- params.AddPostcode(v);
+ {"addr:postcode", "*", [&addrPostcode](string & k, string & v)
+ {
+ addrPostcode = std::move(v);
+ k.clear();
+ v.clear();
+ }},
+ {"postal_code", "*", [&addrPostcode](string & k, string & v)
+ {
+ addrPostcode = std::move(v);
+ k.clear();
+ v.clear();
}},
{"population", "*",
[¶ms](string & k, string & v) {
@@ -1120,6 +1129,7 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params,
}},
});
+ params.SetPostcode(addrPostcode);
params.SetHouseNumberAndHouseName(std::move(houseNumber), std::move(houseName));
// Stage4: Match tags to classificator feature types via mapcss-mapping.csv.
diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp
index cfa29a6262..3a1d1c73bd 100644
--- a/indexer/feature_data.cpp
+++ b/indexer/feature_data.cpp
@@ -523,17 +523,31 @@ uint32_t FeatureParams::GetTypeForIndex(uint32_t i)
return classif().GetTypeForIndex(i);
}
-void FeatureBuilderParams::AddStreet(string s)
+void FeatureBuilderParams::SetStreet(string s)
{
+ if (s.empty())
+ return;
+
// Replace \n with spaces because we write addresses to txt file.
replace(s.begin(), s.end(), '\n', ' ');
- m_addrTags.Add(AddressData::Type::Street, s);
+ m_addrTags.Set(AddressData::Type::Street, s);
}
-void FeatureBuilderParams::AddPostcode(string const & s)
+std::string_view FeatureBuilderParams::GetStreet() const
{
- m_addrTags.Add(AddressData::Type::Postcode, s);
+ return m_addrTags.Get(AddressData::Type::Street);
+}
+
+void FeatureBuilderParams::SetPostcode(string const & s)
+{
+ if (!s.empty())
+ m_metadata.Set(Metadata::FMD_POSTCODE, s);
+}
+
+std::string_view FeatureBuilderParams::GetPostcode() const
+{
+ return m_metadata.Get(Metadata::FMD_POSTCODE);
}
namespace
@@ -607,8 +621,8 @@ string DebugPrint(FeatureBuilderParams const & p)
{
ostringstream oss;
oss << "ReversedGeometry: " << (p.GetReversedGeometry() ? "true" : "false") << "; ";
- oss << DebugPrint(p.GetMetadata()) << "; ";
- oss << DebugPrint(p.GetAddressData()) << "; ";
+ oss << DebugPrint(p.m_metadata) << "; ";
+ oss << DebugPrint(p.m_addrTags) << "; ";
oss << DebugPrint(static_cast(p));
return oss.str();
}
diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp
index 8929212850..00199c4a99 100644
--- a/indexer/feature_data.hpp
+++ b/indexer/feature_data.hpp
@@ -7,15 +7,10 @@
#include "coding/string_utf8_multilang.hpp"
#include "coding/value_opt_string.hpp"
-#include "geometry/point2d.hpp"
-
#include
#include
-#include
-#include
#include
#include
-#include
#include
struct FeatureParamsBase;
@@ -301,6 +296,8 @@ public:
/// @todo Make protected and update EditableMapObject code.
Types m_types;
+ friend std::string DebugPrint(FeatureParams const & p);
+
private:
using Base = FeatureParamsBase;
@@ -326,17 +323,23 @@ public:
m_reversedGeometry = rhs.m_reversedGeometry;
}
- /// Used to store address to temporary TEMP_ADDR_FILE_TAG section.
- void AddStreet(std::string s);
- void AddPostcode(std::string const & s);
+ /// @name Used to store address to temporary TEMP_ADDR_FILE_TAG section.
+ /// @{
+ void SetStreet(std::string s);
+ std::string_view GetStreet() const;
+
+ template void SerializeAddress(TSink & sink) const
+ {
+ m_addrTags.SerializeForMwmTmp(sink);
+ }
+ /// @}
+
+ void SetPostcode(std::string const & s);
+ std::string_view GetPostcode() const;
- feature::AddressData const & GetAddressData() const { return m_addrTags; }
feature::Metadata const & GetMetadata() const { return m_metadata; }
feature::Metadata & GetMetadata() { return m_metadata; }
- void SetMetadata(feature::Metadata && metadata) { m_metadata = std::move(metadata); }
- void ClearMetadata() { SetMetadata({}); }
-
template
void Write(Sink & sink) const
{
@@ -359,11 +362,10 @@ public:
/// @return true If any inconsistency was found here.
bool RemoveInconsistentTypes();
+ friend std::string DebugPrint(FeatureBuilderParams const & p);
+
private:
bool m_reversedGeometry = false;
feature::Metadata m_metadata;
feature::AddressData m_addrTags;
};
-
-std::string DebugPrint(FeatureParams const & p);
-std::string DebugPrint(FeatureBuilderParams const & p);
diff --git a/indexer/feature_meta.cpp b/indexer/feature_meta.cpp
index 01e3fb98a5..5b2017cd25 100644
--- a/indexer/feature_meta.cpp
+++ b/indexer/feature_meta.cpp
@@ -95,11 +95,9 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType)
outType = Metadata::FMD_TURN_LANES_BACKWARD;
else if (k == "email" || k == "contact:email")
outType = Metadata::FMD_EMAIL;
-
- // https://wiki.openstreetmap.org/wiki/Key:postal_code
- else if (k == "addr:postcode" || k == "postal_code")
+ // Process only _main_ tag here, needed for editor ser/des. Actual postcode parsing happens in GetNameAndType.
+ else if (k == "addr:postcode")
outType = Metadata::FMD_POSTCODE;
-
else if (k == "wikipedia")
outType = Metadata::FMD_WIKIPEDIA;
else if (k == "wikimedia_commons")
@@ -259,10 +257,8 @@ string DebugPrint(Metadata const & metadata)
return res;
}
-string DebugPrint(feature::AddressData const & addressData)
+string DebugPrint(AddressData const & addressData)
{
- return std::string("AddressData [")
- .append("Street = \"").append(addressData.Get(AddressData::Type::Street)).append("\"; ")
- .append("Postcode = \"").append(addressData.Get(AddressData::Type::Postcode)).append("\"]");
+ return string("AddressData { Street = \"").append(addressData.Get(AddressData::Type::Street)) + "\" }";
}
} // namespace feature
diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp
index c83ee0cc77..1cfbba4dac 100644
--- a/indexer/feature_meta.hpp
+++ b/indexer/feature_meta.hpp
@@ -179,12 +179,11 @@ public:
enum class Type : uint8_t
{
Street,
- Postcode
};
- void Add(Type type, std::string const & s)
+ // Store single value only.
+ void Set(Type type, std::string const & s)
{
- // Store single value only.
MetadataBase::Set(base::Underlying(type), s);
}
diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp
index bfdae100b2..bf7f9167b9 100644
--- a/search/search_integration_tests/processor_test.cpp
+++ b/search/search_integration_tests/processor_test.cpp
@@ -127,7 +127,7 @@ public:
TestStreet::Serialize(fb);
if (!m_street.empty())
- fb.GetParams().AddStreet(m_street);
+ fb.GetParams().SetStreet(m_street);
}
private: