[search][android][ios] Exposed categories synonyms.

This commit is contained in:
Yuri Gorshenin 2016-09-07 12:04:07 +03:00
parent e34ff29fc1
commit e8a77fb0fb
10 changed files with 97 additions and 37 deletions

View file

@ -5,8 +5,8 @@
extern "C"
{
JNIEXPORT jobjectArray JNICALL
Java_com_mapswithme_maps_search_DisplayedCategories_nativeGet(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_search_DisplayedCategories_nativeGetKeys(JNIEnv * env, jclass clazz)
{
return jni::ToJavaStringArray(env, search::GetDisplayedCategories());
return jni::ToJavaStringArray(env, search::DisplayedCategories::GetKeys());
}
} // extern "C"

View file

@ -36,22 +36,20 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
final boolean isNightTheme = ThemeUtils.isNightTheme();
final Resources resources = fragment.getActivity().getResources();
final String[] categories = DisplayedCategories.get();
final String[] keys = DisplayedCategories.getKeys();
final int numKeys = keys.length;
final int len = categories.length;
mCategoryResIds = new int[len];
mIconResIds = new int[len];
for (int i = 0; i < len; i++)
mCategoryResIds = new int[numKeys];
mIconResIds = new int[numKeys];
for (int i = 0; i < numKeys; i++)
{
mCategoryResIds[i] = resources.getIdentifier(categories[i], "string", packageName);
if (mCategoryResIds[i] == 0)
{
throw new IllegalStateException(
"Can't get string resource id for category:" + categories[i]);
}
String key = keys[i];
String iconId = "ic_category_" + categories[i];
mCategoryResIds[i] = resources.getIdentifier(key, "string", packageName);
if (mCategoryResIds[i] == 0)
throw new IllegalStateException("Can't get string resource id for category:" + key);
String iconId = "ic_category_" + key;
if (isNightTheme)
iconId = iconId + "_night";
mIconResIds[i] = resources.getIdentifier(iconId, "drawable", packageName);

View file

@ -2,7 +2,7 @@ package com.mapswithme.maps.search;
class DisplayedCategories
{
public static String[] get() { return nativeGet(); }
public static String[] getKeys() { return nativeGetKeys(); }
private static native String[] nativeGet();
private static native String[] nativeGetKeys();
}

View file

@ -22,8 +22,12 @@ enum State
// static
int8_t const CategoriesHolder::kEnglishCode = 1;
int8_t const CategoriesHolder::kUnsupportedLocaleCode = -1;
// *NOTE* These constants should be updated when
// adding new translation to categories.txt.
// *NOTE* These constants should be updated when adding new
// translation to categories.txt. When editing, keep in mind to check
// CategoriesHolder::MapLocaleToInteger() and
// CategoriesHolder::MapIntegerToLocale() as their implementations
// highly depend on the contents of the variable.
vector<CategoriesHolder::Mapping> const CategoriesHolder::kLocaleMapping = {{"en", 1},
{"ru", 2},
{"uk", 3},
@ -111,6 +115,7 @@ void CategoriesHolder::LoadFromStream(istream & s)
{
m_type2cat.clear();
m_name2type.clear();
m_groupTranslations.clear();
State state = EParseTypes;
string line;
@ -118,7 +123,6 @@ void CategoriesHolder::LoadFromStream(istream & s)
Category cat;
vector<uint32_t> types;
vector<string> currentGroups;
multimap<string, Category::Name> groupTranslations;
Classificator const & c = classif();
@ -184,9 +188,11 @@ void CategoriesHolder::LoadFromStream(istream & s)
{
for (string const & group : currentGroups)
{
auto trans = groupTranslations.equal_range(group);
for (auto it = trans.first; it != trans.second; ++it)
cat.m_synonyms.push_back(it->second);
auto it = m_groupTranslations.find(group);
if (it == m_groupTranslations.end())
continue;
for (auto const & synonym : it->second)
cat.m_synonyms.push_back(synonym);
}
}
@ -242,7 +248,7 @@ void CategoriesHolder::LoadFromStream(istream & s)
if (currentGroups.size() == 1 && types.empty())
{
// Not a translation, but a category group definition
groupTranslations.emplace(currentGroups[0], name);
m_groupTranslations[currentGroups[0]].push_back(name);
}
else
cat.m_synonyms.push_back(name);
@ -308,6 +314,7 @@ bool CategoriesHolder::IsTypeExist(uint32_t type) const
return range.first != range.second;
}
// static
int8_t CategoriesHolder::MapLocaleToInteger(string const & locale)
{
ASSERT(!kLocaleMapping.empty(), ());
@ -338,3 +345,11 @@ int8_t CategoriesHolder::MapLocaleToInteger(string const & locale)
return kUnsupportedLocaleCode;
}
// static
string CategoriesHolder::MapIntegerToLocale(int8_t code)
{
if (code <= 0 || code > kLocaleMapping.size())
return string();
return kLocaleMapping[code - 1].m_name;
}

View file

@ -41,6 +41,8 @@ public:
int8_t m_code;
};
using GroupTranslations = unordered_map<string, vector<Category::Name>>;
private:
typedef strings::UniString StringT;
typedef multimap<uint32_t, shared_ptr<Category> > Type2CategoryContT;
@ -49,6 +51,7 @@ private:
Type2CategoryContT m_type2cat;
Name2CatContT m_name2type;
GroupTranslations m_groupTranslations;
public:
static int8_t const kEnglishCode;
@ -107,6 +110,8 @@ public:
}
}
inline GroupTranslations const & GetGroupTranslations() const { return m_groupTranslations; }
/// Search name for type with preffered locale language.
/// If no name for this language, return first (en) name.
/// @return false if no categories for type.
@ -123,9 +128,15 @@ public:
m_name2type.swap(r.m_name2type);
}
/// Converts any language locale from UI to internal integer code
// Converts any language |locale| from UI to the corresponding
// internal integer code
static int8_t MapLocaleToInteger(string const & locale);
// Returns corresponding string representation for an internal
// integer |code|. Returns an empty string in case of invalid
// |code|.
static string MapIntegerToLocale(int8_t code);
private:
void AddCategory(Category & cat, vector<uint32_t> & types);
static bool ValidKeyToken(StringT const & s);

