forked from thingful/hypercat-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
item.go
136 lines (110 loc) · 3.26 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
package hypercat
import (
"encoding/json"
"errors"
)
// Item is the representation of the HyperCat item object, which is the main
// object stored within a catalogue instance.
type Item struct {
Href string `json:"href"`
Metadata Metadata `json:"i-object-metadata"`
Description string `json:"-"` // Spec is unclear about whether there can be more than one description. We assume not.
}
// Items is a simple type alias for a slice of Item structs.
type Items []Item
// NewItem is a constructor function that creates and returns an Item instance.
func NewItem(href, description string) *Item {
return &Item{
Href: href,
Description: description,
Metadata: Metadata{},
}
}
// AddRel is a function for adding a Rel object to an item. This may result in
// duplicated Rel keys as this is permitted by the HyperCat spec.
func (item *Item) AddRel(rel, val string) {
item.Metadata = append(item.Metadata, Rel{Rel: rel, Val: val})
}
// ReplaceRel is a function that attempts to replace the value of a specific
// Rel object if it is attached to this Item. If the Rel key isn't found this
// will have no effect.
func (item *Item) ReplaceRel(rel, val string) {
for i, relationship := range item.Metadata {
if relationship.Rel == rel {
item.Metadata[i] = Rel{Rel: rel, Val: val}
}
}
}
// IsCatalogue returns true if the Item is a HyperCat catalogue, false
// otherwise.
func (item *Item) IsCatalogue() bool {
for _, rel := range item.Metadata {
if rel.Rel == ContentTypeRel && rel.Val == HyperCatMediaType {
return true
}
}
return false
}
// MarshalJSON returns the JSON encoding of an Item. This function is the the
// required function for structs that implement the Marshaler interface.
func (item *Item) MarshalJSON() ([]byte, error) {
metadata := item.Metadata
if item.Description != "" {
metadata = append(metadata, Rel{Rel: DescriptionRel, Val: item.Description})
}
return json.Marshal(struct {
Href string `json:"href"`
Metadata *Metadata `json:"i-object-metadata"`
}{
Href: item.Href,
Metadata: &metadata,
})
}
// UnmarshalJSON is the required function for structs that implement the
// Unmarshaler interface.
func (item *Item) UnmarshalJSON(b []byte) error {
type tempItem struct {
Href string `json:"href"`
Metadata Metadata `json:"i-object-metadata"`
}
t := tempItem{}
err := json.Unmarshal(b, &t)
if err != nil {
return err
}
item.Href = t.Href
for _, rel := range t.Metadata {
if rel.Rel == DescriptionRel {
item.Description = rel.Val
} else {
item.Metadata = append(item.Metadata, rel)
}
}
if item.Href == "" {
err := errors.New(`"href" is a mandatory attribute`)
return err
}
if item.Description == "" {
err := errors.New(`"` + DescriptionRel + `" is a mandatory metadata element`)
return err
}
return nil
}
// Rels returns a slice containing all the Rel values of this item.
func (item *Item) Rels() []string {
rels := make([]string, len(item.Metadata))
for i, rel := range item.Metadata {
rels[i] = rel.Rel
}
return rels
}
// Vals returns a slice of all values that match the given rel value.
func (item *Item) Vals(key string) []string {
vals := []string{}
for _, rel := range item.Metadata {
if rel.Rel == key {
vals = append(vals, rel.Val)
}
}
return vals
}