blob: 6e615946b64b7ff88b020e67dd57589d6e0e727d [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// Copyright 2015 go-swagger maintainers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package validate
16
17import (
18 "fmt"
19 "reflect"
20
21 "github.com/go-openapi/spec"
22 "github.com/go-openapi/strfmt"
23)
24
25type schemaSliceValidator struct {
26 Path string
27 In string
28 MaxItems *int64
29 MinItems *int64
30 UniqueItems bool
31 AdditionalItems *spec.SchemaOrBool
32 Items *spec.SchemaOrArray
33 Root interface{}
34 KnownFormats strfmt.Registry
35}
36
37func (s *schemaSliceValidator) SetPath(path string) {
38 s.Path = path
39}
40
41func (s *schemaSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
42 _, ok := source.(*spec.Schema)
43 r := ok && kind == reflect.Slice
44 return r
45}
46
47func (s *schemaSliceValidator) Validate(data interface{}) *Result {
48 result := new(Result)
49 if data == nil {
50 return result
51 }
52 val := reflect.ValueOf(data)
53 size := val.Len()
54
55 if s.Items != nil && s.Items.Schema != nil {
56 validator := NewSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats)
57 for i := 0; i < size; i++ {
58 validator.SetPath(fmt.Sprintf("%s.%d", s.Path, i))
59 value := val.Index(i)
60 result.mergeForSlice(val, i, validator.Validate(value.Interface()))
61 }
62 }
63
64 itemsSize := 0
65 if s.Items != nil && len(s.Items.Schemas) > 0 {
66 itemsSize = len(s.Items.Schemas)
67 for i := 0; i < itemsSize; i++ {
68 validator := NewSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats)
69 if val.Len() <= i {
70 break
71 }
72 result.mergeForSlice(val, int(i), validator.Validate(val.Index(i).Interface()))
73 }
74 }
75 if s.AdditionalItems != nil && itemsSize < size {
76 if s.Items != nil && len(s.Items.Schemas) > 0 && !s.AdditionalItems.Allows {
77 result.AddErrors(arrayDoesNotAllowAdditionalItemsMsg())
78 }
79 if s.AdditionalItems.Schema != nil {
80 for i := itemsSize; i < size-itemsSize+1; i++ {
81 validator := NewSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats)
82 result.mergeForSlice(val, int(i), validator.Validate(val.Index(int(i)).Interface()))
83 }
84 }
85 }
86
87 if s.MinItems != nil {
88 if err := MinItems(s.Path, s.In, int64(size), *s.MinItems); err != nil {
89 result.AddErrors(err)
90 }
91 }
92 if s.MaxItems != nil {
93 if err := MaxItems(s.Path, s.In, int64(size), *s.MaxItems); err != nil {
94 result.AddErrors(err)
95 }
96 }
97 if s.UniqueItems {
98 if err := UniqueItems(s.Path, s.In, val.Interface()); err != nil {
99 result.AddErrors(err)
100 }
101 }
102 result.Inc()
103 return result
104}