bookmark_index.h revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_INDEX_H_
6#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_INDEX_H_
7
8#include <list>
9#include <map>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/basictypes.h"
15
16class BookmarkNode;
17class Profile;
18class QueryNode;
19class QueryParser;
20
21namespace bookmark_utils {
22struct TitleMatch;
23}
24
25namespace history {
26class URLDatabase;
27}
28
29// BookmarkIndex maintains an index of the titles of bookmarks for quick
30// look up. BookmarkIndex is owned and maintained by BookmarkModel, you
31// shouldn't need to interact directly with BookmarkIndex.
32//
33// BookmarkIndex maintains the index (index_) as a map of sets. The map (type
34// Index) maps from a lower case string to the set (type NodeSet) of
35// BookmarkNodes that contain that string in their title.
36
37class BookmarkIndex {
38 public:
39  explicit BookmarkIndex(Profile* profile) : profile_(profile) {}
40
41  // Invoked when a bookmark has been added to the model.
42  void Add(const BookmarkNode* node);
43
44  // Invoked when a bookmark has been removed from the model.
45  void Remove(const BookmarkNode* node);
46
47  // Returns up to |max_count| of bookmarks containing the text |query|.
48  void GetBookmarksWithTitlesMatching(
49      const std::wstring& query,
50      size_t max_count,
51      std::vector<bookmark_utils::TitleMatch>* results);
52
53 private:
54  typedef std::set<const BookmarkNode*> NodeSet;
55  typedef std::map<std::wstring, NodeSet> Index;
56
57  // Used when finding the set of bookmarks that match a query. Each match
58  // represents a set of terms (as an interator into the Index) matching the
59  // query as well as the set of nodes that contain those terms in their titles.
60  struct Match {
61    // List of terms matching the query.
62    std::list<Index::const_iterator> terms;
63
64    // The set of nodes matching the terms. As an optimization this is empty
65    // when we match only one term, and is filled in when we get more than one
66    // term. We can do this as when we have only one matching term we know
67    // the set of matching nodes is terms.front()->second.
68    //
69    // Use nodes_begin() and nodes_end() to get an iterator over the set as
70    // it handles the necessary switching between nodes and terms.front().
71    NodeSet nodes;
72
73    // Returns an iterator to the beginning of the matching nodes. See
74    // description of nodes for why this should be used over nodes.begin().
75    NodeSet::const_iterator nodes_begin() const;
76
77    // Returns an iterator to the beginning of the matching nodes. See
78    // description of nodes for why this should be used over nodes.end().
79    NodeSet::const_iterator nodes_end() const;
80  };
81
82  typedef std::vector<Match> Matches;
83
84  // Pairs BookmarkNodes and the number of times the nodes' URLs were typed.
85  // Used to sort Matches in decreasing order of typed count.
86  typedef std::pair<const BookmarkNode*, int> NodeTypedCountPair;
87  typedef std::vector<NodeTypedCountPair> NodeTypedCountPairs;
88
89  // Extracts |matches.nodes| into NodeTypedCountPairs and sorts the pairs in
90  // decreasing order of typed count.
91  void SortMatches(const Matches& matches,
92                   NodeTypedCountPairs* node_typed_counts) const;
93
94  // Extracts BookmarkNodes from |match| and retrieves typed counts for each
95  // node from the in-memory database. Inserts pairs containing the node and
96  // typed count into the vector |node_typed_counts|. |node_typed_counts| is
97  // sorted in decreasing order of typed count.
98  void ExtractBookmarkNodePairs(history::URLDatabase* url_db,
99                                const Match& match,
100                                NodeTypedCountPairs* node_typed_counts) const;
101
102  // Sort function for NodeTypedCountPairs. We sort in decreasing order of typed
103  // count so that the best matches will always be added to the results.
104  static bool NodeTypedCountPairSortFunc(const NodeTypedCountPair& a,
105                                         const NodeTypedCountPair& b) {
106      return a.second > b.second;
107  }
108
109  // Add |node| to |results| if the node matches the query.
110  void AddMatchToResults(const BookmarkNode* node,
111                         QueryParser* parser,
112                         const std::vector<QueryNode*>& query_nodes,
113                         std::vector<bookmark_utils::TitleMatch>* results);
114
115  // Populates |matches| for the specified term. If |first_term| is true, this
116  // is the first term in the query. Returns true if there is at least one node
117  // matching the term.
118  bool GetBookmarksWithTitleMatchingTerm(const std::wstring& term,
119                                         bool first_term,
120                                         Matches* matches);
121
122  // Iterates over |matches| updating each Match's nodes to contain the
123  // intersection of the Match's current nodes and the nodes at |index_i|.
124  // If the intersection is empty, the Match is removed.
125  //
126  // This is invoked from GetBookmarksWithTitleMatchingTerm.
127  void CombineMatchesInPlace(const Index::const_iterator& index_i,
128                             Matches* matches);
129
130  // Iterates over |current_matches| calculating the intersection between the
131  // Match's nodes and the nodes at |index_i|. If the intersection between the
132  // two is non-empty, a new match is added to |result|.
133  //
134  // This differs from CombineMatchesInPlace in that if the intersection is
135  // non-empty the result is added to result, not combined in place. This
136  // variant is used for prefix matching.
137  //
138  // This is invoked from GetBookmarksWithTitleMatchingTerm.
139  void CombineMatches(const Index::const_iterator& index_i,
140                      const Matches& current_matches,
141                      Matches* result);
142
143  // Returns the set of query words from |query|.
144  std::vector<std::wstring> ExtractQueryWords(const std::wstring& query);
145
146  // Adds |node| to |index_|.
147  void RegisterNode(const std::wstring& term, const BookmarkNode* node);
148
149  // Removes |node| from |index_|.
150  void UnregisterNode(const std::wstring& term, const BookmarkNode* node);
151
152  Index index_;
153
154  Profile* profile_;
155
156  DISALLOW_COPY_AND_ASSIGN(BookmarkIndex);
157};
158
159#endif  // CHROME_BROWSER_BOOKMARKS_BOOKMARK_INDEX_H_
160