[Callhistory] Added remove, removeBatch/All implementation.
authorTomasz Marciniak <t.marciniak@samsung.com>
Sun, 14 Dec 2014 07:41:58 +0000 (08:41 +0100)
committerTomasz Marciniak <t.marciniak@samsung.com>
Tue, 16 Dec 2014 09:38:24 +0000 (10:38 +0100)
[Verification] Code compiles without errors.
CallHistoryEntry can be removed.

Change-Id: Ic54075d1f52ff00520663cbe6a63f85bc8760db0
Signed-off-by: Tomasz Marciniak <t.marciniak@samsung.com>
src/callhistory/callhistory.cc
src/callhistory/callhistory.h
src/callhistory/callhistory_api.js
src/callhistory/callhistory_instance.cc

index c941eb29533f79f45c019b208f3149acf55d25c0..0c20ecdd82ee8b769f173585b06a760d7e804424 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "common/logger.h"
 #include "common/platform_exception.h"
+#include "common/task-queue.h"
 #include "callhistory_instance.h"
 #include "callhistory_types.h"
 #include "callhistory_utils.h"
@@ -40,6 +41,16 @@ static void get_sim_msisdn_cb(TapiHandle *handle, int result, void *data, void *
     std::string n = number ? std::string(number) : "";
     prom->set_value(n);
 }
+
+void ReportSuccess(picojson::object& out) {
+  out.insert(std::make_pair("status", picojson::value("success")));
+}
+
+void ReportError(const PlatformException& ex, picojson::object& out) {
+  out.insert(std::make_pair("status", picojson::value("error")));
+  out.insert(std::make_pair("error", ex.ToJSON()));
+}
+
 }
 
 CallHistory::CallHistory():
@@ -85,19 +96,177 @@ void CallHistory::find()
 
 }
 
-void CallHistory::remove()
+void CallHistory::remove(const picojson::object& args)
 {
+    LoggerD("Entered");
+
+    const auto it_uid = args.find("uid");
+    const auto it_args_end = args.end();
 
+    if (it_uid == it_args_end ||
+        !it_uid->second.is<std::string>()) {
+        LoggerE("Invalid parameter was passed.");
+        throw InvalidValuesException("Invalid parameter was passed.");
+    }
+
+    int uid = atoi((it_uid->second.get<std::string>()).c_str());
+    int ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)uid);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LoggerE("Failed to delete log record [%d] with error: %d", uid, ret);
+        throw UnknownException("Failed to delete log record.");
+    }
 }
 
