Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorygorshenin <mipt.vi002@gmail.com>2016-09-08 19:05:37 +0300
committerGitHub <noreply@github.com>2016-09-08 19:05:37 +0300
commite383c53c4606372337973eca9d750c55e973d398 (patch)
treec7bbce0008d6694a1db4aec56e3e3786e98fba51 /indexer
parent93baffbcb2681df9065c7e4bf758b9a7451524a1 (diff)
parent0ab1c3472d431302c31c2be33b33ca456c60a33b (diff)
Merge pull request #4229 from milchakov/MAPSME-2292_localized_names_part3
[editor][ios][android] localized names part 3
Diffstat (limited to 'indexer')
-rw-r--r--indexer/editable_map_object.cpp177
-rw-r--r--indexer/editable_map_object.hpp59
-rw-r--r--indexer/indexer_tests/editable_map_object_test.cpp309
3 files changed, 526 insertions, 19 deletions
diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp
index e7866b6a12..f11296d0be 100644
--- a/indexer/editable_map_object.cpp
+++ b/indexer/editable_map_object.cpp
@@ -13,6 +13,8 @@
namespace
{
+size_t const kFakeNamesCount = 2;
+
bool ExtractName(StringUtf8Multilang const & names, int8_t const langCode,
vector<osm::LocalizedName> & result)
{
@@ -70,6 +72,103 @@ bool IsProtocolSpecified(string const & website)
{
return GetProtocolNameLength(website) > 0;
}
+osm::FakeNames MakeFakeSource(StringUtf8Multilang const & source,
+ vector<int8_t> const & mwmLanguages, StringUtf8Multilang & fakeSource)
+{
+ string defaultName;
+ // Fake names works for mono language (official) speaking countries-only.
+ if (mwmLanguages.size() != 1 || !source.GetString(StringUtf8Multilang::kDefaultCode, defaultName))
+ {
+ return {};
+ }
+
+ osm::FakeNames fakeNames;
+ // Mwm name has higher priority then English name.
+ array<int8_t, kFakeNamesCount> fillCandidates = {{mwmLanguages.front(), StringUtf8Multilang::kEnglishCode}};
+ fakeSource = source;
+
+ string tempName;
+ for (auto const code : fillCandidates)
+ {
+ if (!source.GetString(code, tempName))
+ {
+ tempName = defaultName;
+ fakeSource.AddString(code, defaultName);
+ }
+
+ fakeNames.m_names.emplace_back(code, tempName);
+ }
+
+ fakeNames.m_defaultName = defaultName;
+
+ return fakeNames;
+}
+
+// Tries to set default name from the localized name. Returns false when there's no such localized name.
+bool TryToFillDefaultNameFromCode(int8_t const code, StringUtf8Multilang & names)
+{
+ string newDefaultName;
+ if (code != StringUtf8Multilang::kUnsupportedLanguageCode)
+ names.GetString(code, newDefaultName);
+
+ // Default name can not be empty.
+ if (!newDefaultName.empty())
+ {
+ names.AddString(StringUtf8Multilang::kDefaultCode, newDefaultName);
+ return true;
+ }
+
+ return false;
+}
+
+// Tries to set default name to any non-empty localized name.
+// This is the case when fake names were cleared.
+void TryToFillDefaultNameFromAnyLanguage(StringUtf8Multilang & names)
+{
+ names.ForEach([&names](int8_t langCode, string const & name)
+ {
+ if (name.empty() || langCode == StringUtf8Multilang::kDefaultCode)
+ return true;
+
+ names.AddString(StringUtf8Multilang::kDefaultCode, name);
+ return false;
+ });
+}
+
+void RemoveFakesFromName(osm::FakeNames const & fakeNames, StringUtf8Multilang & name)
+{
+ vector<int8_t> codesToExclude;
+ string defaultName;
+ name.GetString(StringUtf8Multilang::kDefaultCode, defaultName);
+
+ for (auto const & item : fakeNames.m_names)
+ {
+ string tempName;
+ if (!name.GetString(item.m_code, tempName))
+ continue;
+ // No need to save in case when name is empty, duplicate of default name or was not changed.
+ if (tempName.empty() || tempName == defaultName ||
+ (tempName == item.m_filledName && tempName == fakeNames.m_defaultName))
+ {
+ codesToExclude.push_back(item.m_code);
+ }
+ }
+
+ if (codesToExclude.empty())
+ return;
+
+ StringUtf8Multilang nameWithoutFakes;
+ name.ForEach([&codesToExclude, &nameWithoutFakes](int8_t langCode, string const & value)
+ {
+ auto const it = find(codesToExclude.begin(), codesToExclude.end(), langCode);
+ if (it == codesToExclude.end())
+ nameWithoutFakes.AddString(langCode, value);
+
+ return true;
+ });
+
+ name = nameWithoutFakes;
+}
} // namespace
namespace osm
@@ -112,7 +211,7 @@ vector<feature::Metadata::EType> const & EditableMapObject::GetEditableFields()
StringUtf8Multilang const & EditableMapObject::GetName() const { return m_name; }
-NamesDataSource EditableMapObject::GetNamesDataSource() const
+NamesDataSource EditableMapObject::GetNamesDataSource()
{
auto const mwmInfo = GetID().m_mwmId.GetInfo();
@@ -124,7 +223,10 @@ NamesDataSource EditableMapObject::GetNamesDataSource() const
auto const userLangCode = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm());
- return GetNamesDataSource(m_name, mwmLanguages, userLangCode);
+ StringUtf8Multilang fakeSource;
+ m_fakeNames = MakeFakeSource(m_name, mwmLanguages, fakeSource);
+
+ return GetNamesDataSource(fakeSource, mwmLanguages, userLangCode);
}
// static
@@ -190,13 +292,14 @@ void EditableMapObject::SetName(StringUtf8Multilang const & name) { m_name = nam
void EditableMapObject::SetName(string name, int8_t langCode)
{
strings::Trim(name);
- if (name.empty())
- return;
- ASSERT_NOT_EQUAL(StringUtf8Multilang::kDefaultCode, langCode,
- ("Direct editing of default name is deprecated."));
+ if (m_namesAdvancedMode)
+ {
+ m_name.AddString(langCode, name);
+ return;
+ }
- if (!Editor::Instance().OriginalFeatureHasDefaultName(GetID()))
+ if (!name.empty() && !Editor::Instance().OriginalFeatureHasDefaultName(GetID()))
{
const auto mwmInfo = GetID().m_mwmId.GetInfo();
@@ -228,6 +331,43 @@ bool EditableMapObject::CanUseAsDefaultName(int8_t const lang, vector<int8_t> co
return false;
}
+// static
+void EditableMapObject::RemoveFakeNames(FakeNames const & fakeNames, StringUtf8Multilang & name)
+{
+ if (fakeNames.m_names.empty())
+ return;
+
+ int8_t newDefaultNameCode = StringUtf8Multilang::kUnsupportedLanguageCode;
+ size_t changedCount = 0;
+ string defaultName;
+ name.GetString(StringUtf8Multilang::kDefaultCode, defaultName);
+
+ // New default name calculation priority: 1. name on mwm language, 2. english name.
+ for (auto it = fakeNames.m_names.rbegin(); it != fakeNames.m_names.rend(); ++it)
+ {
+ string tempName;
+ if (!name.GetString(it->m_code, tempName))
+ continue;
+
+ if (tempName != it->m_filledName)
+ {
+ if (!tempName.empty())
+ newDefaultNameCode = it->m_code;
+
+ ++changedCount;
+ }
+ }
+
+ // If all previously filled fake names were changed - try to change the default name.
+ if (changedCount == fakeNames.m_names.size())
+ {
+ if (!TryToFillDefaultNameFromCode(newDefaultNameCode, name))
+ TryToFillDefaultNameFromAnyLanguage(name);
+ }
+
+ RemoveFakesFromName(fakeNames, name);
+}
+
void EditableMapObject::SetMercator(m2::PointD const & center) { m_mercator = center; }
void EditableMapObject::SetType(uint32_t featureType)
@@ -357,6 +497,29 @@ void EditableMapObject::SetOpeningHours(string const & openingHours)
void EditableMapObject::SetPointType() { m_geomType = feature::EGeomType::GEOM_POINT; }
+
+void EditableMapObject::RemoveBlankNames()
+{
+ StringUtf8Multilang nameWithoutBlanks;
+ m_name.ForEach([&nameWithoutBlanks](int8_t langCode, string const & name)
+ {
+ if (!name.empty())
+ nameWithoutBlanks.AddString(langCode, name);
+
+ return true;
+ });
+
+ m_name = nameWithoutBlanks;
+}
+
+void EditableMapObject::RemoveNeedlessNames()
+{
+ if (!IsNamesAdvancedModeEnabled())
+ RemoveFakeNames(m_fakeNames, m_name);
+
+ RemoveBlankNames();
+}
+
// static
bool EditableMapObject::ValidateBuildingLevels(string const & buildingLevels)
{
diff --git a/indexer/editable_map_object.hpp b/indexer/editable_map_object.hpp
index d033bc3d04..0ae8e39714 100644
--- a/indexer/editable_map_object.hpp
+++ b/indexer/editable_map_object.hpp
@@ -38,25 +38,49 @@ struct LocalizedName
LocalizedName(int8_t code, string const & name);
LocalizedName(string const & langCode, string const & name);
- // m_code, m_lang and m_langName are defined in StringUtf8Multilang.
+ /// m_code, m_lang and m_langName are defined in StringUtf8Multilang.
int8_t const m_code;
- // Non-owning pointers to internal static char const * array.
+ /// Non-owning pointers to internal static char const * array.
char const * const m_lang;
char const * const m_langName;
string const m_name;
};
-// Class which contains vector of localized names with following priority:
-// 1. Names for Mwm languages
-// 2. User`s language name
-// 3. Other names
-// and mandatoryNamesCount - count of names which should be always shown.
+/// Class which contains vector of localized names with following priority:
+/// 1. Names for Mwm languages
+/// 2. User`s language name
+/// 3. Other names
+/// and mandatoryNamesCount - count of names which should be always shown.
struct NamesDataSource
{
vector<LocalizedName> names;
size_t mandatoryNamesCount = 0;
};
-
+
+struct FakeName
+{
+ FakeName(int8_t code, string filledName)
+ : m_code(code)
+ , m_filledName(filledName)
+ {
+ }
+
+ int8_t m_code;
+ string m_filledName;
+};
+/// Contains information about fake names which were added for user convenience.
+struct FakeNames
+{
+ void Clear()
+ {
+ m_names.clear();
+ m_defaultName.clear();
+ }
+
+ vector<FakeName> m_names;
+ string m_defaultName;
+};
+
struct LocalizedStreet
{
string m_defaultName;
@@ -78,8 +102,8 @@ public:
vector<feature::Metadata::EType> const & GetEditableFields() const;
StringUtf8Multilang const & GetName() const;
- // See comment for NamesDataSource class.
- NamesDataSource GetNamesDataSource() const;
+ /// See comment for NamesDataSource class.
+ NamesDataSource GetNamesDataSource();
LocalizedStreet const & GetStreet() const;
vector<LocalizedStreet> const & GetNearbyStreets() const;
string const & GetHouseNumber() const;
@@ -120,6 +144,13 @@ public:
/// Special mark that it's a point feature, not area or line.
void SetPointType();
+ /// Enables advanced mode with direct access to default name and disables any recalculations.
+ void EnableNamesAdvancedMode() { m_namesAdvancedMode = true; }
+ bool IsNamesAdvancedModeEnabled() const { return m_namesAdvancedMode; }
+ /// Remove blank names for advanced mode.
+ void RemoveBlankNames();
+ /// Calls RemoveBlankNames or RemoveFakeNames depending on mode.
+ void RemoveNeedlessNames();
static bool ValidateBuildingLevels(string const & buildingLevels);
static bool ValidateHouseNumber(string const & houseNumber);
@@ -129,18 +160,22 @@ public:
static bool ValidateWebsite(string const & site);
static bool ValidateEmail(string const & email);
- // Check whether langCode can be used as default name.
+ /// Check whether langCode can be used as default name.
static bool CanUseAsDefaultName(int8_t const langCode, vector<int8_t> const & nativeMwmLanguages);
- // See comment for NamesDataSource class.
+ /// See comment for NamesDataSource class.
static NamesDataSource GetNamesDataSource(StringUtf8Multilang const & source,
vector<int8_t> const & nativeMwmLanguages,
int8_t const userLanguage);
+ /// Removes fake names (which were added for user convenience) from name.
+ static void RemoveFakeNames(FakeNames const & fakeNames, StringUtf8Multilang & name);
private:
string m_houseNumber;
LocalizedStreet m_street;
vector<LocalizedStreet> m_nearbyStreets;
EditableProperties m_editableProperties;
+ FakeNames m_fakeNames;
+ bool m_namesAdvancedMode = false;
};
} // namespace osm
diff --git a/indexer/indexer_tests/editable_map_object_test.cpp b/indexer/indexer_tests/editable_map_object_test.cpp
index 7f0dae3af6..044cc8d6ab 100644
--- a/indexer/indexer_tests/editable_map_object_test.cpp
+++ b/indexer/indexer_tests/editable_map_object_test.cpp
@@ -12,6 +12,38 @@ int8_t GetLangCode(char const * ch)
{
return StringUtf8Multilang::GetLangIndex(ch);
}
+
+struct ExpectedName
+{
+ string m_lang;
+ string m_value;
+};
+
+string DebugPrint(ExpectedName const & expectedName)
+{
+ return expectedName.m_lang + ", " + expectedName.m_value;
+}
+
+void CheckExpectations(StringUtf8Multilang const & s, vector<ExpectedName> const & expectations)
+{
+ size_t counter = 0;
+ s.ForEach([&expectations, &counter](int8_t const code, string const & name) {
+ auto const it = find_if(expectations.begin(), expectations.end(), [&code](ExpectedName const & item)
+ {
+ return GetLangCode(item.m_lang.c_str()) == code;
+ });
+
+ if (it == expectations.end())
+ TEST(false, ("Unexpected language code: ", code, ". Expectations: ", expectations));
+
+ TEST_EQUAL(name, it->m_value, ());
+ ++counter;
+ return true;
+ });
+
+ TEST_EQUAL(counter, expectations.size(), ("Unexpected count of names, expected ", expectations.size(),
+ ", but turned out ", counter, ". Expectations: ", expectations));
+}
UNIT_TEST(EditableMapObject_SetWebsite)
{
@@ -289,4 +321,281 @@ UNIT_TEST(EditableMapObject_SetInternet)
setInternetAndCheck(bunkerEmo, osm::Internet::Wlan, true);
setInternetAndCheck(bunkerEmo, osm::Internet::Wlan, true);
}
+
+UNIT_TEST(EditableMapObject_RemoveFakeNames)
+{
+ EditableMapObject emo;
+ StringUtf8Multilang name;
+ osm::FakeNames fakeNames;
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Default name");
+ name.AddString(GetLangCode("en"), "Default name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Changed name");
+ name.AddString(GetLangCode("en"), "Default name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}, {"ru", "Changed name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Default name");
+ name.AddString(GetLangCode("en"), "Changed name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}, {"en", "Changed name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Changed name");
+ name.AddString(GetLangCode("en"), "Changed name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Changed name ru");
+ name.AddString(GetLangCode("en"), "Changed name en");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed name ru"}, {"en", "Changed name en"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Changed by other logic");
+ name.AddString(GetLangCode("ru"), "Default name");
+ name.AddString(GetLangCode("en"), "Changed name en");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed by other logic"}, {"en", "Changed name en"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Changed by other logic");
+ name.AddString(GetLangCode("ru"), "Changed name ru");
+ name.AddString(GetLangCode("en"), "Changed name en");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed name ru"}, {"en", "Changed name en"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Changed by other logic");
+ name.AddString(GetLangCode("ru"), "Default name");
+ name.AddString(GetLangCode("en"), "Default name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed by other logic"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "Changed name en");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Changed name en"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Changed by other logic");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "");
+ name.AddString(GetLangCode("de"), "Deutch name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Default name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Deutch name"}, {"de", "Deutch name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Test name");
+ name.AddString(GetLangCode("en"), "Default name");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Test name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}, {"ru", "Test name"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Test name changed");
+ name.AddString(GetLangCode("en"), "Default name changed");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Test name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Default name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Test name changed"}, {"en", "Default name changed"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Test name");
+ name.AddString(GetLangCode("en"), "Second test name changed");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Test name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Second test name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Default name"}, {"ru", "Test name"}, {"en", "Second test name changed"}});
+
+ name.Clear();
+ fakeNames.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "Second test name changed");
+ fakeNames.m_names.push_back({GetLangCode("ru"), "Test name"});
+ fakeNames.m_names.push_back({GetLangCode("en"), "Second test name"});
+ fakeNames.m_defaultName = "Default name";
+
+ EditableMapObject::RemoveFakeNames(fakeNames, name);
+
+ CheckExpectations(name, {{"default", "Second test name changed"}});
+}
+
+UNIT_TEST(EditableMapObject_RemoveBlankNames)
+{
+ auto const getCountOfNames = [](StringUtf8Multilang const & names) {
+ size_t counter = 0;
+ names.ForEach([&counter](int8_t const, string const &) {
+ ++counter;
+ return true;
+ });
+
+ return counter;
+ };
+
+ StringUtf8Multilang name;
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "Ru name");
+ name.AddString(GetLangCode("en"), "En name");
+ name.AddString(GetLangCode("de"), "De name");
+
+ EditableMapObject emo;
+ emo.SetName(name);
+ emo.RemoveBlankNames();
+
+ TEST_EQUAL(getCountOfNames(emo.GetName()), 4, ());
+
+ name.Clear();
+
+ name.AddString(GetLangCode("default"), "");
+ name.AddString(GetLangCode("ru"), "Ru name");
+ name.AddString(GetLangCode("en"), "En name");
+ name.AddString(GetLangCode("de"), "");
+
+ emo.SetName(name);
+ emo.RemoveBlankNames();
+
+ TEST_EQUAL(getCountOfNames(emo.GetName()), 2, ());
+
+ name.Clear();
+
+ name.AddString(GetLangCode("default"), "Default name");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "");
+ name.AddString(GetLangCode("de"), "");
+
+ emo.SetName(name);
+ emo.RemoveBlankNames();
+
+ TEST_EQUAL(getCountOfNames(emo.GetName()), 1, ());
+
+ name.Clear();
+
+ name.AddString(GetLangCode("default"), "");
+ name.AddString(GetLangCode("ru"), "");
+ name.AddString(GetLangCode("en"), "");
+ name.AddString(GetLangCode("de"), "De name");
+
+ emo.SetName(name);
+ emo.RemoveBlankNames();
+
+ TEST_EQUAL(getCountOfNames(emo.GetName()), 1, ());
+}
} // namespace