TizenRefApp-5710 Integrate DBChangeObserver class 01/59701/3
authorSergei Kobec <s.kobec@samsung.com>
Thu, 18 Feb 2016 09:36:45 +0000 (11:36 +0200)
committerEugene Kurzberg <i.kurtsberg@samsung.com>
Thu, 18 Feb 2016 11:32:54 +0000 (03:32 -0800)
Change-Id: I5fe9352c632cdaddbbf6454b84153a14b00bb4c1
Signed-off-by: Sergei Kobec <s.kobec@samsung.com>
lib-contact/inc/Contacts/List/Model/PersonProvider.h
lib-contact/inc/Contacts/List/PersonItem.h
lib-contact/src/Contacts/List/Model/DbChangeObserver.cpp
lib-contact/src/Contacts/List/Model/PersonProvider.cpp
lib-contact/src/Contacts/List/PersonItem.cpp

index ee78138..417235a 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef CONTACTS_LIST_MODEL_PERSON_PROVIDER_H
 #define CONTACTS_LIST_MODEL_PERSON_PROVIDER_H
 
+#include "Contacts/List/Model/DbChangeObserver.h"
 #include "Contacts/List/Model/Person.h"
 #include <contacts.h>
 #include <functional>
@@ -57,17 +58,17 @@ namespace Contacts
                                };
 
                                /**
-                                * @brief Person change callback
+                                * @brief Person insert callback
                                 * @param[in]    person        Person object
-                                * @param[in]    changeType    Change type
                                 */
-                               typedef std::function<void(PersonPtr person, contacts_changed_e changeType)> ChangeCallback;
+                               typedef std::function<void(PersonPtr person)> InsertCallback;
 
                                /**
-                                * @brief Person insert callback
+                                * @brief Person change callback
                                 * @param[in]    person        Person object
+                                * @param[in]    changeType    Change type
                                 */
-                               typedef std::function<void(PersonPtr person)> InsertCallback;
+                               typedef std::function<void(PersonPtr person, contacts_changed_e changeType)> ChangeCallback;
 
                                /**
                                 * @brief Constructor
@@ -85,6 +86,17 @@ namespace Contacts
                                PersonList getPersonList() const;
 
                                /**
+                                * @brief Set person insert callback
+                                * @param[in]    callback    Create callback
+                                */
+                               void setInsertCallback(InsertCallback callback);
+
+                               /**
+                                * @brief Unset person insert callback
+                                */
+                               void unsetInsertCallback();
+
+                               /**
                                 * @brief Set person change callback
                                 * @remark It can be update or delete of person
                                 * @param[in]    person      Person
@@ -98,29 +110,15 @@ namespace Contacts
                                 */
                                void unsetChangeCallback(const Person &person);
 
-                               /**
-                                * @brief Set person insert callback
-                                * @param[in]    callback    Create callback
-                                */
-                               void setInsertCallback(InsertCallback callback);
-
-                               /**
-                                * @brief Unset person insert callback
-                                */
-                               void unsetInsertCallback();
-
                        private:
-                               void onChanged(const char *viewUri);
-                               void notify(contacts_changed_e changeType, int contactId);
-
+                               void onPersonInserted(int id, contacts_changed_e changeType);
+                               void onPersonChanged(int id, contacts_changed_e changeType);
 
                                Mode m_Mode;
                                FilterType m_FilterType;
 
-                               int m_DbVersion;
-
-                               std::unordered_map<int, ChangeCallback> m_ChangeCallbacks;
-                               InsertCallback m_InsertCallback;
+                               std::pair<InsertCallback, Model::DbChangeObserver::CallbackHandle> m_InsertCallback;
+                               std::unordered_map<int, std::pair<ChangeCallback, Model::DbChangeObserver::CallbackHandle>> m_ChangeCallbacks;
                        };
                }
        }
index 6d0e900..adee1fc 100644 (file)
@@ -61,7 +61,7 @@ namespace Contacts
                        /**
                         * @return Person object
                         */
