From 50674ccaf91d0000503f19820f6a2df1d7e40430 Mon Sep 17 00:00:00 2001 From: Sergei Kobec Date: Wed, 13 Apr 2016 15:20:43 +0300 Subject: [PATCH] TizenRefApp-6091 Refactor contact's compare logic to support Search Change-Id: I499c589c2c32c54446e38da1b3eaa2bb8f06e26c Signed-off-by: Sergei Kobec --- lib-common/inc/Contacts/Model/SearchEngine.h | 79 ++++++++++ .../src/Contacts/Model/SearchEngine.cpp | 143 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 lib-common/inc/Contacts/Model/SearchEngine.h create mode 100644 lib-common/src/Contacts/Model/SearchEngine.cpp diff --git a/lib-common/inc/Contacts/Model/SearchEngine.h b/lib-common/inc/Contacts/Model/SearchEngine.h new file mode 100644 index 00000000..25093c4e --- /dev/null +++ b/lib-common/inc/Contacts/Model/SearchEngine.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef PHONE_DIALER_SEARCH_ENGINE_H +#define PHONE_DIALER_SEARCH_ENGINE_H + +#include "Contacts/Model/ContactData.h" +#include +#include + +namespace Contacts +{ + namespace Model + { + class SearchProvider; + + /** + * @brief This class provides incremental search logic + */ + class SearchEngine + { + public: + explicit SearchEngine(SearchProvider &searchProvider); + + /** + * @brief Perform incremental search + * @param[in] query Value to find + */ + void search(const std::string &query); + + /** + * @brief Retrieves result list + * @return Result list or nullptr on empty list + */ + const ContactDataList *getSearchResult() const; + + /** + * @return true if there is no results, otherwise false + */ + bool empty() const; + + private: + typedef std::vector SearchHistory; + + void firstSearch(const std::string &query); + void chooseSearch(const std::string &query); + + bool searchInCache(SearchHistory::iterator from, const std::string &query); + SearchHistory::reverse_iterator firstMismatch(const std::string &query); + SearchHistory::reverse_iterator skipEmptyResults(size_t offset); + + void clear(); + + bool needSearch(const std::string &query); + + std::string m_Query; + SearchHistory m_Cache; + int m_LastFoundIndex; + + SearchProvider &m_SearchProvider; + }; + } +} + +#endif /* PHONE_DIALER_SEARCH_ENGINE_H */ diff --git a/lib-common/src/Contacts/Model/SearchEngine.cpp b/lib-common/src/Contacts/Model/SearchEngine.cpp new file mode 100644 index 00000000..673c9c2b --- /dev/null +++ b/lib-common/src/Contacts/Model/SearchEngine.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "Contacts/Model/SearchEngine.h" +#include "Contacts/Model/SearchProvider.h" +#include "Contacts/Utils.h" + +#include +#include + +using namespace Contacts::Model; + +SearchEngine::SearchEngine(SearchProvider &searchProvider) + : m_LastFoundIndex(-1), + m_SearchProvider(searchProvider) +{} + +void SearchEngine::search(const std::string &query) +{ + if (query.empty()) { + clear(); + } else { + chooseSearch(query); + } + + m_Query = query; +} + +const ContactDataList *SearchEngine::getSearchResult() const +{ + if (!m_Cache.empty()) { + return &m_Cache.back(); + } + + return nullptr; +} + +bool SearchEngine::empty() const +{ + return m_Cache.empty() || m_Cache.back().empty(); +} + +void SearchEngine::firstSearch(const std::string &query) +{ + clear(); + + const ContactDataList searchList = m_SearchProvider.getContactDataList(); + + if (!searchList.empty()) { + m_Cache.resize(query.size()); + m_Cache.front() = std::move(searchList); + m_LastFoundIndex = 0; + + if (query.size() > 1) { + if (!searchInCache(m_Cache.begin(), query)) { + clear(); + } + } + } +} + +void SearchEngine::chooseSearch(const std::string &query) +{ + if (m_Query.empty()) { + firstSearch(query); + } + + if (!needSearch(query)) { + return; + } + + m_Cache.resize(query.size()); + auto rIt = firstMismatch(query); + if (rIt == m_Cache.rend()) {//Perform initial search + firstSearch(query); + } else { + searchInCache(rIt.base() - 1, query); + } +} + +bool SearchEngine::searchInCache(SearchHistory::iterator from, const std::string &query) +{ + ContactDataList searchRes; + /* for (auto &&contactData : *from) { Todo: Compare + } */ + + if (!searchRes.empty()) { + m_LastFoundIndex = m_Cache.size() - 1; + m_Cache.back() = std::move(searchRes); + return true; + } else { + return false; + } +} + +SearchEngine::SearchHistory::reverse_iterator SearchEngine::firstMismatch(const std::string &query) +{ + size_t minSize = std::min(m_Query.size(), query.size()); + auto itPair = std::mismatch(m_Query.begin(), m_Query.begin() + minSize, query.begin()); + + auto rIt = skipEmptyResults(itPair.first - m_Query.begin()); + return rIt; +} + +SearchEngine::SearchHistory::reverse_iterator SearchEngine::skipEmptyResults(size_t offset) +{ + auto rIt = std::reverse_iterator(m_Cache.begin() + offset); + + while (rIt != m_Cache.rend() && rIt->empty()) { + ++rIt; + } + + return rIt; +} + +void SearchEngine::clear() +{ + m_Cache.clear(); + m_LastFoundIndex = -1; +} + +bool SearchEngine::needSearch(const std::string &query) +{ + if (query.size() >= m_Query.size() + &&(int)(m_Cache.size() - 1) > m_LastFoundIndex) { + return false; + } + return true; +} -- 2.34.1