vendorify
diff --git a/go/vendor/github.com/go-openapi/validate/object_validator.go b/go/vendor/github.com/go-openapi/validate/object_validator.go
new file mode 100644
index 0000000..14e1982
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/object_validator.go
@@ -0,0 +1,264 @@
+// Copyright 2015 go-swagger maintainers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package validate
+
+import (
+ "reflect"
+ "regexp"
+ "strings"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/spec"
+ "github.com/go-openapi/strfmt"
+)
+
+type objectValidator struct {
+ Path string
+ In string
+ MaxProperties *int64
+ MinProperties *int64
+ Required []string
+ Properties map[string]spec.Schema
+ AdditionalProperties *spec.SchemaOrBool
+ PatternProperties map[string]spec.Schema
+ Root interface{}
+ KnownFormats strfmt.Registry
+}
+
+func (o *objectValidator) SetPath(path string) {
+ o.Path = path
+}
+
+func (o *objectValidator) Applies(source interface{}, kind reflect.Kind) bool {
+ // TODO: this should also work for structs
+ // there is a problem in the type validator where it will be unhappy about null values
+ // so that requires more testing
+ r := reflect.TypeOf(source) == specSchemaType && (kind == reflect.Map || kind == reflect.Struct)
+ debugLog("object validator for %q applies %t for %T (kind: %v)\n", o.Path, r, source, kind)
+ return r
+}
+
+func (o *objectValidator) isPropertyName() bool {
+ p := strings.Split(o.Path, ".")
+ return p[len(p)-1] == "properties" && p[len(p)-2] != "properties"
+}
+
+func (o *objectValidator) checkArrayMustHaveItems(res *Result, val map[string]interface{}) {
+ if t, typeFound := val["type"]; typeFound {
+ if tpe, ok := t.(string); ok && tpe == "array" {
+ if _, itemsKeyFound := val["items"]; !itemsKeyFound {
+ res.AddErrors(errors.Required("items", o.Path))
+ }
+ }
+ }
+}
+
+func (o *objectValidator) checkItemsMustBeTypeArray(res *Result, val map[string]interface{}) {
+ if !o.isPropertyName() {
+ if _, itemsKeyFound := val["items"]; itemsKeyFound {
+ t, typeFound := val["type"]
+ if typeFound {
+ if tpe, ok := t.(string); !ok || tpe != "array" {
+ res.AddErrors(errors.InvalidType(o.Path, o.In, "array", nil))
+ }
+ } else {
+ // there is no type
+ res.AddErrors(errors.Required("type", o.Path))
+ }
+ }
+ }
+}
+
+func (o *objectValidator) precheck(res *Result, val map[string]interface{}) {
+ o.checkArrayMustHaveItems(res, val)
+ o.checkItemsMustBeTypeArray(res, val)
+}
+
+func (o *objectValidator) Validate(data interface{}) *Result {
+ val := data.(map[string]interface{})
+ // TODO: guard against nil data
+ numKeys := int64(len(val))
+
+ if o.MinProperties != nil && numKeys < *o.MinProperties {
+ return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties))
+ }
+ if o.MaxProperties != nil && numKeys > *o.MaxProperties {
+ return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties))
+ }
+
+ res := new(Result)
+
+ o.precheck(res, val)
+
+ // check validity of field names
+ if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows {
+ // Case: additionalProperties: false
+ for k := range val {
+ _, regularProperty := o.Properties[k]
+ matched := false
+
+ for pk := range o.PatternProperties {
+ if matches, _ := regexp.MatchString(pk, k); matches {
+ matched = true
+ break
+ }
+ }
+
+ if !regularProperty && k != "$schema" && k != "id" && !matched {
+ // Special properties "$schema" and "id" are ignored
+ res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k))
+
+ // BUG(fredbi): This section should move to a part dedicated to spec validation as
+ // it will conflict with regular schemas where a property "headers" is defined.
+
+ //
+ // Croaks a more explicit message on top of the standard one
+ // on some recognized cases.
+ //
+ // NOTE: edge cases with invalid type assertion are simply ignored here.
+ // NOTE: prefix your messages here by "IMPORTANT!" so there are not filtered
+ // by higher level callers (the IMPORTANT! tag will be eventually
+ // removed).
+ switch k {
+ // $ref is forbidden in header
+ case "headers":
+ if val[k] != nil {
+ if headers, mapOk := val[k].(map[string]interface{}); mapOk {
+ for headerKey, headerBody := range headers {
+ if headerBody != nil {
+ if headerSchema, mapOfMapOk := headerBody.(map[string]interface{}); mapOfMapOk {
+ if _, found := headerSchema["$ref"]; found {
+ var msg string
+ if refString, stringOk := headerSchema["$ref"].(string); stringOk {
+ msg = strings.Join([]string{", one may not use $ref=\":", refString, "\""}, "")
+ }
+ res.AddErrors(refNotAllowedInHeaderMsg(o.Path, headerKey, msg))
+ }
+ }
+ }
+ }
+ }
+ }
+ /*
+ case "$ref":
+ if val[k] != nil {
+ // TODO: check context of that ref: warn about siblings, check against invalid context
+ }
+ */
+ }
+ }
+ }
+ } else {
+ // Cases: no additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <<schema>> }
+ for key, value := range val {
+ _, regularProperty := o.Properties[key]
+
+ // Validates property against "patternProperties" if applicable
+ // BUG(fredbi): succeededOnce is always false
+
+ // NOTE: how about regular properties which do not match patternProperties?
+ matched, succeededOnce, _ := o.validatePatternProperty(key, value, res)
+
+ if !(regularProperty || matched || succeededOnce) {
+
+ // Cases: properties which are not regular properties and have not been matched by the PatternProperties validator
+ if o.AdditionalProperties != nil && o.AdditionalProperties.Schema != nil {
+ // AdditionalProperties as Schema
+ r := NewSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats).Validate(value)
+ res.mergeForField(data.(map[string]interface{}), key, r)
+ } else if regularProperty && !(matched || succeededOnce) {
+ // TODO: this is dead code since regularProperty=false here
+ res.AddErrors(errors.FailedAllPatternProperties(o.Path, o.In, key))
+ }
+ }
+ }
+ // Valid cases: additionalProperties: true or undefined
+ }
+
+ createdFromDefaults := map[string]bool{}
+
+ // Property types:
+ // - regular Property
+ for pName := range o.Properties {
+ pSchema := o.Properties[pName] // one instance per iteration
+ rName := pName
+ if o.Path != "" {
+ rName = o.Path + "." + pName
+ }
+
+ // Recursively validates each property against its schema
+ if v, ok := val[pName]; ok {
+ r := NewSchemaValidator(&pSchema, o.Root, rName, o.KnownFormats).Validate(v)
+ res.mergeForField(data.(map[string]interface{}), pName, r)
+ } else if pSchema.Default != nil {
+ // If a default value is defined, creates the property from defaults
+ // NOTE: JSON schema does not enforce default values to be valid against schema. Swagger does.
+ createdFromDefaults[pName] = true
+ res.addPropertySchemata(data.(map[string]interface{}), pName, &pSchema)
+ }
+ }
+
+ // Check required properties
+ if len(o.Required) > 0 {
+ for _, k := range o.Required {
+ if _, ok := val[k]; !ok && !createdFromDefaults[k] {
+ res.AddErrors(errors.Required(o.Path+"."+k, o.In))
+ continue
+ }
+ }
+ }
+
+ // Check patternProperties
+ // TODO: it looks like we have done that twice in many cases
+ for key, value := range val {
+ _, regularProperty := o.Properties[key]
+ matched, _ /*succeededOnce*/, patterns := o.validatePatternProperty(key, value, res)
+ if !regularProperty && (matched /*|| succeededOnce*/) {
+ for _, pName := range patterns {
+ if v, ok := o.PatternProperties[pName]; ok {
+ r := NewSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats).Validate(value)
+ res.mergeForField(data.(map[string]interface{}), key, r)
+ }
+ }
+ }
+ }
+ return res
+}
+
+// TODO: succeededOnce is not used anywhere
+func (o *objectValidator) validatePatternProperty(key string, value interface{}, result *Result) (bool, bool, []string) {
+ matched := false
+ succeededOnce := false
+ var patterns []string
+
+ for k, schema := range o.PatternProperties {
+ if match, _ := regexp.MatchString(k, key); match {
+ patterns = append(patterns, k)
+ matched = true
+ validator := NewSchemaValidator(&schema, o.Root, o.Path+"."+key, o.KnownFormats)
+
+ res := validator.Validate(value)
+ result.Merge(res)
+ }
+ }
+
+ // BUG(fredbi): can't get to here. Should remove dead code (commented out).
+
+ //if succeededOnce {
+ // result.Inc()
+ //}
+
+ return matched, succeededOnce, patterns
+}