Class: QDA::Backend::SQLite::CategoryTree

Inherits:
Object
  • Object
show all
Defined in:
lib/weft/backend/sqlite/category_tree.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCategoryTree

Returns a new instance of CategoryTree.



29
30
31
32
# File 'lib/weft/backend/sqlite/category_tree.rb', line 29

def initialize()
  @table = {}
  @roots = []
end

Instance Attribute Details

#rootsObject (readonly)

Returns the value of attribute roots.



28
29
30
# File 'lib/weft/backend/sqlite/category_tree.rb', line 28

def roots
  @roots
end

Class Method Details

.load(str) ⇒ Object



34
35
36
# File 'lib/weft/backend/sqlite/category_tree.rb', line 34

def CategoryTree.load(str)
  Marshal.load( Base64::decode64(str) )
end

Instance Method Details

#[](id) ⇒ Object



38
39
40
# File 'lib/weft/backend/sqlite/category_tree.rb', line 38

def [](id)
  @table[id] or raise QDA::NotFoundError.new("Unknown id #{id.inspect}")
end

#add(parentid, dbid, name) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/weft/backend/sqlite/category_tree.rb', line 42

def add(parentid, dbid, name)
  if parentid
    @table[dbid] = @table[parentid].add(dbid, name)
  else
    @roots.push( CategoryTreeNode.new(nil, dbid, name) )
    @table[dbid] = @roots[-1]
  end
end

#find(path) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/weft/backend/sqlite/category_tree.rb', line 61

def find(path)
  paths = QDA::Category.parse_path(path)
  # if it's a path with "/" at the beginning, search among roots
  if paths[0].empty?
    # maybe a named root e.g. '/CATEORIES'
    fixed_roots = @roots.find_all { | x | x.name =~ /^#{paths[1]}/ }
    # no root category matched, so search starting from all root nodes
    if fixed_roots.empty?
      scope = @roots
    # root matched, and the path is so short it is the root category itself
    elsif paths.length < 3
      return fixed_roots
    # restrict the search to only the matching root categories
    else
      path  = paths[2 .. -1].map { | p | p.gsub(/\//, '//') }.join('/')
      scope = fixed_roots
    end
  # if a relative path (not starting with '/'
  else
    scope = @table.values
  end 
  scope.inject([]) { | a, x | a + x.find(path) }
end

#is_descendant?(ancestor, descendant) ⇒ Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/weft/backend/sqlite/category_tree.rb', line 91

def is_descendant?(ancestor, descendant)
  @table[ancestor].is_ancestor_of?(descendant)
end

#move(dbid, new_parentid) ⇒ Object



85
86
87
88
89
# File 'lib/weft/backend/sqlite/category_tree.rb', line 85

def move(dbid, new_parentid)
  movee = @table[dbid]
  @table[movee.parent].delete(movee)
  movee.move(@table[new_parentid])
end

#pretty_print(out = STDOUT) ⇒ Object



99
100
101
102
103
104
105
106
# File 'lib/weft/backend/sqlite/category_tree.rb', line 99

def pretty_print(out = STDOUT)
  pp = Proc.new do | item, depth |
    out << "-" * depth
    out << " #{item.name} (#{item.dbid})\n"
    item.children.each { | c | pp.call(c, depth + 1) }
  end
  roots.each { | r | pp.call(r, 0) }
end

#remove(dbid) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/weft/backend/sqlite/category_tree.rb', line 51

def remove(dbid)
  me = @table[dbid]
  @table[me.parent].delete(me) if @table[me.parent]
  dbids = []
  me.children.each { | c | dbids += remove(c.dbid) }
  @table.delete(dbid)
  dbids.push(dbid)
  dbids
end

#serialiseObject



95
96
97
# File 'lib/weft/backend/sqlite/category_tree.rb', line 95

def serialise()
  Base64::encode64( Marshal.dump(self) )
end