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