View file

@ -18,7 +18,7 @@ static NSString * const kCellIdentifier = @"MWMSearchCategoryCell";
{
self = [super init];
if (self)
m_categories = search::GetDisplayedCategories();
m_categories = search::DisplayedCategories::GetKeys();
return self;
}

View file

@ -351,6 +351,7 @@ Framework::Framework()
m_model.SetOnMapDeregisteredCallback(bind(&Framework::OnMapDeregistered, this, _1));
LOG(LDEBUG, ("Classificator initialized"));
m_displayedCategories = make_unique<search::DisplayedCategories>(GetDefaultCategories());
// To avoid possible races - init country info getter once in constructor.
InitCountryInfoGetter();

View file

@ -24,6 +24,7 @@
#include "editor/user_stats.hpp"
#include "search/displayed_categories.hpp"
#include "search/downloader_search_callback.hpp"
#include "search/engine.hpp"
#include "search/mode.hpp"
@ -117,12 +118,15 @@ protected:
StringsBundle m_stringsBundle;
model::FeaturesFetcher m_model;
// The order matters here: DisplayedCategories may be used only when
// classificator is loaded (by |m_model|).
unique_ptr<search::DisplayedCategories> m_displayedCategories;
// The order matters here: storage::CountryInfoGetter and
// m_model::FeaturesFetcher must be initialized before
// search::Engine and, therefore, destroyed after search::Engine.
model::FeaturesFetcher m_model;
unique_ptr<storage::CountryInfoGetter> m_infoGetter;
unique_ptr<search::Engine> m_searchEngine;
@ -241,6 +245,10 @@ public:
storage::Storage & GetStorage() { return m_storage; }
storage::Storage const & GetStorage() const { return m_storage; }
search::DisplayedCategories const & GetDisplayedCategories() const
{
return *m_displayedCategories;
}
storage::CountryInfoGetter & GetCountryInfoGetter() { return *m_infoGetter; }
StorageDownloadingPolicy & GetDownloadingPolicy() { return m_storageDownloadingPolicy; }

View file

@ -2,12 +2,15 @@
namespace
{
vector<string> const kDisplayedCategories = {
"food", "hotel", "tourism", "wifi", "transport", "fuel", "parking", "shop",
"atm", "bank", "entertainment", "hospital", "pharmacy", "police", "toilet", "post"};
vector<string> const kKeys = {"food", "hotel", "tourism", "wifi", "transport", "fuel",
"parking", "shop", "atm", "bank", "entertainment", "hospital",
"pharmacy", "police", "toilet", "post"};
} // namespace
namespace search
{
vector<string> const & GetDisplayedCategories() { return kDisplayedCategories; }
DisplayedCategories::DisplayedCategories(CategoriesHolder const & holder) : m_holder(holder) {}
// static
vector<string> const & DisplayedCategories::GetKeys() { return kKeys; }
} // namespace search

View file

@ -1,12 +1,36 @@
#pragma once
#include "indexer/categories_holder.hpp"
#include "std/string.hpp"
#include "std/vector.hpp"
namespace search
{
// Returns a list of English names of displayed categories for the
// categories search tab. It's guaranteed that the list remains the
// same during the application lifetime.
vector<string> const & GetDisplayedCategories();
class DisplayedCategories
{
public:
DisplayedCategories(CategoriesHolder const & holder);
// Returns a list of English names of displayed categories for the
// categories search tab. It's guaranteed that the list remains the
// same during the application lifetime, keys may be used as parts
// of resources ids.
static vector<string> const & GetKeys();
template <typename Fn>
void ForEachSynonym(string const & key, Fn && fn) const
{
auto const & translations = m_holder.GetGroupTranslations();
auto const it = translations.find("@" + key);
if (it == translations.end())
return;
for (auto const & name : it->second)
fn(name.m_name, CategoriesHolder::MapIntegerToLocale(name.m_locale));
}
private:
CategoriesHolder const & m_holder;
};
} // namespace search