forked from namsral/microdata
-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
145 lines (121 loc) · 3.24 KB
/
model.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
package microdata
import (
"fmt"
)
type Microdata struct {
Items []*Item `json:"items"`
}
// addItem adds the item to the items list.
func (m *Microdata) addItem(item *Item) {
m.Items = append(m.Items, item)
}
// GetFirstOfSchemaType returns the first item of the given type with possible https://schema.org/ context.
func (m *Microdata) GetFirstOfSchemaType(itemType string) *Item {
return m.GetFirstOfType(itemType, "http://schema.org/"+itemType, "https://schema.org/"+itemType)
}
// GetFirstOfType returns the first item of the given type.
func (m *Microdata) GetFirstOfType(itemType ...string) *Item {
for _, item := range m.Items {
for _, t1 := range item.Types {
for _, t2 := range itemType {
if t1 == t2 {
return item
}
}
}
if graph, ok := item.GetNested("@graph"); ok {
if item := graph.GetFirstOfType(itemType...); item != nil {
return item
}
}
}
return nil
}
type ValueList []interface{}
type PropertyMap map[string]ValueList
type Item struct {
Types []string `json:"type"`
Properties PropertyMap `json:"properties"`
ID string `json:"id,omitempty"`
}
// addType adds the value to the types list.
func (i *Item) addType(value string) {
i.Types = append(i.Types, value)
}
// addProperty adds the property, value pair to the properties map. It appends to any existing property.
func (i *Item) addProperty(key string, value interface{}) {
i.Properties[key] = append(i.Properties[key], value)
}
// addItem adds the property, value pair to the properties map. It appends to any existing property.
func (i *Item) addItem(key string, value *Item) {
i.Properties[key] = append(i.Properties[key], value)
}
func (i *Item) IsOfSchemaType(itemType string) bool {
return i.IsOfType(itemType, "http://schema.org/"+itemType, "https://schema.org/"+itemType)
}
func (i *Item) IsOfType(itemType ...string) bool {
for _, t1 := range i.Types {
for _, t2 := range itemType {
if t1 == t2 {
return true
}
}
}
return false
}
func (i *Item) GetProperty(keys ...string) (val interface{}, ok bool) {
for _, key := range keys {
if arr, ok := i.GetProperties(key); ok {
return arr[0], true
}
}
return
}
func (i *Item) GetProperties(keys ...string) (arr []interface{}, ok bool) {
for _, key := range keys {
for _, v := range i.Properties[key] {
arr = append(arr, v)
}
if len(arr) > 0 {
return arr, true
}
}
return arr, false
}
func (i *Item) GetNestedItem(keys ...string) (val *Item, ok bool) {
if data, ok := i.GetNested(keys...); ok {
return data.Items[0], true
}
return
}
func (i *Item) GetNested(keys ...string) (data Microdata, ok bool) {
for _, key := range keys {
var arr []*Item
for _, v := range i.Properties[key] {
switch v.(type) {
case *Item:
arr = append(arr, v.(*Item))
}
}
return Microdata{Items: arr}, len(arr) > 0
}
return
}
func (i *Item) CountPaths(prefix string, paths *map[string]int) {
for key, val := range i.Properties {
(*paths)[fmt.Sprintf("%s[%T]", prefix+key, val[0])]++
for _, vv := range val {
switch vv.(type) {
case *Item:
vv.(*Item).CountPaths(prefix+key+".", paths)
}
}
}
}
// NewItem returns a new Item.
func NewItem() *Item {
return &Item{
Types: make([]string, 0),
Properties: make(PropertyMap),
}
}