a378dd5b01e969f7b3aaf6aa7e6242f3a2e6724f
[platform/framework/native/appfw.git] / src / locales / FLcl_LocaleManagerImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18 * @file         FLcl_LocaleManagerImpl.cpp
19 * @brief        This is the implementation file for _LocaleManagerImpl class.
20 */
21 #include <unique_ptr.h>
22 #include <limits.h>
23 #include <time.h>
24 #include <runtime_info.h>
25 #include <unicode/calendar.h>
26 #include <unicode/timezone.h>
27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
29
30 #include <FIo.h>
31 #include <FBaseSysLog.h>
32 #include <FBase_StringConverter.h>
33
34 #include "FLcl_LocaleImpl.h"
35 #include "FLcl_TimeZoneImpl.h"
36 #include "FLcl_LocaleManagerImpl.h"
37
38
39 using namespace Tizen::Base;
40 using namespace Tizen::Base::Utility;
41 using namespace Tizen::Base::Collection;
42 using namespace Tizen::Io;
43
44 struct FreeXmlDoc
45 {
46         void operator ()(xmlDoc* p)
47         {
48                 if (p != null)
49                 {
50                         xmlFreeDoc(p);
51                 }
52         }
53 };
54
55 namespace Tizen { namespace Locales
56 {
57 static const char* LANGUAGE_LIST_FILE_PATH ="/opt/data/setting/langlist.xml";
58 static const char* TIMEZONE_LIST_FILE_PATH = "/opt/data/setting/tzlist.ini";
59 static const char* CLOCALE_LIST_FILE_PATH = "/opt/usr/etc/clocale.list";
60
61
62 Locale
63 _LocaleManagerImpl::GetSystemLocale(void)
64 {
65         char* pRegionPtr;
66         if (runtime_info_get_value_string(RUNTIME_INFO_KEY_REGION, &pRegionPtr) == RUNTIME_INFO_ERROR_NONE)
67         {
68                 SetLastResult(E_SUCCESS);
69
70                 Locale ospLoc = _LocaleImpl(pRegionPtr).GetOspLocale();
71                 free(pRegionPtr);
72                 return ospLoc;
73         }
74
75         SetLastResult(E_SYSTEM);
76         return Locale(LANGUAGE_INVALID, COUNTRY_INVALID, null);
77 }
78
79
80 IMap*
81 _LocaleManagerImpl::GetAvailableEglibcLocaesN(void)
82 {
83         File file;
84         result r = E_SUCCESS;
85         String clocaleFilePath(CLOCALE_LIST_FILE_PATH);
86         
87         std::unique_ptr<HashMap> pClocaleMap(new (std::nothrow) HashMap(SingleObjectDeleter));
88         SysTryReturn(NID_LCL, pClocaleMap, null, E_OUT_OF_MEMORY,
89                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
90         r = file.Construct(clocaleFilePath, "r");
91         SysTryReturn(NID_LCL, r == E_SUCCESS, null,E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the clocale list from the list file.");
92
93         pClocaleMap->Construct();
94
95         do
96         {
97                 String strBuf;
98                 r = file.Read(strBuf);
99                 if ( r == E_END_OF_FILE)
100                 {
101                         break;
102                 }
103                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r, "[%s] It is failed to read the clocale list.", GetErrorMessage(r));
104                 std::unique_ptr< String > pClocaleId(new (std::nothrow) String());
105                 SysTryReturn(NID_LCL, pClocaleId, null, E_OUT_OF_MEMORY,
106                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
107                 r = strBuf.SubString(0, 5, *pClocaleId);
108                 if (IsFailed(r))
109                 {
110                         continue;
111                 }
112
113                 if (!pClocaleMap->ContainsKey(*(pClocaleId.get())))
114                 {
115                         std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
116                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
117                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
118
119                         r = pClocaleMap->Add(*(pClocaleId.get()), *(pDummyValue.get()));
120                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, r,
121                                 "[%s] It is failed to add the clocale id into the clocale map.", GetErrorMessage(r));
122                         pClocaleId.release();
123                         pDummyValue.release();
124                 }
125         }while(1);
126         return pClocaleMap.release();
127 }
128
129 IList*
130 _LocaleManagerImpl::GetAvailableLocalesN(void)
131 {
132         result r = E_SUCCESS;
133         int count = 0;
134         const U_ICU_NAMESPACE::Locale* pIcuLocaleList = U_ICU_NAMESPACE::Locale::getAvailableLocales(count);
135         SysTryReturn(NID_LCL, count > 0, null, E_SYSTEM,
136                 "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
137
138         std::unique_ptr<LinkedList> pAvailableLocaleList(new (std::nothrow) LinkedList(SingleObjectDeleter));
139         SysTryReturn(NID_LCL, pAvailableLocaleList, null, E_OUT_OF_MEMORY,
140                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
141
142         std::unique_ptr< IMap > pClocaleMap(GetAvailableEglibcLocaesN());
143
144         for (int i = 0; i < count; i++)
145         {
146                 const U_ICU_NAMESPACE::Locale* pIcuLocale = (pIcuLocaleList + i);
147                 SysTryReturn(NID_LCL, pIcuLocale, null, E_SYSTEM,
148                         "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
149                 Locale ospLocale = _LocaleImpl(*pIcuLocale).GetOspLocale();
150                 if (_LocaleImpl::IsSupported(ospLocale))
151                 {
152                         std::unique_ptr< Locale > pLocale(new (std::nothrow) Locale(ospLocale));
153                         SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
154                                                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
155
156                         String localeId(pIcuLocale->getLanguage());
157                         localeId = localeId + L"_" + String(pIcuLocale->getCountry());
158
159                         if (!pAvailableLocaleList->Contains(*(pLocale.get())) && pClocaleMap->ContainsKey(localeId))
160                         {
161                                 r = pAvailableLocaleList->Add(*(pLocale.get()));
162                                 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to make the locale list");
163                                 pLocale.release();
164                         }
165                 }
166         }
167
168         SetLastResult(E_SUCCESS);
169         return pAvailableLocaleList.release();
170 }
171
172 String
173 _LocaleManagerImpl::GetSelectedLanguage(void)
174 {
175         char* pLanguagePtr;
176
177         int ret = runtime_info_get_value_string(RUNTIME_INFO_KEY_LANGUAGE, &pLanguagePtr);
178         SysTryReturn(NID_LCL, ret == RUNTIME_INFO_ERROR_NONE, String(), E_SYSTEM,
179                         "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
180         String language(_LocaleImpl(pLanguagePtr).GetLanguageCodeString(false));
181         free(pLanguagePtr);
182
183         return language;
184 }
185
186 IList*
187 _LocaleManagerImpl::GetAvailableLanguagesN(void)
188 {
189         std::unique_ptr<ArrayList> pAvailableLanguageList(new (std::nothrow) ArrayList(SingleObjectDeleter));
190         SysTryReturn(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
191
192         xmlNodePtr cur = null;
193         std::unique_ptr< xmlDoc, FreeXmlDoc > pDoc(xmlParseFile(LANGUAGE_LIST_FILE_PATH));
194         SysTryReturn(NID_LCL, pDoc != null, null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
195
196         cur = xmlDocGetRootElement(pDoc.get());
197         SysTryReturn(NID_LCL, cur != null, null, E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
198         SysTryReturn(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, null, E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
199
200         cur = cur->xmlChildrenNode;
201
202         pAvailableLanguageList->Construct();
203
204         for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
205         {
206                 if (cur_node->type == XML_ELEMENT_NODE)
207                 {
208                         std::unique_ptr < char > pLocId((char*)xmlGetProp(cur_node, (const xmlChar *)"id"));
209                         Locale loc = _LocaleImpl(pLocId.get()).GetOspLocale();
210                         std::unique_ptr<String> pLanguageLocaleID(new (std::nothrow) String(loc.GetLanguageCodeString()));
211                         SysTryReturn(NID_LCL, pLanguageLocaleID, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
212
213                         if (!pAvailableLanguageList->Contains(*(pLanguageLocaleID.get())))
214                         {
215                                 result r = pAvailableLanguageList->Add(pLanguageLocaleID.get());
216                                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
217                                         "[%s] It is failed to add a locale string [%ls].", GetErrorMessage(E_SYSTEM), pLanguageLocaleID->GetPointer());
218                                 pLanguageLocaleID.release();
219                         }
220                 }
221         }
222
223         SetLastResult(E_SUCCESS);
224         return pAvailableLanguageList.release();
225 }
226
227
228 IList*
229 _LocaleManagerImpl::GetAvailableLanguageLocalesN(void)
230 {
231         std::unique_ptr<ArrayList> pAvailableLanguageList(new (std::nothrow) ArrayList(SingleObjectDeleter));
232         SysTryReturn(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
233
234         xmlNodePtr cur = null;
235         std::unique_ptr< xmlDoc, FreeXmlDoc > pDoc(xmlParseFile(LANGUAGE_LIST_FILE_PATH));
236         SysTryReturn(NID_LCL, pDoc != null, null, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
237
238         cur = xmlDocGetRootElement(pDoc.get());
239         SysTryReturn(NID_LCL, cur != null, null, E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
240         SysTryReturn(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, null, E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
241
242         cur = cur->xmlChildrenNode;
243
244         pAvailableLanguageList->Construct();
245
246         for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
247         {
248                 if (cur_node->type == XML_ELEMENT_NODE)
249                 {
250                         std::unique_ptr< char > pLocId((char*)xmlGetProp(cur_node, (const xmlChar *)"id"));
251                         Locale loc = _LocaleImpl(pLocId.get()).GetOspLocale();
252                         if (_LocaleImpl::IsSupported(loc))
253                         {
254                                 std::unique_ptr< Locale > pLocale(new (std::nothrow) Locale(loc));
255                                 SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
256                                         "[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
257
258                                 if (!pAvailableLanguageList->Contains(*(pLocale.get())))
259                                 {
260                                         result r = pAvailableLanguageList->Add(*(pLocale.get()));
261                                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
262                                                 "[%s] It is failed to add a locale string [%s].", GetErrorMessage(E_SYSTEM), pLocId.get());
263                                         pLocale.release();
264                                 }
265                         }
266                 }
267         }
268
269         SetLastResult(E_SUCCESS);
270         return pAvailableLanguageList.release();
271 }
272
273
274 IMap*
275 _LocaleManagerImpl::GetAvailableTimeZonesN(U_ICU_NAMESPACE::StringEnumeration* pIcuTZStrList)
276 {
277         SysTryReturn(NID_LCL, pIcuTZStrList, null, E_SYSTEM,
278                 "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
279
280         std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
281         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
282                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
283         pTimeZoneMap->Construct();
284
285         result r = E_SUCCESS;
286         int resultLength = -1;
287         UErrorCode ec = U_ZERO_ERROR;
288         const char* pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
289         std::unique_ptr<IMap> pTZMap(GetAvailableTimeZonesN());
290         r = GetLastResult();
291         SysTryReturn(NID_LCL, pTZMap, null, r, "[%s] Fail to get available time zone list", GetErrorMessage(r));
292
293         while (pIcuTZStr != null)
294         {
295                 std::unique_ptr< String > pTimeZone(new (std::nothrow) String(pIcuTZStr));
296                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
297                                         "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
298                 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())) && pTZMap->ContainsKey(*(pTimeZone.get())))
299                 {
300                         std::unique_ptr< String > pDummyValue(new  (std::nothrow) String());
301                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
302                         r = pTimeZoneMap->Add(*(pTimeZone.get()), *(pDummyValue.get()));
303                         SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] It is failed to add a TZ into Map.");
304                         pTimeZone.release();
305                         pDummyValue.release();
306                 }
307
308                 pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
309         }
310         SetLastResult(E_SUCCESS);
311         return pTimeZoneMap.release();
312 }
313
314
315 IMap*
316 _LocaleManagerImpl::GetAvailableTimeZonesN(void)
317 {
318         File file;
319         String tzFilePath(TIMEZONE_LIST_FILE_PATH);
320         result r = E_SUCCESS;
321
322         std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
323         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
324                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
325         r = file.Construct(tzFilePath, "r");
326         SysTryReturn(NID_LCL, r == E_SUCCESS, null,E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the tzlist from the ini file.");
327
328         pTimeZoneMap->Construct();
329
330         do
331         {
332                 std::unique_ptr<String> pTimeZone(new (std::nothrow) String());
333                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
334                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
335                 r = file.Read(*(pTimeZone.get()));
336                 if ( r == E_END_OF_FILE)
337                 {
338                         break;
339                 }
340                 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r, "[%s] It is failed to read the tzlist.", GetErrorMessage(r));
341                 pTimeZone->Replace(L"\n", L"\0");
342
343                 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())))
344                 {
345                         std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
346                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
347                                         "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
348
349                         r = pTimeZoneMap->Add(*(pTimeZone.get()), *(pDummyValue.get()));
350                         SysTryReturn(NID_LCL, r == E_SUCCESS, null, r,"[%s] It is failed to make the tz list.", GetErrorMessage(r));
351                         pTimeZone.release();
352                         pDummyValue.release();
353                 }
354         }while (1);
355
356         SetLastResult(E_SUCCESS);
357         return pTimeZoneMap.release();
358 }
359
360
361 IMap*
362 _LocaleManagerImpl::GetAvailableTimeZonesN(int rawOffset)
363 {
364         std::unique_ptr<U_ICU_NAMESPACE::StringEnumeration> pIcuTzList(U_ICU_NAMESPACE::TimeZone::createEnumeration(rawOffset * _TimeZoneImpl::ONE_MIN_IN_MILLISEC));
365         SysTryReturn(NID_LCL, pIcuTzList, null, E_SYSTEM, "[E_SYSTEM] It is failed to get Icu TZ list.");
366         IMap* pTzList =  GetAvailableTimeZonesN(pIcuTzList.get());
367         return pTzList;
368 }
369
370
371 TimeZone
372 _LocaleManagerImpl::GetSystemTimeZone(void)
373 {
374         char tz[PATH_MAX + 1];
375         int len = readlink("/opt/etc/localtime", tz, PATH_MAX);
376
377         SysTryReturn(NID_LCL, len > 0, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
378         tz[len] = '\0';
379         SysTryReturn(NID_LCL, len > 20, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
380
381         String tzId(tz + 20);
382         SysLog(NID_LCL, "System TimeZone id [%ls]", tzId.GetPointer());
383
384         TimeZone timeZone;
385         DateTime utcTime;
386         struct tm* pGmTime = null;
387         time_t currTime = 0;
388         time(&currTime);
389         pGmTime = gmtime(&currTime);
390         utcTime.SetValue(pGmTime->tm_year + 1900, pGmTime->tm_mon + 1, pGmTime->tm_mday, pGmTime->tm_hour, pGmTime->tm_min, pGmTime->tm_sec);
391
392         result r = Tizen::Locales::TimeZone::GetTimeZone(tzId, utcTime, timeZone);
393         SysTryReturn(NID_LCL, r == E_SUCCESS, TimeZone(-1, ""), r, "[%s] error occurs.", GetErrorMessage(r));
394         return timeZone;
395 }
396
397 result
398 _LocaleManagerImpl::IsSupportedLocale(const Tizen::Locales::Locale& locale, bool& isSupportedLocale)
399 {
400         isSupportedLocale = _LocaleImpl::IsSupported(locale);
401         return E_SUCCESS;
402 }
403
404 };
405 };      // Tizen::Locales