Merge "Get a available language list from xml." into tizen_2.1
[platform/framework/native/appfw.git] / src / locales / FLcl_LocaleManagerImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19 * @file         FLcl_LocaleManagerImpl.cpp
20 * @brief        This is the implementation file for _LocaleManagerImpl class.
21 */
22 #include <unique_ptr.h>
23 #include <limits.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 <FBaseSysLog.h>
31 #include <FBase_StringConverter.h>
32
33 #include "FLcl_LocaleImpl.h"
34 #include "FLcl_TimeZoneImpl.h"
35 #include "FLcl_LocaleManagerImpl.h"
36
37
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Utility;
40 using namespace Tizen::Base::Collection;
41
42 namespace Tizen { namespace Locales
43 {
44 static const char* LANGLIST_FILE_PATH ="/opt/data/setting/langlist.xml";
45 static const int TIMEZONE_MAX = 224;
46 static const char* TimeZoneList[TIMEZONE_MAX] =
47 {
48         "Africa/Abidjan",
49         "Africa/Accra",
50         "Africa/Addis_Ababa",
51         "Africa/Algiers",
52         "Africa/Asmara",
53         "Africa/Bamako",
54         "Africa/Bangui",
55         "Africa/Bissau",
56         "Africa/Cairo",
57         "Africa/Casablanca",
58         "Africa/Conakry",
59         "Africa/Dakar",
60         "Africa/Dar_es_Salaam",
61         "Africa/Djibouti",
62         "Africa/Douala",
63         "Africa/Freetown",
64         "Africa/Gaborone",
65         "Africa/Harare",
66         "Africa/Johannesburg",
67         "Africa/Kampala",
68         "Africa/Khartoum",
69         "Africa/Kinshasa",
70         "Africa/Lagos",
71         "Africa/Luanda",
72         "Africa/Lubumbashi",
73         "Africa/Lusaka",
74         "Africa/Malabo",
75         "Africa/Maputo",
76         "Africa/Mogadishu",
77         "Africa/Monrovia",
78         "Africa/Nairobi",
79         "Africa/Ndjamena",
80         "Africa/Niamey",
81         "Africa/Nouakchott",
82         "Africa/Ouagadougou",
83         "Africa/Tripoli",
84         "Africa/Tunis",
85         "America/Anchorage",
86         "America/Antigua",
87         "America/Argentina/Buenos_Aires",
88         "America/Asuncion",
89         "America/Barbados",
90         "America/Belize",
91         "America/Bogota",
92         "America/Caracas",
93         "America/Cayenne",
94         "America/Chicago",
95         "America/Costa_Rica",
96         "America/Denver",
97         "America/Detroit",
98         "America/El_Salvador",
99         "America/Godthab",
100         "America/Guadeloupe",
101         "America/Guatemala",
102         "America/Guayaquil",
103         "America/Guyana",
104         "America/Halifax",
105         "America/Havana",
106         "America/Indiana/Indianapolis",
107         "America/Jamaica",
108         "America/Kentucky/Louisville",
109         "America/La_Paz",
110         "America/Lima",
111         "America/Los_Angeles",
112         "America/Managua",
113         "America/Marigot",
114         "America/Martinique",
115         "America/Mazatlan",
116         "America/Mexico_City",
117         "America/Montevideo",
118         "America/Montreal",
119         "America/New_York",
120         "America/Nome",
121         "America/Panama",
122         "America/Paramaribo",
123         "America/Phoenix",
124         "America/Port-au-Prince",
125         "America/Puerto_Rico",
126         "America/Recife",
127         "America/Regina",
128         "America/Santiago",
129         "America/Santo_Domingo",
130         "America/Sao_Paulo",
131         "America/St_Johns",
132         "America/St_Thomas",
133         "America/Tegucigalpa",
134         "America/Tijuana",
135         "America/Toronto",
136         "America/Tortola",
137         "America/Vancouver",
138         "America/Winnipeg",
139         "Asia/Aden",
140         "Asia/Almaty",
141         "Asia/Amman",
142         "Asia/Anadyr",
143         "Asia/Ashgabat",
144         "Asia/Baghdad",
145         "Asia/Bahrain",
146         "Asia/Baku",
147         "Asia/Bangkok",
148         "Asia/Beirut",
149         "Asia/Bishkek",
150         "Asia/Colombo",
151         "Asia/Damascus",
152         "Asia/Dhaka",
153         "Asia/Dubai",
154         "Asia/Dushanbe",
155         "Asia/Ho_Chi_Minh",
156         "Asia/Hong_Kong",
157         "Asia/Hovd",
158         "Asia/Irkutsk",
159         "Asia/Istanbul",
160         "Asia/Jakarta",
161         "Asia/Jayapura",
162         "Asia/Jerusalem",
163         "Asia/Kabul",
164         "Asia/Kamchatka",
165         "Asia/Karachi",
166         "Asia/Kathmandu",
167         "Asia/Kolkata",
168         "Asia/Krasnoyarsk",
169         "Asia/Kuala_Lumpur",
170         "Asia/Kuwait",
171         "Asia/Macau",
172         "Asia/Magadan",
173         "Asia/Makassar",
174         "Asia/Manila",
175         "Asia/Muscat",
176         "Asia/Novokuznetsk",
177         "Asia/Novosibirsk",
178         "Asia/Omsk",
179         "Asia/Phnom_Penh",
180         "Asia/Pyongyang",
181         "Asia/Qatar",
182         "Asia/Rangoon",
183         "Asia/Riyadh",
184         "Asia/Sakhalin",
185         "Asia/Seoul",
186         "Asia/Shanghai",
187         "Asia/Singapore",
188         "Asia/Taipei",
189         "Asia/Tashkent",
190         "Asia/Tbilisi",
191         "Asia/Tehran",
192         "Asia/Tokyo",
193         "Asia/Ulan_Bator",
194         "Asia/Vladivostok",
195         "Asia/Yakutsk",
196         "Asia/Yekaterinburg",
197         "Asia/Yerevan",
198         "Atlantic/Azores",
199         "Atlantic/Canary",
200         "Atlantic/Reykjavik",
201         "Atlantic/South_Georgia",
202         "Australia/Adelaide",
203         "Australia/Brisbane",
204         "Australia/Canberra",
205         "Australia/Darwin",
206         "Australia/Hobart",
207         "Australia/Melbourne",
208         "Australia/Perth",
209         "Australia/Sydney",
210         "CST6CDT",
211         "EST5EDT",
212         "Europe/Amsterdam",
213         "Europe/Athens",
214         "Europe/Belgrade",
215         "Europe/Berlin",
216         "Europe/Bratislava",
217         "Europe/Brussels",
218         "Europe/Bucharest",
219         "Europe/Budapest",
220         "Europe/Chisinau",
221         "Europe/Copenhagen",
222         "Europe/Dublin",
223         "Europe/Helsinki",
224         "Europe/Istanbul",
225         "Europe/Kaliningrad",
226         "Europe/Kiev",
227         "Europe/Lisbon",
228         "Europe/Ljubljana",
229         "Europe/London",
230         "Europe/Luxembourg",
231         "Europe/Madrid",
232         "Europe/Malta",
233         "Europe/Minsk",
234         "Europe/Moscow",
235         "Europe/Paris",
236         "Europe/Podgorica",
237         "Europe/Prague",
238         "Europe/Riga",
239         "Europe/Rome",
240         "Europe/Samara",
241         "Europe/San_Marino",
242         "Europe/Skopje",
243         "Europe/Sofia",
244         "Europe/Stockholm",
245         "Europe/Tallinn",
246         "Europe/Vaduz",
247         "Europe/Vienna",
248         "Europe/Vilnius",
249         "Europe/Volgograd",
250         "Europe/Warsaw",
251         "Europe/Zagreb",
252         "Europe/Zurich",
253         "Indian/Antananarivo",
254         "Indian/Chagos",
255         "Indian/Maldives",
256         "Indian/Mauritius",
257         "Indian/Reunion",
258         "MST7MDT",
259         "Pacific/Auckland",
260         "Pacific/Easter",
261         "Pacific/Fiji",
262         "Pacific/Galapagos",
263         "Pacific/Guam",
264         "Pacific/Honolulu",
265         "Pacific/Midway",
266         "Pacific/Noumea",
267         "Pacific/Pago_Pago",
268         "Pacific/Tahiti",
269         "Pacific/Tarawa",
270         "Pacific/Tongatapu",
271         "PST8PDT"
272 };
273
274 Locale
275 _LocaleManagerImpl::GetSystemLocale(void)
276 {
277         char* pRegionPtr;
278         if (runtime_info_get_value_string(RUNTIME_INFO_KEY_REGION, &pRegionPtr) == RUNTIME_INFO_ERROR_NONE)
279         {
280                 SetLastResult(E_SUCCESS);
281
282                 Locale ospLoc = _LocaleImpl(pRegionPtr).GetOspLocale();
283                 free(pRegionPtr);
284                 return ospLoc;
285         }
286
287         SetLastResult(E_SYSTEM);
288         return Locale(LANGUAGE_INVALID, COUNTRY_INVALID, null);
289 }
290
291 IList*
292 _LocaleManagerImpl::GetAvailableLocalesN(void)
293 {
294         result r = E_SUCCESS;
295         int count = 0;
296         const U_ICU_NAMESPACE::Locale* pIcuLocaleList = U_ICU_NAMESPACE::Locale::getAvailableLocales(count);
297         SysTryReturn(NID_LCL, count > 0, null, E_SYSTEM,
298                                 "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
299
300         std::unique_ptr<LinkedList, AllElementsDeleter> pAvailableLocaleList(new (std::nothrow) LinkedList());
301         SysTryReturn(NID_LCL, pAvailableLocaleList, null, E_OUT_OF_MEMORY,
302                                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
303
304         for (int i = 0; i < count; i++)
305         {
306                 SysTryReturn(NID_LCL, (pIcuLocaleList + i) != null, null, E_SYSTEM,
307                                         "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
308
309                 Locale ospLocale = _LocaleImpl(*(pIcuLocaleList + i)).GetOspLocale();
310                 if (_LocaleImpl::IsSupported(ospLocale))
311                 {
312                         Locale* pLocale = new (std::nothrow) Locale(ospLocale);
313                         SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
314                                                 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
315                         if (!pAvailableLocaleList->Contains(*pLocale))
316                         {
317                                 r = pAvailableLocaleList->Add(*pLocale);
318                                 if (IsFailed(r))
319                                 {
320                                         delete pLocale;
321                                         SetLastResult(E_SYSTEM);
322                                         return null;
323                                 }
324                         }
325                 }
326         }
327
328         SetLastResult(E_SUCCESS);
329         return pAvailableLocaleList.release();
330 }
331
332 String
333 _LocaleManagerImpl::GetSelectedLanguage(void)
334 {
335         char* pLanguagePtr;
336
337         int ret = runtime_info_get_value_string(RUNTIME_INFO_KEY_LANGUAGE, &pLanguagePtr);
338         SysTryReturn(NID_LCL, ret == RUNTIME_INFO_ERROR_NONE, String(), E_SYSTEM,
339                         "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
340         String language(_LocaleImpl(pLanguagePtr).GetLanguageCodeString(false));
341         free(pLanguagePtr);
342
343         return language;
344 }
345
346 IList*
347 _LocaleManagerImpl::GetAvailableLanguagesN(void)
348 {
349         xmlDocPtr doc;
350         xmlNodePtr cur;
351
352         std::unique_ptr<ArrayList, AllElementsDeleter> pAvailableLanguageList(new (std::nothrow) ArrayList());
353         SysTryCatch(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
354
355         doc = xmlParseFile(LANGLIST_FILE_PATH);
356         SysTryCatch(NID_LCL, doc != null, , E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
357
358         cur = xmlDocGetRootElement(doc);
359         SysTryCatch(NID_LCL, cur != null, , E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
360         SysTryCatch(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, , E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
361
362         cur = cur->xmlChildrenNode;
363
364         pAvailableLanguageList->Construct();
365
366         for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
367         {
368                 if (cur_node->type == XML_ELEMENT_NODE)
369                 {
370                         char* pLocId = (char*)xmlGetProp(cur_node, (const xmlChar *)"id");
371                         Locale loc = _LocaleImpl(pLocId).GetOspLocale();
372                         std::unique_ptr<String> pLanguageLocaleID(new (std::nothrow) String(loc.GetLanguageCodeString()));
373                         SysTryCatch(NID_LCL, pLanguageLocaleID, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
374
375                         result r = pAvailableLanguageList->Add(pLanguageLocaleID.get());
376                         SysTryCatch(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
377                                         "[%s] It is failed to add a locale string [%ls].", GetErrorMessage(E_SYSTEM), pLanguageLocaleID->GetPointer());
378                         pLanguageLocaleID.release();
379                 }
380         }
381
382         SetLastResult(E_SUCCESS);
383
384         if (doc)
385         {
386                 xmlFreeDoc(doc);
387         }
388
389         return pAvailableLanguageList.release();
390
391 CATCH:
392         if (doc)
393         {
394                 xmlFreeDoc(doc);
395         }
396         SysLog(NID_LCL, "It is calling fallback api.");
397         return GetAvailableLanguagesFallBackN();
398 }
399
400
401 IList*
402 _LocaleManagerImpl::GetAvailableLanguagesFallBackN(void)
403 {
404         std::unique_ptr<IList, AllElementsDeleter> pLocaleList (GetAvailableLocalesN());
405         std::unique_ptr<HashMap> pLanguageMap(new (std::nothrow) HashMap());
406
407         SysTryReturn(NID_LCL, pLanguageMap, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
408
409         pLanguageMap->Construct();
410
411         for (int i = 0; i < pLocaleList->GetCount() ; i++)
412         {
413                 Locale* pLocale = (Locale*)pLocaleList->GetAt(i);
414                 std::unique_ptr<String> pLanguageCode(new (std::nothrow) String(pLocale->GetLanguageCodeString()));
415                 SysTryReturn(NID_LCL, pLanguageCode, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
416
417                 if (!pLanguageMap->ContainsKey(*pLanguageCode))
418                 {
419                         std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
420                         SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
421
422                         result r = pLanguageMap->Add(*(pLanguageCode.get()), *(pDummyValue.get()));
423
424                         if (IsFailed(r))
425                         {
426                                 SetLastResult(E_SYSTEM);
427                                 return null;
428                         }
429                         pLanguageCode.release();
430                         pDummyValue.release();
431                 }
432         }
433
434         IList* pAvailableLanguageList;
435         pAvailableLanguageList = pLanguageMap->GetKeysN();
436         SetLastResult(E_SUCCESS);
437         pLanguageMap->RemoveAll();
438         return pAvailableLanguageList;
439 }
440
441
442 IMap*
443 _LocaleManagerImpl::GetAvailableTimeZonesN(U_ICU_NAMESPACE::StringEnumeration* pIcuTZStrList)
444 {
445         SysTryReturn(NID_LCL, pIcuTZStrList, null, E_SYSTEM,
446                                 "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
447
448         std::unique_ptr<HashMap, AllElementsDeleter> pTimeZoneMap(new (std::nothrow) HashMap());
449
450         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
451                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
452         pTimeZoneMap->Construct();
453         result r = E_SUCCESS;
454         int resultLength = -1;
455         UErrorCode ec = U_ZERO_ERROR;
456         const char* pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
457         IMap* pTZMap = GetAvailableTimeZonesN();
458
459         r = GetLastResult();
460         SysTryReturn(NID_LCL, pTZMap, null, r, "[%s] Fail to get available time zone list", GetErrorMessage(r));
461
462         while (pIcuTZStr != null)
463         {
464                 String* pTimeZone = new (std::nothrow) String(pIcuTZStr);
465                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
466                                         "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
467                 if (!pTimeZoneMap->ContainsKey(*pTimeZone) && pTZMap->ContainsKey(*pTimeZone))
468                 {
469                         String* pDummyValue = new  (std::nothrow) String();
470                         r = pTimeZoneMap->Add(*pTimeZone, *pDummyValue);
471                         if (IsFailed(r))
472                         {
473                                 delete pTimeZone;
474                                 delete pDummyValue;
475                                 pTZMap->RemoveAll();
476                                 SetLastResult(E_SYSTEM);
477                                 return null;
478                         }
479                 }
480
481                 pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
482         }
483         SetLastResult(E_SUCCESS);
484         pTZMap->RemoveAll();
485         return pTimeZoneMap.release();
486 }
487
488 IMap*
489 _LocaleManagerImpl::GetAvailableTimeZonesN(void)
490 {
491         std::unique_ptr<HashMap, AllElementsDeleter> pTimeZoneMap(new (std::nothrow) HashMap());
492
493         SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
494                         "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
495
496         result r = E_SUCCESS;
497         int index = 0;
498
499         pTimeZoneMap->Construct();
500
501         do
502         {
503                 String* pTimeZone = new (std::nothrow) String(TimeZoneList[index++]);
504                 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
505                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
506
507                 if (!pTimeZoneMap->ContainsKey(*pTimeZone))
508                 {
509                         String* pDummyValue = new  (std::nothrow) String();
510
511                         r = pTimeZoneMap->Add(*pTimeZone, *pDummyValue);
512                         if (IsFailed(r))
513                         {
514                                 delete pTimeZone;
515                                 delete pDummyValue;
516                                 SetLastResult(E_SYSTEM);
517                                 return null;
518                         }
519                 }
520         }while (index < TIMEZONE_MAX);
521
522         SetLastResult(E_SUCCESS);
523         return pTimeZoneMap.release();
524 }
525
526 IMap*
527 _LocaleManagerImpl::GetAvailableTimeZonesN(int rawOffset)
528 {
529         return GetAvailableTimeZonesN(U_ICU_NAMESPACE::TimeZone::createEnumeration(rawOffset * _TimeZoneImpl::ONE_MIN_IN_MILLISEC));
530 }
531
532
533 TimeZone
534 _LocaleManagerImpl::GetSystemTimeZone(void)
535 {
536         char tz[PATH_MAX + 1];
537         int len = readlink("/opt/etc/localtime", tz, PATH_MAX);
538
539         SysTryReturn(NID_LCL, len > 0, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
540         tz[len] = '\0';
541         SysTryReturn(NID_LCL, len > 20, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
542
543         String tzId(tz + 20);
544         SysLog(NID_LCL, "System TimeZone id [%ls]", tzId.GetPointer());
545         TimeZone timeZone;
546         result r = Tizen::Locales::TimeZone::GetTimeZone(tzId, timeZone);
547         SysTryReturn(NID_LCL, r == E_SUCCESS, TimeZone(-1, ""), r, "[%s] error occurs.", GetErrorMessage(r));
548         return timeZone;
549 }
550
551 result
552 _LocaleManagerImpl::IsSupportedLocale(const Tizen::Locales::Locale& locale, bool& isSupportedLocale)
553 {
554         isSupportedLocale = _LocaleImpl::IsSupported(locale);
555         return E_SUCCESS;
556 }
557
558 };
559 };      // Tizen::Locales