1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package errors
16
17 import (
18 "fmt"
19 "strings"
20 )
21
22 const (
23 invalidType = "%s is an invalid type name"
24 typeFail = "%s in %s must be of type %s"
25 typeFailWithData = "%s in %s must be of type %s: %q"
26 typeFailWithError = "%s in %s must be of type %s, because: %s"
27 requiredFail = "%s in %s is required"
28 tooLongMessage = "%s in %s should be at most %d chars long"
29 tooShortMessage = "%s in %s should be at least %d chars long"
30 patternFail = "%s in %s should match '%s'"
31 enumFail = "%s in %s should be one of %v"
32 multipleOfFail = "%s in %s should be a multiple of %v"
33 maxIncFail = "%s in %s should be less than or equal to %v"
34 maxExcFail = "%s in %s should be less than %v"
35 minIncFail = "%s in %s should be greater than or equal to %v"
36 minExcFail = "%s in %s should be greater than %v"
37 uniqueFail = "%s in %s shouldn't contain duplicates"
38 maxItemsFail = "%s in %s should have at most %d items"
39 minItemsFail = "%s in %s should have at least %d items"
40 typeFailNoIn = "%s must be of type %s"
41 typeFailWithDataNoIn = "%s must be of type %s: %q"
42 typeFailWithErrorNoIn = "%s must be of type %s, because: %s"
43 requiredFailNoIn = "%s is required"
44 tooLongMessageNoIn = "%s should be at most %d chars long"
45 tooShortMessageNoIn = "%s should be at least %d chars long"
46 patternFailNoIn = "%s should match '%s'"
47 enumFailNoIn = "%s should be one of %v"
48 multipleOfFailNoIn = "%s should be a multiple of %v"
49 maxIncFailNoIn = "%s should be less than or equal to %v"
50 maxExcFailNoIn = "%s should be less than %v"
51 minIncFailNoIn = "%s should be greater than or equal to %v"
52 minExcFailNoIn = "%s should be greater than %v"
53 uniqueFailNoIn = "%s shouldn't contain duplicates"
54 maxItemsFailNoIn = "%s should have at most %d items"
55 minItemsFailNoIn = "%s should have at least %d items"
56 noAdditionalItems = "%s in %s can't have additional items"
57 noAdditionalItemsNoIn = "%s can't have additional items"
58 tooFewProperties = "%s in %s should have at least %d properties"
59 tooFewPropertiesNoIn = "%s should have at least %d properties"
60 tooManyProperties = "%s in %s should have at most %d properties"
61 tooManyPropertiesNoIn = "%s should have at most %d properties"
62 unallowedProperty = "%s.%s in %s is a forbidden property"
63 unallowedPropertyNoIn = "%s.%s is a forbidden property"
64 failedAllPatternProps = "%s.%s in %s failed all pattern properties"
65 failedAllPatternPropsNoIn = "%s.%s failed all pattern properties"
66 multipleOfMustBePositive = "factor MultipleOf declared for %s must be positive: %v"
67 )
68
69
70
71 const (
72
73
74 CompositeErrorCode = 422
75
76 InvalidTypeCode = 600 + iota
77 RequiredFailCode
78 TooLongFailCode
79 TooShortFailCode
80 PatternFailCode
81 EnumFailCode
82 MultipleOfFailCode
83 MaxFailCode
84 MinFailCode
85 UniqueFailCode
86 MaxItemsFailCode
87 MinItemsFailCode
88 NoAdditionalItemsCode
89 TooFewPropertiesCode
90 TooManyPropertiesCode
91 UnallowedPropertyCode
92 FailedAllPatternPropsCode
93 MultipleOfMustBePositiveCode
94 )
95
96
97 type CompositeError struct {
98 Errors []error
99 code int32
100 message string
101 }
102
103
104 func (c *CompositeError) Code() int32 {
105 return c.code
106 }
107
108 func (c *CompositeError) Error() string {
109 if len(c.Errors) > 0 {
110 msgs := []string{c.message + ":"}
111 for _, e := range c.Errors {
112 msgs = append(msgs, e.Error())
113 }
114 return strings.Join(msgs, "\n")
115 }
116 return c.message
117 }
118
119
120 func CompositeValidationError(errors ...error) *CompositeError {
121 return &CompositeError{
122 code: CompositeErrorCode,
123 Errors: append([]error{}, errors...),
124 message: "validation failure list",
125 }
126 }
127
128
129 func FailedAllPatternProperties(name, in, key string) *Validation {
130 msg := fmt.Sprintf(failedAllPatternProps, name, key, in)
131 if in == "" {
132 msg = fmt.Sprintf(failedAllPatternPropsNoIn, name, key)
133 }
134 return &Validation{
135 code: FailedAllPatternPropsCode,
136 Name: name,
137 In: in,
138 Value: key,
139 message: msg,
140 }
141 }
142
143
144 func PropertyNotAllowed(name, in, key string) *Validation {
145 msg := fmt.Sprintf(unallowedProperty, name, key, in)
146 if in == "" {
147 msg = fmt.Sprintf(unallowedPropertyNoIn, name, key)
148 }
149 return &Validation{
150 code: UnallowedPropertyCode,
151 Name: name,
152 In: in,
153 Value: key,
154 message: msg,
155 }
156 }
157
158
159 func TooFewProperties(name, in string, minProperties, size int64) *Validation {
160 msg := fmt.Sprintf(tooFewProperties, name, in, minProperties)
161 if in == "" {
162 msg = fmt.Sprintf(tooFewPropertiesNoIn, name, minProperties)
163 }
164 return &Validation{
165 code: TooFewPropertiesCode,
166 Name: name,
167 In: in,
168 Value: size,
169 Valid: minProperties,
170 message: msg,
171 }
172 }
173
174
175 func TooManyProperties(name, in string, maxProperties, size int64) *Validation {
176 msg := fmt.Sprintf(tooManyProperties, name, in, maxProperties)
177 if in == "" {
178 msg = fmt.Sprintf(tooManyPropertiesNoIn, name, maxProperties)
179 }
180 return &Validation{
181 code: TooManyPropertiesCode,
182 Name: name,
183 In: in,
184 Value: size,
185 Valid: maxProperties,
186 message: msg,
187 }
188 }
189
190
191 func AdditionalItemsNotAllowed(name, in string) *Validation {
192 msg := fmt.Sprintf(noAdditionalItems, name, in)
193 if in == "" {
194 msg = fmt.Sprintf(noAdditionalItemsNoIn, name)
195 }
196 return &Validation{
197 code: NoAdditionalItemsCode,
198 Name: name,
199 In: in,
200 message: msg,
201 }
202 }
203
204
205 func InvalidCollectionFormat(name, in, format string) *Validation {
206 return &Validation{
207 code: InvalidTypeCode,
208 Name: name,
209 In: in,
210 Value: format,
211 message: fmt.Sprintf("the collection format %q is not supported for the %s param %q", format, in, name),
212 }
213 }
214
215
216 func InvalidTypeName(typeName string) *Validation {
217 return &Validation{
218 code: InvalidTypeCode,
219 Value: typeName,
220 message: fmt.Sprintf(invalidType, typeName),
221 }
222 }
223
224
225 func InvalidType(name, in, typeName string, value interface{}) *Validation {
226 var message string
227
228 if in != "" {
229 switch value.(type) {
230 case string:
231 message = fmt.Sprintf(typeFailWithData, name, in, typeName, value)
232 case error:
233 message = fmt.Sprintf(typeFailWithError, name, in, typeName, value)
234 default:
235 message = fmt.Sprintf(typeFail, name, in, typeName)
236 }
237 } else {
238 switch value.(type) {
239 case string:
240 message = fmt.Sprintf(typeFailWithDataNoIn, name, typeName, value)
241 case error:
242 message = fmt.Sprintf(typeFailWithErrorNoIn, name, typeName, value)
243 default:
244 message = fmt.Sprintf(typeFailNoIn, name, typeName)
245 }
246 }
247
248 return &Validation{
249 code: InvalidTypeCode,
250 Name: name,
251 In: in,
252 Value: value,
253 message: message,
254 }
255
256 }
257
258
259 func DuplicateItems(name, in string) *Validation {
260 msg := fmt.Sprintf(uniqueFail, name, in)
261 if in == "" {
262 msg = fmt.Sprintf(uniqueFailNoIn, name)
263 }
264 return &Validation{
265 code: UniqueFailCode,
266 Name: name,
267 In: in,
268 message: msg,
269 }
270 }
271
272
273 func TooManyItems(name, in string, max int64, value interface{}) *Validation {
274 msg := fmt.Sprintf(maxItemsFail, name, in, max)
275 if in == "" {
276 msg = fmt.Sprintf(maxItemsFailNoIn, name, max)
277 }
278
279 return &Validation{
280 code: MaxItemsFailCode,
281 Name: name,
282 In: in,
283 Value: value,
284 Valid: max,
285 message: msg,
286 }
287 }
288
289
290 func TooFewItems(name, in string, min int64, value interface{}) *Validation {
291 msg := fmt.Sprintf(minItemsFail, name, in, min)
292 if in == "" {
293 msg = fmt.Sprintf(minItemsFailNoIn, name, min)
294 }
295 return &Validation{
296 code: MinItemsFailCode,
297 Name: name,
298 In: in,
299 Value: value,
300 Valid: min,
301 message: msg,
302 }
303 }
304
305
306 func ExceedsMaximumInt(name, in string, max int64, exclusive bool, value interface{}) *Validation {
307 var message string
308 if in == "" {
309 m := maxIncFailNoIn
310 if exclusive {
311 m = maxExcFailNoIn
312 }
313 message = fmt.Sprintf(m, name, max)
314 } else {
315 m := maxIncFail
316 if exclusive {
317 m = maxExcFail
318 }
319 message = fmt.Sprintf(m, name, in, max)
320 }
321 return &Validation{
322 code: MaxFailCode,
323 Name: name,
324 In: in,
325 Value: value,
326 message: message,
327 }
328 }
329
330
331 func ExceedsMaximumUint(name, in string, max uint64, exclusive bool, value interface{}) *Validation {
332 var message string
333 if in == "" {
334 m := maxIncFailNoIn
335 if exclusive {
336 m = maxExcFailNoIn
337 }
338 message = fmt.Sprintf(m, name, max)
339 } else {
340 m := maxIncFail
341 if exclusive {
342 m = maxExcFail
343 }
344 message = fmt.Sprintf(m, name, in, max)
345 }
346 return &Validation{
347 code: MaxFailCode,
348 Name: name,
349 In: in,
350 Value: value,
351 message: message,
352 }
353 }
354
355
356 func ExceedsMaximum(name, in string, max float64, exclusive bool, value interface{}) *Validation {
357 var message string
358 if in == "" {
359 m := maxIncFailNoIn
360 if exclusive {
361 m = maxExcFailNoIn
362 }
363 message = fmt.Sprintf(m, name, max)
364 } else {
365 m := maxIncFail
366 if exclusive {
367 m = maxExcFail
368 }
369 message = fmt.Sprintf(m, name, in, max)
370 }
371 return &Validation{
372 code: MaxFailCode,
373 Name: name,
374 In: in,
375 Value: value,
376 message: message,
377 }
378 }
379
380
381 func ExceedsMinimumInt(name, in string, min int64, exclusive bool, value interface{}) *Validation {
382 var message string
383 if in == "" {
384 m := minIncFailNoIn
385 if exclusive {
386 m = minExcFailNoIn
387 }
388 message = fmt.Sprintf(m, name, min)
389 } else {
390 m := minIncFail
391 if exclusive {
392 m = minExcFail
393 }
394 message = fmt.Sprintf(m, name, in, min)
395 }
396 return &Validation{
397 code: MinFailCode,
398 Name: name,
399 In: in,
400 Value: value,
401 message: message,
402 }
403 }
404
405
406 func ExceedsMinimumUint(name, in string, min uint64, exclusive bool, value interface{}) *Validation {
407 var message string
408 if in == "" {
409 m := minIncFailNoIn
410 if exclusive {
411 m = minExcFailNoIn
412 }
413 message = fmt.Sprintf(m, name, min)
414 } else {
415 m := minIncFail
416 if exclusive {
417 m = minExcFail
418 }
419 message = fmt.Sprintf(m, name, in, min)
420 }
421 return &Validation{
422 code: MinFailCode,
423 Name: name,
424 In: in,
425 Value: value,
426 message: message,
427 }
428 }
429
430
431 func ExceedsMinimum(name, in string, min float64, exclusive bool, value interface{}) *Validation {
432 var message string
433 if in == "" {
434 m := minIncFailNoIn
435 if exclusive {
436 m = minExcFailNoIn
437 }
438 message = fmt.Sprintf(m, name, min)
439 } else {
440 m := minIncFail
441 if exclusive {
442 m = minExcFail
443 }
444 message = fmt.Sprintf(m, name, in, min)
445 }
446 return &Validation{
447 code: MinFailCode,
448 Name: name,
449 In: in,
450 Value: value,
451 message: message,
452 }
453 }
454
455
456 func NotMultipleOf(name, in string, multiple, value interface{}) *Validation {
457 var msg string
458 if in == "" {
459 msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple)
460 } else {
461 msg = fmt.Sprintf(multipleOfFail, name, in, multiple)
462 }
463 return &Validation{
464 code: MultipleOfFailCode,
465 Name: name,
466 In: in,
467 Value: value,
468 message: msg,
469 }
470 }
471
472
473 func EnumFail(name, in string, value interface{}, values []interface{}) *Validation {
474 var msg string
475 if in == "" {
476 msg = fmt.Sprintf(enumFailNoIn, name, values)
477 } else {
478 msg = fmt.Sprintf(enumFail, name, in, values)
479 }
480
481 return &Validation{
482 code: EnumFailCode,
483 Name: name,
484 In: in,
485 Value: value,
486 Values: values,
487 message: msg,
488 }
489 }
490
491
492 func Required(name, in string) *Validation {
493 var msg string
494 if in == "" {
495 msg = fmt.Sprintf(requiredFailNoIn, name)
496 } else {
497 msg = fmt.Sprintf(requiredFail, name, in)
498 }
499 return &Validation{
500 code: RequiredFailCode,
501 Name: name,
502 In: in,
503 message: msg,
504 }
505 }
506
507
508 func TooLong(name, in string, max int64, value interface{}) *Validation {
509 var msg string
510 if in == "" {
511 msg = fmt.Sprintf(tooLongMessageNoIn, name, max)
512 } else {
513 msg = fmt.Sprintf(tooLongMessage, name, in, max)
514 }
515 return &Validation{
516 code: TooLongFailCode,
517 Name: name,
518 In: in,
519 Value: value,
520 Valid: max,
521 message: msg,
522 }
523 }
524
525
526 func TooShort(name, in string, min int64, value interface{}) *Validation {
527 var msg string
528 if in == "" {
529 msg = fmt.Sprintf(tooShortMessageNoIn, name, min)
530 } else {
531 msg = fmt.Sprintf(tooShortMessage, name, in, min)
532 }
533
534 return &Validation{
535 code: TooShortFailCode,
536 Name: name,
537 In: in,
538 Value: value,
539 Valid: min,
540 message: msg,
541 }
542 }
543
544
545
546 func FailedPattern(name, in, pattern string, value interface{}) *Validation {
547 var msg string
548 if in == "" {
549 msg = fmt.Sprintf(patternFailNoIn, name, pattern)
550 } else {
551 msg = fmt.Sprintf(patternFail, name, in, pattern)
552 }
553
554 return &Validation{
555 code: PatternFailCode,
556 Name: name,
557 In: in,
558 Value: value,
559 message: msg,
560 }
561 }
562
563
564
565 func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation {
566 return &Validation{
567 code: MultipleOfMustBePositiveCode,
568 Name: name,
569 In: in,
570 Value: factor,
571 message: fmt.Sprintf(multipleOfMustBePositive, name, factor),
572 }
573 }
574
View as plain text