wrt-plugins-tizen_0.4.23
[framework/web/wrt-plugins-tizen.git] / src / Callhistory / CallHistory.cpp
1 //
2 // Tizen Web Device API
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 #include "CallHistory.h"
20
21 #include <vector>
22 #include <string>
23 #include <sstream>
24 #include <cassert>
25 #include <Commons/Exception.h>
26 #include <CommonsJavaScript/JSCallbackManager.h>
27 #include <dpl/shared_ptr.h>
28 #include <Logger.h>
29
30 #include <IFilter.h>
31 #include <IFilterVisitor.h>
32 #include "CallHistoryDefine.h"
33
34 #include "CallHistoryFilter.h"
35
36 using namespace DeviceAPI::Tizen;
37 using namespace WrtDeviceApis;
38 using namespace WrtDeviceApis::Commons;
39 using namespace WrtDeviceApis::CommonsJavaScript;
40 using namespace DPL;
41
42 namespace DeviceAPI {
43 namespace CallHistory {
44
45 std::vector<CallHistory::WatcherPtr> CallHistory::m_watchers;
46
47 CallHistory::CallHistory()
48 {
49         LoggerD("Enter ");
50         if (contacts_connect2() == CONTACTS_ERROR_NONE) {
51                 LoggerD("Successful to connect Call history DB ");
52         } else {
53                 LoggerD("Failed to connect Call history DB ");
54         }
55
56         EventCallHistoryPtr event(new EventCallHistory());
57         event->setCmdType(EventCallHistory::CONNECT);
58         event->setForSynchronousCall();
59         EventRequestReceiver<EventCallHistory>::PostRequest(event);
60 }
61
62 CallHistory::~CallHistory()
63 {
64         LoggerD("Enter ");
65
66         if (contacts_disconnect2()  == CONTACTS_ERROR_NONE) {
67                 LoggerD("Successful to disconnect Call history DB ");
68         } else {
69                 LoggerD("Failed to disconnect Call history DB ");
70         }
71
72         int ret = CONTACTS_ERROR_NONE;
73         std::vector<CallHistory::WatcherPtr>::iterator it = CallHistory::m_watchers.begin();
74
75         if (m_watchers.size() > 0) {
76                 for (;it < CallHistory::m_watchers.end();) {
77                         //ret = contacts_db_remove_changed_cb(_contacts_phone_log._uri, callhistoryListenerCB, it->Get());
78                         ret = contacts_db_remove_changed_cb_with_info(_contacts_phone_log._uri, callhistoryListenerCB, it->Get());
79
80                         if (ret != CONTACTS_ERROR_NONE) {
81                                 LoggerD("callhistory remove listener error [" << ret << "]");
82                         }
83
84                         it = CallHistory::m_watchers.erase(it);
85                 }
86                 LoggerD("CallHistory Watcher is removed. (" << CallHistory::m_watchers.size() << ")");
87         }
88
89         EventCallHistoryPtr event(new EventCallHistory());
90         event->setCmdType(EventCallHistory::DISCONNECT);
91         event->setForSynchronousCall();
92         EventRequestReceiver<EventCallHistory>::PostRequest(event);
93 }
94
95 void CallHistory::callhistoryListenerCB(const char* view_uri, char *changes, void* user_data)
96 {
97         
98         if (user_data != NULL) {
99                 ((CallHistory::Watcher*)user_data)->ListenerCB(changes);
100         }
101 }
102
103 void CallHistory::removeBatchCB(int error, void *user_data)
104 {
105         LoggerD("enter");
106         if (user_data != NULL) {
107                 CallHistory* chManager = (CallHistory *)((EventCallHistoryPtrs<EventRemoveBatch> *)user_data)->getThisPtr();
108
109                 if (chManager) {
110                         EventRemoveBatchPtr event = ((EventCallHistoryPtrs<EventRemoveBatch> *)user_data)->getEventPtrs();
111                         chManager->callRemoveBatchEvent(error, event);
112                 }
113         }
114         return;
115 }
116
117 void CallHistory::removeAllCB(int error, void *user_data)
118 {
119         LoggerD("enter");
120         if (user_data != NULL) {
121                 CallHistory* chManager = (CallHistory *)((EventCallHistoryPtrs<EventRemoveAll> *)user_data)->getThisPtr();
122
123                 if (chManager) {
124                         EventRemoveAllPtr event = ((EventCallHistoryPtrs<EventRemoveAll> *)user_data)->getEventPtrs();
125                         chManager->callRemoveAllEvent(error, event);
126                 }
127         }
128         return;
129 }
130
131 bool CallHistory::convertCallHistory(callhistory_query_s *query_log, CallHistoryEntryListPtr &callEntries)
132 {
133         if (query_log == NULL || callEntries == NULL)
134                 return false;
135
136         CallHistoryEntryPropertiesPtr callHistoryItem(new CallHistoryEntryProperties());
137         StringArrayPtr stringArray(new StringArray());
138         RemotePartyPtr remoteParty(new RemoteParty());
139         RemotePartyListPtr remotePartyList(new RemotePartyList());
140
141         std::string callType("");
142         std::string tags("");
143         std::string direction("");
144         std::string number("");
145
146         if (query_log->phone_number != NULL) {
147                 number.append(query_log->phone_number);
148         }
149
150         switch(query_log->calllog_type) {
151         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING:
152                 callType.append(STR_TIZEN_TEL);
153                 tags.append(STR_CALL_VOICE);
154                 direction.append(STR_RECEIVED);
155                 break;
156         case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
157                 callType.append(STR_TIZEN_TEL);
158                 tags.append(STR_CALL_VOICE);
159                 direction.append(STR_DIALED);
160                 break;
161         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN:
162                 callType.append(STR_TIZEN_TEL);
163                 tags.append(STR_CALL_VOICE);
164                 direction.append(STR_MISSED);
165                 break;
166         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN:
167                 callType.append(STR_TIZEN_TEL);
168                 tags.append(STR_CALL_VOICE);
169                 direction.append(STR_MISSED_NEW);
170                 break;
171         case CONTACTS_PLOG_TYPE_VOICE_REJECT:
172                 callType.append(STR_TIZEN_TEL);
173                 tags.append(STR_CALL_VOICE);
174                 direction.append(STR_REJECTED);
175                 break;
176         case CONTACTS_PLOG_TYPE_VOICE_BLOCKED:
177                 callType.append(STR_TIZEN_TEL);
178                 tags.append(STR_CALL_VOICE);
179                 direction.append(STR_BLOCKED);
180                 break;
181         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING:
182                 callType.append(STR_TIZEN_TEL);
183                 tags.append(STR_CALL_VIDEO);
184                 direction.append(STR_RECEIVED);
185                 break;
186         case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
187                 callType.append(STR_TIZEN_TEL);
188                 tags.append(STR_CALL_VIDEO);
189                 direction.append(STR_DIALED);
190                 break;
191         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN:
192                 callType.append(STR_TIZEN_TEL);
193                 tags.append(STR_CALL_VIDEO);
194                 direction.append(STR_MISSED);
195                 break;
196         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN:
197                 callType.append(STR_TIZEN_TEL);
198                 tags.append(STR_CALL_VIDEO);
199                 direction.append(STR_MISSED_NEW);
200                 break;
201         case CONTACTS_PLOG_TYPE_VIDEO_REJECT:
202                 callType.append(STR_TIZEN_TEL);
203                 tags.append(STR_CALL_VIDEO);
204                 direction.append(STR_REJECTED);
205                 break;
206         case CONTACTS_PLOG_TYPE_VIDEO_BLOCKED:
207                 callType.append(STR_TIZEN_TEL);
208                 tags.append(STR_CALL_VIDEO);
209                 direction.append(STR_BLOCKED);
210                 break;
211         default:
212                 return false;
213         }
214
215         callHistoryItem->setEntryId(query_log->calllog_db_id);
216         callHistoryItem->setCallType(callType);
217         stringArray->push_back(tags);
218         callHistoryItem->setTags(stringArray);
219
220         remoteParty->setRemoteParty(number);
221         std::stringstream personIdStream;
222         personIdStream << query_log->person_db_id;
223         remoteParty->setPersonId(personIdStream.str());
224
225         remotePartyList->push_back(remoteParty);
226         callHistoryItem->setRemoteParties(remotePartyList);
227
228         callHistoryItem->setStartTime(query_log->timestamp);
229         callHistoryItem->setDuration((unsigned long)(query_log->duration_sec));
230         callHistoryItem->setDirection(direction);
231
232         callEntries->insert(callEntries->end(), callHistoryItem);
233
234         return true;
235 }
236
237 void CallHistory::find(const EventFindCallHistoryPtr& event)
238 {
239         EventRequestReceiver<EventFindCallHistory>::PostRequest(event);
240 }
241
242 bool CallHistory::remove(const unsigned long entryId)
243 {
244         try {
245                 int ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)entryId);
246
247                 if (ret == CONTACTS_ERROR_NONE) {
248                         return true;
249                 } else {
250                         return false;
251                 }
252         } catch (const Commons::PlatformException& ex) {
253                 ThrowMsg(Commons::PlatformException, ex.GetMessage());
254         }
255 }
256
257 void CallHistory::removeBatch(const EventRemoveBatchPtr& event)
258 {
259         EventRequestReceiver<EventRemoveBatch>::PostRequest(event);
260 }
261
262 void CallHistory::removeAll(const EventRemoveAllPtr& event)
263 {
264         EventRequestReceiver<EventRemoveAll>::PostRequest(event);
265 }
266
267 long CallHistory::addListener(const EventCallHistoryListenerEmitterPtr& emitter)
268 {
269         int ret =0;
270
271         if (CallHistory::m_watchers.size() == 0) {
272                 WatcherPtr watcher(new Watcher(0, emitter));
273                 ret = contacts_db_add_changed_cb_with_info(_contacts_phone_log._uri, callhistoryListenerCB, watcher.Get());
274
275                 watcher->setHandle(static_cast<long>(emitter->getId()));
276                 CallHistory::m_watchers.push_back(watcher);
277                 return watcher->getHandle();
278         } else {
279                 return 0;
280         }
281 }
282
283 void CallHistory::removeListener(const long id)
284 {
285         std::vector<CallHistory::WatcherPtr>::iterator it = CallHistory::m_watchers.begin();
286         bool flag = false;
287         int ret = CONTACTS_ERROR_NONE;
288
289         for (;it < CallHistory::m_watchers.end();) {
290
291                 LoggerD("removeListener : id ["<<id<<"]");
292                 LoggerD("removeListener : handle() ["<<(*it)->getHandle()<<"]");
293
294                 if (id == (*it)->getHandle()) {
295                         flag = true;
296                         ret = contacts_db_remove_changed_cb_with_info(_contacts_phone_log._uri, callhistoryListenerCB, it->Get());
297
298                         if (ret != CONTACTS_ERROR_NONE) {
299                                 LoggerD("callhistory remove listener error [" << ret << "]");
300                         }
301
302                         it = CallHistory::m_watchers.erase(it);
303                         continue;
304                 }
305                 ++it;
306         }
307
308         if (!flag) {
309                 ThrowMsg(Commons::InvalidArgumentException, "Invalid values error : handle");
310         }
311 }
312
313 bool CallHistory::parseRecord(contacts_list_h *recordList, CallHistoryEntryListPtr &callEntries)
314 {
315         int ret = CONTACTS_ERROR_NONE;
316         unsigned int total = 0;
317         contacts_record_h record = NULL;
318         callhistory_query_s query_data;
319         int logType = 0;
320         int time = 0;
321
322         contacts_list_get_count(*recordList, &total);
323
324         for (int i = 0; i < total; i++) {
325                 ret = contacts_list_get_current_record_p(*recordList, &record);
326
327                 if (record == NULL) {
328                         ret = contacts_list_next(*recordList);
329                         if (ret != CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
330                                 LoggerD("callhistory parse error [" << ret << "]");
331                                 return false;
332                         } else {
333                                 continue;
334                         }
335                 }
336
337                 memset(&query_data, 0x00, sizeof(callhistory_query_s));
338
339                 if (ret == CONTACTS_ERROR_NONE) {
340                         contacts_record_get_int(record, _contacts_phone_log.id, &(query_data.calllog_db_id));
341                         contacts_record_get_int(record, _contacts_phone_log.log_type , &logType);
342                         contacts_record_get_int(record, _contacts_phone_log.person_id, &(query_data.person_db_id));
343                         contacts_record_get_str_p(record, _contacts_phone_log.address, &(query_data.phone_number));
344                         contacts_record_get_int(record, _contacts_phone_log.log_time, &time);
345                         contacts_record_get_int(record, _contacts_phone_log.extra_data1, &(query_data.duration_sec));
346                         query_data.calllog_type = static_cast<contacts_phone_log_type_e>(logType);
347                         query_data.timestamp = static_cast<time_t>(time);
348                         convertCallHistory(&query_data, callEntries);
349                 }
350
351                 ret = contacts_list_next(*recordList);
352                 if (ret != CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
353                         LoggerD("callhistory parse error [" << ret << "]");
354                         return false;
355                 }
356         }
357
358         return true;
359
360 }
361
362 unsigned int CallHistory::convertAttrName(std::string &name)
363 {
364         std::string attrName("");
365         if (name.compare(STR_RP_REMOTEPARTY) == 0) {
366                 return _contacts_phone_log.address;
367         } else if (name.compare(STR_START_TIME) == 0) {
368                 return _contacts_phone_log.log_time;
369         } else if (name.compare(STR_DURATION) == 0) {
370                 return _contacts_phone_log.extra_data1;
371         } else if (name.compare(STR_DIRECTION) == 0) {
372                 return _contacts_phone_log.log_type;
373         } else if (name.compare(STR_ENTRY_ID) == 0) {
374                 return _contacts_phone_log.id;
375         } else {
376                 return 0;
377         }
378 }
379
380 void CallHistory::OnRequestReceived(const EventCallHistoryPtr& event)
381 {
382         try {
383                 if (event->getCmdType() == EventCallHistory::CONNECT) {
384                         if (contacts_connect2() == CONTACTS_ERROR_NONE) {
385                                 LoggerD("Successful to connect Call history DB by sub thread");
386                         } else {
387                                 LoggerD("Failed to connect Call history DB by sub thread");
388                         }
389                 } else if (event->getCmdType() == EventCallHistory::DISCONNECT) {
390                         if (contacts_disconnect2()  == CONTACTS_ERROR_NONE) {
391                                 LoggerD("Successful to disconnect Call history DB by sub thread");
392                         } else {
393                                 LoggerD("Failed to disconnect Call history DB by sub thread");
394                         }
395                 }
396         } catch (const Commons::PlatformException& ex) {
397                 LoggerE("Exception: " << ex.GetMessage());
398                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
399         }
400 }
401
402 void CallHistory::OnRequestReceived(const EventFindCallHistoryPtr& event)
403 {
404         try {
405                 LoggerD("enter");
406                 CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
407                 int ret = CONTACTS_ERROR_NONE;
408
409                 contacts_query_h query = NULL;
410                 contacts_filter_h filter = NULL;
411                 contacts_list_h recordList = NULL;
412                 bool isAscending = false;
413                 int limit = 0;
414                 int offset = 0;
415
416                 contacts_query_create(_contacts_phone_log._uri, &query);
417                 contacts_filter_create(_contacts_phone_log._uri, &filter);
418
419                 CallHistoryFilterPtr filtering(new CallHistoryFilter(filter));
420                 IFilterVisitorPtr filterTraversal = DPL::StaticPointerCast<IFilterVisitor>(filtering);
421
422                 if (event->getFilterIsSet()) {
423                         FilterPtr filterPtr = event->getFilter();
424                         filterPtr->travel(filterTraversal, 0);
425
426                         contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_AND);
427                         contacts_filter_add_int(filter, _contacts_phone_log.log_type, CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
428                 } else {
429                         contacts_filter_add_int(filter, _contacts_phone_log.log_type, CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
430                 }
431                 contacts_query_set_filter(query, filter);
432
433                 if (event->getSortModesIsSet()) {
434                         if (event->getSortMode()->getOrder() == DeviceAPI::Tizen::ASCENDING_SORT_ORDER) {
435                                 isAscending = true;
436                         } else {
437                                 isAscending = false;
438                         }
439                         std::string attriName(event->getSortMode()->getAttributeName());
440                         ret = contacts_query_set_sort(query, convertAttrName(attriName), isAscending);
441
442                 } else {
443                         ret = contacts_query_set_sort(query, _contacts_phone_log.id, isAscending);
444                 }
445
446                 if (ret != CONTACTS_ERROR_NONE) {
447                         LoggerD("callhistory query error [" << ret << "]");
448                 }
449
450
451                 if (event->getLimitIsSet()) {
452                         limit = static_cast<int>(event->getLimit());
453                 }
454
455                 if (event->getOffsetIsSet()) {
456                         offset = static_cast<int>(event->getOffset());
457                 }
458
459                 ret = contacts_db_get_records_with_query(query, offset, limit, &recordList);
460
461                 if (ret != CONTACTS_ERROR_NONE) {
462                         LoggerD("callhistory query error [" << ret << "]");
463                 }
464
465                 if (parseRecord(&recordList, callHistoryListPtr)) {
466                         event->setResult(callHistoryListPtr);
467                 }
468
469                 contacts_list_destroy(recordList, true);
470                 contacts_query_destroy(query);
471                 contacts_filter_destroy(filter);
472         } catch (const Commons::PlatformException& ex) {
473                 LoggerE("Exception: " << ex.GetMessage());
474                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
475         }
476 }
477
478 void CallHistory::OnRequestReceived(const EventRemoveBatchPtr& event)
479 {
480         int* list = NULL;
481
482         try {
483                 std::vector<unsigned long> entryIds = event->getEntryIds();
484                 unsigned int cnt = 0;
485                 int ret = CONTACTS_ERROR_NONE;
486                 list = new int[entryIds.size()];
487
488                 for (cnt = 0; cnt < entryIds.size(); cnt++) {
489                         list[cnt] = static_cast<int>(entryIds[cnt]);
490                 }
491
492                 if (entryIds.size() > 0) {
493                         EventRemoveBatchDataPtr eventData( new EventCallHistoryPtrs<EventRemoveBatch>(event, this));
494
495                         JSCallbackManagerPtr data = DPL::DynamicPointerCast<JSCallbackManager>(event->getPrivateData());
496                         if (data != NULL) {
497                                 if (data->getOnSuccess() != NULL) {
498                                         ret = contacts_db_delete_records_async(_contacts_phone_log._uri, list, entryIds.size(), removeBatchCB, eventData.Get());
499                                         if (ret == CONTACTS_ERROR_NONE) {
500                                                 m_removeBatchEvent.push_back(eventData);
501                                                 event->switchToManualAnswer();
502                                         } else {
503                                                 LoggerD("callhistory remove Batch error [" << ret << "]");
504                                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
505                                         }
506                                 } else {
507                                         ret = contacts_db_delete_records(_contacts_phone_log._uri, list, entryIds.size());
508                                         if (ret != CONTACTS_ERROR_NONE) {
509                                                 LoggerD("callhistory remove Batch error [" << ret << "]");
510                                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
511                                         }
512                                 }
513                         } else {
514                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
515                         }
516                 }
517
518         } catch (const Commons::PlatformException& ex) {
519                 LoggerE("Exception: " << ex.GetMessage());
520                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
521         }
522
523         if (list != NULL) {
524                 delete[] list;
525                 list = NULL;
526         }
527 }
528
529 void CallHistory::OnRequestReceived(const EventRemoveAllPtr& event)
530 {
531         int* list = NULL;
532
533         try {
534                 int ret = CONTACTS_ERROR_NONE;
535                 contacts_list_h record_list = NULL;
536                 contacts_record_h record = NULL;
537                 unsigned int total = 0;
538                 unsigned int cnt = 0;
539                 int value = 0;
540
541                 ret = contacts_db_get_all_records(_contacts_phone_log._uri, 0, 0, &record_list);
542
543                 if (record_list == NULL) {
544                         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
545                         return;
546                 }
547
548                 contacts_list_get_count(record_list, &total);
549
550                 list = new int[total];
551                 LoggerD("total [" << total << "]");
552                 for (unsigned int i = 0; i < total; i++) {
553                         ret = contacts_list_get_current_record_p(record_list, &record);
554
555                         if (record == NULL) {
556                                 ret = contacts_list_next(record_list);
557                                 if ( !(ret==CONTACTS_ERROR_NONE || ret==CONTACTS_ERROR_NO_DATA) ){
558                                         LoggerD("callhistory remove All error [" << ret << "]");
559                                         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
560                                 }
561                                 continue;
562                         }
563
564                         if (ret == CONTACTS_ERROR_NONE) {
565                                 ret = contacts_record_get_int(record, _contacts_phone_log.id , &value);
566                                 if (ret == CONTACTS_ERROR_NONE) {
567                                         list[cnt] = value;
568                                         cnt++;
569                                 }
570                         }
571                         value = 0;
572                         ret = contacts_list_next(record_list);
573                         if ( !(ret==CONTACTS_ERROR_NONE || ret==CONTACTS_ERROR_NO_DATA) ){
574                                 LoggerD("callhistory remove All error [" << ret << "]");
575                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
576                         }
577                 }
578
579                 LoggerD("cnt [" << cnt << "]");
580
581                 if (cnt > 0) {
582                         EventRemoveAllDataPtr eventData( new EventCallHistoryPtrs<EventRemoveAll>(event, this));
583
584                         JSCallbackManagerPtr data = DPL::DynamicPointerCast<JSCallbackManager>(event->getPrivateData());
585                         if (data != NULL) {
586                                 if (data->getOnSuccess() != NULL) {
587                                         ret = contacts_db_delete_records_async(_contacts_phone_log._uri, list, cnt, removeAllCB, eventData.Get());
588                                         if (ret == CONTACTS_ERROR_NONE) {
589                                                 m_removeAllEvent.push_back(eventData);
590                                                 event->switchToManualAnswer();
591                                         } else {
592                                                 LoggerD("callhistory remove All error [" << ret << "]");
593                                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
594                                         }
595                                 } else {
596                                         ret = contacts_db_delete_records(_contacts_phone_log._uri, list, cnt);
597                                         if (ret != CONTACTS_ERROR_NONE) {
598                                                 LoggerD("callhistory remove All error [" << ret << "]");
599                                                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
600                                         }
601                                 }
602                         }
603                 }
604
605                 contacts_list_destroy(record_list, true);
606         } catch (const Commons::PlatformException& ex) {
607                 LoggerE("Exception: " << ex.GetMessage());
608                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
609         }
610
611         if (list != NULL) {
612                 delete[] list;
613                 list = NULL;
614         }
615 }
616
617 void CallHistory::callRemoveBatchEvent(int error, const EventRemoveBatchPtr &event)
618 {
619         if (error != CONTACTS_ERROR_NONE) {
620                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
621         }
622
623         EventRequestReceiver<EventRemoveBatch>::ManualAnswer(event);
624
625         std::vector<EventRemoveBatchDataPtr>::iterator it;
626         for (it = m_removeBatchEvent.begin(); it != m_removeBatchEvent.end(); ++it) {
627                 if ((*it)->getEventPtrs() == event) {
628                         m_removeBatchEvent.erase(it);
629                         LoggerD("event is removed. (" << m_removeBatchEvent.size() << ")");
630                         break;
631                 }
632         }
633 }
634
635 void CallHistory::callRemoveAllEvent(int error, const EventRemoveAllPtr &event)
636 {
637         if (error != CONTACTS_ERROR_NONE) {
638                 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
639         }
640
641         EventRequestReceiver<EventRemoveAll>::ManualAnswer(event);
642
643         std::vector<EventRemoveAllDataPtr>::iterator it;
644         for (it = m_removeAllEvent.begin(); it != m_removeAllEvent.end(); ++it) {
645                 if ((*it)->getEventPtrs() == event) {
646                         m_removeAllEvent.erase(it);
647                         LoggerD("event is removed. (" << m_removeAllEvent.size() << ")");
648                         break;
649                 }
650         }
651 }
652
653 CallHistory::Watcher::Watcher(long handle, const EventCallHistoryListenerEmitterPtr& emitter) :
654                         m_handle(handle),
655                         m_emitter(emitter),
656                         m_currentLogId(0)
657 {
658         m_missedCallList = MissedCallListPtr(new MissedCallList());
659         if (contacts_connect2() == CONTACTS_ERROR_NONE) {
660                 LoggerD("Successful to connect Call history DB ");
661         } else {
662                 LoggerD("Failed to connect Call history DB ");
663         }
664 }
665
666 CallHistory::Watcher::~Watcher()
667 {
668         if (contacts_disconnect2()  == CONTACTS_ERROR_NONE) {
669                 LoggerD("Successful to disconnect Call history DB ");
670         } else {
671                 LoggerD("Failed to disconnect Call history DB ");
672         }
673 }
674
675 void CallHistory::Watcher::stateHasChanged(CallHistoryEntryListPtr &entryList, EventCallHistoryListener::ResultStates state)
676 {
677         if (entryList == NULL)
678                 return;
679
680         LoggerD("enter");
681
682         EventCallHistoryListenerPtr event(new EventCallHistoryListener());
683         event->setResultState(state);
684         event->setResult(entryList);
685         m_emitter->emit(event);
686 }
687
688 void CallHistory::Watcher::stateHasRemoved(StringArrayPtr &entryList, EventCallHistoryListener::ResultStates state)
689 {
690         if (entryList == NULL)
691                 return;
692
693         LoggerD("enter");
694
695         EventCallHistoryListenerPtr event(new EventCallHistoryListener());
696         event->setResultState(state);
697         event->setRemoveResult(entryList);
698         m_emitter->emit(event);
699 }
700
701
702 bool CallHistory::Watcher::parseRecord(contacts_list_h *recordList, CallHistoryEntryListPtr &entryList)
703 {
704         CallHistory* callHistory = (CallHistory *) this;
705         if (callHistory != NULL) {
706                 return callHistory->parseRecord(recordList, entryList);
707         }
708         return false;
709 }
710
711 bool CallHistory::Watcher::parseRemoveRecord(char* record, StringArrayPtr &removeRecords)
712 {
713         std::string recordStr(record);
714         removeRecords->push_back(recordStr);
715
716         return true;
717 }
718
719 void CallHistory::Watcher::ListenerCB(char* changes)
720 {
721         LoggerD("enter");
722
723         char seps[] = ",:";
724         char* tokenType = NULL;
725         char* tokenId = NULL;
726         int changeType = 0;
727         int changeId = 0;
728
729         CallHistoryEntryListPtr callHistoryListPtr(new CallHistoryEntryList());
730         StringArrayPtr RemoveListPtr(new StringArray());
731
732         tokenType = strtok( changes, seps );
733         while( tokenType != NULL )
734         {
735                 tokenId = strtok( NULL, seps );
736                 LoggerD("[ %s / %s ]", tokenType , tokenId );
737                 changeType = atoi((const char*)tokenType);
738                 changeId = atoi((const char*)tokenId);
739
740
741                 contacts_query_h query = NULL;
742                 contacts_filter_h filter = NULL;
743                 contacts_list_h recordList = NULL;
744                 int ret = CONTACTS_ERROR_NONE;
745
746                 contacts_query_create(_contacts_phone_log._uri, &query);
747                 contacts_filter_create(_contacts_phone_log._uri, &filter);
748                 contacts_filter_add_int(filter, _contacts_phone_log.id, CONTACTS_MATCH_EQUAL, changeId  );
749
750                 contacts_query_set_filter(query, filter);
751
752                 ret = contacts_query_set_sort(query, _contacts_phone_log.id, false);
753                 if (ret != CONTACTS_ERROR_NONE) {
754                         LoggerD("callhistory query error [" << ret << "]");
755                 }
756
757                 ret = contacts_db_get_records_with_query(query, 0, 1, &recordList);
758                 if (ret != CONTACTS_ERROR_NONE) {
759                         contacts_list_destroy(recordList, true);
760                         contacts_query_destroy(query);
761                         contacts_filter_destroy(filter);
762                         LoggerD("callhistory query error [" << ret << "]");
763                         return;
764                 }
765
766                 if((changeType == CONTACTS_CHANGE_INSERTED)||(changeType == CONTACTS_CHANGE_UPDATED)){
767                         if (parseRecord(&recordList, callHistoryListPtr)) {
768                                 if (callHistoryListPtr->size() > 0) {
769                                         setCurrentLogId((*callHistoryListPtr)[0]->getEntryId());
770                                 }
771                         }
772                 }else if(changeType == CONTACTS_CHANGE_DELETED){
773                         parseRemoveRecord(tokenId, RemoveListPtr);
774                 }
775
776                 contacts_list_destroy(recordList, true);
777                 contacts_query_destroy(query);
778                 contacts_filter_destroy(filter);
779
780                 tokenType = strtok( NULL, seps );
781         }
782
783
784         if((changeType == CONTACTS_CHANGE_INSERTED)||(changeType == CONTACTS_CHANGE_UPDATED)){
785                 if (callHistoryListPtr->size() > 0) {
786                         setCurrentLogId((*callHistoryListPtr)[0]->getEntryId());
787
788                         if(changeType == CONTACTS_CHANGE_INSERTED){
789                                 stateHasChanged(callHistoryListPtr, EventCallHistoryListener::ADDED);
790                         }else if(changeType == CONTACTS_CHANGE_UPDATED){
791                                 stateHasChanged(callHistoryListPtr, EventCallHistoryListener::CHANGED);
792                         }
793
794                 }
795         }else if(changeType == CONTACTS_CHANGE_DELETED){
796                 stateHasRemoved(RemoveListPtr, EventCallHistoryListener::REMOVED);
797         }
798
799 }
800
801 }
802 }
803