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