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 const WrtDB::TizenAppId &tzAppId,
301 const DPL::String &url)
303 return getFilePathInWidgetPackageFromUrl(
304 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
308 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
309 WrtDB::WidgetDAOReadOnlyPtr dao,
310 const DPL::String &url)
312 DPL::String req = url;
315 DPL::String::size_type pos = req.find_first_of('#');
316 if(pos != DPL::String::npos)
318 suffix = req.substr(pos) + suffix;
319 req.resize(pos); //truncate fragment identifier
322 pos = req.find_first_of('?');
323 if(pos != DPL::String::npos)
325 suffix = req.substr(pos) + suffix;
326 req.resize(pos); //truncate query string
329 if (req.find(WIDGET_URI_BEGIN) == 0) {
330 req.erase(0, WIDGET_URI_BEGIN.length());
331 } else if (req.find(FILE_URI_BEGIN) == 0) {
332 req.erase(0, FILE_URI_BEGIN.length());
333 if (req.find(dao->getPath()) == 0) {
334 req.erase(0, dao->getPath().length());
336 if (req.find(LOCALE_PREFIX) == 0) {
337 req.erase(0, LOCALE_PREFIX.length());
338 size_t position = req.find('/');
339 // should always be >0 as correct locales path is
340 // always locales/xx/ or locales/xx-XX/
341 if (position != std::string::npos && position > 0) {
342 req.erase(0, position + 1);
345 } else if(req.find(APP_URI_BEGIN) == 0) {
346 req.erase(0, APP_URI_BEGIN.length());
347 DPL::String id = dao->getTizenAppId();
348 if(req.substr(0, id.size()) != id)
350 LogError("Tizen id does not match, ignoring");
351 return DPL::Optional<DPL::String>::Null;
353 req.erase(0, id.length());
355 LogDebug("Unknown path format, ignoring");
356 return DPL::Optional<DPL::String>::Null;
359 auto widgetPath = dao->getPath();
361 LogDebug("Required path: " << req);
362 DPL::Optional<DPL::String> found =
363 GetFilePathInWidgetPackageInternal(widgetPath, req);
366 LogError("Path not found within current locale in current widget");
367 return DPL::Optional<DPL::String>::Null;
370 found = widgetPath + *found + suffix;
375 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
376 const WrtDB::TizenAppId &tzAppId,
377 const DPL::String& file)
379 return getFilePathInWidgetPackage(
380 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
384 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
385 WrtDB::WidgetDAOReadOnlyPtr dao,
386 const DPL::String& file)
388 return GetFilePathInWidgetPackageInternal(dao->getPath(), file);
391 DPL::OptionalString getStartFile(const WrtDB::TizenAppId & tzAppId)
393 return getStartFile(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
396 DPL::OptionalString getStartFile(WrtDB::WidgetDAOReadOnlyPtr dao)
398 WidgetDAOReadOnly::LocalizedStartFileList locList =
399 dao->getLocalizedStartFileList();
400 WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
401 LanguageTags tagsList =
402 LanguageTagsProviderSingleton::Instance().getLanguageTags();
404 DPL::OptionalString defaultLoc = dao->getDefaultlocale();
406 tagsList.push_back(*defaultLoc);
409 FOREACH(tag, tagsList)
411 FOREACH(sFile, locList)
413 if (*tag == sFile->widgetLocale) {
416 if (it->startFileId == sFile->startFileId) {
424 return DPL::OptionalString::Null;
427 OptionalWidgetIcon getIcon(const WrtDB::TizenAppId & tzAppId)
429 return getIcon(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
432 OptionalWidgetIcon getIcon(WrtDB::WidgetDAOReadOnlyPtr dao)
434 WidgetDAOReadOnly::WidgetLocalizedIconList locList =
435 dao->getLocalizedIconList();
436 WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
437 LanguageTags tagsList =
438 LanguageTagsProviderSingleton::Instance().getLanguageTags();
440 DPL::OptionalString defaultLoc = dao->getDefaultlocale();
442 tagsList.push_back(*defaultLoc);
445 FOREACH(tag, tagsList)
447 FOREACH(icon, locList)
449 if (*tag == icon->widgetLocale) {
452 if (it->iconId == icon->iconId) {
454 ret.src = it->iconSrc;
455 ret.width = it->iconWidth;
456 ret.height = it->iconHeight;
464 return OptionalWidgetIcon::Null;
467 WidgetIconList getValidIconsList(const WrtDB::TizenAppId &tzAppId)
469 return getValidIconsList(
470 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
473 WidgetIconList getValidIconsList(WrtDB::WidgetDAOReadOnlyPtr dao)
475 WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
477 WidgetIconList outlist;
481 LogDebug(":" << it->iconSrc);
482 if (!!getFilePathInWidgetPackage(dao->getTizenAppId(),
486 ret.src = it->iconSrc;
487 ret.width = it->iconWidth;
488 ret.height = it->iconHeight;
489 outlist.push_back(ret);
495 OptionalWidgetStartFileInfo getStartFileInfo(
496 const WrtDB::TizenAppId &tzAppId)
498 return getStartFileInfo(
499 WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
502 OptionalWidgetStartFileInfo getStartFileInfo(WrtDB::WidgetDAOReadOnlyPtr dao)
504 WidgetStartFileInfo info;
506 WidgetDAOReadOnly::LocalizedStartFileList locList =
507 dao->getLocalizedStartFileList();
508 WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
509 const LanguageTags tagsList =
510 LanguageTagsProviderSingleton::Instance().getLanguageTags();
512 FOREACH(tag, tagsList)
514 FOREACH(sFile, locList)
516 if (*tag == sFile->widgetLocale) {
519 if (it->startFileId ==
523 info.encoding = sFile->encoding;
524 info.type = sFile->type;
526 info.localizedPath = it->src;
528 info.localizedPath = L"locales/" + *tag + L"/";
529 info.localizedPath += it->src;
538 return OptionalWidgetStartFileInfo::Null;
541 WidgetLocalizedInfo getLocalizedInfo(const WrtDB::TizenAppId & tzAppId)
543 return getLocalizedInfo(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
546 WidgetLocalizedInfo getLocalizedInfo(WidgetDAOReadOnlyPtr dao)
548 LanguageTags languages =
549 LanguageTagsProviderSingleton::Instance().getLanguageTags();
550 DPL::OptionalString dl = dao->getDefaultlocale();
552 languages.push_back(*dl);
555 WidgetLocalizedInfo result;
556 FOREACH(i, languages)
558 WidgetLocalizedInfo languageResult = dao->getLocalizedInfo(*i);
560 #define OVERWRITE_IF_NULL(FIELD) if (!result.FIELD) { \
561 result.FIELD = languageResult.FIELD; \
564 OVERWRITE_IF_NULL(name);
565 OVERWRITE_IF_NULL(shortName);
566 OVERWRITE_IF_NULL(description);
567 OVERWRITE_IF_NULL(license);
568 OVERWRITE_IF_NULL(licenseHref);
570 #undef OVERWRITE_IF_NULL