1# Copyright (c) 2011 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"""BookmarkModel: python representation of the bookmark model.
6
7Obtain one of these from PyUITestSuite::GetBookmarkModel() call.
8"""
9
10import os
11import simplejson as json
12import sys
13
14class BookmarkModel(object):
15
16  def __init__(self, json_string):
17    """Initialize a BookmarkModel from a string of json.
18
19    The JSON representation is the same as used by the bookmark model
20    to save to disk.
21
22    Args:
23      json_string: a string of JSON.
24    """
25    self.bookdict = json.loads(json_string)
26
27  def BookmarkBar(self):
28    """Return the bookmark bar node as a dict."""
29    return self.bookdict['roots']['bookmark_bar']
30
31  def Other(self):
32    """Return the 'other' node (e.g. parent of "Other Bookmarks")"""
33    return self.bookdict['roots']['other']
34
35  def NodeCount(self, node=None):
36    """Return a count of bookmark nodes, including folders.
37
38    The root node itself is included in the count.
39
40    Args:
41      node: the root to start with.  If not specified, count all."""
42    if node == None:
43      return reduce(lambda x, y: x + y,
44                    [self.NodeCount(x)
45                     for x in self.bookdict['roots'].values()])
46    total = 1
47    children = node.get('children', None)
48    if children:
49      total = total + reduce(lambda x,y: x + y,
50                             [self.NodeCount(x) for x in children])
51    return total
52
53  def FindByID(self, id, nodes=None):
54    """Find the bookmark by id.  Return the dict or None.
55
56    Args:
57      id: the id to look for.
58      nodes: an iterable of nodes to start with.  If not specified, search all.
59        'Not specified' means None, not [].
60    """
61    # Careful; we may get an empty list which is different than not
62    # having specified a list.
63    if nodes == None:
64      nodes = self.bookdict['roots'].values()
65    # Check each item.  If it matches, return.  If not, check each of
66    # their kids.
67    for node in nodes:
68      if node['id'] == id:
69        return node
70      for child in node.get('children', []):
71        found_node = self.FindByID(id, [child])
72        if found_node:
73          return found_node
74    # Not found at all.
75    return None
76
77  def FindByTitle(self, title, nodes=None):
78    """Return a tuple of all nodes which have |title| in their title.
79
80    Args:
81      title: the title to look for.
82      node: an iterable of nodes to start with.  If not specified, search all.
83        'Not specified' means None, not [].
84    """
85    # Careful; we may get an empty list which is different than not
86    # having specified a list.
87    if nodes == None:
88      nodes = self.bookdict['roots'].values()
89    # Check each item.  If it matches, return.  If not, check each of
90    # their kids.
91    results = []
92    for node in nodes:
93      node_title = node.get('title', None) or node.get('name', None)
94      if title == node_title:
95        results.append(node)
96      # Note we check everything; unlike the FindByID, we do not stop early.
97      for child in node.get('children', []):
98        results += self.FindByTitle(title, [child])
99    return results
100