This repository has been archived by the owner on Oct 28, 2022. It is now read-only.
/
tree.go
121 lines (101 loc) · 3.07 KB
/
tree.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package matcher
import (
"errors"
"github.com/script-development/RT-CV/db"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// Tree contains the cache for the tree so tree resolution can be fast
type Tree struct {
branches map[primitive.ObjectID]*Branch
rootBranches []primitive.ObjectID
}
// GetBranch returns a branch with all the child branches in a tree structure
func (tc *Tree) GetBranch(dbConn db.Connection, branchID *primitive.ObjectID) (*Branch, error) {
err := tc.build(dbConn)
if err != nil {
return nil, err
}
if branchID != nil {
// TODO what do we do when a branch cannot be found?
return tc.branches[*branchID], nil
}
parsedBranches := make([]*Branch, len(tc.rootBranches))
for idx := range tc.rootBranches {
// TODO what do we do when a branch cannot be found?
parsedBranches[idx] = tc.branches[tc.rootBranches[idx]]
}
return &Branch{
Titles: nil,
TitleKind: Root,
Branches: tc.rootBranches,
ParsedBranches: parsedBranches,
}, nil
}
// GetIDsForBranch returns a spesific branches child branches their ids
func (tc *Tree) GetIDsForBranch(dbConn db.Connection, branchID primitive.ObjectID) ([]primitive.ObjectID, error) {
err := tc.build(dbConn)
if err != nil {
return nil, err
}
resp := []primitive.ObjectID{}
err = tc.findIDsForBranch(branchID, &resp)
return resp, err
}
// findIDsForBranch adds a spesific branches child branches their ids to addTo parameter
func (tc *Tree) findIDsForBranch(branchID primitive.ObjectID, addTo *[]primitive.ObjectID) error {
*addTo = append(*addTo, branchID)
branch, ok := tc.branches[branchID]
if !ok {
return errors.New("branch not found")
}
for _, id := range branch.Branches {
err := tc.findIDsForBranch(id, addTo)
if err != nil {
return err
}
}
return nil
}
// build builds the tree cache
func (tc *Tree) build(dbConn db.Connection) error {
branches := []Branch{}
err := dbConn.Find(&Branch{}, &branches, bson.M{})
if err != nil {
return err
}
tc.branches = map[primitive.ObjectID]*Branch{}
tc.rootBranches = []primitive.ObjectID{}
// fill the branches map and set the HasParents property
for idx := range branches {
branch := branches[idx]
for _, id := range branch.Branches {
referencedBranch := tc.branches[id]
if referencedBranch == nil {
tc.branches[id] = &Branch{HasParents: true}
} else {
referencedBranch.HasParents = true
}
}
if exsitingBranch, ok := tc.branches[branch.ID]; ok {
branch.HasParents = exsitingBranch.HasParents
*exsitingBranch = branch
} else {
tc.branches[branch.ID] = &branch
}
}
// Link the branches to their parents
// And find the root branches
for _, branch := range tc.branches {
branch.ParsedBranches = make([]*Branch, len(branch.Branches))
for idx := 0; idx < len(branch.Branches); idx++ {
// TODO what do we do when a branch cannot be found?
referencedBranch := tc.branches[branch.Branches[idx]]
branch.ParsedBranches[idx] = referencedBranch
}
if !branch.HasParents {
tc.rootBranches = append(tc.rootBranches, branch.ID)
}
}
return nil
}