Fix code for TDIS-5396
[framework/osp/social.git] / src / FScl_ContactDbMonitor.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  * @file                FScl_ContactDbMonitor.cpp
19  * @brief               This is the implementation for _ContactDbMonitor class.
20  *
21  * This file contains definitions of @e _ContactDbMonitor class.
22  */
23
24 #include <new>
25 #include <contacts.h>
26 #include <FBaseRtMutex.h>
27 #include <FBaseSysLog.h>
28 #include <FBaseColArrayListT.h>
29 #include "FScl_IContactDbChangeEventListener.h"
30 #include "FScl_ContactDbChangeEvent.h"
31 #include "FScl_ContactDbChangeEventArg.h"
32 #include "FScl_ContactDbConnector.h"
33 #include "FScl_ContactDbMonitor.h"
34
35 using namespace Tizen::Base;
36 using namespace Tizen::Base::Runtime;
37
38 namespace Tizen { namespace Social
39 {
40
41 _ContactDbMonitor* _ContactDbMonitor::__pTheInstance = null;
42
43 _ContactDbMonitor::__Callback::__Callback(const char* uri, contacts_db_changed_cb callback, void* pData)
44 : __uri(null)
45 , __callback(callback)
46 , __pData(pData)
47 , __registerred(false)
48 {
49         __uri = strdup(uri);
50 }
51
52 result
53 _ContactDbMonitor::__Callback::Register(void)
54 {
55         int ret = contacts_db_add_changed_cb(__uri, __callback, __pData);
56         SysTryReturn(NID_SCL, ret == CONTACTS_ERROR_NONE, E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
57
58         __registerred = true;
59
60         return E_SUCCESS;
61 }
62
63 _ContactDbMonitor::__Callback::~__Callback(void)
64 {
65         if (__registerred)
66         {
67                 contacts_db_remove_changed_cb(__uri, __callback, __pData);
68         }
69
70         if (__uri != null)
71         {
72                 free(__uri);
73         }
74 }
75
76 _ContactDbMonitor::_ContactDbMonitor(void)
77 : __pEvent(null)
78 , __pMutex(null)
79 , __pContactChangeCallback(null)
80 , __pGroupChangeCallback(null)
81 , __pGroupRelationChagneCallback(null)
82 , __pAddressbookChagneCallback(null)
83 , __pAddressbookList(null)
84 {
85         // empty body.
86 }
87
88 _ContactDbMonitor::~_ContactDbMonitor(void)
89 {
90         if (__pAddressbookList != null)
91         {
92                 contacts_list_destroy(__pAddressbookList, true);
93         }
94 }
95
96 result
97 _ContactDbMonitor::Construct(void)
98 {
99         SysTryReturn(NID_SCL, _ContactDbConnector::EnsureDbConnection() == E_SUCCESS, GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
100
101         result r = E_SUCCESS;
102
103         std::unique_ptr<Mutex> pMutex(new (std::nothrow) Mutex());
104         SysTryReturn(NID_SCL, pMutex != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
105
106         r = pMutex->Create();
107         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
108
109         std::unique_ptr<_ContactDbChangeEvent> pEvent(new (std::nothrow) _ContactDbChangeEvent());
110         SysTryReturnResult(NID_SCL, pEvent != null, E_OUT_OF_MEMORY, "Not enough memory.");
111
112         r = pEvent->Construct();
113         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
114
115         std::unique_ptr<__Callback> pContactChangeCallback(new (std::nothrow) __Callback(_contacts_contact._uri, OnContactDbChanged, this));
116         SysTryReturn(NID_SCL, pContactChangeCallback != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
117
118         r = pContactChangeCallback->Register();
119         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
120
121         std::unique_ptr<__Callback> pGroupChangeCallback(new (std::nothrow) __Callback(_contacts_group._uri, OnContactDbChanged, this));
122         SysTryReturn(NID_SCL, pGroupChangeCallback != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
123
124         r = pGroupChangeCallback->Register();
125         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
126
127         std::unique_ptr<__Callback> pGroupRelationChangeCallback(new (std::nothrow) __Callback(_contacts_group_relation._uri, OnContactDbChanged, this));
128         SysTryReturn(NID_SCL, pGroupRelationChangeCallback != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
129
130         r = pGroupRelationChangeCallback->Register();
131         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
132
133         std::unique_ptr<__Callback> pAddressbookChangeCallback(new (std::nothrow) __Callback(_contacts_address_book._uri, OnContactDbChanged, this));
134         SysTryReturn(NID_SCL, pAddressbookChangeCallback != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
135
136         r = pAddressbookChangeCallback->Register();
137         SysTryReturn(NID_SCL, !IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
138
139         __pMutex = move(pMutex);
140         __pEvent = move(pEvent);
141         __pContactChangeCallback = move(pContactChangeCallback);
142         __pGroupChangeCallback = move(pGroupChangeCallback);
143         __pGroupRelationChagneCallback = move(pGroupRelationChangeCallback);
144         __pAddressbookChagneCallback = move(pAddressbookChangeCallback);
145
146         return E_SUCCESS;
147 }
148
149 result
150 _ContactDbMonitor::AddListener(const _IContactDbChangeEventListener& listener)
151 {
152         result r = __pMutex->Acquire();
153         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
154
155         r = __pEvent->AddListener(listener);
156         SysTryCatch(NID_SCL, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
157
158         r = __pMutex->Release();
159         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
160
161         return E_SUCCESS;
162
163 CATCH:
164         r = __pMutex->Release();
165         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
166
167         return r;
168 }
169
170 result
171 _ContactDbMonitor::RemoveListener(const _IContactDbChangeEventListener& listener)
172 {
173         result r = __pMutex->Acquire();
174         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
175
176         r = __pEvent->RemoveListener(listener);
177         SysTryCatch(NID_SCL, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
178
179         r = __pMutex->Release();
180         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
181
182         return E_SUCCESS;
183
184 CATCH:
185         r = __pMutex->Release();
186         SysTryReturn(NID_SCL, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
187
188         return r;
189 }
190
191 _ContactDbMonitor*
192 _ContactDbMonitor::GetInstance(void)
193 {
194         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
195         if (__pTheInstance == null)
196         {
197                 ClearLastResult();
198
199                 pthread_once(&onceBlock, InitSingleton);
200
201                 result r = GetLastResult();
202                 if (IsFailed(r))
203                 {
204                         onceBlock = PTHREAD_ONCE_INIT;
205                 }
206         }
207
208         return __pTheInstance;
209 }
210
211 void
212 _ContactDbMonitor::OnContactDbChanged(const char* viewUri, void* pUserData)
213 {
214         result r = E_SUCCESS;
215
216         _ContactDbMonitor* pContactDbMonitor = static_cast<_ContactDbMonitor*>(pUserData);
217         _ContactDbChangeEvent* pEvent = pContactDbMonitor->__pEvent.get();
218
219         std::unique_ptr<_ContactDbChangeEventArg> pArg;
220
221         if (strcmp(viewUri, _contacts_contact._uri) == 0)
222         {
223                 pArg.reset(new (std::nothrow) _ContactDbChangeEventArg(_CONTACT_DB_CHANGE_TYPE_CONTACT));
224                 SysTryReturnVoidResult(NID_SCL, pArg != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
225         }
226         else if (strcmp(viewUri, _contacts_group._uri) == 0)
227         {
228                 pArg.reset(new (std::nothrow) _ContactDbChangeEventArg(_CONTACT_DB_CHANGE_TYPE_GROUP));
229                 SysTryReturnVoidResult(NID_SCL, pArg != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
230
231         }
232         else if (strcmp(viewUri, _contacts_group_relation._uri) == 0)
233         {
234                 pArg.reset(new (std::nothrow) _ContactDbChangeEventArg(_CONTACT_DB_CHANGE_TYPE_RELATION));
235                 SysTryReturnVoidResult(NID_SCL, pArg != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
236
237         }
238         else if (strcmp(viewUri, _contacts_address_book._uri) == 0)
239         {
240                 pContactDbMonitor->UpdateAddressbookList();
241
242                 pArg.reset(new (std::nothrow) _ContactDbChangeEventArg(_CONTACT_DB_CHANGE_TYPE_ADDRESSBOOK));
243                 SysTryReturnVoidResult(NID_SCL, pArg != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
244         }
245         else
246         {
247                 return;
248         }
249
250         r = pEvent->Fire(*pArg);
251         SysTryReturnVoidResult(NID_SCL, !IsFailed(r), r, "[%s] Propagating.", GetErrorMessage(r));
252
253         pArg.release();
254 }
255
256 result
257 _ContactDbMonitor::UpdateAddressbookList(void)
258 {
259         SysTryReturn(NID_SCL, _ContactDbConnector::EnsureDbConnection() == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
260
261         ClearLastResult();
262
263         contacts_list_h pAddressbookList = null;
264         int ret = contacts_db_get_all_records(_contacts_address_book._uri, 0, 0, &pAddressbookList);
265         SysTryReturn(NID_SCL, ret != CONTACTS_ERROR_OUT_OF_MEMORY, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
266         SysTryReturn(NID_SCL, ret == CONTACTS_ERROR_NONE, E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
267
268         __List list(pAddressbookList);
269
270         __Lock lock(__pMutex.get());
271         result r = GetLastResult();
272         SysTryReturn(NID_SCL, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[%s] A system error has been occurred.", GetErrorMessage(E_SYSTEM));
273
274         if (__pAddressbookList != null)
275         {
276                 contacts_list_destroy(__pAddressbookList, true);
277         }
278
279         __pAddressbookList = list.Release();
280
281         return E_SUCCESS;
282 }
283
284 int
285 _ContactDbMonitor::GetAccountIdByAddressbookId(int addressbookId)
286 {
287         ClearLastResult();
288
289         __Lock lock(__pMutex.get());
290
291         if (__pAddressbookList == null)
292         {
293                 result r = UpdateAddressbookList();
294                 SysTryReturn(NID_SCL, r == E_SUCCESS, -1, r, "[%s] Propagating.", GetErrorMessage(r));
295         }
296
297         int intValue = 0;
298         unsigned int count = 0;
299         contacts_record_h pAddressbook = null;
300
301         contacts_list_get_count(__pAddressbookList, &count);
302         contacts_list_first(__pAddressbookList);
303
304         for (unsigned int i = 0; i < count; i++)
305         {
306                 contacts_list_get_current_record_p(__pAddressbookList, &pAddressbook);
307                 contacts_record_get_int(pAddressbook, _contacts_address_book.id, &intValue);
308                 if (intValue == addressbookId)
309                 {
310                         contacts_record_get_int(pAddressbook, _contacts_address_book.account_id, &intValue);
311
312                         return intValue;
313                 }
314
315                 if (contacts_list_next(__pAddressbookList) != CONTACTS_ERROR_NONE)
316                 {
317                         break;
318                 }
319         }
320
321         return -1;
322 }
323
324 void
325 _ContactDbMonitor::InitSingleton(void)
326 {
327         std::unique_ptr<_ContactDbMonitor> pInst(new (std::nothrow) _ContactDbMonitor());
328         SysTryReturnVoidResult(NID_SCL, pInst, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
329
330         result r = pInst->Construct();
331         SysTryReturnVoidResult(NID_SCL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
332
333         __pTheInstance = pInst.release();
334
335         std::atexit(DestroySingleton);
336 }
337
338 void
339 _ContactDbMonitor::DestroySingleton(void)
340 {
341         delete __pTheInstance;
342 }
343
344 }}  // Tizen::Social