This repository has been archived by the owner on Jan 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
item.go
157 lines (127 loc) · 4.23 KB
/
item.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package nebula
import (
"github.com/benpate/derp"
"github.com/benpate/rosetta/convert"
"github.com/benpate/rosetta/maps"
)
// Item represents a single piece of content. It will be rendered by one of several rendering
// Libraries, using the custom data it contains.
type Item struct {
Type string `json:"type" bson:"type"` // The type of contem item (WYSIWYG, CONTAINER, OEMBED, ETC...)
Check string `json:"check" bson:"check"` // A random code or nonce to authenticate requests
Refs []int `json:"refs,omitempty" bson:"refs"` // Indexes of sub-items contained by this item
Data maps.Map `json:"data,omitempty" bson:"data"` // Additional data specific to this item type.
}
// NewItem returns a fully initialized Item
func NewItem(t string, refs ...int) Item {
return Item{
Type: t,
Data: make(maps.Map),
Refs: refs,
Check: newChecksum(),
}
}
// IsEmpty returns TRUE if this item does not have a valid item.Type
func (item *Item) IsEmpty() bool {
return (item == nil) || (item.Type == "")
}
// Validate checks that an item has a type (meaning it has been found by container.GetItem)
// and has a valid checksum
func (item *Item) Validate(checksum string) error {
if item.IsEmpty() {
return derp.NewBadRequestError("Item.Validate", "Item is empty")
}
if item.Check != checksum {
return derp.NewBadRequestError("Item.Validate", "Invalid checksum", checksum)
}
return nil
}
// AddFirstReference adds an itemID to the beginning of the reference list
func (item *Item) AddFirstReference(id int) {
item.Refs = append([]int{id}, item.Refs...)
}
// AddLastReference adds and itemID to the end of the reference list
func (item *Item) AddLastReference(id int) {
item.Refs = append(item.Refs, id)
}
// AddReference adds a new item into the middle of the reference list
func (item *Item) AddReference(id int, index int) {
// special case for empty refs. No need to do all that work.
if len(item.Refs) == 0 {
item.Refs = []int{id}
return
}
// efficient insert for already-populated refs.
item.Refs = append(item.Refs, 0)
copy(item.Refs[index+1:], item.Refs[index:])
item.Refs[index] = id
}
// UpdateReference migrates references from an old value to a new one
func (item *Item) UpdateReference(from int, to int) {
for index := range item.Refs {
if item.Refs[index] == from {
item.Refs[index] = to
return
}
}
}
// DeleteReference removes a reference from this Item.
func (item *Item) DeleteReference(itemID int) {
for index := range item.Refs {
if item.Refs[index] == itemID {
item.Refs = append(item.Refs[:index], item.Refs[index+1:]...)
return
}
}
}
// UnmarshalMap extracts data from a map[string]interface{} to populate this Item
func (item *Item) UnmarshalMap(value map[string]interface{}) {
item.Type = convert.String(value["type"])
item.Refs = convert.SliceOfInt(value["refs"])
item.Data = convert.MapOfInterface("data")
item.Check = newChecksum()
}
/*****************************************
* Data Accessors
*****************************************/
func (item *Item) GetPath(path string) (interface{}, bool) {
return item.Data.GetPath(path)
}
func (item *Item) GetString(key string) string {
return item.Data.GetString(key)
}
func (item *Item) GetBytes(key string) []byte {
return item.Data.GetBytes(key)
}
func (item *Item) GetInt(key string) int {
return item.Data.GetInt(key)
}
func (item *Item) GetSliceOfInt(key string) []int {
return item.Data.GetSliceOfInt(key)
}
func (item *Item) GetSliceOfString(key string) []string {
return item.Data.GetSliceOfString(key)
}
func (item *Item) GetInterface(key string) interface{} {
return item.Data.GetInterface(key)
}
func (item *Item) SetPath(path string, value interface{}) error {
return item.Data.SetPath(path, value)
}
func (item *Item) Set(key string, value interface{}) *Item {
item.Data[key] = value
return item
}
/*****************************************
* Other Utilities
*****************************************/
// findReference searches for another itemID in the item's reference list, and returns it place.
// if the item does not exist in this list, then -1 is returned instead
func (item *Item) findReference(itemID int) int {
for index, refID := range item.Refs {
if refID == itemID {
return index
}
}
return -1
}