Serge Bazanski | cc25bdf | 2018-10-25 14:02:58 +0200 | [diff] [blame^] | 1 | // 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 | |
| 15 | package validate |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "reflect" |
| 20 | |
| 21 | "github.com/go-openapi/spec" |
| 22 | "github.com/go-openapi/strfmt" |
| 23 | ) |
| 24 | |
| 25 | type 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 | |
| 37 | func (s *schemaSliceValidator) SetPath(path string) { |
| 38 | s.Path = path |
| 39 | } |
| 40 | |
| 41 | func (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 | |
| 47 | func (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 | } |