1 package jsonschema
2
3 import (
4 "context"
5 "encoding/json"
6 "strconv"
7
8 jptr "github.com/qri-io/jsonpointer"
9 )
10
11
12 type AllOf []*Schema
13
14
15 func NewAllOf() Keyword {
16 return &AllOf{}
17 }
18
19
20 func (a *AllOf) Register(uri string, registry *SchemaRegistry) {
21 for _, sch := range *a {
22 sch.Register(uri, registry)
23 }
24 }
25
26
27 func (a *AllOf) Resolve(pointer jptr.Pointer, uri string) *Schema {
28 if pointer == nil {
29 return nil
30 }
31 current := pointer.Head()
32 if current == nil {
33 return nil
34 }
35
36 pos, err := strconv.Atoi(*current)
37 if err != nil {
38 return nil
39 }
40
41 if pos < 0 || pos >= len(*a) {
42 return nil
43 }
44
45 return (*a)[pos].Resolve(pointer.Tail(), uri)
46
47 return nil
48 }
49
50
51 func (a *AllOf) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
52 schemaDebug("[AllOf] Validating")
53 stateCopy := currentState.NewSubState()
54 stateCopy.ClearState()
55 invalid := false
56 for i, sch := range *a {
57 subState := currentState.NewSubState()
58 subState.ClearState()
59 subState.DescendBase("allOf", strconv.Itoa(i))
60 subState.DescendRelative("allOf", strconv.Itoa(i))
61 subState.Errs = &[]KeyError{}
62 sch.ValidateKeyword(ctx, subState, data)
63 currentState.AddSubErrors(*subState.Errs...)
64 stateCopy.UpdateEvaluatedPropsAndItems(subState)
65 if !subState.IsValid() {
66 invalid = true
67 }
68 }
69 if !invalid {
70 currentState.UpdateEvaluatedPropsAndItems(stateCopy)
71 }
72 }
73
74
75 func (a AllOf) JSONProp(name string) interface{} {
76 idx, err := strconv.Atoi(name)
77 if err != nil {
78 return nil
79 }
80 if idx > len(a) || idx < 0 {
81 return nil
82 }
83 return a[idx]
84 }
85
86
87 func (a AllOf) JSONChildren() (res map[string]JSONPather) {
88 res = map[string]JSONPather{}
89 for i, sch := range a {
90 res[strconv.Itoa(i)] = sch
91 }
92 return
93 }
94
95
96 type AnyOf []*Schema
97
98
99 func NewAnyOf() Keyword {
100 return &AnyOf{}
101 }
102
103
104 func (a *AnyOf) Register(uri string, registry *SchemaRegistry) {
105 for _, sch := range *a {
106 sch.Register(uri, registry)
107 }
108 }
109
110
111 func (a *AnyOf) Resolve(pointer jptr.Pointer, uri string) *Schema {
112 if pointer == nil {
113 return nil
114 }
115 current := pointer.Head()
116 if current == nil {
117 return nil
118 }
119
120 pos, err := strconv.Atoi(*current)
121 if err != nil {
122 return nil
123 }
124
125 if pos < 0 || pos >= len(*a) {
126 return nil
127 }
128
129 return (*a)[pos].Resolve(pointer.Tail(), uri)
130
131 return nil
132 }
133
134
135 func (a *AnyOf) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
136 schemaDebug("[AnyOf] Validating")
137 for i, sch := range *a {
138 subState := currentState.NewSubState()
139 subState.ClearState()
140 subState.DescendBase("anyOf", strconv.Itoa(i))
141 subState.DescendRelative("anyOf", strconv.Itoa(i))
142 subState.Errs = &[]KeyError{}
143 sch.ValidateKeyword(ctx, subState, data)
144 if subState.IsValid() {
145 currentState.UpdateEvaluatedPropsAndItems(subState)
146 return
147 }
148 }
149
150 currentState.AddError(data, "did Not match any specified AnyOf schemas")
151 }
152
153
154 func (a AnyOf) JSONProp(name string) interface{} {
155 idx, err := strconv.Atoi(name)
156 if err != nil {
157 return nil
158 }
159 if idx > len(a) || idx < 0 {
160 return nil
161 }
162 return a[idx]
163 }
164
165
166 func (a AnyOf) JSONChildren() (res map[string]JSONPather) {
167 res = map[string]JSONPather{}
168 for i, sch := range a {
169 res[strconv.Itoa(i)] = sch
170 }
171 return
172 }
173
174
175 type OneOf []*Schema
176
177
178 func NewOneOf() Keyword {
179 return &OneOf{}
180 }
181
182
183 func (o *OneOf) Register(uri string, registry *SchemaRegistry) {
184 for _, sch := range *o {
185 sch.Register(uri, registry)
186 }
187 }
188
189
190 func (o *OneOf) Resolve(pointer jptr.Pointer, uri string) *Schema {
191 if pointer == nil {
192 return nil
193 }
194 current := pointer.Head()
195 if current == nil {
196 return nil
197 }
198
199 pos, err := strconv.Atoi(*current)
200 if err != nil {
201 return nil
202 }
203
204 if pos < 0 || pos >= len(*o) {
205 return nil
206 }
207
208 return (*o)[pos].Resolve(pointer.Tail(), uri)
209
210 return nil
211 }
212
213
214 func (o *OneOf) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
215 schemaDebug("[OneOf] Validating")
216 matched := false
217 stateCopy := currentState.NewSubState()
218 stateCopy.ClearState()
219 for i, sch := range *o {
220 subState := currentState.NewSubState()
221 subState.ClearState()
222 subState.DescendBase("oneOf", strconv.Itoa(i))
223 subState.DescendRelative("oneOf", strconv.Itoa(i))
224 subState.Errs = &[]KeyError{}
225 sch.ValidateKeyword(ctx, subState, data)
226 stateCopy.UpdateEvaluatedPropsAndItems(subState)
227 if subState.IsValid() {
228 if matched {
229 currentState.AddError(data, "matched more than one specified OneOf schemas")
230 return
231 }
232 matched = true
233 }
234 }
235 if !matched {
236 currentState.AddError(data, "did not match any of the specified OneOf schemas")
237 } else {
238 currentState.UpdateEvaluatedPropsAndItems(stateCopy)
239 }
240 }
241
242
243 func (o OneOf) JSONProp(name string) interface{} {
244 idx, err := strconv.Atoi(name)
245 if err != nil {
246 return nil
247 }
248 if idx > len(o) || idx < 0 {
249 return nil
250 }
251 return o[idx]
252 }
253
254
255 func (o OneOf) JSONChildren() (res map[string]JSONPather) {
256 res = map[string]JSONPather{}
257 for i, sch := range o {
258 res[strconv.Itoa(i)] = sch
259 }
260 return
261 }
262
263
264 type Not Schema
265
266
267 func NewNot() Keyword {
268 return &Not{}
269 }
270
271
272 func (n *Not) Register(uri string, registry *SchemaRegistry) {
273 (*Schema)(n).Register(uri, registry)
274 }
275
276
277 func (n *Not) Resolve(pointer jptr.Pointer, uri string) *Schema {
278 return (*Schema)(n).Resolve(pointer, uri)
279 }
280
281
282 func (n *Not) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
283 schemaDebug("[Not] Validating")
284 subState := currentState.NewSubState()
285 subState.DescendBase("not")
286 subState.DescendRelative("not")
287
288 subState.Errs = &[]KeyError{}
289 sch := Schema(*n)
290 sch.ValidateKeyword(ctx, subState, data)
291 if subState.IsValid() {
292 currentState.AddError(data, "result was valid, ('not') expected invalid")
293 }
294 }
295
296
297 func (n Not) JSONProp(name string) interface{} {
298 return Schema(n).JSONProp(name)
299 }
300
301
302 func (n Not) JSONChildren() (res map[string]JSONPather) {
303 return Schema(n).JSONChildren()
304 }
305
306
307 func (n *Not) UnmarshalJSON(data []byte) error {
308 var sch Schema
309 if err := json.Unmarshal(data, &sch); err != nil {
310 return err
311 }
312 *n = Not(sch)
313 return nil
314 }
315
316
317 func (n Not) MarshalJSON() ([]byte, error) {
318 return json.Marshal(Schema(n))
319 }
320
View as plain text