vendorify
diff --git a/go/vendor/github.com/go-openapi/validate/.editorconfig b/go/vendor/github.com/go-openapi/validate/.editorconfig
new file mode 100644
index 0000000..3152da6
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/.editorconfig
@@ -0,0 +1,26 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+
+# Set default charset
+[*.{js,py,go,scala,rb,java,html,css,less,sass,md}]
+charset = utf-8
+
+# Tab indentation (no size specified)
+[*.go]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/go/vendor/github.com/go-openapi/validate/.gitignore b/go/vendor/github.com/go-openapi/validate/.gitignore
new file mode 100644
index 0000000..fea8b84
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/.gitignore
@@ -0,0 +1,5 @@
+secrets.yml
+coverage.out
+*.cov
+*.out
+playground
diff --git a/go/vendor/github.com/go-openapi/validate/.golangci.yml b/go/vendor/github.com/go-openapi/validate/.golangci.yml
new file mode 100644
index 0000000..c2c5071
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/.golangci.yml
@@ -0,0 +1,20 @@
+linters-settings:
+  govet:
+    check-shadowing: true
+  golint:
+    min-confidence: 0
+  gocyclo:
+    min-complexity: 25
+  maligned:
+    suggest-new: true
+  dupl:
+    threshold: 100
+  goconst:
+    min-len: 2
+    min-occurrences: 2
+
+linters:
+  enable-all: true
+  disable:
+    - maligned
+    - lll
diff --git a/go/vendor/github.com/go-openapi/validate/.travis.yml b/go/vendor/github.com/go-openapi/validate/.travis.yml
new file mode 100644
index 0000000..c0d6fca
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/.travis.yml
@@ -0,0 +1,35 @@
+after_success:
+- bash <(curl -s https://codecov.io/bash)
+env:
+- TEST_COMMAND="go test -v -race -covermode=atomic"
+- TEST_COMMAND="go test -v -timeout=20m -cover -coverprofile=coverage.txt -args -enable-long"
+- TEST_COMMAND="go test -v -timeout=30m -args -enable-go-swagger"
+- TEST_COMMAND="go test -v -timeout=30m github.com/go-openapi/runtime/..."
+go:
+- '1.9'
+- 1.10.x
+- 1.11.x
+install:
+- go get -u github.com/axw/gocov/gocov
+- go get -u gopkg.in/matm/v1/gocov-html
+- go get -u github.com/cee-dub/go-junit-report
+- go get -u github.com/stretchr/testify/assert
+- go get -u github.com/kr/pretty
+- go get -u gopkg.in/yaml.v2
+- go get -u github.com/go-openapi/spec
+- go get -u github.com/go-openapi/analysis
+- go get -u github.com/go-openapi/errors
+- go get -u github.com/go-openapi/loads
+- go get -u github.com/go-openapi/strfmt
+- go get -u github.com/go-openapi/runtime
+- go get -u github.com/docker/go-units
+language: go
+matrix:
+  exclude:
+  - env: TEST_COMMAND="go test -v -timeout=30m -args -enable-go-swagger"
+    go: 1.8
+notifications:
+  slack:
+    secure: EmObnQuM9Mw8J9vpFaKKHqSMN4Wsr/A9+v7ewAD5cEhA0T1P4m7MbJMiJOhxUhj/X+BFh2DamW+P2lT8mybj5wg8wnkQ2BteKA8Tawi6f9PRw2NRheO8tAi8o/npLnlmet0kc93mn+oLuqHw36w4+j5mkOl2FghkfGiUVhwrhkCP7KXQN+3TU87e+/HzQumlJ3nsE+6terVxkH3PmaUTsS5ONaODZfuxFpfb7RsoEl3skHf6d+tr+1nViLxxly7558Nc33C+W1mr0qiEvMLZ+kJ/CpGWBJ6CUJM3jm6hNe2eMuIPwEK2hxZob8c7n22VPap4K6a0bBRoydoDXaba+2sD7Ym6ivDO/DVyL44VeBBLyIiIBylDGQdZH+6SoWm90Qe/i7tnY/T5Ao5igT8f3cfQY1c3EsTfqmlDfrhmACBmwSlgkdVBLTprHL63JMY24LWmh4jhxsmMRZhCL4dze8su1w6pLN/pD1pGHtKYCEVbdTmaM3PblNRFf12XB7qosmQsgUndH4Vq3bTbU0s1pKjeDhRyLvFzvR0TBbo0pDLEoF1A/i5GVFWa7yLZNUDudQERRh7qv/xBl2excIaQ1sV4DSVm7bAE9l6Kp+yeHQJW2uN6Y3X8wu9gB9nv9l5HBze7wh8KE6PyWAOLYYqZg9/sAtsv/2GcQqXcKFF1zcA=
+script:
+- (eval "$TEST_COMMAND")
diff --git a/go/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md b/go/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..9322b06
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at ivan+abuse@flanders.co.nz. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/go/vendor/github.com/go-openapi/validate/LICENSE b/go/vendor/github.com/go-openapi/validate/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/go/vendor/github.com/go-openapi/validate/README.md b/go/vendor/github.com/go-openapi/validate/README.md
new file mode 100644
index 0000000..08fb352
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/README.md
@@ -0,0 +1,6 @@
+# Validation helpers [![Build Status](https://travis-ci.org/go-openapi/validate.svg?branch=master)](https://travis-ci.org/go-openapi/validate) [![codecov](https://codecov.io/gh/go-openapi/validate/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/validate) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
+
+[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/validate/master/LICENSE)
+[![GoDoc](https://godoc.org/github.com/go-openapi/validate?status.svg)](http://godoc.org/github.com/go-openapi/validate)
+[![GolangCI](https://golangci.com/badges/github.com/go-openapi/validate.svg)](https://golangci.com)
+[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/validate)](https://goreportcard.com/report/github.com/go-openapi/validate)
diff --git a/go/vendor/github.com/go-openapi/validate/debug.go b/go/vendor/github.com/go-openapi/validate/debug.go
new file mode 100644
index 0000000..8815fd9
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/debug.go
@@ -0,0 +1,47 @@
+// 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 (
+	"fmt"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+)
+
+var (
+	// Debug is true when the SWAGGER_DEBUG env var is not empty.
+	// It enables a more verbose logging of validators.
+	Debug = os.Getenv("SWAGGER_DEBUG") != ""
+	// validateLogger is a debug logger for this package
+	validateLogger *log.Logger
+)
+
+func init() {
+	debugOptions()
+}
+
+func debugOptions() {
+	validateLogger = log.New(os.Stdout, "validate:", log.LstdFlags)
+}
+
+func debugLog(msg string, args ...interface{}) {
+	// A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog()
+	if Debug {
+		_, file1, pos1, _ := runtime.Caller(1)
+		validateLogger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...))
+	}
+}
diff --git a/go/vendor/github.com/go-openapi/validate/default_validator.go b/go/vendor/github.com/go-openapi/validate/default_validator.go
new file mode 100644
index 0000000..35c631b
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/default_validator.go
@@ -0,0 +1,278 @@
+// 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 (
+	"fmt"
+	"strings"
+
+	"github.com/go-openapi/spec"
+)
+
+// defaultValidator validates default values in a spec.
+// According to Swagger spec, default values MUST validate their schema.
+type defaultValidator struct {
+	SpecValidator  *SpecValidator
+	visitedSchemas map[string]bool
+}
+
+// resetVisited resets the internal state of visited schemas
+func (d *defaultValidator) resetVisited() {
+	d.visitedSchemas = map[string]bool{}
+}
+
+// beingVisited asserts a schema is being visited
+func (d *defaultValidator) beingVisited(path string) {
+	d.visitedSchemas[path] = true
+}
+
+// isVisited tells if a path has already been visited
+func (d *defaultValidator) isVisited(path string) bool {
+	found := d.visitedSchemas[path]
+	if !found {
+		// search for overlapping paths
+		frags := strings.Split(path, ".")
+		if len(frags) < 2 {
+			// shortcut exit on smaller paths
+			return found
+		}
+		last := len(frags) - 1
+		var currentFragStr, parent string
+		for i := range frags {
+			if i == 0 {
+				currentFragStr = frags[last]
+			} else {
+				currentFragStr = strings.Join([]string{frags[last-i], currentFragStr}, ".")
+			}
+			if i < last {
+				parent = strings.Join(frags[0:last-i], ".")
+			} else {
+				parent = ""
+			}
+			if strings.HasSuffix(parent, currentFragStr) {
+				found = true
+				break
+			}
+		}
+	}
+	return found
+}
+
+// Validate validates the default values declared in the swagger spec
+func (d *defaultValidator) Validate() (errs *Result) {
+	errs = new(Result)
+	if d == nil || d.SpecValidator == nil {
+		return errs
+	}
+	d.resetVisited()
+	errs.Merge(d.validateDefaultValueValidAgainstSchema()) // error -
+	return errs
+}
+
+func (d *defaultValidator) validateDefaultValueValidAgainstSchema() *Result {
+	// every default value that is specified must validate against the schema for that property
+	// headers, items, parameters, schema
+
+	res := new(Result)
+	s := d.SpecValidator
+
+	for method, pathItem := range s.analyzer.Operations() {
+		if pathItem != nil { // Safeguard
+			for path, op := range pathItem {
+				// parameters
+				for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+					if param.Default != nil && param.Required {
+						res.AddWarnings(requiredHasDefaultMsg(param.Name, param.In))
+					}
+
+					// reset explored schemas to get depth-first recursive-proof exploration
+					d.resetVisited()
+
+					// Check simple parameters first
+					// default values provided must validate against their inline definition (no explicit schema)
+					if param.Default != nil && param.Schema == nil {
+						// check param default value is valid
+						red := NewParamValidator(&param, s.KnownFormats).Validate(param.Default)
+						if red.HasErrorsOrWarnings() {
+							res.AddErrors(defaultValueDoesNotValidateMsg(param.Name, param.In))
+							res.Merge(red)
+						}
+					}
+
+					// Recursively follows Items and Schemas
+					if param.Items != nil {
+						red := d.validateDefaultValueItemsAgainstSchema(param.Name, param.In, &param, param.Items)
+						if red.HasErrorsOrWarnings() {
+							res.AddErrors(defaultValueItemsDoesNotValidateMsg(param.Name, param.In))
+							res.Merge(red)
+						}
+					}
+
+					if param.Schema != nil {
+						// Validate default value against schema
+						red := d.validateDefaultValueSchemaAgainstSchema(param.Name, param.In, param.Schema)
+						if red.HasErrorsOrWarnings() {
+							res.AddErrors(defaultValueDoesNotValidateMsg(param.Name, param.In))
+							res.Merge(red)
+						}
+					}
+				}
+
+				if op.Responses != nil {
+					if op.Responses.Default != nil {
+						// Same constraint on default Response
+						res.Merge(d.validateDefaultInResponse(op.Responses.Default, "default", path, 0, op.ID))
+					}
+					// Same constraint on regular Responses
+					if op.Responses.StatusCodeResponses != nil { // Safeguard
+						for code, r := range op.Responses.StatusCodeResponses {
+							res.Merge(d.validateDefaultInResponse(&r, "response", path, code, op.ID))
+						}
+					}
+				} else {
+					// Empty op.ID means there is no meaningful operation: no need to report a specific message
+					if op.ID != "" {
+						res.AddErrors(noValidResponseMsg(op.ID))
+					}
+				}
+			}
+		}
+	}
+	if s.spec.Spec().Definitions != nil { // Safeguard
+		// reset explored schemas to get depth-first recursive-proof exploration
+		d.resetVisited()
+		for nm, sch := range s.spec.Spec().Definitions {
+			res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("definitions.%s", nm), "body", &sch))
+		}
+	}
+	return res
+}
+
+func (d *defaultValidator) validateDefaultInResponse(resp *spec.Response, responseType, path string, responseCode int, operationID string) *Result {
+	s := d.SpecValidator
+
+	response, res := responseHelp.expandResponseRef(resp, path, s)
+	if !res.IsValid() {
+		return res
+	}
+
+	responseName, responseCodeAsStr := responseHelp.responseMsgVariants(responseType, responseCode)
+
+	if response.Headers != nil { // Safeguard
+		for nm, h := range response.Headers {
+			// reset explored schemas to get depth-first recursive-proof exploration
+			d.resetVisited()
+
+			if h.Default != nil {
+				red := NewHeaderValidator(nm, &h, s.KnownFormats).Validate(h.Default)
+				if red.HasErrorsOrWarnings() {
+					res.AddErrors(defaultValueHeaderDoesNotValidateMsg(operationID, nm, responseName))
+					res.Merge(red)
+				}
+			}
+
+			// Headers have inline definition, like params
+			if h.Items != nil {
+				red := d.validateDefaultValueItemsAgainstSchema(nm, "header", &h, h.Items)
+				if red.HasErrorsOrWarnings() {
+					res.AddErrors(defaultValueHeaderItemsDoesNotValidateMsg(operationID, nm, responseName))
+					res.Merge(red)
+				}
+			}
+
+			if _, err := compileRegexp(h.Pattern); err != nil {
+				res.AddErrors(invalidPatternInHeaderMsg(operationID, nm, responseName, h.Pattern, err))
+			}
+
+			// Headers don't have schema
+		}
+	}
+	if response.Schema != nil {
+		// reset explored schemas to get depth-first recursive-proof exploration
+		d.resetVisited()
+
+		red := d.validateDefaultValueSchemaAgainstSchema(responseCodeAsStr, "response", response.Schema)
+		if red.HasErrorsOrWarnings() {
+			// Additional message to make sure the context of the error is not lost
+			res.AddErrors(defaultValueInDoesNotValidateMsg(operationID, responseName))
+			res.Merge(red)
+		}
+	}
+	return res
+}
+
+func (d *defaultValidator) validateDefaultValueSchemaAgainstSchema(path, in string, schema *spec.Schema) *Result {
+	if schema == nil || d.isVisited(path) {
+		// Avoids recursing if we are already done with that check
+		return nil
+	}
+	d.beingVisited(path)
+	res := new(Result)
+	s := d.SpecValidator
+
+	if schema.Default != nil {
+		res.Merge(NewSchemaValidator(schema, s.spec.Spec(), path+".default", s.KnownFormats).Validate(schema.Default))
+	}
+	if schema.Items != nil {
+		if schema.Items.Schema != nil {
+			res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+".items.default", in, schema.Items.Schema))
+		}
+		// Multiple schemas in items
+		if schema.Items.Schemas != nil { // Safeguard
+			for i, sch := range schema.Items.Schemas {
+				res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.items[%d].default", path, i), in, &sch))
+			}
+		}
+	}
+	if _, err := compileRegexp(schema.Pattern); err != nil {
+		res.AddErrors(invalidPatternInMsg(path, in, schema.Pattern))
+	}
+	if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+		// NOTE: we keep validating values, even though additionalItems is not supported by Swagger 2.0 (and 3.0 as well)
+		res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.additionalItems", path), in, schema.AdditionalItems.Schema))
+	}
+	for propName, prop := range schema.Properties {
+		res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+"."+propName, in, &prop))
+	}
+	for propName, prop := range schema.PatternProperties {
+		res.Merge(d.validateDefaultValueSchemaAgainstSchema(path+"."+propName, in, &prop))
+	}
+	if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+		res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.additionalProperties", path), in, schema.AdditionalProperties.Schema))
+	}
+	if schema.AllOf != nil {
+		for i, aoSch := range schema.AllOf {
+			res.Merge(d.validateDefaultValueSchemaAgainstSchema(fmt.Sprintf("%s.allOf[%d]", path, i), in, &aoSch))
+		}
+	}
+	return res
+}
+
+func (d *defaultValidator) validateDefaultValueItemsAgainstSchema(path, in string, root interface{}, items *spec.Items) *Result {
+	res := new(Result)
+	s := d.SpecValidator
+	if items != nil {
+		if items.Default != nil {
+			res.Merge(newItemsValidator(path, in, items, root, s.KnownFormats).Validate(0, items.Default))
+		}
+		if items.Items != nil {
+			res.Merge(d.validateDefaultValueItemsAgainstSchema(path+"[0].default", in, root, items.Items))
+		}
+		if _, err := compileRegexp(items.Pattern); err != nil {
+			res.AddErrors(invalidPatternInMsg(path, in, items.Pattern))
+		}
+	}
+	return res
+}
diff --git a/go/vendor/github.com/go-openapi/validate/doc.go b/go/vendor/github.com/go-openapi/validate/doc.go
new file mode 100644
index 0000000..f5ca9a5
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/doc.go
@@ -0,0 +1,85 @@
+// 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 provides methods to validate a swagger specification,
+as well as tools to validate data against their schema.
+
+This package follows Swagger 2.0. specification (aka OpenAPI 2.0). Reference
+can be found here: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md.
+
+Validating a specification
+
+Validates a spec document (from JSON or YAML) against the JSON schema for swagger,
+then checks a number of extra rules that can't be expressed in JSON schema.
+
+Entry points:
+  - Spec()
+  - NewSpecValidator()
+  - SpecValidator.Validate()
+
+Reported as errors:
+  [x] definition can't declare a property that's already defined by one of its ancestors
+  [x] definition's ancestor can't be a descendant of the same model
+  [x] path uniqueness: each api path should be non-verbatim (account for path param names) unique per method
+  [x] each security reference should contain only unique scopes
+  [x] each security scope in a security definition should be unique
+  [x] parameters in path must be unique
+  [x] each path parameter must correspond to a parameter placeholder and vice versa
+  [x] each referenceable definition must have references
+  [x] each definition property listed in the required array must be defined in the properties of the model
+  [x] each parameter should have a unique `name` and `type` combination
+  [x] each operation should have only 1 parameter of type body
+  [x] each reference must point to a valid object
+  [x] every default value that is specified must validate against the schema for that property
+  [x] items property is required for all schemas/definitions of type `array`
+  [x] path parameters must be declared a required
+  [x] headers must not contain $ref
+  [x] schema and property examples provided must validate against their respective object's schema
+  [x] examples provided must validate their schema
+
+Reported as warnings:
+  [x] path parameters should not contain any of [{,},\w]
+  [x] empty path
+  [x] unused definitions
+  [x] unsupported validation of examples on non-JSON media types
+  [x] examples in response without schema
+  [x] readOnly properties should not be required
+
+Validating a schema
+
+The schema validation toolkit validates data against JSON-schema-draft 04 schema.
+
+It is tested against the full json-schema-testing-suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite),
+except for the optional part (bignum, ECMA regexp, ...).
+
+It supports the complete JSON-schema vocabulary, including keywords not supported by Swagger (e.g. additionalItems, ...)
+
+Entry points:
+  - AgainstSchema()
+  - ...
+
+Known limitations
+
+With the current version of this package, the following aspects of swagger are not yet supported:
+  [ ] errors and warnings are not reported with key/line number in spec
+  [ ] default values and examples on responses only support application/json producer type
+  [ ] invalid numeric constraints (such as Minimum, etc..) are not checked except for default and example values
+  [ ] rules for collectionFormat are not implemented
+  [ ] no validation rule for polymorphism support (discriminator) [not done here]
+  [ ] valid js ECMA regexp not supported by Go regexp engine are considered invalid
+  [ ] arbitrary large numbers are not supported: max is math.MaxFloat64
+
+*/
+package validate
diff --git a/go/vendor/github.com/go-openapi/validate/example_validator.go b/go/vendor/github.com/go-openapi/validate/example_validator.go
new file mode 100644
index 0000000..b2acf10
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/example_validator.go
@@ -0,0 +1,299 @@
+// 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 (
+	"fmt"
+	"strings"
+
+	"github.com/go-openapi/spec"
+)
+
+// ExampleValidator validates example values defined in a spec
+type exampleValidator struct {
+	SpecValidator  *SpecValidator
+	visitedSchemas map[string]bool
+}
+
+// resetVisited resets the internal state of visited schemas
+func (ex *exampleValidator) resetVisited() {
+	ex.visitedSchemas = map[string]bool{}
+}
+
+// beingVisited asserts a schema is being visited
+func (ex *exampleValidator) beingVisited(path string) {
+	ex.visitedSchemas[path] = true
+}
+
+// isVisited tells if a path has already been visited
+func (ex *exampleValidator) isVisited(path string) bool {
+	found := ex.visitedSchemas[path]
+	if !found {
+		// search for overlapping paths
+		frags := strings.Split(path, ".")
+		if len(frags) < 2 {
+			// shortcut exit on smaller paths
+			return found
+		}
+		last := len(frags) - 1
+		var currentFragStr, parent string
+		for i := range frags {
+			if i == 0 {
+				currentFragStr = frags[last]
+			} else {
+				currentFragStr = strings.Join([]string{frags[last-i], currentFragStr}, ".")
+			}
+			if i < last {
+				parent = strings.Join(frags[0:last-i], ".")
+			} else {
+				parent = ""
+			}
+			if strings.HasSuffix(parent, currentFragStr) {
+				found = true
+				break
+			}
+		}
+	}
+	return found
+}
+
+// Validate validates the example values declared in the swagger spec
+// Example values MUST conform to their schema.
+//
+// With Swagger 2.0, examples are supported in:
+//   - schemas
+//   - individual property
+//   - responses
+//
+func (ex *exampleValidator) Validate() (errs *Result) {
+	errs = new(Result)
+	if ex == nil || ex.SpecValidator == nil {
+		return errs
+	}
+	ex.resetVisited()
+	errs.Merge(ex.validateExampleValueValidAgainstSchema()) // error -
+
+	return errs
+}
+
+func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result {
+	// every example value that is specified must validate against the schema for that property
+	// in: schemas, properties, object, items
+	// not in: headers, parameters without schema
+
+	res := new(Result)
+	s := ex.SpecValidator
+
+	for method, pathItem := range s.analyzer.Operations() {
+		if pathItem != nil { // Safeguard
+			for path, op := range pathItem {
+				// parameters
+				for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+
+					// As of swagger 2.0, Examples are not supported in simple parameters
+					// However, it looks like it is supported by go-openapi
+
+					// reset explored schemas to get depth-first recursive-proof exploration
+					ex.resetVisited()
+
+					// Check simple parameters first
+					// default values provided must validate against their inline definition (no explicit schema)
+					if param.Example != nil && param.Schema == nil {
+						// check param default value is valid
+						red := NewParamValidator(&param, s.KnownFormats).Validate(param.Example)
+						if red.HasErrorsOrWarnings() {
+							res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In))
+							res.MergeAsWarnings(red)
+						}
+					}
+
+					// Recursively follows Items and Schemas
+					if param.Items != nil {
+						red := ex.validateExampleValueItemsAgainstSchema(param.Name, param.In, &param, param.Items)
+						if red.HasErrorsOrWarnings() {
+							res.AddWarnings(exampleValueItemsDoesNotValidateMsg(param.Name, param.In))
+							res.Merge(red)
+						}
+					}
+
+					if param.Schema != nil {
+						// Validate example value against schema
+						red := ex.validateExampleValueSchemaAgainstSchema(param.Name, param.In, param.Schema)
+						if red.HasErrorsOrWarnings() {
+							res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In))
+							res.Merge(red)
+						}
+					}
+				}
+
+				if op.Responses != nil {
+					if op.Responses.Default != nil {
+						// Same constraint on default Response
+						res.Merge(ex.validateExampleInResponse(op.Responses.Default, "default", path, 0, op.ID))
+					}
+					// Same constraint on regular Responses
+					if op.Responses.StatusCodeResponses != nil { // Safeguard
+						for code, r := range op.Responses.StatusCodeResponses {
+							res.Merge(ex.validateExampleInResponse(&r, "response", path, code, op.ID))
+						}
+					}
+				} else {
+					// Empty op.ID means there is no meaningful operation: no need to report a specific message
+					if op.ID != "" {
+						res.AddErrors(noValidResponseMsg(op.ID))
+					}
+				}
+			}
+		}
+	}
+	if s.spec.Spec().Definitions != nil { // Safeguard
+		// reset explored schemas to get depth-first recursive-proof exploration
+		ex.resetVisited()
+		for nm, sch := range s.spec.Spec().Definitions {
+			res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("definitions.%s", nm), "body", &sch))
+		}
+	}
+	return res
+}
+
+func (ex *exampleValidator) validateExampleInResponse(resp *spec.Response, responseType, path string, responseCode int, operationID string) *Result {
+	s := ex.SpecValidator
+
+	response, res := responseHelp.expandResponseRef(resp, path, s)
+	if !res.IsValid() { // Safeguard
+		return res
+	}
+
+	responseName, responseCodeAsStr := responseHelp.responseMsgVariants(responseType, responseCode)
+
+	if response.Headers != nil { // Safeguard
+		for nm, h := range response.Headers {
+			// reset explored schemas to get depth-first recursive-proof exploration
+			ex.resetVisited()
+
+			if h.Example != nil {
+				red := NewHeaderValidator(nm, &h, s.KnownFormats).Validate(h.Example)
+				if red.HasErrorsOrWarnings() {
+					res.AddWarnings(exampleValueHeaderDoesNotValidateMsg(operationID, nm, responseName))
+					res.MergeAsWarnings(red)
+				}
+			}
+
+			// Headers have inline definition, like params
+			if h.Items != nil {
+				red := ex.validateExampleValueItemsAgainstSchema(nm, "header", &h, h.Items)
+				if red.HasErrorsOrWarnings() {
+					res.AddWarnings(exampleValueHeaderItemsDoesNotValidateMsg(operationID, nm, responseName))
+					res.MergeAsWarnings(red)
+				}
+			}
+
+			if _, err := compileRegexp(h.Pattern); err != nil {
+				res.AddErrors(invalidPatternInHeaderMsg(operationID, nm, responseName, h.Pattern, err))
+			}
+
+			// Headers don't have schema
+		}
+	}
+	if response.Schema != nil {
+		// reset explored schemas to get depth-first recursive-proof exploration
+		ex.resetVisited()
+
+		red := ex.validateExampleValueSchemaAgainstSchema(responseCodeAsStr, "response", response.Schema)
+		if red.HasErrorsOrWarnings() {
+			// Additional message to make sure the context of the error is not lost
+			res.AddWarnings(exampleValueInDoesNotValidateMsg(operationID, responseName))
+			res.Merge(red)
+		}
+	}
+
+	if response.Examples != nil {
+		if response.Schema != nil {
+			if example, ok := response.Examples["application/json"]; ok {
+				res.MergeAsWarnings(NewSchemaValidator(response.Schema, s.spec.Spec(), path, s.KnownFormats).Validate(example))
+			} else {
+				// TODO: validate other media types too
+				res.AddWarnings(examplesMimeNotSupportedMsg(operationID, responseName))
+			}
+		} else {
+			res.AddWarnings(examplesWithoutSchemaMsg(operationID, responseName))
+		}
+	}
+	return res
+}
+
+func (ex *exampleValidator) validateExampleValueSchemaAgainstSchema(path, in string, schema *spec.Schema) *Result {
+	if schema == nil || ex.isVisited(path) {
+		// Avoids recursing if we are already done with that check
+		return nil
+	}
+	ex.beingVisited(path)
+	s := ex.SpecValidator
+	res := new(Result)
+
+	if schema.Example != nil {
+		res.MergeAsWarnings(NewSchemaValidator(schema, s.spec.Spec(), path+".example", s.KnownFormats).Validate(schema.Example))
+	}
+	if schema.Items != nil {
+		if schema.Items.Schema != nil {
+			res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+".items.example", in, schema.Items.Schema))
+		}
+		// Multiple schemas in items
+		if schema.Items.Schemas != nil { // Safeguard
+			for i, sch := range schema.Items.Schemas {
+				res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.items[%d].example", path, i), in, &sch))
+			}
+		}
+	}
+	if _, err := compileRegexp(schema.Pattern); err != nil {
+		res.AddErrors(invalidPatternInMsg(path, in, schema.Pattern))
+	}
+	if schema.AdditionalItems != nil && schema.AdditionalItems.Schema != nil {
+		// NOTE: we keep validating values, even though additionalItems is unsupported in Swagger 2.0 (and 3.0 as well)
+		res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.additionalItems", path), in, schema.AdditionalItems.Schema))
+	}
+	for propName, prop := range schema.Properties {
+		res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+"."+propName, in, &prop))
+	}
+	for propName, prop := range schema.PatternProperties {
+		res.Merge(ex.validateExampleValueSchemaAgainstSchema(path+"."+propName, in, &prop))
+	}
+	if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil {
+		res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.additionalProperties", path), in, schema.AdditionalProperties.Schema))
+	}
+	if schema.AllOf != nil {
+		for i, aoSch := range schema.AllOf {
+			res.Merge(ex.validateExampleValueSchemaAgainstSchema(fmt.Sprintf("%s.allOf[%d]", path, i), in, &aoSch))
+		}
+	}
+	return res
+}
+
+func (ex *exampleValidator) validateExampleValueItemsAgainstSchema(path, in string, root interface{}, items *spec.Items) *Result {
+	res := new(Result)
+	s := ex.SpecValidator
+	if items != nil {
+		if items.Example != nil {
+			res.MergeAsWarnings(newItemsValidator(path, in, items, root, s.KnownFormats).Validate(0, items.Example))
+		}
+		if items.Items != nil {
+			res.Merge(ex.validateExampleValueItemsAgainstSchema(path+"[0].example", in, root, items.Items))
+		}
+		if _, err := compileRegexp(items.Pattern); err != nil {
+			res.AddErrors(invalidPatternInMsg(path, in, items.Pattern))
+		}
+	}
+	return res
+}
diff --git a/go/vendor/github.com/go-openapi/validate/formats.go b/go/vendor/github.com/go-openapi/validate/formats.go
new file mode 100644
index 0000000..b7afe98
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/formats.go
@@ -0,0 +1,73 @@
+// 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"
+
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+)
+
+type formatValidator struct {
+	Format       string
+	Path         string
+	In           string
+	KnownFormats strfmt.Registry
+}
+
+func (f *formatValidator) SetPath(path string) {
+	f.Path = path
+}
+
+func (f *formatValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	doit := func() bool {
+		if source == nil {
+			return false
+		}
+		switch source.(type) {
+		case *spec.Items:
+			it := source.(*spec.Items)
+			return kind == reflect.String && f.KnownFormats.ContainsName(it.Format)
+		case *spec.Parameter:
+			par := source.(*spec.Parameter)
+			return kind == reflect.String && f.KnownFormats.ContainsName(par.Format)
+		case *spec.Schema:
+			sch := source.(*spec.Schema)
+			return kind == reflect.String && f.KnownFormats.ContainsName(sch.Format)
+		case *spec.Header:
+			hdr := source.(*spec.Header)
+			return kind == reflect.String && f.KnownFormats.ContainsName(hdr.Format)
+		}
+		return false
+	}
+	r := doit()
+	debugLog("format validator for %q applies %t for %T (kind: %v)\n", f.Path, r, source, kind)
+	return r
+}
+
+func (f *formatValidator) Validate(val interface{}) *Result {
+	result := new(Result)
+	debugLog("validating \"%v\" against format: %s", val, f.Format)
+
+	if err := FormatOf(f.Path, f.In, f.Format, val.(string), f.KnownFormats); err != nil {
+		result.AddErrors(err)
+	}
+
+	if result.HasErrors() {
+		return result
+	}
+	return nil
+}
diff --git a/go/vendor/github.com/go-openapi/validate/go.mod b/go/vendor/github.com/go-openapi/validate/go.mod
new file mode 100644
index 0000000..cb6199a
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/go.mod
@@ -0,0 +1,14 @@
+module github.com/go-openapi/validate
+
+require (
+	github.com/go-openapi/analysis v0.17.0
+	github.com/go-openapi/errors v0.17.0
+	github.com/go-openapi/jsonpointer v0.17.0
+	github.com/go-openapi/loads v0.17.0
+	github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9
+	github.com/go-openapi/spec v0.17.0
+	github.com/go-openapi/strfmt v0.17.0
+	github.com/go-openapi/swag v0.17.0
+	github.com/stretchr/testify v1.2.2
+	gopkg.in/yaml.v2 v2.2.1
+)
diff --git a/go/vendor/github.com/go-openapi/validate/go.sum b/go/vendor/github.com/go-openapi/validate/go.sum
new file mode 100644
index 0000000..34286d4
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/go.sum
@@ -0,0 +1,41 @@
+github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
+github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvUbuvHW93esHg7F8N/OYeBBcJoTr0=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
+github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
+github.com/go-openapi/analysis v0.17.0 h1:8JV+dzJJiK46XqGLqqLav8ZfEiJECp8jlOFhpiCdZ+0=
+github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/errors v0.17.0 h1:47T+LqPrQUxFXQnB22aLBfsTRFSqWp5y4OiFgQm+/Lw=
+github.com/go-openapi/errors v0.17.0/go.mod h1:La0D2x9HoXenv7MDEiAv6vWoe84CXFo0PQRk/jdQlww=
+github.com/go-openapi/jsonpointer v0.17.0 h1:Bpl2DtZ6k7wKqfFs7e+4P08+M9I3FQgn09a1UsRUQbk=
+github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonreference v0.17.0 h1:d/o7/fsLWWQZACbihvZxcyLQ59jfUVs7WOJv/ak7T7A=
+github.com/go-openapi/jsonreference v0.17.0/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/loads v0.17.0 h1:H22nMs3GDQk4SwAaFQ+jLNw+0xoFeCueawhZlv8MBYs=
+github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9 h1:zXd+rkzHwMIYVTJ/j/v8zUQ9j3Ir32gC5Dn9DzZVvCk=
+github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
+github.com/go-openapi/spec v0.17.0 h1:MM5YaXBdBOEcjGHW5WayrAY5Ze2ydNyy71JHeTi7xUc=
+github.com/go-openapi/spec v0.17.0/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/strfmt v0.17.0 h1:79+bCyGHowS3rkr6z8RcG5jVzdKpeKXlDuW6yqE50TM=
+github.com/go-openapi/strfmt v0.17.0/go.mod h1:/bCWipNKhC9QMhD8HRe2EGbU8G0D4Yvh0G6X4k1Xwvg=
+github.com/go-openapi/swag v0.17.0 h1:7wu+dZ5k83kvUWeAb+WUkFiUhDzwGqzTR/NhWzeo1JU=
+github.com/go-openapi/swag v0.17.0/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/go/vendor/github.com/go-openapi/validate/helpers.go b/go/vendor/github.com/go-openapi/validate/helpers.go
new file mode 100644
index 0000000..7ac8771
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/helpers.go
@@ -0,0 +1,265 @@
+// 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
+
+// TODO: define this as package validate/internal
+// This must be done while keeping CI intact with all tests and test coverage
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/spec"
+)
+
+const swaggerBody = "body"
+const objectType = "object"
+
+// Helpers available at the package level
+var (
+	pathHelp     *pathHelper
+	valueHelp    *valueHelper
+	errorHelp    *errorHelper
+	paramHelp    *paramHelper
+	responseHelp *responseHelper
+)
+
+type errorHelper struct {
+	// A collection of unexported helpers for error construction
+}
+
+func (h *errorHelper) sErr(err errors.Error) *Result {
+	// Builds a Result from standard errors.Error
+	return &Result{Errors: []error{err}}
+}
+
+func (h *errorHelper) addPointerError(res *Result, err error, ref string, fromPath string) *Result {
+	// Provides more context on error messages
+	// reported by the jsoinpointer package by altering the passed Result
+	if err != nil {
+		res.AddErrors(cannotResolveRefMsg(fromPath, ref, err))
+	}
+	return res
+}
+
+type pathHelper struct {
+	// A collection of unexported helpers for path validation
+}
+
+func (h *pathHelper) stripParametersInPath(path string) string {
+	// Returns a path stripped from all path parameters, with multiple or trailing slashes removed.
+	//
+	// Stripping is performed on a slash-separated basis, e.g '/a{/b}' remains a{/b} and not /a.
+	//  - Trailing "/" make a difference, e.g. /a/ !~ /a (ex: canary/bitbucket.org/swagger.json)
+	//  - presence or absence of a parameter makes a difference, e.g. /a/{log} !~ /a/ (ex: canary/kubernetes/swagger.json)
+
+	// Regexp to extract parameters from path, with surrounding {}.
+	// NOTE: important non-greedy modifier
+	rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
+	strippedSegments := []string{}
+
+	for _, segment := range strings.Split(path, "/") {
+		strippedSegments = append(strippedSegments, rexParsePathParam.ReplaceAllString(segment, "X"))
+	}
+	return strings.Join(strippedSegments, "/")
+}
+
+func (h *pathHelper) extractPathParams(path string) (params []string) {
+	// Extracts all params from a path, with surrounding "{}"
+	rexParsePathParam := mustCompileRegexp(`{[^{}]+?}`)
+
+	for _, segment := range strings.Split(path, "/") {
+		for _, v := range rexParsePathParam.FindAllStringSubmatch(segment, -1) {
+			params = append(params, v...)
+		}
+	}
+	return
+}
+
+type valueHelper struct {
+	// A collection of unexported helpers for value validation
+}
+
+func (h *valueHelper) asInt64(val interface{}) int64 {
+	// Number conversion function for int64, without error checking
+	// (implements an implicit type upgrade).
+	v := reflect.ValueOf(val)
+	switch v.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int()
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return int64(v.Uint())
+	case reflect.Float32, reflect.Float64:
+		return int64(v.Float())
+	default:
+		//panic("Non numeric value in asInt64()")
+		return 0
+	}
+}
+
+func (h *valueHelper) asUint64(val interface{}) uint64 {
+	// Number conversion function for uint64, without error checking
+	// (implements an implicit type upgrade).
+	v := reflect.ValueOf(val)
+	switch v.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return uint64(v.Int())
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return v.Uint()
+	case reflect.Float32, reflect.Float64:
+		return uint64(v.Float())
+	default:
+		//panic("Non numeric value in asUint64()")
+		return 0
+	}
+}
+
+// Same for unsigned floats
+func (h *valueHelper) asFloat64(val interface{}) float64 {
+	// Number conversion function for float64, without error checking
+	// (implements an implicit type upgrade).
+	v := reflect.ValueOf(val)
+	switch v.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return float64(v.Int())
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return float64(v.Uint())
+	case reflect.Float32, reflect.Float64:
+		return v.Float()
+	default:
+		//panic("Non numeric value in asFloat64()")
+		return 0
+	}
+}
+
+type paramHelper struct {
+	// A collection of unexported helpers for parameters resolution
+}
+
+func (h *paramHelper) safeExpandedParamsFor(path, method, operationID string, res *Result, s *SpecValidator) (params []spec.Parameter) {
+	operation, ok := s.analyzer.OperationFor(method, path)
+	if ok {
+		// expand parameters first if necessary
+		resolvedParams := []spec.Parameter{}
+		for _, ppr := range operation.Parameters {
+			resolvedParam, red := h.resolveParam(path, method, operationID, &ppr, s)
+			res.Merge(red)
+			if resolvedParam != nil {
+				resolvedParams = append(resolvedParams, *resolvedParam)
+			}
+		}
+		// remove params with invalid expansion from Slice
+		operation.Parameters = resolvedParams
+
+		for _, ppr := range s.analyzer.SafeParamsFor(method, path,
+			func(p spec.Parameter, err error) bool {
+				// since params have already been expanded, there are few causes for error
+				res.AddErrors(someParametersBrokenMsg(path, method, operationID))
+				// original error from analyzer
+				res.AddErrors(err)
+				return true
+			}) {
+			params = append(params, ppr)
+		}
+	}
+	return
+}
+
+func (h *paramHelper) resolveParam(path, method, operationID string, param *spec.Parameter, s *SpecValidator) (*spec.Parameter, *Result) {
+	// Ensure parameter is expanded
+	var err error
+	res := new(Result)
+	isRef := param.Ref.String() != ""
+	if s.spec.SpecFilePath() == "" {
+		err = spec.ExpandParameterWithRoot(param, s.spec.Spec(), nil)
+	} else {
+		err = spec.ExpandParameter(param, s.spec.SpecFilePath())
+
+	}
+	if err != nil { // Safeguard
+		// NOTE: we may enter enter here when the whole parameter is an unresolved $ref
+		refPath := strings.Join([]string{"\"" + path + "\"", method}, ".")
+		errorHelp.addPointerError(res, err, param.Ref.String(), refPath)
+		return nil, res
+	}
+	res.Merge(h.checkExpandedParam(param, param.Name, param.In, operationID, isRef))
+	return param, res
+}
+
+func (h *paramHelper) checkExpandedParam(pr *spec.Parameter, path, in, operation string, isRef bool) *Result {
+	// Secure parameter structure after $ref resolution
+	res := new(Result)
+	simpleZero := spec.SimpleSchema{}
+	// Try to explain why... best guess
+	if pr.In == swaggerBody && (pr.SimpleSchema != simpleZero && pr.SimpleSchema.Type != objectType) {
+		if isRef {
+			// Most likely, a $ref with a sibling is an unwanted situation: in itself this is a warning...
+			// but we detect it because of the following error:
+			// schema took over Parameter for an unexplained reason
+			res.AddWarnings(refShouldNotHaveSiblingsMsg(path, operation))
+		}
+		res.AddErrors(invalidParameterDefinitionMsg(path, in, operation))
+	} else if pr.In != swaggerBody && pr.Schema != nil {
+		if isRef {
+			res.AddWarnings(refShouldNotHaveSiblingsMsg(path, operation))
+		}
+		res.AddErrors(invalidParameterDefinitionAsSchemaMsg(path, in, operation))
+	} else if (pr.In == swaggerBody && pr.Schema == nil) ||
+		(pr.In != swaggerBody && pr.SimpleSchema == simpleZero) { // Safeguard
+		// Other unexpected mishaps
+		res.AddErrors(invalidParameterDefinitionMsg(path, in, operation))
+	}
+	return res
+}
+
+type responseHelper struct {
+	// A collection of unexported helpers for response resolution
+}
+
+func (r *responseHelper) expandResponseRef(
+	response *spec.Response,
+	path string, s *SpecValidator) (*spec.Response, *Result) {
+	// Ensure response is expanded
+	var err error
+	res := new(Result)
+	if s.spec.SpecFilePath() == "" {
+		// there is no physical document to resolve $ref in response
+		err = spec.ExpandResponseWithRoot(response, s.spec.Spec(), nil)
+	} else {
+		err = spec.ExpandResponse(response, s.spec.SpecFilePath())
+	}
+	if err != nil { // Safeguard
+		// NOTE: we may enter here when the whole response is an unresolved $ref.
+		errorHelp.addPointerError(res, err, response.Ref.String(), path)
+		return nil, res
+	}
+	return response, res
+}
+
+func (r *responseHelper) responseMsgVariants(
+	responseType string,
+	responseCode int) (responseName, responseCodeAsStr string) {
+	// Path variants for messages
+	if responseType == "default" {
+		responseCodeAsStr = "default"
+		responseName = "default response"
+	} else {
+		responseCodeAsStr = strconv.Itoa(responseCode)
+		responseName = "response " + responseCodeAsStr
+	}
+	return
+}
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
+}
diff --git a/go/vendor/github.com/go-openapi/validate/options.go b/go/vendor/github.com/go-openapi/validate/options.go
new file mode 100644
index 0000000..deeec2f
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/options.go
@@ -0,0 +1,43 @@
+// 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 "sync"
+
+// Opts specifies validation options for a SpecValidator.
+//
+// NOTE: other options might be needed, for example a go-swagger specific mode.
+type Opts struct {
+	ContinueOnErrors bool // true: continue reporting errors, even if spec is invalid
+}
+
+var (
+	defaultOpts      = Opts{ContinueOnErrors: false} // default is to stop validation on errors
+	defaultOptsMutex = &sync.Mutex{}
+)
+
+// SetContinueOnErrors sets global default behavior regarding spec validation errors reporting.
+//
+// For extended error reporting, you most likely want to set it to true.
+// For faster validation, it's better to give up early when a spec is detected as invalid: set it to false (this is the default).
+//
+// Setting this mode does NOT affect the validation status.
+//
+// NOTE: this method affects global defaults. It is not suitable for a concurrent usage.
+func SetContinueOnErrors(c bool) {
+	defer defaultOptsMutex.Unlock()
+	defaultOptsMutex.Lock()
+	defaultOpts.ContinueOnErrors = c
+}
diff --git a/go/vendor/github.com/go-openapi/validate/result.go b/go/vendor/github.com/go-openapi/validate/result.go
new file mode 100644
index 0000000..ae9b8db
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/result.go
@@ -0,0 +1,484 @@
+// 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 (
+	"fmt"
+	"reflect"
+	"strings"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/spec"
+)
+
+// Result represents a validation result set, composed of
+// errors and warnings.
+//
+// It is used to keep track of all detected errors and warnings during
+// the validation of a specification.
+//
+// Matchcount is used to determine
+// which errors are relevant in the case of AnyOf, OneOf
+// schema validation. Results from the validation branch
+// with most matches get eventually selected.
+//
+// TODO: keep path of key originating the error
+type Result struct {
+	Errors     []error
+	Warnings   []error
+	MatchCount int
+
+	// the object data
+	data interface{}
+
+	// Schemata for the root object
+	rootObjectSchemata schemata
+	// Schemata for object fields
+	fieldSchemata []fieldSchemata
+	// Schemata for slice items
+	itemSchemata []itemSchemata
+
+	cachedFieldSchemta map[FieldKey][]*spec.Schema
+	cachedItemSchemata map[ItemKey][]*spec.Schema
+}
+
+// FieldKey is a pair of an object and a field, usable as a key for a map.
+type FieldKey struct {
+	object reflect.Value // actually a map[string]interface{}, but the latter cannot be a key
+	field  string
+}
+
+// ItemKey is a pair of a slice and an index, usable as a key for a map.
+type ItemKey struct {
+	slice reflect.Value // actually a []interface{}, but the latter cannot be a key
+	index int
+}
+
+// NewFieldKey returns a pair of an object and field usable as a key of a map.
+func NewFieldKey(obj map[string]interface{}, field string) FieldKey {
+	return FieldKey{object: reflect.ValueOf(obj), field: field}
+}
+
+// Object returns the underlying object of this key.
+func (fk *FieldKey) Object() map[string]interface{} {
+	return fk.object.Interface().(map[string]interface{})
+}
+
+// Field returns the underlying field of this key.
+func (fk *FieldKey) Field() string {
+	return fk.field
+}
+
+// NewItemKey returns a pair of a slice and index usable as a key of a map.
+func NewItemKey(slice interface{}, i int) ItemKey {
+	return ItemKey{slice: reflect.ValueOf(slice), index: i}
+}
+
+// Slice returns the underlying slice of this key.
+func (ik *ItemKey) Slice() []interface{} {
+	return ik.slice.Interface().([]interface{})
+}
+
+// Index returns the underlying index of this key.
+func (ik *ItemKey) Index() int {
+	return ik.index
+}
+
+type fieldSchemata struct {
+	obj      map[string]interface{}
+	field    string
+	schemata schemata
+}
+
+type itemSchemata struct {
+	slice    reflect.Value
+	index    int
+	schemata schemata
+}
+
+// Merge merges this result with the other one(s), preserving match counts etc.
+func (r *Result) Merge(others ...*Result) *Result {
+	for _, other := range others {
+		if other == nil {
+			continue
+		}
+		r.mergeWithoutRootSchemata(other)
+		r.rootObjectSchemata.Append(other.rootObjectSchemata)
+	}
+	return r
+}
+
+// Data returns the original data object used for validation. Mutating this renders
+// the result invalid.
+func (r *Result) Data() interface{} {
+	return r.data
+}
+
+// RootObjectSchemata returns the schemata which apply to the root object.
+func (r *Result) RootObjectSchemata() []*spec.Schema {
+	return r.rootObjectSchemata.Slice()
+}
+
+// FieldSchemata returns the schemata which apply to fields in objects.
+func (r *Result) FieldSchemata() map[FieldKey][]*spec.Schema {
+	if r.cachedFieldSchemta != nil {
+		return r.cachedFieldSchemta
+	}
+
+	ret := make(map[FieldKey][]*spec.Schema, len(r.fieldSchemata))
+	for _, fs := range r.fieldSchemata {
+		key := NewFieldKey(fs.obj, fs.field)
+		if fs.schemata.one != nil {
+			ret[key] = append(ret[key], fs.schemata.one)
+		} else if len(fs.schemata.multiple) > 0 {
+			ret[key] = append(ret[key], fs.schemata.multiple...)
+		}
+	}
+	r.cachedFieldSchemta = ret
+	return ret
+}
+
+// ItemSchemata returns the schemata which apply to items in slices.
+func (r *Result) ItemSchemata() map[ItemKey][]*spec.Schema {
+	if r.cachedItemSchemata != nil {
+		return r.cachedItemSchemata
+	}
+
+	ret := make(map[ItemKey][]*spec.Schema, len(r.itemSchemata))
+	for _, ss := range r.itemSchemata {
+		key := NewItemKey(ss.slice, ss.index)
+		if ss.schemata.one != nil {
+			ret[key] = append(ret[key], ss.schemata.one)
+		} else if len(ss.schemata.multiple) > 0 {
+			ret[key] = append(ret[key], ss.schemata.multiple...)
+		}
+	}
+	r.cachedItemSchemata = ret
+	return ret
+}
+
+func (r *Result) resetCaches() {
+	r.cachedFieldSchemta = nil
+	r.cachedItemSchemata = nil
+}
+
+// mergeForField merges other into r, assigning other's root schemata to the given Object and field name.
+func (r *Result) mergeForField(obj map[string]interface{}, field string, other *Result) *Result {
+	if other == nil {
+		return r
+	}
+	r.mergeWithoutRootSchemata(other)
+
+	if other.rootObjectSchemata.Len() > 0 {
+		if r.fieldSchemata == nil {
+			r.fieldSchemata = make([]fieldSchemata, len(obj))
+		}
+		r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{
+			obj:      obj,
+			field:    field,
+			schemata: other.rootObjectSchemata,
+		})
+	}
+
+	return r
+}
+
+// mergeForSlice merges other into r, assigning other's root schemata to the given slice and index.
+func (r *Result) mergeForSlice(slice reflect.Value, i int, other *Result) *Result {
+	if other == nil {
+		return r
+	}
+	r.mergeWithoutRootSchemata(other)
+
+	if other.rootObjectSchemata.Len() > 0 {
+		if r.itemSchemata == nil {
+			r.itemSchemata = make([]itemSchemata, slice.Len())
+		}
+		r.itemSchemata = append(r.itemSchemata, itemSchemata{
+			slice:    slice,
+			index:    i,
+			schemata: other.rootObjectSchemata,
+		})
+	}
+
+	return r
+}
+
+// addRootObjectSchemata adds the given schemata for the root object of the result.
+// The slice schemata might be reused. I.e. do not modify it after being added to a result.
+func (r *Result) addRootObjectSchemata(s *spec.Schema) {
+	r.rootObjectSchemata.Append(schemata{one: s})
+}
+
+// addPropertySchemata adds the given schemata for the object and field.
+// The slice schemata might be reused. I.e. do not modify it after being added to a result.
+func (r *Result) addPropertySchemata(obj map[string]interface{}, fld string, schema *spec.Schema) {
+	if r.fieldSchemata == nil {
+		r.fieldSchemata = make([]fieldSchemata, 0, len(obj))
+	}
+	r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{obj: obj, field: fld, schemata: schemata{one: schema}})
+}
+
+// addSliceSchemata adds the given schemata for the slice and index.
+// The slice schemata might be reused. I.e. do not modify it after being added to a result.
+func (r *Result) addSliceSchemata(slice reflect.Value, i int, schema *spec.Schema) {
+	if r.itemSchemata == nil {
+		r.itemSchemata = make([]itemSchemata, 0, slice.Len())
+	}
+	r.itemSchemata = append(r.itemSchemata, itemSchemata{slice: slice, index: i, schemata: schemata{one: schema}})
+}
+
+// mergeWithoutRootSchemata merges other into r, ignoring the rootObject schemata.
+func (r *Result) mergeWithoutRootSchemata(other *Result) {
+	r.resetCaches()
+	r.AddErrors(other.Errors...)
+	r.AddWarnings(other.Warnings...)
+	r.MatchCount += other.MatchCount
+
+	if other.fieldSchemata != nil {
+		if r.fieldSchemata == nil {
+			r.fieldSchemata = other.fieldSchemata
+		} else {
+			for _, x := range other.fieldSchemata {
+				r.fieldSchemata = append(r.fieldSchemata, x)
+			}
+		}
+	}
+
+	if other.itemSchemata != nil {
+		if r.itemSchemata == nil {
+			r.itemSchemata = other.itemSchemata
+		} else {
+			for _, x := range other.itemSchemata {
+				r.itemSchemata = append(r.itemSchemata, x)
+			}
+		}
+	}
+}
+
+// MergeAsErrors merges this result with the other one(s), preserving match counts etc.
+//
+// Warnings from input are merged as Errors in the returned merged Result.
+func (r *Result) MergeAsErrors(others ...*Result) *Result {
+	for _, other := range others {
+		if other != nil {
+			r.resetCaches()
+			r.AddErrors(other.Errors...)
+			r.AddErrors(other.Warnings...)
+			r.MatchCount += other.MatchCount
+		}
+	}
+	return r
+}
+
+// MergeAsWarnings merges this result with the other one(s), preserving match counts etc.
+//
+// Errors from input are merged as Warnings in the returned merged Result.
+func (r *Result) MergeAsWarnings(others ...*Result) *Result {
+	for _, other := range others {
+		if other != nil {
+			r.resetCaches()
+			r.AddWarnings(other.Errors...)
+			r.AddWarnings(other.Warnings...)
+			r.MatchCount += other.MatchCount
+		}
+	}
+	return r
+}
+
+// AddErrors adds errors to this validation result (if not already reported).
+//
+// Since the same check may be passed several times while exploring the
+// spec structure (via $ref, ...) reported messages are kept
+// unique.
+func (r *Result) AddErrors(errors ...error) {
+	for _, e := range errors {
+		found := false
+		if e != nil {
+			for _, isReported := range r.Errors {
+				if e.Error() == isReported.Error() {
+					found = true
+					break
+				}
+			}
+			if !found {
+				r.Errors = append(r.Errors, e)
+			}
+		}
+	}
+}
+
+// AddWarnings adds warnings to this validation result (if not already reported).
+func (r *Result) AddWarnings(warnings ...error) {
+	for _, e := range warnings {
+		found := false
+		if e != nil {
+			for _, isReported := range r.Warnings {
+				if e.Error() == isReported.Error() {
+					found = true
+					break
+				}
+			}
+			if !found {
+				r.Warnings = append(r.Warnings, e)
+			}
+		}
+	}
+}
+
+func (r *Result) keepRelevantErrors() *Result {
+	// TODO: this one is going to disapear...
+	// keepRelevantErrors strips a result from standard errors and keeps
+	// the ones which are supposedly more accurate.
+	//
+	// The original result remains unaffected (creates a new instance of Result).
+	// This method is used to work around the "matchCount" filter which would otherwise
+	// strip our result from some accurate error reporting from lower level validators.
+	//
+	// NOTE: this implementation with a placeholder (IMPORTANT!) is neither clean nor
+	// very efficient. On the other hand, relying on go-openapi/errors to manipulate
+	// codes would require to change a lot here. So, for the moment, let's go with
+	// placeholders.
+	strippedErrors := []error{}
+	for _, e := range r.Errors {
+		if strings.HasPrefix(e.Error(), "IMPORTANT!") {
+			strippedErrors = append(strippedErrors, fmt.Errorf(strings.TrimPrefix(e.Error(), "IMPORTANT!")))
+		}
+	}
+	strippedWarnings := []error{}
+	for _, e := range r.Warnings {
+		if strings.HasPrefix(e.Error(), "IMPORTANT!") {
+			strippedWarnings = append(strippedWarnings, fmt.Errorf(strings.TrimPrefix(e.Error(), "IMPORTANT!")))
+		}
+	}
+	strippedResult := new(Result)
+	strippedResult.Errors = strippedErrors
+	strippedResult.Warnings = strippedWarnings
+	return strippedResult
+}
+
+// IsValid returns true when this result is valid.
+//
+// Returns true on a nil *Result.
+func (r *Result) IsValid() bool {
+	if r == nil {
+		return true
+	}
+	return len(r.Errors) == 0
+}
+
+// HasErrors returns true when this result is invalid.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasErrors() bool {
+	if r == nil {
+		return false
+	}
+	return !r.IsValid()
+}
+
+// HasWarnings returns true when this result contains warnings.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasWarnings() bool {
+	if r == nil {
+		return false
+	}
+	return len(r.Warnings) > 0
+}
+
+// HasErrorsOrWarnings returns true when this result contains
+// either errors or warnings.
+//
+// Returns false on a nil *Result.
+func (r *Result) HasErrorsOrWarnings() bool {
+	if r == nil {
+		return false
+	}
+	return len(r.Errors) > 0 || len(r.Warnings) > 0
+}
+
+// Inc increments the match count
+func (r *Result) Inc() {
+	r.MatchCount++
+}
+
+// AsError renders this result as an error interface
+//
+// TODO: reporting / pretty print with path ordered and indented
+func (r *Result) AsError() error {
+	if r.IsValid() {
+		return nil
+	}
+	return errors.CompositeValidationError(r.Errors...)
+}
+
+// schemata is an arbitrary number of schemata. It does a distinction between zero,
+// one and many schemata to avoid slice allocations.
+type schemata struct {
+	// one is set if there is exactly one schema. In that case multiple must be nil.
+	one *spec.Schema
+	// multiple is an arbitrary number of schemas. If it is set, one must be nil.
+	multiple []*spec.Schema
+}
+
+func (s *schemata) Len() int {
+	if s.one != nil {
+		return 1
+	}
+	return len(s.multiple)
+}
+
+func (s *schemata) Slice() []*spec.Schema {
+	if s == nil {
+		return nil
+	}
+	if s.one != nil {
+		return []*spec.Schema{s.one}
+	}
+	return s.multiple
+}
+
+// appendSchemata appends the schemata in other to s. It mutated s in-place.
+func (s *schemata) Append(other schemata) {
+	if other.one == nil && len(other.multiple) == 0 {
+		return
+	}
+	if s.one == nil && len(s.multiple) == 0 {
+		*s = other
+		return
+	}
+
+	if s.one != nil {
+		if other.one != nil {
+			s.multiple = []*spec.Schema{s.one, other.one}
+		} else {
+			t := make([]*spec.Schema, 0, 1+len(other.multiple))
+			s.multiple = append(append(t, s.one), other.multiple...)
+		}
+		s.one = nil
+	} else {
+		if other.one != nil {
+			s.multiple = append(s.multiple, other.one)
+		} else {
+			if cap(s.multiple) >= len(s.multiple)+len(other.multiple) {
+				s.multiple = append(s.multiple, other.multiple...)
+			} else {
+				t := make([]*spec.Schema, 0, len(s.multiple)+len(other.multiple))
+				s.multiple = append(append(t, s.multiple...), other.multiple...)
+			}
+		}
+	}
+}
diff --git a/go/vendor/github.com/go-openapi/validate/rexp.go b/go/vendor/github.com/go-openapi/validate/rexp.go
new file mode 100644
index 0000000..5a08243
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/rexp.go
@@ -0,0 +1,71 @@
+// 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 (
+	re "regexp"
+	"sync"
+	"sync/atomic"
+)
+
+// Cache for compiled regular expressions
+var (
+	cacheMutex = &sync.Mutex{}
+	reDict     = atomic.Value{} //map[string]*re.Regexp
+)
+
+func compileRegexp(pattern string) (*re.Regexp, error) {
+	if cache, ok := reDict.Load().(map[string]*re.Regexp); ok {
+		if r := cache[pattern]; r != nil {
+			return r, nil
+		}
+	}
+
+	r, err := re.Compile(pattern)
+	if err != nil {
+		return nil, err
+	}
+	cacheRegexp(r)
+	return r, nil
+}
+
+func mustCompileRegexp(pattern string) *re.Regexp {
+	if cache, ok := reDict.Load().(map[string]*re.Regexp); ok {
+		if r := cache[pattern]; r != nil {
+			return r
+		}
+	}
+
+	r := re.MustCompile(pattern)
+	cacheRegexp(r)
+	return r
+}
+
+func cacheRegexp(r *re.Regexp) {
+	cacheMutex.Lock()
+	defer cacheMutex.Unlock()
+
+	if cache, ok := reDict.Load().(map[string]*re.Regexp); !ok || cache[r.String()] == nil {
+		newCache := map[string]*re.Regexp{
+			r.String(): r,
+		}
+
+		for k, v := range cache {
+			newCache[k] = v
+		}
+
+		reDict.Store(newCache)
+	}
+}
diff --git a/go/vendor/github.com/go-openapi/validate/schema.go b/go/vendor/github.com/go-openapi/validate/schema.go
new file mode 100644
index 0000000..860b30e
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/schema.go
@@ -0,0 +1,248 @@
+// 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 (
+	"encoding/json"
+	"reflect"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+	"github.com/go-openapi/swag"
+)
+
+var (
+	specSchemaType    = reflect.TypeOf(&spec.Schema{})
+	specParameterType = reflect.TypeOf(&spec.Parameter{})
+	specItemsType     = reflect.TypeOf(&spec.Items{})
+	specHeaderType    = reflect.TypeOf(&spec.Header{})
+)
+
+// SchemaValidator validates data against a JSON schema
+type SchemaValidator struct {
+	Path         string
+	in           string
+	Schema       *spec.Schema
+	validators   []valueValidator
+	Root         interface{}
+	KnownFormats strfmt.Registry
+}
+
+// AgainstSchema validates the specified data against the provided schema, using a registry of supported formats.
+//
+// When no pre-parsed *spec.Schema structure is provided, it uses a JSON schema as default. See example.
+func AgainstSchema(schema *spec.Schema, data interface{}, formats strfmt.Registry) error {
+	res := NewSchemaValidator(schema, nil, "", formats).Validate(data)
+	if res.HasErrors() {
+		return errors.CompositeValidationError(res.Errors...)
+	}
+	return nil
+}
+
+// NewSchemaValidator creates a new schema validator.
+//
+// Panics if the provided schema is invalid.
+func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string, formats strfmt.Registry) *SchemaValidator {
+	if schema == nil {
+		return nil
+	}
+
+	if rootSchema == nil {
+		rootSchema = schema
+	}
+
+	if schema.ID != "" || schema.Ref.String() != "" || schema.Ref.IsRoot() {
+		err := spec.ExpandSchema(schema, rootSchema, nil)
+		if err != nil {
+			msg := invalidSchemaProvidedMsg(err).Error()
+			panic(msg)
+		}
+	}
+	s := SchemaValidator{Path: root, in: "body", Schema: schema, Root: rootSchema, KnownFormats: formats}
+	s.validators = []valueValidator{
+		s.typeValidator(),
+		s.schemaPropsValidator(),
+		s.stringValidator(),
+		s.formatValidator(),
+		s.numberValidator(),
+		s.sliceValidator(),
+		s.commonValidator(),
+		s.objectValidator(),
+	}
+	return &s
+}
+
+// SetPath sets the path for this schema valdiator
+func (s *SchemaValidator) SetPath(path string) {
+	s.Path = path
+}
+
+// Applies returns true when this schema validator applies
+func (s *SchemaValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	_, ok := source.(*spec.Schema)
+	return ok
+}
+
+// Validate validates the data against the schema
+func (s *SchemaValidator) Validate(data interface{}) *Result {
+	result := &Result{data: data}
+	if s == nil {
+		return result
+	}
+	if s.Schema != nil {
+		result.addRootObjectSchemata(s.Schema)
+	}
+
+	if data == nil {
+		result.Merge(s.validators[0].Validate(data)) // type validator
+		result.Merge(s.validators[6].Validate(data)) // common validator
+		return result
+	}
+
+	tpe := reflect.TypeOf(data)
+	kind := tpe.Kind()
+	for kind == reflect.Ptr {
+		tpe = tpe.Elem()
+		kind = tpe.Kind()
+	}
+	d := data
+
+	if kind == reflect.Struct {
+		// NOTE: since reflect retrieves the true nature of types
+		// this means that all strfmt types passed here (e.g. strfmt.Datetime, etc..)
+		// are converted here to strings, and structs are systematically converted
+		// to map[string]interface{}.
+		d = swag.ToDynamicJSON(data)
+	}
+
+	// TODO: this part should be handed over to type validator
+	// Handle special case of json.Number data (number marshalled as string)
+	isnumber := s.Schema.Type.Contains("number") || s.Schema.Type.Contains("integer")
+	if num, ok := data.(json.Number); ok && isnumber {
+		if s.Schema.Type.Contains("integer") { // avoid lossy conversion
+			in, erri := num.Int64()
+			if erri != nil {
+				result.AddErrors(invalidTypeConversionMsg(s.Path, erri))
+				result.Inc()
+				return result
+			}
+			d = in
+		} else {
+			nf, errf := num.Float64()
+			if errf != nil {
+				result.AddErrors(invalidTypeConversionMsg(s.Path, errf))
+				result.Inc()
+				return result
+			}
+			d = nf
+		}
+
+		tpe = reflect.TypeOf(d)
+		kind = tpe.Kind()
+	}
+
+	for _, v := range s.validators {
+		if !v.Applies(s.Schema, kind) {
+			debugLog("%T does not apply for %v", v, kind)
+			continue
+		}
+
+		err := v.Validate(d)
+		result.Merge(err)
+		result.Inc()
+	}
+	result.Inc()
+
+	return result
+}
+
+func (s *SchemaValidator) typeValidator() valueValidator {
+	return &typeValidator{Type: s.Schema.Type, Format: s.Schema.Format, In: s.in, Path: s.Path}
+}
+
+func (s *SchemaValidator) commonValidator() valueValidator {
+	return &basicCommonValidator{
+		Path: s.Path,
+		In:   s.in,
+		Enum: s.Schema.Enum,
+	}
+}
+
+func (s *SchemaValidator) sliceValidator() valueValidator {
+	return &schemaSliceValidator{
+		Path:            s.Path,
+		In:              s.in,
+		MaxItems:        s.Schema.MaxItems,
+		MinItems:        s.Schema.MinItems,
+		UniqueItems:     s.Schema.UniqueItems,
+		AdditionalItems: s.Schema.AdditionalItems,
+		Items:           s.Schema.Items,
+		Root:            s.Root,
+		KnownFormats:    s.KnownFormats,
+	}
+}
+
+func (s *SchemaValidator) numberValidator() valueValidator {
+	return &numberValidator{
+		Path:             s.Path,
+		In:               s.in,
+		Default:          s.Schema.Default,
+		MultipleOf:       s.Schema.MultipleOf,
+		Maximum:          s.Schema.Maximum,
+		ExclusiveMaximum: s.Schema.ExclusiveMaximum,
+		Minimum:          s.Schema.Minimum,
+		ExclusiveMinimum: s.Schema.ExclusiveMinimum,
+	}
+}
+
+func (s *SchemaValidator) stringValidator() valueValidator {
+	return &stringValidator{
+		Path:      s.Path,
+		In:        s.in,
+		MaxLength: s.Schema.MaxLength,
+		MinLength: s.Schema.MinLength,
+		Pattern:   s.Schema.Pattern,
+	}
+}
+
+func (s *SchemaValidator) formatValidator() valueValidator {
+	return &formatValidator{
+		Path:         s.Path,
+		In:           s.in,
+		Format:       s.Schema.Format,
+		KnownFormats: s.KnownFormats,
+	}
+}
+
+func (s *SchemaValidator) schemaPropsValidator() valueValidator {
+	sch := s.Schema
+	return newSchemaPropsValidator(s.Path, s.in, sch.AllOf, sch.OneOf, sch.AnyOf, sch.Not, sch.Dependencies, s.Root, s.KnownFormats)
+}
+
+func (s *SchemaValidator) objectValidator() valueValidator {
+	return &objectValidator{
+		Path:                 s.Path,
+		In:                   s.in,
+		MaxProperties:        s.Schema.MaxProperties,
+		MinProperties:        s.Schema.MinProperties,
+		Required:             s.Schema.Required,
+		Properties:           s.Schema.Properties,
+		AdditionalProperties: s.Schema.AdditionalProperties,
+		PatternProperties:    s.Schema.PatternProperties,
+		Root:                 s.Root,
+		KnownFormats:         s.KnownFormats,
+	}
+}
diff --git a/go/vendor/github.com/go-openapi/validate/schema_messages.go b/go/vendor/github.com/go-openapi/validate/schema_messages.go
new file mode 100644
index 0000000..786e2e3
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/schema_messages.go
@@ -0,0 +1,78 @@
+// 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 (
+	"github.com/go-openapi/errors"
+)
+
+// Error messages related to schema validation and returned as results.
+const (
+	// ArrayDoesNotAllowAdditionalItemsError when an additionalItems construct is not verified by the array values provided.
+	//
+	// TODO: should move to package go-openapi/errors
+	ArrayDoesNotAllowAdditionalItemsError = "array doesn't allow for additional items"
+
+	// HasDependencyError indicates that a dependencies construct was not verified
+	HasDependencyError = "%q has a dependency on %s"
+
+	// InvalidSchemaProvidedError indicates that the schema provided to validate a value cannot be properly compiled
+	InvalidSchemaProvidedError = "Invalid schema provided to SchemaValidator: %v"
+
+	// InvalidTypeConversionError indicates that a numerical conversion for the given type could not be carried on
+	InvalidTypeConversionError = "invalid type conversion in %s: %v "
+
+	// MustValidateAtLeastOneSchemaError indicates that in a AnyOf construct, none of the schema constraints specified were verified
+	MustValidateAtLeastOneSchemaError = "%q must validate at least one schema (anyOf)"
+
+	// MustValidateOnlyOneSchemaError indicates that in a OneOf construct, either none of the schema constraints specified were verified, or several were
+	MustValidateOnlyOneSchemaError = "%q must validate one and only one schema (oneOf). %s"
+
+	// MustValidateAllSchemasError indicates that in a AllOf construct, at least one of the schema constraints specified were not verified
+	//
+	// TODO: punctuation in message
+	MustValidateAllSchemasError = "%q must validate all the schemas (allOf)%s"
+
+	// MustNotValidateSchemaError indicates that in a Not construct, the schema constraint specified was verified
+	MustNotValidateSchemaError = "%q must not validate the schema (not)"
+)
+
+// Warning messages related to schema validation and returned as results
+const ()
+
+func invalidSchemaProvidedMsg(err error) errors.Error {
+	return errors.New(InternalErrorCode, InvalidSchemaProvidedError, err)
+}
+func invalidTypeConversionMsg(path string, err error) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidTypeConversionError, path, err)
+}
+func mustValidateOnlyOneSchemaMsg(path, additionalMsg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, MustValidateOnlyOneSchemaError, path, additionalMsg)
+}
+func mustValidateAtLeastOneSchemaMsg(path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, MustValidateAtLeastOneSchemaError, path)
+}
+func mustValidateAllSchemasMsg(path, additionalMsg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, MustValidateAllSchemasError, path, additionalMsg)
+}
+func mustNotValidatechemaMsg(path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, MustNotValidateSchemaError, path)
+}
+func hasADependencyMsg(path, depkey string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, HasDependencyError, path, depkey)
+}
+func arrayDoesNotAllowAdditionalItemsMsg() errors.Error {
+	return errors.New(errors.CompositeErrorCode, ArrayDoesNotAllowAdditionalItemsError)
+}
diff --git a/go/vendor/github.com/go-openapi/validate/schema_props.go b/go/vendor/github.com/go-openapi/validate/schema_props.go
new file mode 100644
index 0000000..c3dfa79
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/schema_props.go
@@ -0,0 +1,231 @@
+// 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 (
+	"fmt"
+	"reflect"
+
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+)
+
+type schemaPropsValidator struct {
+	Path            string
+	In              string
+	AllOf           []spec.Schema
+	OneOf           []spec.Schema
+	AnyOf           []spec.Schema
+	Not             *spec.Schema
+	Dependencies    spec.Dependencies
+	anyOfValidators []SchemaValidator
+	allOfValidators []SchemaValidator
+	oneOfValidators []SchemaValidator
+	notValidator    *SchemaValidator
+	Root            interface{}
+	KnownFormats    strfmt.Registry
+}
+
+func (s *schemaPropsValidator) SetPath(path string) {
+	s.Path = path
+}
+
+func newSchemaPropsValidator(path string, in string, allOf, oneOf, anyOf []spec.Schema, not *spec.Schema, deps spec.Dependencies, root interface{}, formats strfmt.Registry) *schemaPropsValidator {
+	anyValidators := make([]SchemaValidator, 0, len(anyOf))
+	for _, v := range anyOf {
+		anyValidators = append(anyValidators, *NewSchemaValidator(&v, root, path, formats))
+	}
+	allValidators := make([]SchemaValidator, 0, len(allOf))
+	for _, v := range allOf {
+		allValidators = append(allValidators, *NewSchemaValidator(&v, root, path, formats))
+	}
+	oneValidators := make([]SchemaValidator, 0, len(oneOf))
+	for _, v := range oneOf {
+		oneValidators = append(oneValidators, *NewSchemaValidator(&v, root, path, formats))
+	}
+
+	var notValidator *SchemaValidator
+	if not != nil {
+		notValidator = NewSchemaValidator(not, root, path, formats)
+	}
+
+	return &schemaPropsValidator{
+		Path:            path,
+		In:              in,
+		AllOf:           allOf,
+		OneOf:           oneOf,
+		AnyOf:           anyOf,
+		Not:             not,
+		Dependencies:    deps,
+		anyOfValidators: anyValidators,
+		allOfValidators: allValidators,
+		oneOfValidators: oneValidators,
+		notValidator:    notValidator,
+		Root:            root,
+		KnownFormats:    formats,
+	}
+}
+
+func (s *schemaPropsValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	r := reflect.TypeOf(source) == specSchemaType
+	debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind)
+	return r
+}
+
+func (s *schemaPropsValidator) Validate(data interface{}) *Result {
+	mainResult := new(Result)
+
+	// Intermediary error results
+
+	// IMPORTANT! messages from underlying validators
+	keepResultAnyOf := new(Result)
+	keepResultOneOf := new(Result)
+	keepResultAllOf := new(Result)
+
+	// Validates at least one in anyOf schemas
+	var firstSuccess *Result
+	if len(s.anyOfValidators) > 0 {
+		var bestFailures *Result
+		succeededOnce := false
+		for _, anyOfSchema := range s.anyOfValidators {
+			result := anyOfSchema.Validate(data)
+			// We keep inner IMPORTANT! errors no matter what MatchCount tells us
+			keepResultAnyOf.Merge(result.keepRelevantErrors())
+			if result.IsValid() {
+				bestFailures = nil
+				succeededOnce = true
+				if firstSuccess == nil {
+					firstSuccess = result
+				}
+				keepResultAnyOf = new(Result)
+				break
+			}
+			// MatchCount is used to select errors from the schema with most positive checks
+			if bestFailures == nil || result.MatchCount > bestFailures.MatchCount {
+				bestFailures = result
+			}
+		}
+
+		if !succeededOnce {
+			mainResult.AddErrors(mustValidateAtLeastOneSchemaMsg(s.Path))
+		}
+		if bestFailures != nil {
+			mainResult.Merge(bestFailures)
+		} else if firstSuccess != nil {
+			mainResult.Merge(firstSuccess)
+		}
+	}
+
+	// Validates exactly one in oneOf schemas
+	if len(s.oneOfValidators) > 0 {
+		var bestFailures *Result
+		var firstSuccess *Result
+		validated := 0
+
+		for _, oneOfSchema := range s.oneOfValidators {
+			result := oneOfSchema.Validate(data)
+			// We keep inner IMPORTANT! errors no matter what MatchCount tells us
+			keepResultOneOf.Merge(result.keepRelevantErrors())
+			if result.IsValid() {
+				validated++
+				bestFailures = nil
+				if firstSuccess == nil {
+					firstSuccess = result
+				}
+				keepResultOneOf = new(Result)
+				continue
+			}
+			// MatchCount is used to select errors from the schema with most positive checks
+			if validated == 0 && (bestFailures == nil || result.MatchCount > bestFailures.MatchCount) {
+				bestFailures = result
+			}
+		}
+
+		if validated != 1 {
+			additionalMsg := ""
+			if validated == 0 {
+				additionalMsg = "Found none valid"
+			} else {
+				additionalMsg = fmt.Sprintf("Found %d valid alternatives", validated)
+			}
+
+			mainResult.AddErrors(mustValidateOnlyOneSchemaMsg(s.Path, additionalMsg))
+			if bestFailures != nil {
+				mainResult.Merge(bestFailures)
+			}
+		} else if firstSuccess != nil {
+			mainResult.Merge(firstSuccess)
+		}
+	}
+
+	// Validates all of allOf schemas
+	if len(s.allOfValidators) > 0 {
+		validated := 0
+
+		for _, allOfSchema := range s.allOfValidators {
+			result := allOfSchema.Validate(data)
+			// We keep inner IMPORTANT! errors no matter what MatchCount tells us
+			keepResultAllOf.Merge(result.keepRelevantErrors())
+			//keepResultAllOf.Merge(result)
+			if result.IsValid() {
+				validated++
+			}
+			mainResult.Merge(result)
+		}
+
+		if validated != len(s.allOfValidators) {
+			additionalMsg := ""
+			if validated == 0 {
+				additionalMsg = ". None validated"
+			}
+
+			mainResult.AddErrors(mustValidateAllSchemasMsg(s.Path, additionalMsg))
+		}
+	}
+
+	if s.notValidator != nil {
+		result := s.notValidator.Validate(data)
+		// We keep inner IMPORTANT! errors no matter what MatchCount tells us
+		if result.IsValid() {
+			mainResult.AddErrors(mustNotValidatechemaMsg(s.Path))
+		}
+	}
+
+	if s.Dependencies != nil && len(s.Dependencies) > 0 && reflect.TypeOf(data).Kind() == reflect.Map {
+		val := data.(map[string]interface{})
+		for key := range val {
+			if dep, ok := s.Dependencies[key]; ok {
+
+				if dep.Schema != nil {
+					mainResult.Merge(NewSchemaValidator(dep.Schema, s.Root, s.Path+"."+key, s.KnownFormats).Validate(data))
+					continue
+				}
+
+				if len(dep.Property) > 0 {
+					for _, depKey := range dep.Property {
+						if _, ok := val[depKey]; !ok {
+							mainResult.AddErrors(hasADependencyMsg(s.Path, depKey))
+						}
+					}
+				}
+			}
+		}
+	}
+
+	mainResult.Inc()
+	// In the end we retain best failures for schema validation
+	// plus, if any, composite errors which may explain special cases (tagged as IMPORTANT!).
+	return mainResult.Merge(keepResultAllOf, keepResultOneOf, keepResultAnyOf)
+}
diff --git a/go/vendor/github.com/go-openapi/validate/slice_validator.go b/go/vendor/github.com/go-openapi/validate/slice_validator.go
new file mode 100644
index 0000000..6e61594
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/slice_validator.go
@@ -0,0 +1,104 @@
+// 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 (
+	"fmt"
+	"reflect"
+
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+)
+
+type schemaSliceValidator struct {
+	Path            string
+	In              string
+	MaxItems        *int64
+	MinItems        *int64
+	UniqueItems     bool
+	AdditionalItems *spec.SchemaOrBool
+	Items           *spec.SchemaOrArray
+	Root            interface{}
+	KnownFormats    strfmt.Registry
+}
+
+func (s *schemaSliceValidator) SetPath(path string) {
+	s.Path = path
+}
+
+func (s *schemaSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	_, ok := source.(*spec.Schema)
+	r := ok && kind == reflect.Slice
+	return r
+}
+
+func (s *schemaSliceValidator) Validate(data interface{}) *Result {
+	result := new(Result)
+	if data == nil {
+		return result
+	}
+	val := reflect.ValueOf(data)
+	size := val.Len()
+
+	if s.Items != nil && s.Items.Schema != nil {
+		validator := NewSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats)
+		for i := 0; i < size; i++ {
+			validator.SetPath(fmt.Sprintf("%s.%d", s.Path, i))
+			value := val.Index(i)
+			result.mergeForSlice(val, i, validator.Validate(value.Interface()))
+		}
+	}
+
+	itemsSize := 0
+	if s.Items != nil && len(s.Items.Schemas) > 0 {
+		itemsSize = len(s.Items.Schemas)
+		for i := 0; i < itemsSize; i++ {
+			validator := NewSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats)
+			if val.Len() <= i {
+				break
+			}
+			result.mergeForSlice(val, int(i), validator.Validate(val.Index(i).Interface()))
+		}
+	}
+	if s.AdditionalItems != nil && itemsSize < size {
+		if s.Items != nil && len(s.Items.Schemas) > 0 && !s.AdditionalItems.Allows {
+			result.AddErrors(arrayDoesNotAllowAdditionalItemsMsg())
+		}
+		if s.AdditionalItems.Schema != nil {
+			for i := itemsSize; i < size-itemsSize+1; i++ {
+				validator := NewSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats)
+				result.mergeForSlice(val, int(i), validator.Validate(val.Index(int(i)).Interface()))
+			}
+		}
+	}
+
+	if s.MinItems != nil {
+		if err := MinItems(s.Path, s.In, int64(size), *s.MinItems); err != nil {
+			result.AddErrors(err)
+		}
+	}
+	if s.MaxItems != nil {
+		if err := MaxItems(s.Path, s.In, int64(size), *s.MaxItems); err != nil {
+			result.AddErrors(err)
+		}
+	}
+	if s.UniqueItems {
+		if err := UniqueItems(s.Path, s.In, val.Interface()); err != nil {
+			result.AddErrors(err)
+		}
+	}
+	result.Inc()
+	return result
+}
diff --git a/go/vendor/github.com/go-openapi/validate/spec.go b/go/vendor/github.com/go-openapi/validate/spec.go
new file mode 100644
index 0000000..08ccd22
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/spec.go
@@ -0,0 +1,777 @@
+// 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 (
+	"encoding/json"
+	"fmt"
+	"sort"
+	"strings"
+
+	"github.com/go-openapi/analysis"
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/jsonpointer"
+	"github.com/go-openapi/loads"
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+)
+
+// Spec validates an OpenAPI 2.0 specification document.
+//
+// Returns an error flattening in a single standard error, all validation messages.
+//
+//  - TODO: $ref should not have siblings
+//  - TODO: make sure documentation reflects all checks and warnings
+//  - TODO: check on discriminators
+//  - TODO: explicit message on unsupported keywords (better than "forbidden property"...)
+//  - TODO: full list of unresolved refs
+//  - TODO: validate numeric constraints (issue#581): this should be handled like defaults and examples
+//  - TODO: option to determine if we validate for go-swagger or in a more general context
+//  - TODO: check on required properties to support anyOf, allOf, oneOf
+//
+// NOTE: SecurityScopes are maps: no need to check uniqueness
+//
+func Spec(doc *loads.Document, formats strfmt.Registry) error {
+	errs, _ /*warns*/ := NewSpecValidator(doc.Schema(), formats).Validate(doc)
+	if errs.HasErrors() {
+		return errors.CompositeValidationError(errs.Errors...)
+	}
+	return nil
+}
+
+// SpecValidator validates a swagger 2.0 spec
+type SpecValidator struct {
+	schema       *spec.Schema // swagger 2.0 schema
+	spec         *loads.Document
+	analyzer     *analysis.Spec
+	expanded     *loads.Document
+	KnownFormats strfmt.Registry
+	Options      Opts // validation options
+}
+
+// NewSpecValidator creates a new swagger spec validator instance
+func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry) *SpecValidator {
+	return &SpecValidator{
+		schema:       schema,
+		KnownFormats: formats,
+		Options:      defaultOpts,
+	}
+}
+
+// Validate validates the swagger spec
+func (s *SpecValidator) Validate(data interface{}) (errs *Result, warnings *Result) {
+	var sd *loads.Document
+	errs = new(Result)
+
+	switch v := data.(type) {
+	case *loads.Document:
+		sd = v
+	}
+	if sd == nil {
+		errs.AddErrors(invalidDocumentMsg())
+		return
+	}
+	s.spec = sd
+	s.analyzer = analysis.New(sd.Spec())
+
+	warnings = new(Result)
+
+	// Swagger schema validator
+	schv := NewSchemaValidator(s.schema, nil, "", s.KnownFormats)
+	var obj interface{}
+
+	// Raw spec unmarshalling errors
+	if err := json.Unmarshal(sd.Raw(), &obj); err != nil {
+		// NOTE: under normal conditions, the *load.Document has been already unmarshalled
+		// So this one is just a paranoid check on the behavior of the spec package
+		panic(InvalidDocumentError)
+	}
+
+	defer func() {
+		// errs holds all errors and warnings,
+		// warnings only warnings
+		errs.MergeAsWarnings(warnings)
+		warnings.AddErrors(errs.Warnings...)
+	}()
+
+	errs.Merge(schv.Validate(obj)) // error -
+	// There may be a point in continuing to try and determine more accurate errors
+	if !s.Options.ContinueOnErrors && errs.HasErrors() {
+		return // no point in continuing
+	}
+
+	errs.Merge(s.validateReferencesValid()) // error -
+	// There may be a point in continuing to try and determine more accurate errors
+	if !s.Options.ContinueOnErrors && errs.HasErrors() {
+		return // no point in continuing
+	}
+
+	errs.Merge(s.validateDuplicateOperationIDs())
+	errs.Merge(s.validateDuplicatePropertyNames()) // error -
+	errs.Merge(s.validateParameters())             // error -
+	errs.Merge(s.validateItems())                  // error -
+
+	// Properties in required definition MUST validate their schema
+	// Properties SHOULD NOT be declared as both required and readOnly (warning)
+	errs.Merge(s.validateRequiredDefinitions()) // error and warning
+
+	// There may be a point in continuing to try and determine more accurate errors
+	if !s.Options.ContinueOnErrors && errs.HasErrors() {
+		return // no point in continuing
+	}
+
+	// Values provided as default MUST validate their schema
+	df := &defaultValidator{SpecValidator: s}
+	errs.Merge(df.Validate())
+
+	// Values provided as examples MUST validate their schema
+	// Value provided as examples in a response without schema generate a warning
+	// Known limitations: examples in responses for mime type not application/json are ignored (warning)
+	ex := &exampleValidator{SpecValidator: s}
+	errs.Merge(ex.Validate())
+
+	errs.Merge(s.validateNonEmptyPathParamNames())
+
+	//errs.Merge(s.validateRefNoSibling()) // warning only
+	errs.Merge(s.validateReferenced()) // warning only
+
+	return
+}
+
+func (s *SpecValidator) validateNonEmptyPathParamNames() *Result {
+	res := new(Result)
+	if s.spec.Spec().Paths == nil {
+		// There is no Paths object: error
+		res.AddErrors(noValidPathMsg())
+	} else {
+		if s.spec.Spec().Paths.Paths == nil {
+			// Paths may be empty: warning
+			res.AddWarnings(noValidPathMsg())
+		} else {
+			for k := range s.spec.Spec().Paths.Paths {
+				if strings.Contains(k, "{}") {
+					res.AddErrors(emptyPathParameterMsg(k))
+				}
+			}
+		}
+	}
+	return res
+}
+
+func (s *SpecValidator) validateDuplicateOperationIDs() *Result {
+	// OperationID, if specified, must be unique across the board
+	res := new(Result)
+	known := make(map[string]int)
+	for _, v := range s.analyzer.OperationIDs() {
+		if v != "" {
+			known[v]++
+		}
+	}
+	for k, v := range known {
+		if v > 1 {
+			res.AddErrors(nonUniqueOperationIDMsg(k, v))
+		}
+	}
+	return res
+}
+
+type dupProp struct {
+	Name       string
+	Definition string
+}
+
+func (s *SpecValidator) validateDuplicatePropertyNames() *Result {
+	// definition can't declare a property that's already defined by one of its ancestors
+	res := new(Result)
+	for k, sch := range s.spec.Spec().Definitions {
+		if len(sch.AllOf) == 0 {
+			continue
+		}
+
+		knownanc := map[string]struct{}{
+			"#/definitions/" + k: {},
+		}
+
+		ancs, rec := s.validateCircularAncestry(k, sch, knownanc)
+		if rec != nil && (rec.HasErrors() || !rec.HasWarnings()) {
+			res.Merge(rec)
+		}
+		if len(ancs) > 0 {
+			res.AddErrors(circularAncestryDefinitionMsg(k, ancs))
+			return res
+		}
+
+		knowns := make(map[string]struct{})
+		dups, rep := s.validateSchemaPropertyNames(k, sch, knowns)
+		if rep != nil && (rep.HasErrors() || rep.HasWarnings()) {
+			res.Merge(rep)
+		}
+		if len(dups) > 0 {
+			var pns []string
+			for _, v := range dups {
+				pns = append(pns, v.Definition+"."+v.Name)
+			}
+			res.AddErrors(duplicatePropertiesMsg(k, pns))
+		}
+
+	}
+	return res
+}
+
+func (s *SpecValidator) resolveRef(ref *spec.Ref) (*spec.Schema, error) {
+	if s.spec.SpecFilePath() != "" {
+		return spec.ResolveRefWithBase(s.spec.Spec(), ref, &spec.ExpandOptions{RelativeBase: s.spec.SpecFilePath()})
+	}
+	// NOTE: it looks like with the new spec resolver, this code is now unrecheable
+	return spec.ResolveRef(s.spec.Spec(), ref)
+}
+
+func (s *SpecValidator) validateSchemaPropertyNames(nm string, sch spec.Schema, knowns map[string]struct{}) ([]dupProp, *Result) {
+	var dups []dupProp
+
+	schn := nm
+	schc := &sch
+	res := new(Result)
+
+	for schc.Ref.String() != "" {
+		// gather property names
+		reso, err := s.resolveRef(&schc.Ref)
+		if err != nil {
+			errorHelp.addPointerError(res, err, schc.Ref.String(), nm)
+			return dups, res
+		}
+		schc = reso
+		schn = sch.Ref.String()
+	}
+
+	if len(schc.AllOf) > 0 {
+		for _, chld := range schc.AllOf {
+			dup, rep := s.validateSchemaPropertyNames(schn, chld, knowns)
+			if rep != nil && (rep.HasErrors() || rep.HasWarnings()) {
+				res.Merge(rep)
+			}
+			dups = append(dups, dup...)
+		}
+		return dups, res
+	}
+
+	for k := range schc.Properties {
+		_, ok := knowns[k]
+		if ok {
+			dups = append(dups, dupProp{Name: k, Definition: schn})
+		} else {
+			knowns[k] = struct{}{}
+		}
+	}
+
+	return dups, res
+}
+
+func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, knowns map[string]struct{}) ([]string, *Result) {
+	res := new(Result)
+
+	if sch.Ref.String() == "" && len(sch.AllOf) == 0 { // Safeguard. We should not be able to actually get there
+		return nil, res
+	}
+	var ancs []string
+
+	schn := nm
+	schc := &sch
+
+	for schc.Ref.String() != "" {
+		reso, err := s.resolveRef(&schc.Ref)
+		if err != nil {
+			errorHelp.addPointerError(res, err, schc.Ref.String(), nm)
+			return ancs, res
+		}
+		schc = reso
+		schn = sch.Ref.String()
+	}
+
+	if schn != nm && schn != "" {
+		if _, ok := knowns[schn]; ok {
+			ancs = append(ancs, schn)
+		}
+		knowns[schn] = struct{}{}
+
+		if len(ancs) > 0 {
+			return ancs, res
+		}
+	}
+
+	if len(schc.AllOf) > 0 {
+		for _, chld := range schc.AllOf {
+			if chld.Ref.String() != "" || len(chld.AllOf) > 0 {
+				anc, rec := s.validateCircularAncestry(schn, chld, knowns)
+				if rec != nil && (rec.HasErrors() || !rec.HasWarnings()) {
+					res.Merge(rec)
+				}
+				ancs = append(ancs, anc...)
+				if len(ancs) > 0 {
+					return ancs, res
+				}
+			}
+		}
+	}
+	return ancs, res
+}
+
+func (s *SpecValidator) validateItems() *Result {
+	// validate parameter, items, schema and response objects for presence of item if type is array
+	res := new(Result)
+
+	for method, pi := range s.analyzer.Operations() {
+		for path, op := range pi {
+			for _, param := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+
+				if param.TypeName() == "array" && param.ItemsTypeName() == "" {
+					res.AddErrors(arrayInParamRequiresItemsMsg(param.Name, op.ID))
+					continue
+				}
+				if param.In != "body" {
+					if param.Items != nil {
+						items := param.Items
+						for items.TypeName() == "array" {
+							if items.ItemsTypeName() == "" {
+								res.AddErrors(arrayInParamRequiresItemsMsg(param.Name, op.ID))
+								break
+							}
+							items = items.Items
+						}
+					}
+				} else {
+					// In: body
+					if param.Schema != nil {
+						res.Merge(s.validateSchemaItems(*param.Schema, fmt.Sprintf("body param %q", param.Name), op.ID))
+					}
+				}
+			}
+
+			var responses []spec.Response
+			if op.Responses != nil {
+				if op.Responses.Default != nil {
+					responses = append(responses, *op.Responses.Default)
+				}
+				if op.Responses.StatusCodeResponses != nil {
+					for _, v := range op.Responses.StatusCodeResponses {
+						responses = append(responses, v)
+					}
+				}
+			}
+
+			for _, resp := range responses {
+				// Response headers with array
+				for hn, hv := range resp.Headers {
+					if hv.TypeName() == "array" && hv.ItemsTypeName() == "" {
+						res.AddErrors(arrayInHeaderRequiresItemsMsg(hn, op.ID))
+					}
+				}
+				if resp.Schema != nil {
+					res.Merge(s.validateSchemaItems(*resp.Schema, "response body", op.ID))
+				}
+			}
+		}
+	}
+	return res
+}
+
+// Verifies constraints on array type
+func (s *SpecValidator) validateSchemaItems(schema spec.Schema, prefix, opID string) *Result {
+	res := new(Result)
+	if !schema.Type.Contains("array") {
+		return res
+	}
+
+	if schema.Items == nil || schema.Items.Len() == 0 {
+		res.AddErrors(arrayRequiresItemsMsg(prefix, opID))
+		return res
+	}
+
+	if schema.Items.Schema != nil {
+		schema = *schema.Items.Schema
+		if _, err := compileRegexp(schema.Pattern); err != nil {
+			res.AddErrors(invalidItemsPatternMsg(prefix, opID, schema.Pattern))
+		}
+
+		res.Merge(s.validateSchemaItems(schema, prefix, opID))
+	}
+	return res
+}
+
+func (s *SpecValidator) validatePathParamPresence(path string, fromPath, fromOperation []string) *Result {
+	// Each defined operation path parameters must correspond to a named element in the API's path pattern.
+	// (For example, you cannot have a path parameter named id for the following path /pets/{petId} but you must have a path parameter named petId.)
+	res := new(Result)
+	for _, l := range fromPath {
+		var matched bool
+		for _, r := range fromOperation {
+			if l == "{"+r+"}" {
+				matched = true
+				break
+			}
+		}
+		if !matched {
+			res.AddErrors(noParameterInPathMsg(l))
+		}
+	}
+
+	for _, p := range fromOperation {
+		var matched bool
+		for _, r := range fromPath {
+			if "{"+p+"}" == r {
+				matched = true
+				break
+			}
+		}
+		if !matched {
+			res.AddErrors(pathParamNotInPathMsg(path, p))
+		}
+	}
+
+	return res
+}
+
+func (s *SpecValidator) validateReferenced() *Result {
+	var res Result
+	res.MergeAsWarnings(s.validateReferencedParameters())
+	res.MergeAsWarnings(s.validateReferencedResponses())
+	res.MergeAsWarnings(s.validateReferencedDefinitions())
+	return &res
+}
+
+func (s *SpecValidator) validateReferencedParameters() *Result {
+	// Each referenceable definition should have references.
+	params := s.spec.Spec().Parameters
+	if len(params) == 0 {
+		return nil
+	}
+
+	expected := make(map[string]struct{})
+	for k := range params {
+		expected["#/parameters/"+jsonpointer.Escape(k)] = struct{}{}
+	}
+	for _, k := range s.analyzer.AllParameterReferences() {
+		if _, ok := expected[k]; ok {
+			delete(expected, k)
+		}
+	}
+
+	if len(expected) == 0 {
+		return nil
+	}
+	result := new(Result)
+	for k := range expected {
+		result.AddWarnings(unusedParamMsg(k))
+	}
+	return result
+}
+
+func (s *SpecValidator) validateReferencedResponses() *Result {
+	// Each referenceable definition should have references.
+	responses := s.spec.Spec().Responses
+	if len(responses) == 0 {
+		return nil
+	}
+
+	expected := make(map[string]struct{})
+	for k := range responses {
+		expected["#/responses/"+jsonpointer.Escape(k)] = struct{}{}
+	}
+	for _, k := range s.analyzer.AllResponseReferences() {
+		if _, ok := expected[k]; ok {
+			delete(expected, k)
+		}
+	}
+
+	if len(expected) == 0 {
+		return nil
+	}
+	result := new(Result)
+	for k := range expected {
+		result.AddWarnings(unusedResponseMsg(k))
+	}
+	return result
+}
+
+func (s *SpecValidator) validateReferencedDefinitions() *Result {
+	// Each referenceable definition must have references.
+	defs := s.spec.Spec().Definitions
+	if len(defs) == 0 {
+		return nil
+	}
+
+	expected := make(map[string]struct{})
+	for k := range defs {
+		expected["#/definitions/"+jsonpointer.Escape(k)] = struct{}{}
+	}
+	for _, k := range s.analyzer.AllDefinitionReferences() {
+		if _, ok := expected[k]; ok {
+			delete(expected, k)
+		}
+	}
+
+	if len(expected) == 0 {
+		return nil
+	}
+
+	result := new(Result)
+	for k := range expected {
+		result.AddWarnings(unusedDefinitionMsg(k))
+	}
+	return result
+}
+
+func (s *SpecValidator) validateRequiredDefinitions() *Result {
+	// Each property listed in the required array must be defined in the properties of the model
+	res := new(Result)
+
+DEFINITIONS:
+	for d, schema := range s.spec.Spec().Definitions {
+		if schema.Required != nil { // Safeguard
+			for _, pn := range schema.Required {
+				red := s.validateRequiredProperties(pn, d, &schema)
+				res.Merge(red)
+				if !red.IsValid() && !s.Options.ContinueOnErrors {
+					break DEFINITIONS // there is an error, let's stop that bleeding
+				}
+			}
+		}
+	}
+	return res
+}
+
+func (s *SpecValidator) validateRequiredProperties(path, in string, v *spec.Schema) *Result {
+	// Takes care of recursive property definitions, which may be nested in additionalProperties schemas
+	res := new(Result)
+	propertyMatch := false
+	patternMatch := false
+	additionalPropertiesMatch := false
+	isReadOnly := false
+
+	// Regular properties
+	if _, ok := v.Properties[path]; ok {
+		propertyMatch = true
+		isReadOnly = v.Properties[path].ReadOnly
+	}
+
+	// NOTE: patternProperties are not supported in swagger. Even though, we continue validation here
+	// We check all defined patterns: if one regexp is invalid, croaks an error
+	for pp, pv := range v.PatternProperties {
+		re, err := compileRegexp(pp)
+		if err != nil {
+			res.AddErrors(invalidPatternMsg(pp, in))
+		} else if re.MatchString(path) {
+			patternMatch = true
+			if !propertyMatch {
+				isReadOnly = pv.ReadOnly
+			}
+		}
+	}
+
+	if !(propertyMatch || patternMatch) {
+		if v.AdditionalProperties != nil {
+			if v.AdditionalProperties.Allows && v.AdditionalProperties.Schema == nil {
+				additionalPropertiesMatch = true
+			} else if v.AdditionalProperties.Schema != nil {
+				// additionalProperties as schema are upported in swagger
+				// recursively validates additionalProperties schema
+				// TODO : anyOf, allOf, oneOf like in schemaPropsValidator
+				red := s.validateRequiredProperties(path, in, v.AdditionalProperties.Schema)
+				if red.IsValid() {
+					additionalPropertiesMatch = true
+					if !propertyMatch && !patternMatch {
+						isReadOnly = v.AdditionalProperties.Schema.ReadOnly
+					}
+				}
+				res.Merge(red)
+			}
+		}
+	}
+
+	if !(propertyMatch || patternMatch || additionalPropertiesMatch) {
+		res.AddErrors(requiredButNotDefinedMsg(path, in))
+	}
+
+	if isReadOnly {
+		res.AddWarnings(readOnlyAndRequiredMsg(in, path))
+	}
+	return res
+}
+
+func (s *SpecValidator) validateParameters() *Result {
+	// - for each method, path is unique, regardless of path parameters
+	//   e.g. GET:/petstore/{id}, GET:/petstore/{pet}, GET:/petstore are
+	//   considered duplicate paths
+	// - each parameter should have a unique `name` and `type` combination
+	// - each operation should have only 1 parameter of type body
+	// - there must be at most 1 parameter in body
+	// - parameters with pattern property must specify valid patterns
+	// - $ref in parameters must resolve
+	// - path param must be required
+	res := new(Result)
+	rexGarbledPathSegment := mustCompileRegexp(`.*[{}\s]+.*`)
+	for method, pi := range s.analyzer.Operations() {
+		methodPaths := make(map[string]map[string]string)
+		if pi != nil { // Safeguard
+			for path, op := range pi {
+				pathToAdd := pathHelp.stripParametersInPath(path)
+
+				// Warn on garbled path afer param stripping
+				if rexGarbledPathSegment.MatchString(pathToAdd) {
+					res.AddWarnings(pathStrippedParamGarbledMsg(pathToAdd))
+				}
+
+				// Check uniqueness of stripped paths
+				if _, found := methodPaths[method][pathToAdd]; found {
+
+					// Sort names for stable, testable output
+					if strings.Compare(path, methodPaths[method][pathToAdd]) < 0 {
+						res.AddErrors(pathOverlapMsg(path, methodPaths[method][pathToAdd]))
+					} else {
+						res.AddErrors(pathOverlapMsg(methodPaths[method][pathToAdd], path))
+					}
+				} else {
+					if _, found := methodPaths[method]; !found {
+						methodPaths[method] = map[string]string{}
+					}
+					methodPaths[method][pathToAdd] = path //Original non stripped path
+
+				}
+
+				var bodyParams []string
+				var paramNames []string
+				var hasForm, hasBody bool
+
+				// Check parameters names uniqueness for operation
+				// TODO: should be done after param expansion
+				res.Merge(s.checkUniqueParams(path, method, op))
+
+				for _, pr := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) {
+					// Validate pattern regexp for parameters with a Pattern property
+					if _, err := compileRegexp(pr.Pattern); err != nil {
+						res.AddErrors(invalidPatternInParamMsg(op.ID, pr.Name, pr.Pattern))
+					}
+
+					// There must be at most one parameter in body: list them all
+					if pr.In == "body" {
+						bodyParams = append(bodyParams, fmt.Sprintf("%q", pr.Name))
+						hasBody = true
+					}
+
+					if pr.In == "path" {
+						paramNames = append(paramNames, pr.Name)
+						// Path declared in path must have the required: true property
+						if !pr.Required {
+							res.AddErrors(pathParamRequiredMsg(op.ID, pr.Name))
+						}
+					}
+
+					if pr.In == "formData" {
+						hasForm = true
+					}
+				}
+
+				// In:formData and In:body are mutually exclusive
+				if hasBody && hasForm {
+					res.AddErrors(bothFormDataAndBodyMsg(op.ID))
+				}
+				// There must be at most one body param
+				// Accurately report situations when more than 1 body param is declared (possibly unnamed)
+				if len(bodyParams) > 1 {
+					sort.Strings(bodyParams)
+					res.AddErrors(multipleBodyParamMsg(op.ID, bodyParams))
+				}
+
+				// Check uniqueness of parameters in path
+				paramsInPath := pathHelp.extractPathParams(path)
+				for i, p := range paramsInPath {
+					for j, q := range paramsInPath {
+						if p == q && i > j {
+							res.AddErrors(pathParamNotUniqueMsg(path, p, q))
+							break
+						}
+					}
+				}
+
+				// Warns about possible malformed params in path
+				rexGarbledParam := mustCompileRegexp(`{.*[{}\s]+.*}`)
+				for _, p := range paramsInPath {
+					if rexGarbledParam.MatchString(p) {
+						res.AddWarnings(pathParamGarbledMsg(path, p))
+					}
+				}
+
+				// Match params from path vs params from params section
+				res.Merge(s.validatePathParamPresence(path, paramsInPath, paramNames))
+			}
+		}
+	}
+	return res
+}
+
+func (s *SpecValidator) validateReferencesValid() *Result {
+	// each reference must point to a valid object
+	res := new(Result)
+	for _, r := range s.analyzer.AllRefs() {
+		if !r.IsValidURI(s.spec.SpecFilePath()) { // Safeguard - spec should always yield a valid URI
+			res.AddErrors(invalidRefMsg(r.String()))
+		}
+	}
+	if !res.HasErrors() {
+		// NOTE: with default settings, loads.Document.Expanded()
+		// stops on first error. Anyhow, the expand option to continue
+		// on errors fails to report errors at all.
+		exp, err := s.spec.Expanded()
+		if err != nil {
+			res.AddErrors(unresolvedReferencesMsg(err))
+		}
+		s.expanded = exp
+	}
+	return res
+}
+
+func (s *SpecValidator) checkUniqueParams(path, method string, op *spec.Operation) *Result {
+	// Check for duplicate parameters declaration in param section.
+	// Each parameter should have a unique `name` and `type` combination
+	// NOTE: this could be factorized in analysis (when constructing the params map)
+	// However, there are some issues with such a factorization:
+	// - analysis does not seem to fully expand params
+	// - param keys may be altered by x-go-name
+	res := new(Result)
+	pnames := make(map[string]struct{})
+
+	if op.Parameters != nil { // Safeguard
+		for _, ppr := range op.Parameters {
+			var ok bool
+			pr, red := paramHelp.resolveParam(path, method, op.ID, &ppr, s)
+			res.Merge(red)
+
+			if pr != nil && pr.Name != "" { // params with empty name does no participate the check
+				key := fmt.Sprintf("%s#%s", pr.In, pr.Name)
+
+				if _, ok = pnames[key]; ok {
+					res.AddErrors(duplicateParamNameMsg(pr.In, pr.Name, op.ID))
+				}
+				pnames[key] = struct{}{}
+			}
+		}
+	}
+	return res
+}
+
+// SetContinueOnErrors sets the ContinueOnErrors option for this validator.
+func (s *SpecValidator) SetContinueOnErrors(c bool) {
+	s.Options.ContinueOnErrors = c
+}
diff --git a/go/vendor/github.com/go-openapi/validate/spec_messages.go b/go/vendor/github.com/go-openapi/validate/spec_messages.go
new file mode 100644
index 0000000..441bb51
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/spec_messages.go
@@ -0,0 +1,354 @@
+// 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 (
+	"net/http"
+
+	"github.com/go-openapi/errors"
+)
+
+// Error messages related to spec validation and returned as results.
+const (
+	// ArrayRequiresItemsError ...
+	ArrayRequiresItemsError = "%s for %q is a collection without an element type (array requires items definition)"
+
+	// ArrayInParamRequiresItemsError ...
+	ArrayInParamRequiresItemsError = "param %q for %q is a collection without an element type (array requires item definition)"
+
+	// ArrayInHeaderRequiresItemsError ...
+	ArrayInHeaderRequiresItemsError = "header %q for %q is a collection without an element type (array requires items definition)"
+
+	// BothFormDataAndBodyError indicates that an operation specifies both a body and a formData parameter, which is forbidden
+	BothFormDataAndBodyError = "operation %q has both formData and body parameters. Only one such In: type may be used for a given operation"
+
+	// CannotResolveRefError when a $ref could not be resolved
+	CannotResolveReferenceError = "could not resolve reference in %s to $ref %s: %v"
+
+	// CircularAncestryDefinitionError ...
+	CircularAncestryDefinitionError = "definition %q has circular ancestry: %v"
+
+	// DefaultValueDoesNotValidateError results from an invalid default value provided
+	DefaultValueDoesNotValidateError = "default value for %s in %s does not validate its schema"
+
+	// DefaultValueItemsDoesNotValidateError results from an invalid default value provided for Items
+	DefaultValueItemsDoesNotValidateError = "default value for %s.items in %s does not validate its schema"
+
+	// DefaultValueHeaderDoesNotValidateError results from an invalid default value provided in header
+	DefaultValueHeaderDoesNotValidateError = "in operation %q, default value in header %s for %s does not validate its schema"
+
+	// DefaultValueHeaderItemsDoesNotValidateError results from an invalid default value provided in header.items
+	DefaultValueHeaderItemsDoesNotValidateError = "in operation %q, default value in header.items %s for %s does not validate its schema"
+
+	// DefaultValueInDoesNotValidateError ...
+	DefaultValueInDoesNotValidateError = "in operation %q, default value in %s does not validate its schema"
+
+	// DuplicateParamNameError ...
+	DuplicateParamNameError = "duplicate parameter name %q for %q in operation %q"
+
+	// DuplicatePropertiesError ...
+	DuplicatePropertiesError = "definition %q contains duplicate properties: %v"
+
+	// ExampleValueDoesNotValidateError results from an invalid example value provided
+	ExampleValueDoesNotValidateError = "example value for %s in %s does not validate its schema"
+
+	// ExampleValueItemsDoesNotValidateError results from an invalid example value provided for Items
+	ExampleValueItemsDoesNotValidateError = "example value for %s.items in %s does not validate its schema"
+
+	// ExampleValueHeaderDoesNotValidateError results from an invalid example value provided in header
+	ExampleValueHeaderDoesNotValidateError = "in operation %q, example value in header %s for %s does not validate its schema"
+
+	// ExampleValueHeaderItemsDoesNotValidateError results from an invalid example value provided in header.items
+	ExampleValueHeaderItemsDoesNotValidateError = "in operation %q, example value in header.items %s for %s does not validate its schema"
+
+	// ExampleValueInDoesNotValidateError ...
+	ExampleValueInDoesNotValidateError = "in operation %q, example value in %s does not validate its schema"
+
+	// EmptyPathParameterError means that a path parameter was found empty (e.g. "{}")
+	EmptyPathParameterError = "%q contains an empty path parameter"
+
+	// InvalidDocumentError states that spec validation only processes spec.Document objects
+	InvalidDocumentError = "spec validator can only validate spec.Document objects"
+
+	// InvalidItemsPatternError indicates an Items definition with invalid pattern
+	InvalidItemsPatternError = "%s for %q has invalid items pattern: %q"
+
+	// InvalidParameterDefinitionError indicates an error detected on a parameter definition
+	InvalidParameterDefinitionError = "invalid definition for parameter %s in %s in operation %q"
+
+	// InvalidParameterDefinitionAsSchemaError indicates an error detected on a parameter definition, which was mistaken with a schema definition.
+	// Most likely, this situation is encountered whenever a $ref has been added as a sibling of the parameter definition.
+	InvalidParameterDefinitionAsSchemaError = "invalid definition as Schema for parameter %s in %s in operation %q"
+
+	// InvalidPatternError ...
+	InvalidPatternError = "pattern %q is invalid in %s"
+
+	// InvalidPatternInError indicates an invalid pattern in a schema or items definition
+	InvalidPatternInError = "%s in %s has invalid pattern: %q"
+
+	// InvalidPatternInHeaderError indicates a header definition with an invalid pattern
+	InvalidPatternInHeaderError = "in operation %q, header %s for %s has invalid pattern %q: %v"
+
+	// InvalidPatternInParamError ...
+	InvalidPatternInParamError = "operation %q has invalid pattern in param %q: %q"
+
+	// InvalidReferenceError indicates that a $ref property could not be resolved
+	InvalidReferenceError = "invalid ref %q"
+
+	// InvalidResponseDefinitionAsSchemaError indicates an error detected on a response definition, which was mistaken with a schema definition.
+	// Most likely, this situation is encountered whenever a $ref has been added as a sibling of the response definition.
+	InvalidResponseDefinitionAsSchemaError = "invalid definition as Schema for response %s in %s"
+
+	// MultipleBodyParamError indicates that an operation specifies multiple parameter with in: body
+	MultipleBodyParamError = "operation %q has more than 1 body param: %v"
+
+	// NonUniqueOperationIDError indicates that the same operationId has been specified several times
+	NonUniqueOperationIDError = "%q is defined %d times"
+
+	// NoParameterInPathError indicates that a path was found without any parameter
+	NoParameterInPathError = "path param %q has no parameter definition"
+
+	// NoValidPathErrorOrWarning indicates that no single path could be validated. If Paths is empty, this message is only a warning.
+	NoValidPathErrorOrWarning = "spec has no valid path defined"
+
+	// NoValidResponseError indicates that no valid response description could be found for an operation
+	NoValidResponseError = "operation %q has no valid response"
+
+	// PathOverlapError ...
+	PathOverlapError = "path %s overlaps with %s"
+
+	// PathParamNotInPathError indicates that a parameter specified with in: path was not found in the path specification
+	PathParamNotInPathError = "path param %q is not present in path %q"
+
+	// PathParamNotUniqueError ...
+	PathParamNotUniqueError = "params in path %q must be unique: %q conflicts with %q"
+
+	// PathParamNotRequiredError ...
+	PathParamRequiredError = "in operation %q,path param %q must be declared as required"
+
+	// RefNotAllowedInHeaderError indicates a $ref was found in a header definition, which is not allowed by Swagger
+	RefNotAllowedInHeaderError = "IMPORTANT!in %q: $ref are not allowed in headers. In context for header %q%s"
+
+	// RequiredButNotDefinedError ...
+	RequiredButNotDefinedError = "%q is present in required but not defined as property in definition %q"
+
+	// SomeParametersBrokenError indicates that some parameters could not be resolved, which might result in partial checks to be carried on
+	SomeParametersBrokenError = "some parameters definitions are broken in %q.%s. Cannot carry on full checks on parameters for operation %s"
+
+	// UnresolvedReferencesError indicates that at least one $ref could not be resolved
+	UnresolvedReferencesError = "some references could not be resolved in spec. First found: %v"
+)
+
+// Warning messages related to spec validation and returned as results
+const (
+	// ExamplesWithoutSchemaWarning indicates that examples are provided for a response,but not schema to validate the example against
+	ExamplesWithoutSchemaWarning = "Examples provided without schema in operation %q, %s"
+
+	// ExamplesMimeNotSupportedWarning indicates that examples are provided with a mime type different than application/json, which
+	// the validator dos not support yetl
+	ExamplesMimeNotSupportedWarning = "No validation attempt for examples for media types other than application/json, in operation %q, %s"
+
+	// PathParamGarbledWarning ...
+	PathParamGarbledWarning = "in path %q, param %q contains {,} or white space. Albeit not stricly illegal, this is probably no what you want"
+
+	// PathStrippedParamGarbledWarning ...
+	PathStrippedParamGarbledWarning = "path stripped from path parameters %s contains {,} or white space. This is probably no what you want."
+
+	// ReadOnlyAndRequiredWarning ...
+	ReadOnlyAndRequiredWarning = "Required property %s in %q should not be marked as both required and readOnly"
+
+	// RefShouldNotHaveSiblingsWarning indicates that a $ref was found with a sibling definition. This results in the $ref taking over its siblings,
+	// which is most likely not wanted.
+	RefShouldNotHaveSiblingsWarning = "$ref property should have no sibling in %q.%s"
+
+	// RequiredHasDefaultWarning indicates that a required parameter property should not have a default
+	RequiredHasDefaultWarning = "%s in %s has a default value and is required as parameter"
+
+	// UnusedDefinitionWarning ...
+	UnusedDefinitionWarning = "definition %q is not used anywhere"
+
+	// UnusedParamWarning ...
+	UnusedParamWarning = "parameter %q is not used anywhere"
+
+	// UnusedResponseWarning ...
+	UnusedResponseWarning = "response %q is not used anywhere"
+)
+
+// Additional error codes
+const (
+	// InternalErrorCode reports an internal technical error
+	InternalErrorCode = http.StatusInternalServerError
+	// NotFoundErrorCode indicates that a resource (e.g. a $ref) could not be found
+	NotFoundErrorCode = http.StatusNotFound
+)
+
+func invalidDocumentMsg() errors.Error {
+	return errors.New(InternalErrorCode, InvalidDocumentError)
+}
+func invalidRefMsg(path string) errors.Error {
+	return errors.New(NotFoundErrorCode, InvalidReferenceError, path)
+}
+func unresolvedReferencesMsg(err error) errors.Error {
+	return errors.New(errors.CompositeErrorCode, UnresolvedReferencesError, err)
+}
+func noValidPathMsg() errors.Error {
+	return errors.New(errors.CompositeErrorCode, NoValidPathErrorOrWarning)
+}
+func emptyPathParameterMsg(path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, EmptyPathParameterError, path)
+}
+func nonUniqueOperationIDMsg(path string, i int) errors.Error {
+	return errors.New(errors.CompositeErrorCode, NonUniqueOperationIDError, path, i)
+}
+func circularAncestryDefinitionMsg(path string, args interface{}) errors.Error {
+	return errors.New(errors.CompositeErrorCode, CircularAncestryDefinitionError, path, args)
+}
+func duplicatePropertiesMsg(path string, args interface{}) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DuplicatePropertiesError, path, args)
+}
+func pathParamNotInPathMsg(path, param string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathParamNotInPathError, param, path)
+}
+func arrayRequiresItemsMsg(path, operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ArrayRequiresItemsError, path, operation)
+}
+func arrayInParamRequiresItemsMsg(path, operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ArrayInParamRequiresItemsError, path, operation)
+}
+func arrayInHeaderRequiresItemsMsg(path, operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ArrayInHeaderRequiresItemsError, path, operation)
+}
+func invalidItemsPatternMsg(path, operation, pattern string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidItemsPatternError, path, operation, pattern)
+}
+func invalidPatternMsg(pattern, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidPatternError, pattern, path)
+}
+func requiredButNotDefinedMsg(path, definition string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, RequiredButNotDefinedError, path, definition)
+}
+func pathParamGarbledMsg(path, param string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathParamGarbledWarning, path, param)
+}
+func pathStrippedParamGarbledMsg(path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathStrippedParamGarbledWarning, path)
+}
+func pathOverlapMsg(path, arg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathOverlapError, path, arg)
+}
+func invalidPatternInParamMsg(operation, param, pattern string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidPatternInParamError, operation, param, pattern)
+}
+func pathParamRequiredMsg(operation, param string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathParamRequiredError, operation, param)
+}
+func bothFormDataAndBodyMsg(operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, BothFormDataAndBodyError, operation)
+}
+func multipleBodyParamMsg(operation string, args interface{}) errors.Error {
+	return errors.New(errors.CompositeErrorCode, MultipleBodyParamError, operation, args)
+}
+func pathParamNotUniqueMsg(path, param, arg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, PathParamNotUniqueError, path, param, arg)
+}
+func duplicateParamNameMsg(path, param, operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DuplicateParamNameError, param, path, operation)
+}
+func unusedParamMsg(arg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, UnusedParamWarning, arg)
+}
+func unusedDefinitionMsg(arg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, UnusedDefinitionWarning, arg)
+}
+func unusedResponseMsg(arg string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, UnusedResponseWarning, arg)
+}
+func readOnlyAndRequiredMsg(path, param string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ReadOnlyAndRequiredWarning, param, path)
+}
+func noParameterInPathMsg(param string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, NoParameterInPathError, param)
+}
+func requiredHasDefaultMsg(param, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, RequiredHasDefaultWarning, param, path)
+}
+func defaultValueDoesNotValidateMsg(param, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DefaultValueDoesNotValidateError, param, path)
+}
+func defaultValueItemsDoesNotValidateMsg(param, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DefaultValueItemsDoesNotValidateError, param, path)
+}
+func noValidResponseMsg(operation string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, NoValidResponseError, operation)
+}
+func defaultValueHeaderDoesNotValidateMsg(operation, header, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DefaultValueHeaderDoesNotValidateError, operation, header, path)
+}
+func defaultValueHeaderItemsDoesNotValidateMsg(operation, header, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DefaultValueHeaderItemsDoesNotValidateError, operation, header, path)
+}
+func invalidPatternInHeaderMsg(operation, header, path, pattern string, args interface{}) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidPatternInHeaderError, operation, header, path, pattern, args)
+}
+func invalidPatternInMsg(path, in, pattern string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidPatternInError, path, in, pattern)
+}
+func defaultValueInDoesNotValidateMsg(operation, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, DefaultValueInDoesNotValidateError, operation, path)
+}
+func exampleValueDoesNotValidateMsg(param, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExampleValueDoesNotValidateError, param, path)
+}
+func exampleValueItemsDoesNotValidateMsg(param, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExampleValueItemsDoesNotValidateError, param, path)
+}
+func exampleValueHeaderDoesNotValidateMsg(operation, header, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExampleValueHeaderDoesNotValidateError, operation, header, path)
+}
+func exampleValueHeaderItemsDoesNotValidateMsg(operation, header, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExampleValueHeaderItemsDoesNotValidateError, operation, header, path)
+}
+func exampleValueInDoesNotValidateMsg(operation, path string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExampleValueInDoesNotValidateError, operation, path)
+}
+func examplesWithoutSchemaMsg(operation, response string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExamplesWithoutSchemaWarning, operation, response)
+}
+func examplesMimeNotSupportedMsg(operation, response string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, ExamplesMimeNotSupportedWarning, operation, response)
+}
+func refNotAllowedInHeaderMsg(path, header, ref string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, RefNotAllowedInHeaderError, path, header, ref)
+}
+func cannotResolveRefMsg(path, ref string, err error) errors.Error {
+	return errors.New(errors.CompositeErrorCode, CannotResolveReferenceError, path, ref, err)
+}
+func invalidParameterDefinitionMsg(path, method, operationID string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidParameterDefinitionError, path, method, operationID)
+}
+func invalidParameterDefinitionAsSchemaMsg(path, method, operationID string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, InvalidParameterDefinitionAsSchemaError, path, method, operationID)
+}
+
+// disabled
+//func invalidResponseDefinitionAsSchemaMsg(path, method string) errors.Error {
+//	return errors.New(errors.CompositeErrorCode, InvalidResponseDefinitionAsSchemaError, path, method)
+//}
+func someParametersBrokenMsg(path, method, operationID string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, SomeParametersBrokenError, path, method, operationID)
+}
+func refShouldNotHaveSiblingsMsg(path, operationID string) errors.Error {
+	return errors.New(errors.CompositeErrorCode, RefShouldNotHaveSiblingsWarning, operationID, path)
+}
diff --git a/go/vendor/github.com/go-openapi/validate/type.go b/go/vendor/github.com/go-openapi/validate/type.go
new file mode 100644
index 0000000..72c81a9
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/type.go
@@ -0,0 +1,177 @@
+// 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"
+	"strings"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/runtime"
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+	"github.com/go-openapi/swag"
+)
+
+type typeValidator struct {
+	Type   spec.StringOrArray
+	Format string
+	In     string
+	Path   string
+}
+
+func (t *typeValidator) schemaInfoForType(data interface{}) (string, string) {
+	// internal type to JSON type with swagger 2.0 format (with go-openapi/strfmt extensions),
+	// see https://github.com/go-openapi/strfmt/blob/master/README.md
+	// TODO: this switch really is some sort of reverse lookup for formats. It should be provided by strfmt.
+	switch data.(type) {
+	case []byte, strfmt.Base64, *strfmt.Base64:
+		return "string", "byte"
+	case strfmt.CreditCard, *strfmt.CreditCard:
+		return "string", "creditcard"
+	case strfmt.Date, *strfmt.Date:
+		return "string", "date"
+	case strfmt.DateTime, *strfmt.DateTime:
+		return "string", "date-time"
+	case strfmt.Duration, *strfmt.Duration:
+		return "string", "duration"
+	case runtime.File, *runtime.File:
+		return "file", ""
+	case strfmt.Email, *strfmt.Email:
+		return "string", "email"
+	case strfmt.HexColor, *strfmt.HexColor:
+		return "string", "hexcolor"
+	case strfmt.Hostname, *strfmt.Hostname:
+		return "string", "hostname"
+	case strfmt.IPv4, *strfmt.IPv4:
+		return "string", "ipv4"
+	case strfmt.IPv6, *strfmt.IPv6:
+		return "string", "ipv6"
+	case strfmt.ISBN, *strfmt.ISBN:
+		return "string", "isbn"
+	case strfmt.ISBN10, *strfmt.ISBN10:
+		return "string", "isbn10"
+	case strfmt.ISBN13, *strfmt.ISBN13:
+		return "string", "isbn13"
+	case strfmt.MAC, *strfmt.MAC:
+		return "string", "mac"
+	case strfmt.ObjectId, *strfmt.ObjectId:
+		return "string", "bsonobjectid"
+	case strfmt.Password, *strfmt.Password:
+		return "string", "password"
+	case strfmt.RGBColor, *strfmt.RGBColor:
+		return "string", "rgbcolor"
+	case strfmt.SSN, *strfmt.SSN:
+		return "string", "ssn"
+	case strfmt.URI, *strfmt.URI:
+		return "string", "uri"
+	case strfmt.UUID, *strfmt.UUID:
+		return "string", "uuid"
+	case strfmt.UUID3, *strfmt.UUID3:
+		return "string", "uuid3"
+	case strfmt.UUID4, *strfmt.UUID4:
+		return "string", "uuid4"
+	case strfmt.UUID5, *strfmt.UUID5:
+		return "string", "uuid5"
+	// TODO: missing binary (io.ReadCloser)
+	// TODO: missing json.Number
+	default:
+		val := reflect.ValueOf(data)
+		tpe := val.Type()
+		switch tpe.Kind() {
+		case reflect.Bool:
+			return "boolean", ""
+		case reflect.String:
+			return "string", ""
+		case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
+			// NOTE: that is the spec. With go-openapi, is that not uint32 for unsigned integers?
+			return "integer", "int32"
+		case reflect.Int, reflect.Int64, reflect.Uint, reflect.Uint64:
+			return "integer", "int64"
+		case reflect.Float32:
+			// NOTE: is that not "float"?
+			return "number", "float32"
+		case reflect.Float64:
+			// NOTE: is that not "double"?
+			return "number", "float64"
+		// NOTE: go arrays (reflect.Array) are not supported (fixed length)
+		case reflect.Slice:
+			return "array", ""
+		case reflect.Map, reflect.Struct:
+			return "object", ""
+		case reflect.Interface:
+			// What to do here?
+			panic("dunno what to do here")
+		case reflect.Ptr:
+			return t.schemaInfoForType(reflect.Indirect(val).Interface())
+		}
+	}
+	return "", ""
+}
+
+func (t *typeValidator) SetPath(path string) {
+	t.Path = path
+}
+
+func (t *typeValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	// typeValidator applies to Schema, Parameter and Header objects
+	stpe := reflect.TypeOf(source)
+	r := (len(t.Type) > 0 || t.Format != "") && (stpe == specSchemaType || stpe == specParameterType || stpe == specHeaderType)
+	debugLog("type validator for %q applies %t for %T (kind: %v)\n", t.Path, r, source, kind)
+	return r
+}
+
+func (t *typeValidator) Validate(data interface{}) *Result {
+	result := new(Result)
+	result.Inc()
+	if data == nil || reflect.DeepEqual(reflect.Zero(reflect.TypeOf(data)), reflect.ValueOf(data)) {
+		// nil or zero value for the passed structure require Type: null
+		if len(t.Type) > 0 && !t.Type.Contains("null") { // TODO: if a property is not required it also passes this
+			return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), "null"))
+		}
+		return result
+	}
+
+	// check if the type matches, should be used in every validator chain as first item
+	val := reflect.Indirect(reflect.ValueOf(data))
+	kind := val.Kind()
+
+	// infer schema type (JSON) and format from passed data type
+	schType, format := t.schemaInfoForType(data)
+
+	debugLog("path: %s, schType: %s,  format: %s, expType: %s, expFmt: %s, kind: %s", t.Path, schType, format, t.Type, t.Format, val.Kind().String())
+
+	// check numerical types
+	// TODO: check unsigned ints
+	// TODO: check json.Number (see schema.go)
+	isLowerInt := t.Format == "int64" && format == "int32"
+	isLowerFloat := t.Format == "float64" && format == "float32"
+	isFloatInt := schType == "number" && swag.IsFloat64AJSONInteger(val.Float()) && t.Type.Contains("integer")
+	isIntFloat := schType == "integer" && t.Type.Contains("number")
+
+	if kind != reflect.String && kind != reflect.Slice && t.Format != "" && !(t.Type.Contains(schType) || format == t.Format || isFloatInt || isIntFloat || isLowerInt || isLowerFloat) {
+		// TODO: test case
+		return errorHelp.sErr(errors.InvalidType(t.Path, t.In, t.Format, format))
+	}
+
+	if !(t.Type.Contains("number") || t.Type.Contains("integer")) && t.Format != "" && (kind == reflect.String || kind == reflect.Slice) {
+		return result
+	}
+
+	if !(t.Type.Contains(schType) || isFloatInt || isIntFloat) {
+		return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), schType))
+	}
+	return result
+}
diff --git a/go/vendor/github.com/go-openapi/validate/update-fixtures.sh b/go/vendor/github.com/go-openapi/validate/update-fixtures.sh
new file mode 100755
index 0000000..21b06e2
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/update-fixtures.sh
@@ -0,0 +1,15 @@
+#!/bin/bash 
+
+set -eu -o pipefail
+dir=$(git rev-parse --show-toplevel)
+scratch=$(mktemp -d -t tmp.XXXXXXXXXX)
+
+function finish {
+  rm -rf "$scratch"
+}
+trap finish EXIT SIGHUP SIGINT SIGTERM
+
+cd "$scratch"
+git clone https://github.com/json-schema-org/JSON-Schema-Test-Suite Suite
+cp -r Suite/tests/draft4/* "$dir/fixtures/jsonschema_suite"
+cp -a Suite/remotes "$dir/fixtures/jsonschema_suite"
diff --git a/go/vendor/github.com/go-openapi/validate/validator.go b/go/vendor/github.com/go-openapi/validate/validator.go
new file mode 100644
index 0000000..98c9f54
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/validator.go
@@ -0,0 +1,638 @@
+// 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 (
+	"fmt"
+	"reflect"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/spec"
+	"github.com/go-openapi/strfmt"
+)
+
+// An EntityValidator is an interface for things that can validate entities
+type EntityValidator interface {
+	Validate(interface{}) *Result
+}
+
+type valueValidator interface {
+	SetPath(path string)
+	Applies(interface{}, reflect.Kind) bool
+	Validate(interface{}) *Result
+}
+
+type itemsValidator struct {
+	items        *spec.Items
+	root         interface{}
+	path         string
+	in           string
+	validators   []valueValidator
+	KnownFormats strfmt.Registry
+}
+
+func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry) *itemsValidator {
+	iv := &itemsValidator{path: path, in: in, items: items, root: root, KnownFormats: formats}
+	iv.validators = []valueValidator{
+		&typeValidator{
+			Type:   spec.StringOrArray([]string{items.Type}),
+			Format: items.Format,
+			In:     in,
+			Path:   path,
+		},
+		iv.stringValidator(),
+		iv.formatValidator(),
+		iv.numberValidator(),
+		iv.sliceValidator(),
+		iv.commonValidator(),
+	}
+	return iv
+}
+
+func (i *itemsValidator) Validate(index int, data interface{}) *Result {
+	tpe := reflect.TypeOf(data)
+	kind := tpe.Kind()
+	mainResult := new(Result)
+	path := fmt.Sprintf("%s.%d", i.path, index)
+
+	for _, validator := range i.validators {
+		validator.SetPath(path)
+		if validator.Applies(i.root, kind) {
+			result := validator.Validate(data)
+			mainResult.Merge(result)
+			mainResult.Inc()
+			if result != nil && result.HasErrors() {
+				return mainResult
+			}
+		}
+	}
+	return mainResult
+}
+
+func (i *itemsValidator) commonValidator() valueValidator {
+	return &basicCommonValidator{
+		In:      i.in,
+		Default: i.items.Default,
+		Enum:    i.items.Enum,
+	}
+}
+
+func (i *itemsValidator) sliceValidator() valueValidator {
+	return &basicSliceValidator{
+		In:           i.in,
+		Default:      i.items.Default,
+		MaxItems:     i.items.MaxItems,
+		MinItems:     i.items.MinItems,
+		UniqueItems:  i.items.UniqueItems,
+		Source:       i.root,
+		Items:        i.items.Items,
+		KnownFormats: i.KnownFormats,
+	}
+}
+
+func (i *itemsValidator) numberValidator() valueValidator {
+	return &numberValidator{
+		In:               i.in,
+		Default:          i.items.Default,
+		MultipleOf:       i.items.MultipleOf,
+		Maximum:          i.items.Maximum,
+		ExclusiveMaximum: i.items.ExclusiveMaximum,
+		Minimum:          i.items.Minimum,
+		ExclusiveMinimum: i.items.ExclusiveMinimum,
+		Type:             i.items.Type,
+		Format:           i.items.Format,
+	}
+}
+
+func (i *itemsValidator) stringValidator() valueValidator {
+	return &stringValidator{
+		In:              i.in,
+		Default:         i.items.Default,
+		MaxLength:       i.items.MaxLength,
+		MinLength:       i.items.MinLength,
+		Pattern:         i.items.Pattern,
+		AllowEmptyValue: false,
+	}
+}
+
+func (i *itemsValidator) formatValidator() valueValidator {
+	return &formatValidator{
+		In: i.in,
+		//Default:      i.items.Default,
+		Format:       i.items.Format,
+		KnownFormats: i.KnownFormats,
+	}
+}
+
+type basicCommonValidator struct {
+	Path    string
+	In      string
+	Default interface{}
+	Enum    []interface{}
+}
+
+func (b *basicCommonValidator) SetPath(path string) {
+	b.Path = path
+}
+
+func (b *basicCommonValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	switch source.(type) {
+	case *spec.Parameter, *spec.Schema, *spec.Header:
+		return true
+	}
+	return false
+}
+
+func (b *basicCommonValidator) Validate(data interface{}) (res *Result) {
+	if len(b.Enum) > 0 {
+		for _, enumValue := range b.Enum {
+			actualType := reflect.TypeOf(enumValue)
+			if actualType != nil { // Safeguard
+				expectedValue := reflect.ValueOf(data)
+				if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+					if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
+						return nil
+					}
+				}
+			}
+		}
+		return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum))
+	}
+	return nil
+}
+
+// A HeaderValidator has very limited subset of validations to apply
+type HeaderValidator struct {
+	name         string
+	header       *spec.Header
+	validators   []valueValidator
+	KnownFormats strfmt.Registry
+}
+
+// NewHeaderValidator creates a new header validator object
+func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry) *HeaderValidator {
+	p := &HeaderValidator{name: name, header: header, KnownFormats: formats}
+	p.validators = []valueValidator{
+		&typeValidator{
+			Type:   spec.StringOrArray([]string{header.Type}),
+			Format: header.Format,
+			In:     "header",
+			Path:   name,
+		},
+		p.stringValidator(),
+		p.formatValidator(),
+		p.numberValidator(),
+		p.sliceValidator(),
+		p.commonValidator(),
+	}
+	return p
+}
+
+// Validate the value of the header against its schema
+func (p *HeaderValidator) Validate(data interface{}) *Result {
+	result := new(Result)
+	tpe := reflect.TypeOf(data)
+	kind := tpe.Kind()
+
+	for _, validator := range p.validators {
+		if validator.Applies(p.header, kind) {
+			if err := validator.Validate(data); err != nil {
+				result.Merge(err)
+				if err.HasErrors() {
+					return result
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func (p *HeaderValidator) commonValidator() valueValidator {
+	return &basicCommonValidator{
+		Path:    p.name,
+		In:      "response",
+		Default: p.header.Default,
+		Enum:    p.header.Enum,
+	}
+}
+
+func (p *HeaderValidator) sliceValidator() valueValidator {
+	return &basicSliceValidator{
+		Path:         p.name,
+		In:           "response",
+		Default:      p.header.Default,
+		MaxItems:     p.header.MaxItems,
+		MinItems:     p.header.MinItems,
+		UniqueItems:  p.header.UniqueItems,
+		Items:        p.header.Items,
+		Source:       p.header,
+		KnownFormats: p.KnownFormats,
+	}
+}
+
+func (p *HeaderValidator) numberValidator() valueValidator {
+	return &numberValidator{
+		Path:             p.name,
+		In:               "response",
+		Default:          p.header.Default,
+		MultipleOf:       p.header.MultipleOf,
+		Maximum:          p.header.Maximum,
+		ExclusiveMaximum: p.header.ExclusiveMaximum,
+		Minimum:          p.header.Minimum,
+		ExclusiveMinimum: p.header.ExclusiveMinimum,
+		Type:             p.header.Type,
+		Format:           p.header.Format,
+	}
+}
+
+func (p *HeaderValidator) stringValidator() valueValidator {
+	return &stringValidator{
+		Path:            p.name,
+		In:              "response",
+		Default:         p.header.Default,
+		Required:        true,
+		MaxLength:       p.header.MaxLength,
+		MinLength:       p.header.MinLength,
+		Pattern:         p.header.Pattern,
+		AllowEmptyValue: false,
+	}
+}
+
+func (p *HeaderValidator) formatValidator() valueValidator {
+	return &formatValidator{
+		Path: p.name,
+		In:   "response",
+		//Default:      p.header.Default,
+		Format:       p.header.Format,
+		KnownFormats: p.KnownFormats,
+	}
+}
+
+// A ParamValidator has very limited subset of validations to apply
+type ParamValidator struct {
+	param        *spec.Parameter
+	validators   []valueValidator
+	KnownFormats strfmt.Registry
+}
+
+// NewParamValidator creates a new param validator object
+func NewParamValidator(param *spec.Parameter, formats strfmt.Registry) *ParamValidator {
+	p := &ParamValidator{param: param, KnownFormats: formats}
+	p.validators = []valueValidator{
+		&typeValidator{
+			Type:   spec.StringOrArray([]string{param.Type}),
+			Format: param.Format,
+			In:     param.In,
+			Path:   param.Name,
+		},
+		p.stringValidator(),
+		p.formatValidator(),
+		p.numberValidator(),
+		p.sliceValidator(),
+		p.commonValidator(),
+	}
+	return p
+}
+
+// Validate the data against the description of the parameter
+func (p *ParamValidator) Validate(data interface{}) *Result {
+	result := new(Result)
+	tpe := reflect.TypeOf(data)
+	kind := tpe.Kind()
+
+	// TODO: validate type
+	for _, validator := range p.validators {
+		if validator.Applies(p.param, kind) {
+			if err := validator.Validate(data); err != nil {
+				result.Merge(err)
+				if err.HasErrors() {
+					return result
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func (p *ParamValidator) commonValidator() valueValidator {
+	return &basicCommonValidator{
+		Path:    p.param.Name,
+		In:      p.param.In,
+		Default: p.param.Default,
+		Enum:    p.param.Enum,
+	}
+}
+
+func (p *ParamValidator) sliceValidator() valueValidator {
+	return &basicSliceValidator{
+		Path:         p.param.Name,
+		In:           p.param.In,
+		Default:      p.param.Default,
+		MaxItems:     p.param.MaxItems,
+		MinItems:     p.param.MinItems,
+		UniqueItems:  p.param.UniqueItems,
+		Items:        p.param.Items,
+		Source:       p.param,
+		KnownFormats: p.KnownFormats,
+	}
+}
+
+func (p *ParamValidator) numberValidator() valueValidator {
+	return &numberValidator{
+		Path:             p.param.Name,
+		In:               p.param.In,
+		Default:          p.param.Default,
+		MultipleOf:       p.param.MultipleOf,
+		Maximum:          p.param.Maximum,
+		ExclusiveMaximum: p.param.ExclusiveMaximum,
+		Minimum:          p.param.Minimum,
+		ExclusiveMinimum: p.param.ExclusiveMinimum,
+		Type:             p.param.Type,
+		Format:           p.param.Format,
+	}
+}
+
+func (p *ParamValidator) stringValidator() valueValidator {
+	return &stringValidator{
+		Path:            p.param.Name,
+		In:              p.param.In,
+		Default:         p.param.Default,
+		AllowEmptyValue: p.param.AllowEmptyValue,
+		Required:        p.param.Required,
+		MaxLength:       p.param.MaxLength,
+		MinLength:       p.param.MinLength,
+		Pattern:         p.param.Pattern,
+	}
+}
+
+func (p *ParamValidator) formatValidator() valueValidator {
+	return &formatValidator{
+		Path: p.param.Name,
+		In:   p.param.In,
+		//Default:      p.param.Default,
+		Format:       p.param.Format,
+		KnownFormats: p.KnownFormats,
+	}
+}
+
+type basicSliceValidator struct {
+	Path           string
+	In             string
+	Default        interface{}
+	MaxItems       *int64
+	MinItems       *int64
+	UniqueItems    bool
+	Items          *spec.Items
+	Source         interface{}
+	itemsValidator *itemsValidator
+	KnownFormats   strfmt.Registry
+}
+
+func (s *basicSliceValidator) SetPath(path string) {
+	s.Path = path
+}
+
+func (s *basicSliceValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	switch source.(type) {
+	case *spec.Parameter, *spec.Items, *spec.Header:
+		return kind == reflect.Slice
+	}
+	return false
+}
+
+func (s *basicSliceValidator) Validate(data interface{}) *Result {
+	val := reflect.ValueOf(data)
+
+	size := int64(val.Len())
+	if s.MinItems != nil {
+		if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.MaxItems != nil {
+		if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.UniqueItems {
+		if err := UniqueItems(s.Path, s.In, data); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.itemsValidator == nil && s.Items != nil {
+		s.itemsValidator = newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats)
+	}
+
+	if s.itemsValidator != nil {
+		for i := 0; i < int(size); i++ {
+			ele := val.Index(i)
+			if err := s.itemsValidator.Validate(i, ele.Interface()); err != nil && err.HasErrors() {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func (s *basicSliceValidator) hasDuplicates(value reflect.Value, size int) bool {
+	dict := make(map[interface{}]struct{})
+	for i := 0; i < size; i++ {
+		ele := value.Index(i)
+		if _, ok := dict[ele.Interface()]; ok {
+			return true
+		}
+		dict[ele.Interface()] = struct{}{}
+	}
+	return false
+}
+
+type numberValidator struct {
+	Path             string
+	In               string
+	Default          interface{}
+	MultipleOf       *float64
+	Maximum          *float64
+	ExclusiveMaximum bool
+	Minimum          *float64
+	ExclusiveMinimum bool
+	// Allows for more accurate behavior regarding integers
+	Type   string
+	Format string
+}
+
+func (n *numberValidator) SetPath(path string) {
+	n.Path = path
+}
+
+func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	switch source.(type) {
+	case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
+		isInt := kind >= reflect.Int && kind <= reflect.Uint64
+		isFloat := kind == reflect.Float32 || kind == reflect.Float64
+		r := isInt || isFloat
+		debugLog("schema props validator for %q applies %t for %T (kind: %v) isInt=%t, isFloat=%t\n", n.Path, r, source, kind, isInt, isFloat)
+		return r
+	}
+	debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", n.Path, false, source, kind)
+	return false
+}
+
+// Validate provides a validator for generic JSON numbers,
+//
+// By default, numbers are internally represented as float64.
+// Formats float, or float32 may alter this behavior by mapping to float32.
+// A special validation process is followed for integers, with optional "format":
+// this is an attempt to provide a validation with native types.
+//
+// NOTE: since the constraint specified (boundary, multipleOf) is unmarshalled
+// as float64, loss of information remains possible (e.g. on very large integers).
+//
+// Since this value directly comes from the unmarshalling, it is not possible
+// at this stage of processing to check further and guarantee the correctness of such values.
+//
+// Normally, the JSON Number.MAX_SAFE_INTEGER (resp. Number.MIN_SAFE_INTEGER)
+// would check we do not get such a loss.
+//
+// If this is the case, replace AddErrors() by AddWarnings() and IsValid() by !HasWarnings().
+//
+// TODO: consider replacing boundary check errors by simple warnings.
+//
+// TODO: default boundaries with MAX_SAFE_INTEGER are not checked (specific to json.Number?)
+func (n *numberValidator) Validate(val interface{}) *Result {
+	res := new(Result)
+
+	resMultiple := new(Result)
+	resMinimum := new(Result)
+	resMaximum := new(Result)
+
+	// Used only to attempt to validate constraint on value,
+	// even though value or constraint specified do not match type and format
+	data := valueHelp.asFloat64(val)
+
+	// Is the provided value within the range of the specified numeric type and format?
+	res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
+
+	if n.MultipleOf != nil {
+		// Is the constraint specifier within the range of the specific numeric type and format?
+		resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
+		if resMultiple.IsValid() {
+			// Constraint validated with compatible types
+			if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
+				resMultiple.Merge(errorHelp.sErr(err))
+			}
+		} else {
+			// Constraint nevertheless validated, converted as general number
+			if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
+				resMultiple.Merge(errorHelp.sErr(err))
+			}
+		}
+	}
+
+	if n.Maximum != nil {
+		// Is the constraint specifier within the range of the specific numeric type and format?
+		resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
+		if resMaximum.IsValid() {
+			// Constraint validated with compatible types
+			if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
+				resMaximum.Merge(errorHelp.sErr(err))
+			}
+		} else {
+			// Constraint nevertheless validated, converted as general number
+			if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
+				resMaximum.Merge(errorHelp.sErr(err))
+			}
+		}
+	}
+
+	if n.Minimum != nil {
+		// Is the constraint specifier within the range of the specific numeric type and format?
+		resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
+		if resMinimum.IsValid() {
+			// Constraint validated with compatible types
+			if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
+				resMinimum.Merge(errorHelp.sErr(err))
+			}
+		} else {
+			// Constraint nevertheless validated, converted as general number
+			if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
+				resMinimum.Merge(errorHelp.sErr(err))
+			}
+		}
+	}
+	res.Merge(resMultiple, resMinimum, resMaximum)
+	res.Inc()
+	return res
+}
+
+type stringValidator struct {
+	Default         interface{}
+	Required        bool
+	AllowEmptyValue bool
+	MaxLength       *int64
+	MinLength       *int64
+	Pattern         string
+	Path            string
+	In              string
+}
+
+func (s *stringValidator) SetPath(path string) {
+	s.Path = path
+}
+
+func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool {
+	switch source.(type) {
+	case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header:
+		r := kind == reflect.String
+		debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind)
+		return r
+	}
+	debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, false, source, kind)
+	return false
+}
+
+func (s *stringValidator) Validate(val interface{}) *Result {
+	data, ok := val.(string)
+	if !ok {
+		return errorHelp.sErr(errors.InvalidType(s.Path, s.In, "string", val))
+	}
+
+	if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") {
+		if err := RequiredString(s.Path, s.In, data); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.MaxLength != nil {
+		if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.MinLength != nil {
+		if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+
+	if s.Pattern != "" {
+		if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
+			return errorHelp.sErr(err)
+		}
+	}
+	return nil
+}
diff --git a/go/vendor/github.com/go-openapi/validate/values.go b/go/vendor/github.com/go-openapi/validate/values.go
new file mode 100644
index 0000000..24606da
--- /dev/null
+++ b/go/vendor/github.com/go-openapi/validate/values.go
@@ -0,0 +1,398 @@
+// 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 (
+	"fmt"
+	"reflect"
+	"unicode/utf8"
+
+	"github.com/go-openapi/errors"
+	"github.com/go-openapi/strfmt"
+	"github.com/go-openapi/swag"
+)
+
+// Enum validates if the data is a member of the enum
+func Enum(path, in string, data interface{}, enum interface{}) *errors.Validation {
+	val := reflect.ValueOf(enum)
+	if val.Kind() != reflect.Slice {
+		return nil
+	}
+
+	var values []interface{}
+	for i := 0; i < val.Len(); i++ {
+		ele := val.Index(i)
+		enumValue := ele.Interface()
+		if data != nil {
+			if reflect.DeepEqual(data, enumValue) {
+				return nil
+			}
+			actualType := reflect.TypeOf(enumValue)
+			if actualType == nil { // Safeguard. Frankly, I don't know how we may get a nil
+				continue
+			}
+			expectedValue := reflect.ValueOf(data)
+			if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+				// Attempt comparison after type conversion
+				if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
+					return nil
+				}
+			}
+		}
+		values = append(values, enumValue)
+	}
+	return errors.EnumFail(path, in, data, values)
+}
+
+// MinItems validates that there are at least n items in a slice
+func MinItems(path, in string, size, min int64) *errors.Validation {
+	if size < min {
+		return errors.TooFewItems(path, in, min)
+	}
+	return nil
+}
+
+// MaxItems validates that there are at most n items in a slice
+func MaxItems(path, in string, size, max int64) *errors.Validation {
+	if size > max {
+		return errors.TooManyItems(path, in, max)
+	}
+	return nil
+}
+
+// UniqueItems validates that the provided slice has unique elements
+func UniqueItems(path, in string, data interface{}) *errors.Validation {
+	val := reflect.ValueOf(data)
+	if val.Kind() != reflect.Slice {
+		return nil
+	}
+	var unique []interface{}
+	for i := 0; i < val.Len(); i++ {
+		v := val.Index(i).Interface()
+		for _, u := range unique {
+			if reflect.DeepEqual(v, u) {
+				return errors.DuplicateItems(path, in)
+			}
+		}
+		unique = append(unique, v)
+	}
+	return nil
+}
+
+// MinLength validates a string for minimum length
+func MinLength(path, in, data string, minLength int64) *errors.Validation {
+	strLen := int64(utf8.RuneCount([]byte(data)))
+	if strLen < minLength {
+		return errors.TooShort(path, in, minLength)
+	}
+	return nil
+}
+
+// MaxLength validates a string for maximum length
+func MaxLength(path, in, data string, maxLength int64) *errors.Validation {
+	strLen := int64(utf8.RuneCount([]byte(data)))
+	if strLen > maxLength {
+		return errors.TooLong(path, in, maxLength)
+	}
+	return nil
+}
+
+// Required validates an interface for requiredness
+func Required(path, in string, data interface{}) *errors.Validation {
+	val := reflect.ValueOf(data)
+	if val.IsValid() {
+		if reflect.DeepEqual(reflect.Zero(val.Type()).Interface(), val.Interface()) {
+			return errors.Required(path, in)
+		}
+		return nil
+	}
+	return errors.Required(path, in)
+}
+
+// RequiredString validates a string for requiredness
+func RequiredString(path, in, data string) *errors.Validation {
+	if data == "" {
+		return errors.Required(path, in)
+	}
+	return nil
+}
+
+// RequiredNumber validates a number for requiredness
+func RequiredNumber(path, in string, data float64) *errors.Validation {
+	if data == 0 {
+		return errors.Required(path, in)
+	}
+	return nil
+}
+
+// Pattern validates a string against a regular expression
+func Pattern(path, in, data, pattern string) *errors.Validation {
+	re, err := compileRegexp(pattern)
+	if err != nil {
+		return errors.FailedPattern(path, in, fmt.Sprintf("%s, but pattern is invalid: %s", pattern, err.Error()))
+	}
+	if !re.MatchString(data) {
+		return errors.FailedPattern(path, in, pattern)
+	}
+	return nil
+}
+
+// MaximumInt validates if a number is smaller than a given maximum
+func MaximumInt(path, in string, data, max int64, exclusive bool) *errors.Validation {
+	if (!exclusive && data > max) || (exclusive && data >= max) {
+		return errors.ExceedsMaximumInt(path, in, max, exclusive)
+	}
+	return nil
+}
+
+// MaximumUint validates if a number is smaller than a given maximum
+func MaximumUint(path, in string, data, max uint64, exclusive bool) *errors.Validation {
+	if (!exclusive && data > max) || (exclusive && data >= max) {
+		return errors.ExceedsMaximumUint(path, in, max, exclusive)
+	}
+	return nil
+}
+
+// Maximum validates if a number is smaller than a given maximum
+func Maximum(path, in string, data, max float64, exclusive bool) *errors.Validation {
+	if (!exclusive && data > max) || (exclusive && data >= max) {
+		return errors.ExceedsMaximum(path, in, max, exclusive)
+	}
+	return nil
+}
+
+// Minimum validates if a number is smaller than a given minimum
+func Minimum(path, in string, data, min float64, exclusive bool) *errors.Validation {
+	if (!exclusive && data < min) || (exclusive && data <= min) {
+		return errors.ExceedsMinimum(path, in, min, exclusive)
+	}
+	return nil
+}
+
+// MinimumInt validates if a number is smaller than a given minimum
+func MinimumInt(path, in string, data, min int64, exclusive bool) *errors.Validation {
+	if (!exclusive && data < min) || (exclusive && data <= min) {
+		return errors.ExceedsMinimumInt(path, in, min, exclusive)
+	}
+	return nil
+}
+
+// MinimumUint validates if a number is smaller than a given minimum
+func MinimumUint(path, in string, data, min uint64, exclusive bool) *errors.Validation {
+	if (!exclusive && data < min) || (exclusive && data <= min) {
+		return errors.ExceedsMinimumUint(path, in, min, exclusive)
+	}
+	return nil
+}
+
+// MultipleOf validates if the provided number is a multiple of the factor
+func MultipleOf(path, in string, data, factor float64) *errors.Validation {
+	// multipleOf factor must be positive
+	if factor < 0 {
+		return errors.MultipleOfMustBePositive(path, in, factor)
+	}
+	var mult float64
+	if factor < 1 {
+		mult = 1 / factor * data
+	} else {
+		mult = data / factor
+	}
+	if !swag.IsFloat64AJSONInteger(mult) {
+		return errors.NotMultipleOf(path, in, factor)
+	}
+	return nil
+}
+
+// MultipleOfInt validates if the provided integer is a multiple of the factor
+func MultipleOfInt(path, in string, data int64, factor int64) *errors.Validation {
+	// multipleOf factor must be positive
+	if factor < 0 {
+		return errors.MultipleOfMustBePositive(path, in, factor)
+	}
+	mult := data / factor
+	if mult*factor != data {
+		return errors.NotMultipleOf(path, in, factor)
+	}
+	return nil
+}
+
+// MultipleOfUint validates if the provided unsigned integer is a multiple of the factor
+func MultipleOfUint(path, in string, data, factor uint64) *errors.Validation {
+	mult := data / factor
+	if mult*factor != data {
+		return errors.NotMultipleOf(path, in, factor)
+	}
+	return nil
+}
+
+// FormatOf validates if a string matches a format in the format registry
+func FormatOf(path, in, format, data string, registry strfmt.Registry) *errors.Validation {
+	if registry == nil {
+		registry = strfmt.Default
+	}
+	if ok := registry.ContainsName(format); !ok {
+		return errors.InvalidTypeName(format)
+	}
+	if ok := registry.Validates(format, data); !ok {
+		return errors.InvalidType(path, in, format, data)
+	}
+	return nil
+}
+
+// MaximumNativeType provides native type constraint validation as a facade
+// to various numeric types versions of Maximum constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the max value is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MaximumNativeType(path, in string, val interface{}, max float64, exclusive bool) *errors.Validation {
+	kind := reflect.ValueOf(val).Type().Kind()
+	switch kind {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		value := valueHelp.asInt64(val)
+		return MaximumInt(path, in, value, int64(max), exclusive)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		value := valueHelp.asUint64(val)
+		if max < 0 {
+			return errors.ExceedsMaximum(path, in, max, exclusive)
+		}
+		return MaximumUint(path, in, value, uint64(max), exclusive)
+	case reflect.Float32, reflect.Float64:
+		fallthrough
+	default:
+		value := valueHelp.asFloat64(val)
+		return Maximum(path, in, value, max, exclusive)
+	}
+}
+
+// MinimumNativeType provides native type constraint validation as a facade
+// to various numeric types versions of Minimum constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the min value is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MinimumNativeType(path, in string, val interface{}, min float64, exclusive bool) *errors.Validation {
+	kind := reflect.ValueOf(val).Type().Kind()
+	switch kind {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		value := valueHelp.asInt64(val)
+		return MinimumInt(path, in, value, int64(min), exclusive)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		value := valueHelp.asUint64(val)
+		if min < 0 {
+			return nil
+		}
+		return MinimumUint(path, in, value, uint64(min), exclusive)
+	case reflect.Float32, reflect.Float64:
+		fallthrough
+	default:
+		value := valueHelp.asFloat64(val)
+		return Minimum(path, in, value, min, exclusive)
+	}
+}
+
+// MultipleOfNativeType provides native type constraint validation as a facade
+// to various numeric types version of MultipleOf constraint check.
+//
+// Assumes that any possible loss conversion during conversion has been
+// checked beforehand.
+//
+// NOTE: currently, the multipleOf factor is marshalled as a float64, no matter what,
+// which means there may be a loss during conversions (e.g. for very large integers)
+//
+// TODO: Normally, a JSON MAX_SAFE_INTEGER check would ensure conversion remains loss-free
+func MultipleOfNativeType(path, in string, val interface{}, multipleOf float64) *errors.Validation {
+	kind := reflect.ValueOf(val).Type().Kind()
+	switch kind {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		value := valueHelp.asInt64(val)
+		return MultipleOfInt(path, in, value, int64(multipleOf))
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		value := valueHelp.asUint64(val)
+		return MultipleOfUint(path, in, value, uint64(multipleOf))
+	case reflect.Float32, reflect.Float64:
+		fallthrough
+	default:
+		value := valueHelp.asFloat64(val)
+		return MultipleOf(path, in, value, multipleOf)
+	}
+}
+
+// IsValueValidAgainstRange checks that a numeric value is compatible with
+// the range defined by Type and Format, that is, may be converted without loss.
+//
+// NOTE: this check is about type capacity and not formal verification such as: 1.0 != 1L
+func IsValueValidAgainstRange(val interface{}, typeName, format, prefix, path string) error {
+	kind := reflect.ValueOf(val).Type().Kind()
+
+	// What is the string representation of val
+	stringRep := ""
+	switch kind {
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		stringRep = swag.FormatUint64(valueHelp.asUint64(val))
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		stringRep = swag.FormatInt64(valueHelp.asInt64(val))
+	case reflect.Float32, reflect.Float64:
+		stringRep = swag.FormatFloat64(valueHelp.asFloat64(val))
+	default:
+		return fmt.Errorf("%s value number range checking called with invalid (non numeric) val type in %s", prefix, path)
+	}
+
+	var errVal error
+
+	switch typeName {
+	case "integer":
+		switch format {
+		case "int32":
+			_, errVal = swag.ConvertInt32(stringRep)
+		case "uint32":
+			_, errVal = swag.ConvertUint32(stringRep)
+		case "uint64":
+			_, errVal = swag.ConvertUint64(stringRep)
+		case "int64":
+			fallthrough
+		default:
+			_, errVal = swag.ConvertInt64(stringRep)
+		}
+	case "number":
+		fallthrough
+	default:
+		switch format {
+		case "float", "float32":
+			_, errVal = swag.ConvertFloat32(stringRep)
+		case "double", "float64":
+			fallthrough
+		default:
+			// No check can be performed here since
+			// no number beyond float64 is supported
+		}
+	}
+	if errVal != nil { // We don't report the actual errVal from strconv
+		if format != "" {
+			errVal = fmt.Errorf("%s value must be of type %s with format %s in %s", prefix, typeName, format, path)
+		} else {
+			errVal = fmt.Errorf("%s value must be of type %s (default format) in %s", prefix, typeName, path)
+		}
+	}
+	return errVal
+}