--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 MODEL_SEARCH_DATA_H
+#define MODEL_SEARCH_DATA_H
+
+#include "Model2/DataItem.h"
+#include "Model2/SearchResult.h"
+
+namespace Model2
+{
+ class EXPORT_API SearchData : public DataItem
+ {
+ public:
+ /**
+ * @brief Called when SearchResult is changed.
+ * @param[in] Search result
+ */
+ typedef std::function<void(const SearchResult *)> ChangeCallback;
+
+ /**
+ * @brief Create SearchData object.
+ * @param[in] dataItem Data item reference
+ */
+ explicit SearchData(DataItem &dataItem);
+
+ /**
+ * @return DataItem reference.
+ */
+ DataItem &getDataItem();
+
+ /**
+ * @return DataItem reference.
+ */
+ const DataItem &getDataItem() const;
+
+ /**
+ * @return Search result.
+ */
+ const SearchResult *getSearchResult() const;
+
+ /**
+ * @brief Set search result.
+ * @param[in] searchResult Search result
+ */
+ void setSearchResult(SearchResult *searchResult);
+
+ /**
+ * @brief Set change callback.
+ * @param[in] callback @see ChangeCallback
+ */
+ void setChangeCallback(ChangeCallback callback);
+
+ protected:
+ virtual int onUpdate(void *data) override;
+
+ private:
+ DataItem &m_DataItem;
+ SearchResult *m_SearchResult;
+ ChangeCallback m_OnChanged;
+ };
+}
+
+#endif /* MODEL_SEARCH_DATA_H */
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 MODEL_SEARCH_ENGINE_H
+#define MODEL_SEARCH_ENGINE_H
+
+#include "Model2/SearchResult.h"
+#include "Model2/DataProvider.h"
+
+#include <string>
+#include <vector>
+
+namespace Model2
+{
+ class SearchData;
+
+ /**
+ * @brief This is a callable object which provides match logic
+ * @param[in] Search data
+ * @param[in] Query
+ * @return Search result
+ */
+ typedef std::function<SearchResultPtr(const SearchData &, const std::string &)> SearchComparator;
+
+ /**
+ * @brief This class provides incremental search logic
+ */
+ class EXPORT_API SearchEngine
+ {
+ public:
+ typedef DataProvider::DataList DataList;
+
+ /**
+ * @brief Create search engine
+ * @param[in] dataList ContactData list
+ * @param[in] comparator Callable match comparator
+ */
+ explicit SearchEngine(const DataList &dataList, SearchComparator comparator);
+
+ /**
+ * @brief Perform incremental search
+ * @param[in] query Value to find
+ */
+ void search(std::string query);
+
+ /**
+ * @return true if there is no results, otherwise false
+ */
+ bool empty() const;
+
+ /**@{*/
+ /**
+ * @brief Notify engine that SearchData was Inserted/Updated/Deleted
+ * @param[in] searchData SearchData object
+ */
+ void insertSearchData(SearchData *searchData);
+ void updateSearchData(SearchData *searchData);
+ void deleteSearchData(SearchData *searchData);
+ /**@}*/
+
+ private:
+ typedef std::pair<SearchData *, SearchResultPtr> SearchResultItem;
+ typedef std::list<SearchResultItem> ResultList;
+ typedef std::vector<ResultList> SearchHistory;
+ typedef std::function<bool(const std::string &, ResultList &)> HistoryForFn;
+
+ bool needSearch(const std::string &query);
+ template <typename List>
+ void incrementalSearch(const List &list, const std::string &query);
+
+ SearchData *getSearchData(const DataItemPtr &data);
+ SearchData *getSearchData(const SearchResultItem &searchItem);
+
+ void updateSearchResult(ResultList &list);
+ void resetSearchResult();
+ void clear();
+
+ SearchHistory::iterator getMatch(const std::string &query);
+ SearchHistory::iterator skipEmptyResults(size_t offset);
+
+ void historyFor(HistoryForFn function);
+ static ResultList::iterator findSearchData(ResultList &list, SearchData *searchData);
+
+ std::string m_Query;
+ SearchHistory m_History;
+ int m_LastFoundIndex;
+
+ const DataList &m_DataList;
+
+ SearchComparator m_Comparator;
+ };
+}
+
+#endif /* MODEL_SEARCH_ENGINE_H */
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 MODEL_SEARCH_PROVIDER_H
+#define MODEL_SEARCH_PROVIDER_H
+
+#include "Model2/SearchEngine.h"
+#include "Model2/DataProvider.h"
+
+namespace Model2
+{
+ class SearchData;
+
+ class EXPORT_API SearchProvider : public DataProvider
+ {
+ public:
+
+ /**
+ * @brief Create SearchProvider
+ * @param[in] provider DataProvider
+ * @param[in] comparator Callable match comparator
+ */
+ explicit SearchProvider(DataProvider &provider, SearchComparator comparator);
+ virtual ~SearchProvider() override;
+
+ /**
+ * @brief Invoke search
+ * @param[in] query Passed search string
+ */
+ void search(const char *query);
+
+ /**
+ * @return Whether there is no results for the current query.
+ */
+ bool empty() const;
+
+ private:
+ virtual void onInitialize() override;
+
+ SearchData *createSearchData(DataItem &dataItem);
+ void onInserted(DataItem &dataItem);
+ void onUpdated(SearchData &searchData, int changes);
+ void onDeleted(SearchData &searchData);
+
+ DataProvider &m_Provider;
+ SearchEngine m_SearchEngine;
+ };
+}
+
+#endif /* MODEL_SEARCH_PROVIDER_H */
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 MODEL_SEARCH_RESULT_H
+#define MODEL_SEARCH_RESULT_H
+
+#include <memory>
+#include <tizen.h>
+#include "Utils/Range.h"
+
+namespace Model2
+{
+ class EXPORT_API SearchResult
+ {
+ public:
+ /**
+ * @brief Represents substring of matched string.
+ */
+ typedef Utils::Range<const char *> Substring;
+
+ SearchResult();
+
+ /**
+ * @brief Create SearchResult object.
+ * @param[in] fieldId Field ID matched with query
+ * @param[in] str Matched string
+ * @param[in] substr Matched substring
+ */
+ SearchResult(int fieldId, const char *str, Substring substr);
+
+ /**
+ * @return Field ID matched with query.
+ */
+ int getMatchedField() const;
+
+ /**
+ * @return Matched string.
+ */
+ const char *getMatchedString() const;
+
+ /**
+ * @return Matched substring.
+ */
+ const Substring &getMatchedSubstring() const;
+
+ private:
+ int m_MatchedField;
+ const char *m_MatchedString;
+ Substring m_MatchedSubstring;
+ };
+
+ typedef std::unique_ptr<SearchResult> SearchResultPtr;
+}
+
+#endif /* MODEL_SEARCH_RESULT_H */
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 "Model2/SearchData.h"
+
+using namespace Model2;
+
+SearchData::SearchData(DataItem &dataItem)
+ : m_DataItem(dataItem),
+ m_SearchResult(nullptr)
+{
+}
+
+DataItem &SearchData::getDataItem()
+{
+ return m_DataItem;
+}
+
+const DataItem &SearchData::getDataItem() const
+{
+ return m_DataItem;
+}
+
+const SearchResult *SearchData::getSearchResult() const
+{
+ return m_SearchResult;
+}
+
+void SearchData::setSearchResult(SearchResult *searchResult)
+{
+ m_SearchResult = searchResult;
+
+ if (m_OnChanged) {
+ m_OnChanged(m_SearchResult);
+ }
+}
+
+void SearchData::setChangeCallback(ChangeCallback callback)
+{
+ m_OnChanged = std::move(callback);
+}
+
+int SearchData::onUpdate(void *data)
+{
+ return (long) data;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 "Model2/SearchEngine.h"
+#include "Model2/SearchData.h"
+
+#include <utility>
+#include <algorithm>
+
+using namespace Model2;
+using namespace std::placeholders;
+
+SearchEngine::SearchEngine(const DataList &dataList, SearchComparator comparator)
+ : m_LastFoundIndex(-1),
+ m_DataList(dataList),
+ m_Comparator(std::move(comparator))
+{
+}
+
+void SearchEngine::search(std::string query)
+{
+ if (query.empty()) {
+ clear();
+ if (!m_Query.empty()) {
+ resetSearchResult();
+ }
+ } else {
+ if (!needSearch(query)) {
+ return;
+ }
+
+ auto matchIt = getMatch(query);
+ size_t matchPos = matchIt - m_History.begin();
+ bool nothingFound = matchIt == m_History.end();
+
+ m_History.erase(nothingFound ? m_History.begin() : (matchIt + 1), m_History.end());
+ m_History.resize(query.size());
+
+ if (m_Query.empty() || nothingFound) {
+ incrementalSearch(m_DataList, query);
+ } else if (matchPos == m_History.size()) {
+ updateSearchResult(m_History.back());
+ } else {
+ incrementalSearch(m_History[matchPos], query);
+ }
+ }
+
+ m_Query = std::move(query);
+}
+
+bool SearchEngine::empty() const
+{
+ return m_History.empty() || m_History.back().empty();
+}
+
+void SearchEngine::insertSearchData(SearchData *searchData)
+{
+ SearchResult *lastResult = nullptr;
+
+ historyFor([searchData, &lastResult, this](const std::string &query, ResultList &list) {
+ SearchResultPtr searchResult = m_Comparator(*searchData, query);
+ lastResult = searchResult.get();
+
+ if (searchResult) {
+ list.emplace_back(searchData, std::move(searchResult));
+ return true;
+ }
+
+ return false;
+ });
+
+ searchData->setSearchResult(lastResult);
+}
+
+void SearchEngine::updateSearchData(SearchData *searchData)
+{
+ SearchResult *lastResult = nullptr;
+
+ historyFor([searchData, &lastResult, this](const std::string &query, ResultList &list) {
+ auto it = findSearchData(list, searchData);
+ if (it != list.end()) {
+ SearchResultPtr searchResult = m_Comparator(*searchData, query);
+ lastResult = searchResult.get();
+
+ if (searchResult) {
+ it->second = std::move(searchResult);
+ } else {
+ list.erase(it);
+ }
+ }
+
+ return true;
+ });
+
+ searchData->setSearchResult(lastResult);
+}
+
+void SearchEngine::deleteSearchData(SearchData *searchData)
+{
+ for (auto &&list : m_History) {
+ auto it = findSearchData(list, searchData);
+ if (it != list.end()) {
+ list.erase(it);
+ }
+ }
+}
+
+bool SearchEngine::needSearch(const std::string &query)
+{
+ if (query.size() >= m_Query.size()
+ &&(int)(m_History.size() - 1) > m_LastFoundIndex) {
+ return false;
+ }
+
+ return true;
+}
+
+template <typename List>
+void SearchEngine::incrementalSearch(const List &list, const std::string &query)
+{
+ ResultList resultList;
+ for (auto &&data : list) {
+ SearchData *searchData = getSearchData(data);
+ SearchResultPtr searchResult = m_Comparator(*searchData, query);
+ searchData->setSearchResult(searchResult.get());
+
+ if (searchResult) {
+ resultList.emplace_back(searchData, std::move(searchResult));
+ }
+ }
+
+ if (!resultList.empty()) {
+ m_LastFoundIndex = m_History.size() - 1;
+ m_History.back() = std::move(resultList);
+ }
+}
+
+SearchData *SearchEngine::getSearchData(const DataItemPtr &data)
+{
+ return static_cast<SearchData *>(data.get());
+}
+
+SearchData *SearchEngine::getSearchData(const SearchResultItem &resultItem)
+{
+ return resultItem.first;
+}
+
+void SearchEngine::updateSearchResult(ResultList &list)
+{
+ for (auto &&resultItem : list) {
+ resultItem.first->setSearchResult(resultItem.second.get());
+ }
+}
+
+void SearchEngine::resetSearchResult()
+{
+ for (auto &&data : m_DataList) {
+ SearchData *searchData = static_cast<SearchData *>(data.get());
+ searchData->setSearchResult(nullptr);
+ }
+}
+
+void SearchEngine::clear()
+{
+ m_History.clear();
+ m_LastFoundIndex = -1;
+}
+
+SearchEngine::SearchHistory::iterator SearchEngine::getMatch(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());
+
+ return skipEmptyResults(itPair.first - m_Query.begin());
+}
+
+SearchEngine::SearchHistory::iterator SearchEngine::skipEmptyResults(size_t offset)
+{
+ auto rIt = std::reverse_iterator<SearchHistory::iterator>(m_History.begin() + offset);
+
+ while (rIt != m_History.rend() && rIt->empty()) {
+ ++rIt;
+ }
+
+ return rIt == m_History.rend() ? m_History.end() : rIt.base() - 1;
+}
+
+void SearchEngine::historyFor(HistoryForFn function)
+{
+ std::string query;
+ query.reserve(m_Query.size());
+
+ for (size_t i = 0; i < m_History.size(); ++i) {
+ auto &list = m_History[i];
+ query.append(1, m_Query[i]);
+
+ if ((int) i < m_LastFoundIndex && list.empty()) {
+ continue;
+ }
+
+ if (!function(query, list)) {
+ break;
+ }
+ }
+}
+
+SearchEngine::ResultList::iterator SearchEngine::findSearchData(ResultList &list, SearchData *searchData)
+{
+ return std::find_if(list.begin(), list.end(),
+ [searchData](const SearchResultItem &item) {
+ return item.first == searchData;
+ });
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 "Model2/SearchProvider.h"
+#include "Model2/SearchData.h"
+
+using namespace Model2;
+using namespace std::placeholders;
+
+SearchProvider::SearchProvider(DataProvider &provider, SearchComparator comparator)
+ : m_Provider(provider), m_SearchEngine(getDataList(), std::move(comparator))
+{
+ m_Provider.setInsertCallback(std::bind(&SearchProvider::onInserted, this, _1));
+ m_Provider.setUpdateStartCallback(std::bind(&SearchProvider::onUpdateStarted, this));
+ m_Provider.setUpdateFinishCallback(std::bind(&SearchProvider::onUpdateFinished, this));
+}
+
+SearchProvider::~SearchProvider()
+{
+ m_Provider.setInsertCallback(nullptr);
+ m_Provider.setUpdateStartCallback(nullptr);
+ m_Provider.setUpdateFinishCallback(nullptr);
+}
+
+void SearchProvider::search(const char *query)
+{
+ m_SearchEngine.search(query ? query : "");
+}
+
+bool SearchProvider::empty() const
+{
+ return m_SearchEngine.empty();
+}
+
+void SearchProvider::onInitialize()
+{
+ m_Provider.initialize([this] {
+ DataList dataList;
+ for (auto &&dataItem : m_Provider.getDataList()) {
+ dataList.push_back(DataItemPtr(createSearchData(*dataItem)));
+ }
+
+ onInitialized(std::move(dataList));
+ });
+}
+
+SearchData *SearchProvider::createSearchData(DataItem &dataItem)
+{
+ auto searchData = new SearchData(dataItem);
+ dataItem.setUpdateCallback(std::bind(&SearchProvider::onUpdated, this, std::ref(*searchData), _1));
+ dataItem.setDeleteCallback(std::bind(&SearchProvider::onDeleted, this, std::ref(*searchData)));
+ return searchData;
+}
+
+void SearchProvider::onInserted(DataItem &dataItem)
+{
+ SearchData *searchData = createSearchData(dataItem);
+ insertDataItem(DataItemPtr(searchData));
+ m_SearchEngine.insertSearchData(searchData);
+}
+
+void SearchProvider::onUpdated(SearchData &searchData, int changes)
+{
+ searchData.update((void *)(long) changes);
+ m_SearchEngine.updateSearchData(&searchData);
+}
+
+void SearchProvider::onDeleted(SearchData &searchData)
+{
+ m_SearchEngine.deleteSearchData(&searchData);
+ deleteDataItem(searchData);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2016 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 "Model2/SearchResult.h"
+
+using namespace Model2;
+
+SearchResult::SearchResult()
+ : m_MatchedField(-1),
+ m_MatchedString(nullptr)
+{
+}
+
+SearchResult::SearchResult(int fieldId, const char *str, Substring substr)
+ : m_MatchedField(fieldId),
+ m_MatchedString(str),
+ m_MatchedSubstring(substr)
+{
+}
+
+int SearchResult::getMatchedField() const
+{
+ return m_MatchedField;
+}
+
+const char *SearchResult::getMatchedString() const
+{
+ return m_MatchedString;
+}
+
+const SearchResult::Substring &SearchResult::getMatchedSubstring() const
+{
+ return m_MatchedSubstring;
+}