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