2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file w3c_file_localization.cpp
18 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
22 #include <sys/types.h>
27 #include <dpl/localization/w3c_file_localization.h>
29 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
30 #include <dpl/localization/localization_utils.h>
32 #include <dpl/log/log.h>
33 #include <dpl/string.h>
34 #include <dpl/optional.h>
35 #include <dpl/foreach.h>
37 #include <LanguageTagsProvider.h>
39 using namespace WrtDB;
42 const DPL::String FILE_URI_BEGIN = L"file://";
43 const DPL::String WIDGET_URI_BEGIN = L"widget://";
44 const DPL::String APP_URI_BEGIN = L"app://";
45 const DPL::String LOCALE_PREFIX = L"locales/";
47 DPL::Optional<std::string> GetFilePathInWidgetPackageInternal(
48 const std::string& basePath,
51 LogDebug("Looking for file: " << filePath << " in: " << basePath);
53 const LanguageTags& ltags =
54 LanguageTagsProviderSingleton::Instance().getLanguageTags();
56 //Check if string isn't empty
57 if (filePath.size() == 0) {
58 return DPL::Optional<std::string>::Null;
60 //Removing preceding '/'
61 if (filePath[0] == '/') {
64 // In some cases (start file localization) url has unnecessary "/" at the
66 if (filePath[filePath.size() - 1] == '/') {
67 filePath.erase(filePath.size() - 1, 1);
69 //Check if string isn't empty
70 if (filePath.size() == 0) {
71 return DPL::Optional<std::string>::Null;
74 LogDebug("locales size = " << ltags.size());
75 for (LanguageTags::const_iterator it = ltags.begin();
79 LogDebug("Trying locale: " << *it);
80 std::string path = basePath;
81 if (path[path.size() - 1] == '/') {
82 path.erase(path.size() - 1);
86 path += "/" + filePath;
88 path += "/locales/" + DPL::ToUTF8String(*it) + "/" + filePath;
91 LogDebug("Trying locale: " << *it << " | " << path);
93 if (0 == stat(path.c_str(), &buf)) {
94 if ((buf.st_mode & S_IFMT) == S_IFREG) {
95 path.erase(0, basePath.length());
96 return DPL::Optional<std::string>(path);
101 return DPL::Optional<std::string>::Null;
104 DPL::Optional<DPL::String> GetFilePathInWidgetPackageInternal(
105 const DPL::String& basePath,
106 const DPL::String& filePath)
108 DPL::Optional<std::string> path =
109 GetFilePathInWidgetPackageInternal(DPL::ToUTF8String(basePath),
110 DPL::ToUTF8String(filePath));
111 DPL::Optional<DPL::String> dplPath;
113 dplPath = DPL::FromUTF8String(*path);
119 namespace W3CFileLocalization {
120 static bool isExistFileCached(const std::string& path)
122 static std::map<std::string, bool> pathCache;
125 if (pathCache.find(path) == pathCache.end())
129 if (0 == stat(path.c_str(), &buf))
131 pathCache[path] = true;
137 pathCache[path] = false;
143 return pathCache[path];
146 std::string getFilePathInWidgetPackageFromUrl(const std::string &tzAppId, const std::string &url)
148 const std::string SCHEME_FILE = "file://";
149 const std::string SCHEME_WIDGET = "widget://";
150 const std::string SCHEM_APP = "app://";
151 const std::string LOCALE_PATH = "locales/";
152 const std::string DOUBLE_ROOT = "//";
154 static std::string lastTzAppId;
155 static WidgetDAOReadOnlyPtr dao;
156 static std::string srcPath;
158 std::string workingUrl = url;
162 if (lastTzAppId != tzAppId)
164 lastTzAppId = tzAppId;
165 dao.reset(new WidgetDAOReadOnly(DPL::FromUTF8String(tzAppId)));
166 srcPath = DPL::ToUTF8String(dao->getPath());
169 // backup suffix string
170 std::string backupSuffix;
171 size_t pos = workingUrl.find_first_of("#?");
173 if (pos != std::string::npos)
175 backupSuffix = workingUrl.substr(pos);
176 workingUrl.resize(pos);
180 if (workingUrl.compare(0, SCHEME_WIDGET.length(), SCHEME_WIDGET) == 0)
182 // remove "widget://"
183 workingUrl.erase(0, SCHEME_WIDGET.length());
185 else if (workingUrl.compare(0, SCHEME_FILE.length(), SCHEME_FILE) == 0)
188 workingUrl.erase(0, SCHEME_FILE.length());
190 // exception handling for "//"
191 if (workingUrl.compare(0, DOUBLE_ROOT.length(), DOUBLE_ROOT) == 0)
193 workingUrl.erase(0, 1);
194 LogDebug("workingUrl: " << workingUrl);
198 if (workingUrl.compare(0, srcPath.length(), srcPath) == 0)
200 workingUrl.erase(0, srcPath.length());
203 // remove locale path
204 if (workingUrl.compare(0, LOCALE_PATH.length(), LOCALE_PATH) == 0)
206 workingUrl.erase(0, LOCALE_PATH.length());
208 pos = workingUrl.find_first_of('/');
210 if (pos != std::string::npos && pos > 0)
212 workingUrl.erase(0, pos+1);
216 else if (workingUrl.compare(0, SCHEM_APP.length(), SCHEM_APP) == 0)
219 workingUrl.erase(0, SCHEM_APP.length());
221 // remove tizen app id
222 if (workingUrl.compare(0, tzAppId.length(), tzAppId) == 0)
224 workingUrl.erase(0, tzAppId.length());
228 LogError("Tizen id does not match, ignoring");
234 if (!workingUrl.empty() && workingUrl[0] == '/')
236 workingUrl.erase(0, 1);
239 if (!workingUrl.empty() && workingUrl[workingUrl.length()-1] == '/') {
240 workingUrl.erase(workingUrl.length()-1, 1);
243 if (workingUrl.empty())
245 LogError("URL Localization Error!");
249 const LanguageTags& ltags = LanguageTagsProviderSingleton::Instance().getLanguageTags();
253 std::string path = srcPath;
259 if (isExistFileCached(path) == false)
264 path += DPL::ToUTF8String(*it) + "/";
266 if (isExistFileCached(path) == false)
274 if (isExistFileCached(path) == true)
282 // restore suffix string
285 // return empty string
290 if (!backupSuffix.empty())
292 workingUrl += backupSuffix;
299 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
300 DbWidgetHandle widgetHandle,
301 const DPL::String &url)
303 return getFilePathInWidgetPackageFromUrl(
304 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)),
308 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
309 const WrtDB::TizenAppId &tzAppId,
310 const DPL::String &url)
312 return getFilePathInWidgetPackageFromUrl(
313 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
317 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
318 WrtDB::WidgetDAOReadOnlyPtr dao,
319 const DPL::String &url)
321 DPL::String req = url;
324 DPL::String::size_type pos = req.find_first_of('#');
325 if(pos != DPL::String::npos)
327 suffix = req.substr(pos) + suffix;
328 req.resize(pos); //truncate fragment identifier
331 pos = req.find_first_of('?');
332 if(pos != DPL::String::npos)
334 suffix = req.substr(pos) + suffix;
335 req.resize(pos); //truncate query string
338 if (req.find(WIDGET_URI_BEGIN) == 0) {
339 req.erase(0, WIDGET_URI_BEGIN.length());
340 } else if (req.find(FILE_URI_BEGIN) == 0) {
341 req.erase(0, FILE_URI_BEGIN.length());
342 if (req.find(dao->getPath()) == 0) {
343 req.erase(0, dao->getPath().length());
345 if (req.find(LOCALE_PREFIX) == 0) {
346 req.erase(0, LOCALE_PREFIX.length());
347 size_t position = req.find('/');
348 // should always be >0 as correct locales path is
349 // always locales/xx/ or locales/xx-XX/
350 if (position != std::string::npos && position > 0) {
351 req.erase(0, position + 1);
354 } else if(req.find(APP_URI_BEGIN) == 0) {
355 req.erase(0, APP_URI_BEGIN.length());
356 DPL::String id = *dao->getTizenAppId();
357 if(req.substr(0, id.size()) != id)
359 LogError("Tizen id does not match, ignoring");
360 return DPL::Optional<DPL::String>::Null;
362 req.erase(0, id.length());
364 LogDebug("Unknown path format, ignoring");
365 return DPL::Optional<DPL::String>::Null;
368 auto widgetPath = dao->getPath();
370 LogDebug("Required path: " << req);
371 DPL::Optional<DPL::String> found =
372 GetFilePathInWidgetPackageInternal(widgetPath, req);
375 LogError("Path not found within current locale in current widget");
376 return DPL::Optional<DPL::String>::Null;
379 found = widgetPath + *found + suffix;
384 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
385 WrtDB::DbWidgetHandle widgetHandle,
386 const DPL::String& file)
388 return getFilePathInWidgetPackage(
389 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)),
393 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
394 const WrtDB::TizenAppId &tzAppId,
395 const DPL::String& file)
397 return getFilePathInWidgetPackage(
398 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
402 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
403 WrtDB::WidgetDAOReadOnlyPtr dao,
404 const DPL::String& file)
406 return GetFilePathInWidgetPackageInternal(dao->getPath(), file);
409 DPL::OptionalString getStartFile(const WrtDB::TizenAppId & tzAppId)
411 return getStartFile(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
414 DPL::OptionalString getStartFile(const WrtDB::DbWidgetHandle handle)
416 return getStartFile(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(handle)));
419 DPL::OptionalString getStartFile(WrtDB::WidgetDAOReadOnlyPtr dao)
421 WidgetDAOReadOnly::LocalizedStartFileList locList =
422 dao->getLocalizedStartFileList();
423 WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
424 LanguageTags tagsList =
425 LanguageTagsProviderSingleton::Instance().getLanguageTags();
427 DPL::OptionalString defaultLoc = dao->getDefaultlocale();
429 tagsList.push_back(*defaultLoc);
432 FOREACH(tag, tagsList)
434 FOREACH(sFile, locList)
436 if (*tag == sFile->widgetLocale) {
439 if (it->startFileId == sFile->startFileId) {
447 return DPL::OptionalString::Null;
450 OptionalWidgetIcon getIcon(const WrtDB::TizenAppId & tzAppId)
452 return getIcon(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
455 OptionalWidgetIcon getIcon(WrtDB::DbWidgetHandle widgetHandle)
457 return getIcon(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
460 OptionalWidgetIcon getIcon(WrtDB::WidgetDAOReadOnlyPtr dao)
462 WidgetDAOReadOnly::WidgetLocalizedIconList locList =
463 dao->getLocalizedIconList();
464 WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
465 LanguageTags tagsList =
466 LanguageTagsProviderSingleton::Instance().getLanguageTags();
468 DPL::OptionalString defaultLoc = dao->getDefaultlocale();
470 tagsList.push_back(*defaultLoc);
473 FOREACH(tag, tagsList)
475 FOREACH(icon, locList)
477 if (*tag == icon->widgetLocale) {
480 if (it->iconId == icon->iconId) {
482 ret.src = it->iconSrc;
483 ret.width = it->iconWidth;
484 ret.height = it->iconHeight;
492 return OptionalWidgetIcon::Null;
495 WidgetIconList getValidIconsList(WrtDB::DbWidgetHandle widgetHandle)
497 return getValidIconsList(
498 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
501 WidgetIconList getValidIconsList(const WrtDB::TizenAppId &tzAppId)
503 return getValidIconsList(
504 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
507 WidgetIconList getValidIconsList(WrtDB::WidgetDAOReadOnlyPtr dao)
509 WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
511 WidgetIconList outlist;
515 LogDebug(":" << it->iconSrc);
516 if (!!getFilePathInWidgetPackage(dao->getHandle(),
520 ret.src = it->iconSrc;
521 ret.width = it->iconWidth;
522 ret.height = it->iconHeight;
523 outlist.push_back(ret);
529 OptionalWidgetStartFileInfo getStartFileInfo(WrtDB::DbWidgetHandle widgetHandle)
531 return getStartFileInfo(
532 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
535 OptionalWidgetStartFileInfo getStartFileInfo(
536 const WrtDB::TizenAppId &tzAppId)
538 return getStartFileInfo(
539 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
542 OptionalWidgetStartFileInfo getStartFileInfo(WrtDB::WidgetDAOReadOnlyPtr dao)
544 WidgetStartFileInfo info;
546 WidgetDAOReadOnly::LocalizedStartFileList locList =
547 dao->getLocalizedStartFileList();
548 WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
549 const LanguageTags tagsList =
550 LanguageTagsProviderSingleton::Instance().getLanguageTags();
552 FOREACH(tag, tagsList)
554 FOREACH(sFile, locList)
556 if (*tag == sFile->widgetLocale) {
559 if (it->startFileId ==
563 info.encoding = sFile->encoding;
564 info.type = sFile->type;
566 info.localizedPath = it->src;
568 info.localizedPath = L"locales/" + *tag + L"/";
569 info.localizedPath += it->src;
578 return OptionalWidgetStartFileInfo::Null;
581 WidgetLocalizedInfo getLocalizedInfo(const WrtDB::DbWidgetHandle handle)
583 return getLocalizedInfo(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(handle)));
586 WidgetLocalizedInfo getLocalizedInfo(const WrtDB::TizenAppId & tzAppId)
588 return getLocalizedInfo(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
591 WidgetLocalizedInfo getLocalizedInfo(WidgetDAOReadOnlyPtr dao)
593 LanguageTags languages =
594 LanguageTagsProviderSingleton::Instance().getLanguageTags();
595 DPL::OptionalString dl = dao->getDefaultlocale();
597 languages.push_back(*dl);
600 WidgetLocalizedInfo result;
601 FOREACH(i, languages)
603 WidgetLocalizedInfo languageResult = dao->getLocalizedInfo(*i);
605 #define OVERWRITE_IF_NULL(FIELD) if (!result.FIELD) { \
606 result.FIELD = languageResult.FIELD; \
609 OVERWRITE_IF_NULL(name);
610 OVERWRITE_IF_NULL(shortName);
611 OVERWRITE_IF_NULL(description);
612 OVERWRITE_IF_NULL(license);
613 OVERWRITE_IF_NULL(licenseHref);
615 #undef OVERWRITE_IF_NULL