...
1
16
17 package proto
18
19 import (
20 "fmt"
21 "sort"
22 "strings"
23 )
24
25
26 const (
27 Integer = "integer"
28 Number = "number"
29 String = "string"
30 Boolean = "boolean"
31
32
33
34 array = "array"
35 object = "object"
36 )
37
38
39
40 type Models interface {
41 LookupModel(string) Schema
42 ListModels() []string
43 }
44
45
46
47
48
49
50
51
52
53 type SchemaVisitor interface {
54 VisitArray(*Array)
55 VisitMap(*Map)
56 VisitPrimitive(*Primitive)
57 VisitKind(*Kind)
58 VisitReference(Reference)
59 }
60
61
62
63
64 type SchemaVisitorArbitrary interface {
65 SchemaVisitor
66 VisitArbitrary(*Arbitrary)
67 }
68
69
70 type Schema interface {
71
72 Accept(SchemaVisitor)
73
74
75 GetName() string
76
77 GetPath() *Path
78
79 GetDescription() string
80
81 GetDefault() interface{}
82
83 GetExtensions() map[string]interface{}
84 }
85
86
87 type Path struct {
88 parent *Path
89 key string
90 }
91
92 func NewPath(key string) Path {
93 return Path{key: key}
94 }
95
96 func (p *Path) Get() []string {
97 if p == nil {
98 return []string{}
99 }
100 if p.key == "" {
101 return p.parent.Get()
102 }
103 return append(p.parent.Get(), p.key)
104 }
105
106 func (p *Path) Len() int {
107 return len(p.Get())
108 }
109
110 func (p *Path) String() string {
111 return strings.Join(p.Get(), "")
112 }
113
114
115 func (p *Path) ArrayPath(i int) Path {
116 return Path{
117 parent: p,
118 key: fmt.Sprintf("[%d]", i),
119 }
120 }
121
122
123 func (p *Path) FieldPath(field string) Path {
124 return Path{
125 parent: p,
126 key: fmt.Sprintf(".%s", field),
127 }
128 }
129
130
131 type BaseSchema struct {
132 Description string
133 Extensions map[string]interface{}
134 Default interface{}
135
136 Path Path
137 }
138
139 func (b *BaseSchema) GetDescription() string {
140 return b.Description
141 }
142
143 func (b *BaseSchema) GetExtensions() map[string]interface{} {
144 return b.Extensions
145 }
146
147 func (b *BaseSchema) GetDefault() interface{} {
148 return b.Default
149 }
150
151 func (b *BaseSchema) GetPath() *Path {
152 return &b.Path
153 }
154
155
156 type Array struct {
157 BaseSchema
158
159 SubType Schema
160 }
161
162 var _ Schema = &Array{}
163
164 func (a *Array) Accept(v SchemaVisitor) {
165 v.VisitArray(a)
166 }
167
168 func (a *Array) GetName() string {
169 return fmt.Sprintf("Array of %s", a.SubType.GetName())
170 }
171
172
173
174
175
176 type Kind struct {
177 BaseSchema
178
179
180 RequiredFields []string
181
182 Fields map[string]Schema
183
184 FieldOrder []string
185 }
186
187 var _ Schema = &Kind{}
188
189 func (k *Kind) Accept(v SchemaVisitor) {
190 v.VisitKind(k)
191 }
192
193 func (k *Kind) GetName() string {
194 properties := []string{}
195 for key := range k.Fields {
196 properties = append(properties, key)
197 }
198 return fmt.Sprintf("Kind(%v)", properties)
199 }
200
201
202 func (k *Kind) IsRequired(field string) bool {
203 for _, f := range k.RequiredFields {
204 if f == field {
205 return true
206 }
207 }
208 return false
209 }
210
211
212 func (k *Kind) Keys() []string {
213 keys := make([]string, 0)
214 for key := range k.Fields {
215 keys = append(keys, key)
216 }
217 sort.Strings(keys)
218 return keys
219 }
220
221
222
223 type Map struct {
224 BaseSchema
225
226 SubType Schema
227 }
228
229 var _ Schema = &Map{}
230
231 func (m *Map) Accept(v SchemaVisitor) {
232 v.VisitMap(m)
233 }
234
235 func (m *Map) GetName() string {
236 return fmt.Sprintf("Map of %s", m.SubType.GetName())
237 }
238
239
240
241 type Primitive struct {
242 BaseSchema
243
244
245 Type string
246 Format string
247 }
248
249 var _ Schema = &Primitive{}
250
251 func (p *Primitive) Accept(v SchemaVisitor) {
252 v.VisitPrimitive(p)
253 }
254
255 func (p *Primitive) GetName() string {
256 if p.Format == "" {
257 return p.Type
258 }
259 return fmt.Sprintf("%s (%s)", p.Type, p.Format)
260 }
261
262
263 type Arbitrary struct {
264 BaseSchema
265 }
266
267 var _ Schema = &Arbitrary{}
268
269 func (a *Arbitrary) Accept(v SchemaVisitor) {
270 if visitor, ok := v.(SchemaVisitorArbitrary); ok {
271 visitor.VisitArbitrary(a)
272 }
273 }
274
275 func (a *Arbitrary) GetName() string {
276 return "Arbitrary value (primitive, object or array)"
277 }
278
279
280 type Reference interface {
281 Schema
282
283 Reference() string
284 SubSchema() Schema
285 }
286
View as plain text