-void CallHistory::removeBatch()
+void CallHistory::removeBatch(const picojson::object& args)
 {
+    LoggerD("Entered");
+
+    const auto it_uid = args.find("uid");
+    const auto it_args_end = args.end();
 
+    if (it_uid == it_args_end ||
+        !it_uid->second.is<picojson::array>()) {
+        throw InvalidValuesException("Invalid parameter was passed.");
+    }
+    const picojson::array& uids = it_uid->second.get<picojson::array>();
+    const double callback_id = args.find("callbackId")->second.get<double>();
+
+    auto remove_batch = [uids](const std::shared_ptr<picojson::value>& response) -> void {
+        try {
+            if (uids.size() == 0) {
+                throw UnknownException("Object is null.");
+            }
+
+            int uid;
+            int ret = CONTACTS_ERROR_NONE;
+            for (unsigned int i = 0; i < uids.size(); ++i) {
+                uid = atoi(uids[i].get<std::string>().c_str());
+                ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)uid);
+                if (CONTACTS_ERROR_NONE != ret) {
+                    LoggerE("Failed to delete log [%d] with code %d", uid, ret);
+                    throw UnknownException("contacts_db_delete_record failed");
+                }
+            }
+            ReportSuccess(response->get<picojson::object>());
+        } catch (const PlatformException& err) {
+            ReportError(err, response->get<picojson::object>());
+        }
+    };
+
+    auto remove_batch_response = [callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", callback_id));
+        CallHistoryInstance::getInstance().PostMessage(response->serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Queue<picojson::value>(
+            remove_batch,
+            remove_batch_response,
+            std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
 }
 
-void CallHistory::removeAll()
+void CallHistory::removeAll(const picojson::object& args)
 {
+    LoggerD("Entered");
 
+    const double callback_id = args.find("callbackId")->second.get<double>();
+
+    auto remove_all = [](const std::shared_ptr<picojson::value>& response) -> void {
+        contacts_list_h record_list = NULL;
+        int* list = NULL;
+
+        try {
+            contacts_record_h record = NULL;
+            int ret = CONTACTS_ERROR_NONE;
+            int total = 0;
+            int value;
+            unsigned int cnt = 0;
+
+            ret = contacts_connect_on_thread();
+            if (CONTACTS_ERROR_NONE != ret) {
+                LoggerW("contacts_connect_on_thread failed");
+            }
+
+            ret = contacts_db_get_all_records(_contacts_phone_log._uri, 0, 0, &record_list);
+            if (CONTACTS_ERROR_NONE != ret || !record_list) {
+                LoggerE("Failed to get all records list");
+                throw UnknownException("Failed to get all records list");
+            }
+
+            ret = contacts_list_get_count(record_list, &total);
+            if (CONTACTS_ERROR_NONE != ret) {
+                LoggerW("Failed to get count");
+            }
+
+            list = new int[total];
+            for (int i = 0; i < total; i++) {
+                LoggerD("Record number: %d", i);
+                ret = contacts_list_get_current_record_p(record_list, &record);
+                if (CONTACTS_ERROR_NONE != ret) {
+                    LoggerW("contacts_list_get_current_record_p function failed");
+                }
+
+                if (!record) {
+                    ret = contacts_list_next(record_list);
+                    if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+                        LoggerE("contacts_list_next function failed");
+                        throw UnknownException("contacts_list_next function failed");
+                    }
+                    continue;
+                }
+
+                if (CONTACTS_ERROR_NONE == ret) {
+                    ret = contacts_record_get_int(record, _contacts_phone_log.id , &value);
+                    if (CONTACTS_ERROR_NONE == ret) {
+                        list[cnt++] = value;
+                    }
+                }
+
+                value = 0;
+                ret = contacts_list_next(record_list);
+                if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+                    LoggerE("contacts_list_next function failed");
+                    throw UnknownException("contacts_list_next function failed");
+                }
+            }
+
+            if (cnt > 0) {
+                ret = contacts_db_delete_records(_contacts_phone_log._uri, list, cnt);
+                if (CONTACTS_ERROR_NONE != ret) {
+                    LoggerE("contacts_db_delete_records function failed");
+                    throw UnknownException("contacts_db_delete_records function failed");
+                }
+            }
+
+            delete[] list;
+            ret = contacts_list_destroy(record_list, true);
+            if (CONTACTS_ERROR_NONE != ret) {
+                LoggerW("contacts_list_destroy failed");
+            }
+
+            ret = contacts_disconnect_on_thread();
+            if (CONTACTS_ERROR_NONE != ret) {
+                LoggerW("contacts_disconnect_on_thread failed");
+            }
+
+            ReportSuccess(response->get<picojson::object>());
+        } catch (const PlatformException& err) {
+            contacts_list_destroy(record_list, true);
+            delete[] list;
+            ReportError(err, response->get<picojson::object>());
+        }
+    };
+
+    auto remove_all_response = [callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", callback_id));
+        CallHistoryInstance::getInstance().PostMessage(response->serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Queue<picojson::value>(
+            remove_all,
+            remove_all_response,
+            std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
 }
 
 std::vector<std::string>& CallHistory::getPhoneNumbers()
index 2f4dcd11dc654e6c90256302fd571e7d69568c29..52a84335204318e6d372f1013ae878426feccbe9 100644 (file)
@@ -10,6 +10,7 @@
 #include <future>
 #include <contacts.h>
 #include <contacts_internal.h>
+#include "common/picojson.h"
 
 namespace extension {
 namespace callhistory {
@@ -23,9 +24,9 @@ public:
     std::vector<std::string>& getPhoneNumbers();
 
     void find();
-    void remove();
-    void removeBatch();
-    void removeAll();
+    void remove(const picojson::object& args);
+    void removeBatch(const picojson::object& args);
+    void removeAll(const picojson::object& args);
     void startCallHistoryChangeListener();
     void stopCallHistoryChangeListener();
 
index 572a0a1977221b8f6203464c6033863c7d2ef740..4b818d5f893c5473743ae43eb6ac210493a26dea 100644 (file)
@@ -42,14 +42,9 @@ Common.prototype.callSync = function (cmd, args) {
     return obj.result;
 };
 
-Common.prototype.getCall = function (module) {
-    return function _call(method, args, callback) {
-        return JSON.parse(native.call(_prepareRequest(module, method, args), function (result) {
-            if (typeof callback === 'function') {
-                callback(JSON.parse(result));
-            }
-        }));
-    };
+Common.prototype.call = function (cmd, args, callback) {
+    var request = _prepareRequest(cmd, args, callback);
+    extension.postMessage(JSON.stringify(request));
 };
 
 Common.prototype.isSuccess = function (result) {
@@ -218,6 +213,8 @@ var C = _common.Common;
 
 var _listeners = {};
 var _listenersId = 0;
+var _callbacks = {};
+var _callbackId = 0;
 
 function _createCallHistoryEntries(e) {
     var entries_array = [];
@@ -230,6 +227,16 @@ function _createCallHistoryEntries(e) {
     return entries_array;
 };
 
+function _getUidFromCallHistoryEntry(entries) {
+    var uid = [];
+
+    entries.forEach(function (data) {
+        uid.push(data.uid);
+    });
+
+    return uid;
+};
+
 extension.setMessageListener(function(msg) {
     var m = JSON.parse(msg);
     if (m.cmd == 'CallHistoryChangeCallback') {
@@ -255,6 +262,9 @@ extension.setMessageListener(function(msg) {
                 _listeners[watchId][m.action](d);
             }
         }
+    } else if (m.hasOwnProperty('callbackId')) {
+       _callbacks[m.callbackId](m);
+       delete _callbacks[m.callbackId];
     }
 });
 
@@ -266,15 +276,93 @@ CallHistory.prototype.find = function() {
 };
 
 CallHistory.prototype.remove = function() {
+    var args = AV.validateArgs(arguments, [
+        {
+            name : 'entry',
+            type : AV.Types.PLATFORM_OBJECT,
+            values : CallHistoryEntry
+        }
+    ]);
+
+    var callArgs = {};
+    callArgs.uid = args.entry.uid;
 
+    C.callSync('CallHistory_remove', callArgs);
 };
 
 CallHistory.prototype.removeBatch = function() {
+    console.log('removeBatch');
+    var args = AV.validateArgs(arguments, [
+        {
+            name : 'entries',
+            type : AV.Types.ARRAY,
+            values : CallHistoryEntry
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (C.isFailure(result)) {
+            C.callIfPossible(args.errorCallback, C.getErrorObject(result));
+        } else {
+            C.callIfPossible(args.successCallback);
+        }
+    };
 
+    var callbackId = ++_callbackId;
+    _callbacks[callbackId] = callback;
+
+    var uid = _getUidFromCallHistoryEntry(args.entries);
+    var callArgs = {};
+
+    callArgs.uid = uid;
+    callArgs.callbackId = callbackId;
+
+    C.call('CallHistory_removeBatch', callArgs, callback);
 };
 
 CallHistory.prototype.removeAll = function() {
+    var args = AV.validateArgs(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (C.isFailure(result)) {
+            C.callIfPossible(args.errorCallback, C.getErrorObject(result));
+        } else {
+            C.callIfPossible(args.successCallback);
+        }
+    };
+
+    var callbackId = ++_callbackId;
+    _callbacks[callbackId] = callback;
+
+    var callArgs = {};
+    callArgs.callbackId = callbackId;
 
+    C.call('CallHistory_removeAll', callArgs, callback);
 };
 
 CallHistory.prototype.addChangeListener = function() {
index 40ac741cd29e8b38207471ea83910ad014a8230c..d3eafe6c5668a698d7f6dbb95b9714bec6189b94 100644 (file)
@@ -48,15 +48,19 @@ void CallHistoryInstance::Find(const picojson::value& args, picojson::object& ou
 }
 
 void CallHistoryInstance::Remove(const picojson::value& args, picojson::object& out) {
-
+    LoggerD("Entered");
+    CallHistory::getInstance()->remove(args.get<picojson::object>());
+    ReportSuccess(out);
 }
 
 void CallHistoryInstance::RemoveBatch(const picojson::value& args, picojson::object& out) {
-
+    LoggerD("Entered");
+    CallHistory::getInstance()->removeBatch(args.get<picojson::object>());
 }
 
 void CallHistoryInstance::RemoveAll(const picojson::value& args, picojson::object& out) {
-
+    LoggerD("Entered");
+    CallHistory::getInstance()->removeAll(args.get<picojson::object>());
 }
 
 void CallHistoryInstance::AddChangeListener(const picojson::value& args, picojson::object& out) {