-                       const Model::Person &getPerson() const;
+                       Model::Person &getPerson();
 
                        /**
                         * @brief Set person object
index fe868ba..a0105ea 100644 (file)
@@ -29,6 +29,16 @@ namespace
        };
 }
 
+DbChangeObserver::DbChangeObserver(Table table)
+       : m_Table(table), m_DbVersion(0), m_IsSubscribed(false)
+{
+}
+
+DbChangeObserver::~DbChangeObserver()
+{
+       unsubscribe();
+}
+
 DbChangeObserver *DbChangeObserver::getInstance(Table table)
 {
        if (table < 0 || table >= Utils::count(m_Observers)) {
@@ -38,11 +48,6 @@ DbChangeObserver *DbChangeObserver::getInstance(Table table)
        return &m_Observers[table];
 }
 
-DbChangeObserver::~DbChangeObserver()
-{
-       unsubscribe();
-}
-
 DbChangeObserver::CallbackHandle DbChangeObserver::addCallback(Callback callback)
 {
        return addCallback(m_Callbacks, std::move(callback));
@@ -67,10 +72,10 @@ void DbChangeObserver::removeCallback(int id, CallbackHandle handle)
        auto it = m_ChangeCallbacks.find(id);
        if (it != m_ChangeCallbacks.end()) {
                it->second.erase(handle);
-       }
 
-       if (it->second.empty()) {
-               m_ChangeCallbacks.erase(it);
+               if (it->second.empty()) {
+                       m_ChangeCallbacks.erase(it);
+               }
        }
 
        if (m_Callbacks.empty() && m_ChangeCallbacks.empty()) {
@@ -78,11 +83,6 @@ void DbChangeObserver::removeCallback(int id, CallbackHandle handle)
        }
 }
 
-DbChangeObserver::DbChangeObserver(Table table)
-       : m_Table(table), m_DbVersion(0), m_IsSubscribed(false)
-{
-}
-
 void DbChangeObserver::subscribe()
 {
        contacts_db_get_current_version(&m_DbVersion);
@@ -142,7 +142,8 @@ void DbChangeObserver::notifyContactChanges()
 void DbChangeObserver::notify(int id, contacts_changed_e changeType)
 {
        auto notifyAll = [id, changeType](const RecordCbs &callbacks) {
-               for (auto &&callback : callbacks) {
+               for (auto it = callbacks.begin(); it != callbacks.end(); ) {
+                       auto &callback = *it++;
                        if (callback) {
                                callback(id, changeType);
                        }
index 8579ab5..b2ff0e7 100644 (file)
@@ -22,6 +22,7 @@
 #include "Utils/Logger.h"
 
 using namespace Contacts::List::Model;
+using namespace std::placeholders;
 
 namespace
 {
@@ -158,14 +159,15 @@ PersonProvider::PersonProvider(Mode modeType, FilterType filterType)
                ERR("ModeTypeMFC is not supported");
                m_Mode = ModeAll;
        }
-
-       contacts_db_get_current_version(&m_DbVersion);
-       contacts_db_add_changed_cb(_contacts_person._uri, makeCallbackWithLastParam(&PersonProvider::onChanged), this);
 }
 
 PersonProvider::~PersonProvider()
 {
-       contacts_db_remove_changed_cb(_contacts_person._uri, makeCallbackWithLastParam(&PersonProvider::onChanged), this);
+       unsetInsertCallback();
+
+       for (auto &&callback : m_ChangeCallbacks) {
+               DbChangeObserver::getInstance()->removeCallback(callback.first, callback.second.second);
+       }
 }
 
 PersonList PersonProvider::getPersonList() const
@@ -183,84 +185,82 @@ PersonList PersonProvider::getPersonList() const
        return personList;
 }
 
-void PersonProvider::setChangeCallback(const Person &person, ChangeCallback callback)
-{
-       auto ids = person.getContactIds();
-
-       auto it = ids.begin();
-       for (; it < ids.end() - 1; ++it) {
-               m_ChangeCallbacks.insert({ *it, callback });
-       }
-       m_ChangeCallbacks.insert({ *it, std::move(callback) });
-}
-
-void PersonProvider::unsetChangeCallback(const Person &person)
-{
-       for (auto &&id: person.getContactIds()) {
-               m_ChangeCallbacks.erase(id);
-       }
-}
-
 void PersonProvider::setInsertCallback(InsertCallback callback)
 {
-       m_InsertCallback = std::move(callback);
+       auto handle = DbChangeObserver::getInstance()->addCallback(
+                       std::bind(&PersonProvider::onPersonInserted, this, _1, _2));
+       m_InsertCallback = { std::move(callback), std::move(handle) };
 }
 
 void PersonProvider::unsetInsertCallback()
 {
-       m_InsertCallback = nullptr;
+       if (m_InsertCallback.first) {
+               auto handle = m_InsertCallback.second;
+               DbChangeObserver::getInstance()->removeCallback(handle);
+               m_InsertCallback.first = nullptr;
+       }
 }
 
-void PersonProvider::onChanged(const char *viewUri)
+void PersonProvider::setChangeCallback(const Person &person, ChangeCallback callback)
 {
-       contacts_list_h changes = nullptr;
-       contacts_db_get_changes_by_version(_contacts_contact_updated_info._uri, 0, m_DbVersion, &changes, &m_DbVersion);
+       auto addCallback = [this](int id, ChangeCallback callback) {
+               auto handle = DbChangeObserver::getInstance()->addCallback(id,
+                       std::bind(&PersonProvider::onPersonChanged, this, _1, _2));
 
-       contacts_record_h record = nullptr;
-       CONTACTS_LIST_FOREACH(changes, record) {
-               int contactId = 0;
-               int changeType = -1;
+               m_ChangeCallbacks.insert({ id, { std::move(callback), std::move(handle) } });
+       };
 
-               contacts_record_get_int(record, _contacts_contact_updated_info.contact_id, &contactId);
-               contacts_record_get_int(record, _contacts_contact_updated_info.type, &changeType);
+       auto ids = person.getContactIds();
+       auto it = ids.begin();
 
-               notify(static_cast<contacts_changed_e>(changeType), contactId);
+       for (; it < ids.end() - 1; ++it) {
+               addCallback(*it, callback);
        }
 
-       contacts_list_destroy(changes, true);
+       addCallback(*it, std::move(callback));
 }
 
-void PersonProvider::notify(contacts_changed_e changeType, int contactId)
+void PersonProvider::unsetChangeCallback(const Person &person)
 {
-       auto getPerson = [this, contactId]() -> PersonPtr {
-               contacts_record_h personRecord = getPersonRecord(contactId, m_Mode, m_FilterType);
-               return personRecord ? PersonPtr(new Person(personRecord)) : nullptr;
-       };
+       for (auto &&id: person.getContactIds()) {
+               auto it = m_ChangeCallbacks.find(id);
+               if (it != m_ChangeCallbacks.end()) {
+                       auto handle = it->second.second;
+                       DbChangeObserver::getInstance()->removeCallback(id, handle);
+
+                       m_ChangeCallbacks.erase(it);
+               }
+       }
+}
 
-       PersonPtr person;
+void PersonProvider::onPersonInserted(int id, contacts_changed_e changeType)
+{
+       if (changeType == CONTACTS_CHANGE_INSERTED) {
+               auto callback = m_InsertCallback.first;
+               if (callback) {
+                       contacts_record_h record = getPersonRecord(id, m_Mode, m_FilterType);
+                       callback(PersonPtr(new Person(record)));
+               }
+       }
+}
 
-       switch (changeType) {
-               case CONTACTS_CHANGE_INSERTED:
-                       person = getPerson();
-                       if (m_InsertCallback && person) {
-                               m_InsertCallback(std::move(person));
-                       }
-                       break;
-               case CONTACTS_CHANGE_UPDATED:
-                       //Todo: If will be link contact functionality, update only when display contact changed
-                       person = getPerson();
-                       if (!person) {
-                               return;
-                       }
-                       //Fallthrough case statement by intention
-               case CONTACTS_CHANGE_DELETED:
-               {
-                       auto it = m_ChangeCallbacks.find(contactId);
-                       if (it != m_ChangeCallbacks.end()) {
-                               //Todo: If will be link contact functionality, delete only when it was last contact in person
-                               it->second(std::move(person), changeType);
+void PersonProvider::onPersonChanged(int id, contacts_changed_e changeType)
+{
+       auto it = m_ChangeCallbacks.find(id);
+       if (it != m_ChangeCallbacks.end()) {
+               auto callback = it->second.first;
+
+               if (callback) {
+                       if (changeType == CONTACTS_CHANGE_UPDATED) {
+                               contacts_record_h record = getPersonRecord(id, m_Mode, m_FilterType);
+                               if (record) {
+                                       callback(PersonPtr(new Person(record)), changeType);
+                               } else {
+                                       callback(nullptr, CONTACTS_CHANGE_DELETED);
+                               }
+                       } else if (changeType == CONTACTS_CHANGE_DELETED) {
+                               callback(nullptr, changeType);
                        }
                }
-                       break;
        }
 }
index d275289..3100eb6 100644 (file)
@@ -32,7 +32,7 @@ void PersonItem::setMode(Mode mode)
        elm_genlist_item_fields_update(getObjectItem(), PART_CHECK, ELM_GENLIST_ITEM_FIELD_CONTENT);
 }
 
-const Person &PersonItem::getPerson() const
+Person &PersonItem::getPerson()
 {
        return *m_Person;
 }