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
|
package menu
import (
"encoding/json"
"fmt"
"io"
"os"
)
type MenuItem struct {
Title string
Ident string
Url string
Children []*MenuItem
Parent *MenuItem
}
func (it MenuItem) IsRoot() bool {
return it.Parent == nil
}
type Menu struct {
byIdent map[string]*MenuItem
root *MenuItem
}
func (m Menu) Root() *MenuItem {
return m.root
}
func (m Menu) ByIdent(ident string) *MenuItem {
return m.byIdent[ident]
}
type JsonMenuItem struct {
Title string
Ident string
Url string
Children []JsonMenuItem `json:",omitempty"`
}
type JsonMenu []JsonMenuItem
func (m *Menu) addJsonMenuItems(jsonItems []JsonMenuItem, parent *MenuItem) {
for _, jsonItem := range jsonItems {
item := MenuItem{
Title: jsonItem.Title,
Ident: jsonItem.Ident,
Url: jsonItem.Url,
Children: make([]*MenuItem, 0, len(jsonItem.Children)),
Parent: parent,
}
parent.Children = append(parent.Children, &item)
m.byIdent[jsonItem.Ident] = &item
m.addJsonMenuItems(jsonItem.Children, &item)
}
}
func (jm JsonMenu) toMenu() *Menu {
root := MenuItem{
Children: make([]*MenuItem, 0, len(jm)),
}
menu := &Menu{
byIdent: make(map[string]*MenuItem),
root: &root,
}
menu.addJsonMenuItems(jm, &root)
return menu
}
func Parse(r io.Reader) (*Menu, error) {
var jsonMenu JsonMenu
if err := json.NewDecoder(r).Decode(&jsonMenu); err != nil {
return nil, err
}
return jsonMenu.toMenu(), nil
}
func LoadFromFile(filename string) (*Menu, error) {
f, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("Could not load menu from %s: %v", filename, err)
}
defer f.Close()
return Parse(f)
}
|