# Generated by API Builder - https://www.apibuilder.io
# Service version: 0.15.77
# apibuilder 0.15.33 app.apibuilder.io/apicollective/apibuilder-spec/latest/ruby_client

require 'cgi'
require 'net/http'
require 'net/https'
require 'uri'
require 'base64'

require 'date'
require 'rubygems'
require 'json'
require 'bigdecimal'

# Specification of apibuilder api.json schema
module Io
  module Apibuilder
    module Spec
      module V0

        class Client

          module Constants

            NAMESPACE = 'io.apibuilder.spec.v0' unless defined?(Constants::NAMESPACE)
            USER_AGENT = 'apibuilder 0.15.33 app.apibuilder.io/apicollective/apibuilder-spec/latest/ruby_client' unless defined?(Constants::USER_AGENT)
            VERSION = '0.15.77' unless defined?(Constants::VERSION)
            VERSION_MAJOR = 0 unless defined?(VERSION_MAJOR)

          end

          attr_reader :url

          def initialize(url, opts={})
            @url = HttpClient::Preconditions.assert_class('url', url, String)
            @base_url = URI(url)
            @authorization = HttpClient::Preconditions.assert_class_or_nil('authorization', opts.delete(:authorization), HttpClient::Authorization)
            @default_headers = HttpClient::Preconditions.assert_class('default_headers', opts.delete(:default_headers) || {}, Hash)
            @http_handler = opts.delete(:http_handler) || HttpClient::DefaultHttpHandler.new

            HttpClient::Preconditions.assert_empty_opts(opts)
            HttpClient::Preconditions.check_state(url.match(/http.+/i), "URL[%s] must start with http" % url)
          end

          def request(path=nil)
            HttpClient::Preconditions.assert_class_or_nil('path', path, String)
            request = HttpClient::Request.new(@http_handler, @base_url, path.to_s).with_header('User-Agent', Constants::USER_AGENT).with_header('X-Apidoc-Version', Constants::VERSION).with_header('X-Apidoc-Version-Major', Constants::VERSION_MAJOR)

            @default_headers.each do |key, value|
              request = request.with_header(key, value)
            end

            if @authorization
              request = request.with_auth(@authorization)
            end

            request
          end


        end

        module Clients



        end

        module Models

          class ResponseCode

            module Types
              # Documents an HTTP status code (e.g. 200, 409, etc.)
              RESPONSE_CODE_INTEGER_WRAPPER = 'integer' unless defined?(RESPONSE_CODE_INTEGER_WRAPPER)
              # An individual operation can specify a response code of default to handle all
              # other response codes. This is most useful for providing consistent error
              # handling from an operation.
              RESPONSE_CODE_OPTION = 'response_code_option' unless defined?(RESPONSE_CODE_OPTION)
            end

            attr_reader :__discriminator__

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @__discriminator__ = opts[:__discriminator__] ||'response_code'
            end

            def subtype_to_hash
              raise 'Cannot serialize an instance of response_code directly - must use one of the specific types: integer, response_code_option'
            end

            def to_hash
              { @__discriminator__ => subtype_to_hash }
            end

            def ResponseCode.from_json(hash)
              HttpClient::Preconditions.assert_class('hash', hash, Hash)
              hash.map do |union_type_name, data|
                case union_type_name
                  when Types::RESPONSE_CODE_INTEGER_WRAPPER; ResponseCodeIntegerWrapper.new(data)
                  when Types::RESPONSE_CODE_OPTION; ResponseCodeOption.new(data)
                  else ResponseCodeUndefinedType.new(:__discriminator__ => union_type_name)
                end
              end.first
            end

          end

          class ResponseCodeUndefinedType < ResponseCode

            attr_reader :name

            def initialize(incoming={})
              super(:__discriminator__ => 'undefined_type')
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:__discriminator__), String)
            end

            def subtype_to_hash
              raise 'Unable to serialize undefined type to json'
            end

            def copy(incoming={})
              raise 'Operation not supported for undefined type'
            end

            def to_hash
              raise 'Operation not supported for undefined type'
            end

          end

          class Method

            attr_reader :value

            def initialize(value)
              @value = HttpClient::Preconditions.assert_class('value', value, String)
            end

            # Returns the instance of Method for this value, creating a new instance for an unknown value
            def Method.apply(value)
              if value.instance_of?(Method)
                value
              else
                HttpClient::Preconditions.assert_class_or_nil('value', value, String)
                value.nil? ? nil : (from_string(value) || Method.new(value))
              end
            end

            # Returns the instance of Method for this value, or nil if not found
            def Method.from_string(value)
              HttpClient::Preconditions.assert_class('value', value, String)
              Method.ALL.find { |v| v.value == value }
            end

            def Method.ALL
              @@all ||= [Method.get, Method.post, Method.put, Method.patch, Method.delete, Method.head, Method.connect, Method.options, Method.trace]
            end

            def Method.get
              @@_get ||= Method.new('GET')
            end

            def Method.post
              @@_post ||= Method.new('POST')
            end

            def Method.put
              @@_put ||= Method.new('PUT')
            end

            def Method.patch
              @@_patch ||= Method.new('PATCH')
            end

            def Method.delete
              @@_delete ||= Method.new('DELETE')
            end

            def Method.head
              @@_head ||= Method.new('HEAD')
            end

            def Method.connect
              @@_connect ||= Method.new('CONNECT')
            end

            def Method.options
              @@_options ||= Method.new('OPTIONS')
            end

            def Method.trace
              @@_trace ||= Method.new('TRACE')
            end

            def to_hash
              value
            end

          end

          class ParameterLocation

            attr_reader :value

            def initialize(value)
              @value = HttpClient::Preconditions.assert_class('value', value, String)
            end

            # Returns the instance of ParameterLocation for this value, creating a new instance for an unknown value
            def ParameterLocation.apply(value)
              if value.instance_of?(ParameterLocation)
                value
              else
                HttpClient::Preconditions.assert_class_or_nil('value', value, String)
                value.nil? ? nil : (from_string(value) || ParameterLocation.new(value))
              end
            end

            # Returns the instance of ParameterLocation for this value, or nil if not found
            def ParameterLocation.from_string(value)
              HttpClient::Preconditions.assert_class('value', value, String)
              ParameterLocation.ALL.find { |v| v.value == value }
            end

            def ParameterLocation.ALL
              @@all ||= [ParameterLocation.path, ParameterLocation.query, ParameterLocation.form, ParameterLocation.header]
            end

            def ParameterLocation.path
              @@_path ||= ParameterLocation.new('Path')
            end

            def ParameterLocation.query
              @@_query ||= ParameterLocation.new('Query')
            end

            def ParameterLocation.form
              @@_form ||= ParameterLocation.new('Form')
            end

            def ParameterLocation.header
              @@_header ||= ParameterLocation.new('Header')
            end

            def to_hash
              value
            end

          end

          class ResponseCodeOption < ResponseCode

            attr_reader :value

            def initialize(value)
              super(:name => ResponseCode::Types::RESPONSE_CODE_OPTION, :__discriminator__ => 'response_code_option')
              @value = HttpClient::Preconditions.assert_class('value', value, String)
            end

            # Returns the instance of ResponseCodeOption for this value, creating a new instance for an unknown value
            def ResponseCodeOption.apply(value)
              if value.instance_of?(ResponseCodeOption)
                value
              else
                HttpClient::Preconditions.assert_class_or_nil('value', value, String)
                value.nil? ? nil : (from_string(value) || ResponseCodeOption.new(value))
              end
            end

            # Returns the instance of ResponseCodeOption for this value, or nil if not found
            def ResponseCodeOption.from_string(value)
              HttpClient::Preconditions.assert_class('value', value, String)
              ResponseCodeOption.ALL.find { |v| v.value == value }
            end

            def ResponseCodeOption.ALL
              @@all ||= [ResponseCodeOption.default]
            end

            def ResponseCodeOption.default
              @@_default ||= ResponseCodeOption.new('Default')
            end

            def subtype_to_hash
              value
            end

          end

          # Used to indicate an API concern for a field that is specific to the field's
          # usage but not necessarily its data type. For example, you might use
          # annotations to mark that certain fields contain PII or PCI data and thus
          # should not be stored once processing is complete. Annotations communicate
          # meaning to consumers of an API and may also be used within an implementation
          # or tooling; for example, using static analysis tools to detect logging of
          # sensitive data.
          class Annotation

            attr_reader :name, :description, :deprecation

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name], 'Annotation')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Annotation.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash
              }
            end

          end

          class Apidoc

            attr_reader :version

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:version], 'Apidoc')
              @version = HttpClient::Preconditions.assert_class('version', opts.delete(:version), String)
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Apidoc.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :version => version
              }
            end

          end

          class Application

            attr_reader :key

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:key], 'Application')
              @key = HttpClient::Preconditions.assert_class('key', opts.delete(:key), String)
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Application.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :key => key
              }
            end

          end

          # Represents an additional attribute that is attached to one of the objects in
          # apibuilder. The main use case is to capture additional metadata that doesn't
          # necessarily define the API but aids in code generation. Examples would be
          # hints for certain code generators about classes to extend, interfaces to
          # implement, annotations to add, names to assign to certain methods, etc. The
          # specific attributes will be applicable only in the context of the specific
          # code generators usings them.
          class Attribute

            attr_reader :name, :value, :description, :deprecation

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :value], 'Attribute')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @value = HttpClient::Preconditions.assert_class('value', HttpClient::Helper.to_object(opts.delete(:value)), Hash)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Attribute.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :value => value,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash
              }
            end

          end

          class Body

            attr_reader :type, :description, :deprecation, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:type], 'Body')
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Body.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :type => type,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          # Describes the primary contact for this service
          class Contact

            attr_reader :name, :url, :email

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @name = (x = opts.delete(:name); x.nil? ? nil : HttpClient::Preconditions.assert_class('name', x, String))
              @url = (x = opts.delete(:url); x.nil? ? nil : HttpClient::Preconditions.assert_class('url', x, String))
              @email = (x = opts.delete(:email); x.nil? ? nil : HttpClient::Preconditions.assert_class('email', x, String))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Contact.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :url => url,
                :email => email
              }
            end

          end

          # Indicates that this particular element is considered deprecated in the API.
          # See the description for details
          class Deprecation

            attr_reader :description

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Deprecation.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :description => description
              }
            end

          end

          class Enum

            attr_reader :name, :plural, :description, :deprecation, :values, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :plural, :values], 'Enum')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @plural = HttpClient::Preconditions.assert_class('plural', opts.delete(:plural), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @values = HttpClient::Preconditions.assert_class('values', opts.delete(:values), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::EnumValue) ? x : ::Io::Apibuilder::Spec::V0::Models::EnumValue.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Enum.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :plural => plural,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :values => values.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          class EnumValue

            attr_reader :name, :description, :deprecation, :attributes, :value

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name], 'EnumValue')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @value = (x = opts.delete(:value); x.nil? ? nil : HttpClient::Preconditions.assert_class('value', x, String))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              EnumValue.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :attributes => attributes.map { |o| o.to_hash },
                :value => value
              }
            end

          end

          class Field

            attr_reader :name, :type, :description, :deprecation, :default, :required, :minimum, :maximum, :example, :attributes, :annotations

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :type, :required], 'Field')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @default = (x = opts.delete(:default); x.nil? ? nil : HttpClient::Preconditions.assert_class('default', x, String))
              @required = HttpClient::Preconditions.assert_boolean('required', opts.delete(:required))
              @minimum = (x = opts.delete(:minimum); x.nil? ? nil : HttpClient::Preconditions.assert_class('minimum', x, Integer))
              @maximum = (x = opts.delete(:maximum); x.nil? ? nil : HttpClient::Preconditions.assert_class('maximum', x, Integer))
              @example = (x = opts.delete(:example); x.nil? ? nil : HttpClient::Preconditions.assert_class('example', x, String))
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @annotations = HttpClient::Preconditions.assert_class('annotations', (x = opts.delete(:annotations); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('annotations', v, String) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Field.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :type => type,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :default => default,
                :required => required,
                :minimum => minimum,
                :maximum => maximum,
                :example => example,
                :attributes => attributes.map { |o| o.to_hash },
                :annotations => annotations
              }
            end

          end

          class Header

            attr_reader :name, :type, :description, :deprecation, :required, :default, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :type, :required], 'Header')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @required = HttpClient::Preconditions.assert_boolean('required', opts.delete(:required))
              @default = (x = opts.delete(:default); x.nil? ? nil : HttpClient::Preconditions.assert_class('default', x, String))
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Header.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :type => type,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :required => required,
                :default => default,
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          # An import is used to declare a dependency on another application. This allows
          # you to reference the models and or enums from that application in your own
          # app.
          class Import

            attr_reader :uri, :namespace, :organization, :application, :version, :enums, :interfaces, :unions, :models, :annotations

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:uri, :namespace, :organization, :application, :version], 'Import')
              @uri = HttpClient::Preconditions.assert_class('uri', opts.delete(:uri), String)
              @namespace = HttpClient::Preconditions.assert_class('namespace', opts.delete(:namespace), String)
              @organization = (x = opts.delete(:organization); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Organization) ? x : ::Io::Apibuilder::Spec::V0::Models::Organization.new(x))
              @application = (x = opts.delete(:application); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Application) ? x : ::Io::Apibuilder::Spec::V0::Models::Application.new(x))
              @version = HttpClient::Preconditions.assert_class('version', opts.delete(:version), String)
              @enums = HttpClient::Preconditions.assert_class('enums', (x = opts.delete(:enums); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('enums', v, String) }
              @interfaces = HttpClient::Preconditions.assert_class('interfaces', (x = opts.delete(:interfaces); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('interfaces', v, String) }
              @unions = HttpClient::Preconditions.assert_class('unions', (x = opts.delete(:unions); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('unions', v, String) }
              @models = HttpClient::Preconditions.assert_class('models', (x = opts.delete(:models); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('models', v, String) }
              @annotations = HttpClient::Preconditions.assert_class('annotations', (x = opts.delete(:annotations); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Annotation) ? x : ::Io::Apibuilder::Spec::V0::Models::Annotation.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Import.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :uri => uri,
                :namespace => namespace,
                :organization => organization.to_hash,
                :application => application.to_hash,
                :version => version,
                :enums => enums,
                :interfaces => interfaces,
                :unions => unions,
                :models => models,
                :annotations => annotations.map { |o| o.to_hash }
              }
            end

          end

          # General metadata about this service
          class Info

            attr_reader :license, :contact

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @license = (x = opts.delete(:license); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::License) ? x : ::Io::Apibuilder::Spec::V0::Models::License.new(x)))
              @contact = (x = opts.delete(:contact); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Contact) ? x : ::Io::Apibuilder::Spec::V0::Models::Contact.new(x)))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Info.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :license => license.nil? ? nil : license.to_hash,
                :contact => contact.nil? ? nil : contact.to_hash
              }
            end

          end

          class Interface

            attr_reader :name, :plural, :description, :deprecation, :fields, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :plural, :fields], 'Interface')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @plural = HttpClient::Preconditions.assert_class('plural', opts.delete(:plural), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @fields = HttpClient::Preconditions.assert_class('fields', opts.delete(:fields), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Field) ? x : ::Io::Apibuilder::Spec::V0::Models::Field.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Interface.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :plural => plural,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :fields => fields.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          # Describes the software license contact for this service
          class License

            attr_reader :name, :url

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name], 'License')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @url = (x = opts.delete(:url); x.nil? ? nil : HttpClient::Preconditions.assert_class('url', x, String))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              License.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :url => url
              }
            end

          end

          class Model

            attr_reader :name, :plural, :description, :deprecation, :fields, :attributes, :interfaces

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :plural, :fields], 'Model')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @plural = HttpClient::Preconditions.assert_class('plural', opts.delete(:plural), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @fields = HttpClient::Preconditions.assert_class('fields', opts.delete(:fields), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Field) ? x : ::Io::Apibuilder::Spec::V0::Models::Field.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @interfaces = HttpClient::Preconditions.assert_class('interfaces', (x = opts.delete(:interfaces); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('interfaces', v, String) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Model.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :plural => plural,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :fields => fields.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash },
                :interfaces => interfaces
              }
            end

          end

          class Operation

            attr_reader :method, :path, :description, :deprecation, :body, :parameters, :responses, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:method, :path], 'Operation')
              @method = (x = opts.delete(:method); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Method) ? x : ::Io::Apibuilder::Spec::V0::Models::Method.apply(x))
              @path = HttpClient::Preconditions.assert_class('path', opts.delete(:path), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @body = (x = opts.delete(:body); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Body) ? x : ::Io::Apibuilder::Spec::V0::Models::Body.new(x)))
              @parameters = HttpClient::Preconditions.assert_class('parameters', (x = opts.delete(:parameters); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Parameter) ? x : ::Io::Apibuilder::Spec::V0::Models::Parameter.new(x)) }
              @responses = HttpClient::Preconditions.assert_class('responses', (x = opts.delete(:responses); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Response) ? x : ::Io::Apibuilder::Spec::V0::Models::Response.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Operation.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :method => method.value,
                :path => path,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :body => body.nil? ? nil : body.to_hash,
                :parameters => parameters.map { |o| o.to_hash },
                :responses => responses.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          class Organization

            attr_reader :key

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:key], 'Organization')
              @key = HttpClient::Preconditions.assert_class('key', opts.delete(:key), String)
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Organization.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :key => key
              }
            end

          end

          class Parameter

            attr_reader :name, :type, :location, :description, :deprecation, :required, :default, :minimum, :maximum, :example, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :type, :location, :required], 'Parameter')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @location = (x = opts.delete(:location); x.is_a?(::Io::Apibuilder::Spec::V0::Models::ParameterLocation) ? x : ::Io::Apibuilder::Spec::V0::Models::ParameterLocation.apply(x))
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @required = HttpClient::Preconditions.assert_boolean('required', opts.delete(:required))
              @default = (x = opts.delete(:default); x.nil? ? nil : HttpClient::Preconditions.assert_class('default', x, String))
              @minimum = (x = opts.delete(:minimum); x.nil? ? nil : HttpClient::Preconditions.assert_class('minimum', x, Integer))
              @maximum = (x = opts.delete(:maximum); x.nil? ? nil : HttpClient::Preconditions.assert_class('maximum', x, Integer))
              @example = (x = opts.delete(:example); x.nil? ? nil : HttpClient::Preconditions.assert_class('example', x, String))
              @attributes = (x = opts.delete(:attributes); x.nil? ? nil : HttpClient::Preconditions.assert_class('attributes', x, Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) })
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Parameter.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :type => type,
                :location => location.value,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :required => required,
                :default => default,
                :minimum => minimum,
                :maximum => maximum,
                :example => example,
                :attributes => attributes.nil? ? nil : attributes.map { |o| o.to_hash }
              }
            end

          end

          class Resource

            attr_reader :type, :plural, :path, :description, :deprecation, :operations, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:type, :plural, :operations], 'Resource')
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @plural = HttpClient::Preconditions.assert_class('plural', opts.delete(:plural), String)
              @path = (x = opts.delete(:path); x.nil? ? nil : HttpClient::Preconditions.assert_class('path', x, String))
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @operations = HttpClient::Preconditions.assert_class('operations', opts.delete(:operations), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Operation) ? x : ::Io::Apibuilder::Spec::V0::Models::Operation.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Resource.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :type => type,
                :plural => plural,
                :path => path,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :operations => operations.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash }
              }
            end

          end

          class Response

            attr_reader :code, :type, :headers, :description, :deprecation, :attributes

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:code, :type], 'Response')
              @code = (x = opts.delete(:code); x.is_a?(::Io::Apibuilder::Spec::V0::Models::ResponseCode) ? x : ::Io::Apibuilder::Spec::V0::Models::ResponseCode.from_json(x))
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @headers = (x = opts.delete(:headers); x.nil? ? nil : HttpClient::Preconditions.assert_class('headers', x, Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Header) ? x : ::Io::Apibuilder::Spec::V0::Models::Header.new(x)) })
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @attributes = (x = opts.delete(:attributes); x.nil? ? nil : HttpClient::Preconditions.assert_class('attributes', x, Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) })
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Response.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :code => code.to_hash,
                :type => type,
                :headers => headers.nil? ? nil : headers.map { |o| o.to_hash },
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :attributes => attributes.nil? ? nil : attributes.map { |o| o.to_hash }
              }
            end

          end

          class Service

            attr_reader :apidoc, :name, :organization, :application, :namespace, :version, :base_url, :description, :info, :headers, :imports, :enums, :interfaces, :unions, :models, :resources, :attributes, :annotations

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :organization, :application, :namespace, :version, :info], 'Service')
              @apidoc = (x = opts.delete(:apidoc); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Apidoc) ? x : ::Io::Apibuilder::Spec::V0::Models::Apidoc.new(x)))
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @organization = (x = opts.delete(:organization); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Organization) ? x : ::Io::Apibuilder::Spec::V0::Models::Organization.new(x))
              @application = (x = opts.delete(:application); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Application) ? x : ::Io::Apibuilder::Spec::V0::Models::Application.new(x))
              @namespace = HttpClient::Preconditions.assert_class('namespace', opts.delete(:namespace), String)
              @version = HttpClient::Preconditions.assert_class('version', opts.delete(:version), String)
              @base_url = (x = opts.delete(:base_url); x.nil? ? nil : HttpClient::Preconditions.assert_class('base_url', x, String))
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @info = (x = opts.delete(:info); x.is_a?(::Io::Apibuilder::Spec::V0::Models::Info) ? x : ::Io::Apibuilder::Spec::V0::Models::Info.new(x))
              @headers = HttpClient::Preconditions.assert_class('headers', (x = opts.delete(:headers); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Header) ? x : ::Io::Apibuilder::Spec::V0::Models::Header.new(x)) }
              @imports = HttpClient::Preconditions.assert_class('imports', (x = opts.delete(:imports); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Import) ? x : ::Io::Apibuilder::Spec::V0::Models::Import.new(x)) }
              @enums = HttpClient::Preconditions.assert_class('enums', (x = opts.delete(:enums); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Enum) ? x : ::Io::Apibuilder::Spec::V0::Models::Enum.new(x)) }
              @interfaces = HttpClient::Preconditions.assert_class('interfaces', (x = opts.delete(:interfaces); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Interface) ? x : ::Io::Apibuilder::Spec::V0::Models::Interface.new(x)) }
              @unions = HttpClient::Preconditions.assert_class('unions', (x = opts.delete(:unions); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Union) ? x : ::Io::Apibuilder::Spec::V0::Models::Union.new(x)) }
              @models = HttpClient::Preconditions.assert_class('models', (x = opts.delete(:models); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Model) ? x : ::Io::Apibuilder::Spec::V0::Models::Model.new(x)) }
              @resources = HttpClient::Preconditions.assert_class('resources', (x = opts.delete(:resources); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Resource) ? x : ::Io::Apibuilder::Spec::V0::Models::Resource.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @annotations = HttpClient::Preconditions.assert_class('annotations', (x = opts.delete(:annotations); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Annotation) ? x : ::Io::Apibuilder::Spec::V0::Models::Annotation.new(x)) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Service.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :apidoc => apidoc.nil? ? nil : apidoc.to_hash,
                :name => name,
                :organization => organization.to_hash,
                :application => application.to_hash,
                :namespace => namespace,
                :version => version,
                :base_url => base_url,
                :description => description,
                :info => info.to_hash,
                :headers => headers.map { |o| o.to_hash },
                :imports => imports.map { |o| o.to_hash },
                :enums => enums.map { |o| o.to_hash },
                :interfaces => interfaces.map { |o| o.to_hash },
                :unions => unions.map { |o| o.to_hash },
                :models => models.map { |o| o.to_hash },
                :resources => resources.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash },
                :annotations => annotations.map { |o| o.to_hash }
              }
            end

          end

          class Union

            attr_reader :name, :plural, :discriminator, :description, :deprecation, :types, :attributes, :interfaces

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:name, :plural, :types], 'Union')
              @name = HttpClient::Preconditions.assert_class('name', opts.delete(:name), String)
              @plural = HttpClient::Preconditions.assert_class('plural', opts.delete(:plural), String)
              @discriminator = (x = opts.delete(:discriminator); x.nil? ? nil : HttpClient::Preconditions.assert_class('discriminator', x, String))
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @types = HttpClient::Preconditions.assert_class('types', opts.delete(:types), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::UnionType) ? x : ::Io::Apibuilder::Spec::V0::Models::UnionType.new(x)) }
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @interfaces = HttpClient::Preconditions.assert_class('interfaces', (x = opts.delete(:interfaces); x.nil? ? [] : x), Array).map { |v| HttpClient::Preconditions.assert_class('interfaces', v, String) }
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              Union.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :name => name,
                :plural => plural,
                :discriminator => discriminator,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :types => types.map { |o| o.to_hash },
                :attributes => attributes.map { |o| o.to_hash },
                :interfaces => interfaces
              }
            end

          end

          # Metadata about one of the types that is part of a union type
          class UnionType

            attr_reader :type, :description, :deprecation, :attributes, :default, :discriminator_value

            def initialize(incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:type], 'UnionType')
              @type = HttpClient::Preconditions.assert_class('type', opts.delete(:type), String)
              @description = (x = opts.delete(:description); x.nil? ? nil : HttpClient::Preconditions.assert_class('description', x, String))
              @deprecation = (x = opts.delete(:deprecation); x.nil? ? nil : (x = x; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Deprecation) ? x : ::Io::Apibuilder::Spec::V0::Models::Deprecation.new(x)))
              @attributes = HttpClient::Preconditions.assert_class('attributes', (x = opts.delete(:attributes); x.nil? ? [] : x), Array).map { |v| (x = v; x.is_a?(::Io::Apibuilder::Spec::V0::Models::Attribute) ? x : ::Io::Apibuilder::Spec::V0::Models::Attribute.new(x)) }
              @default = (x = opts.delete(:default); x.nil? ? nil : HttpClient::Preconditions.assert_boolean('default', x))
              @discriminator_value = (x = opts.delete(:discriminator_value); x.nil? ? nil : HttpClient::Preconditions.assert_class('discriminator_value', x, String))
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              UnionType.new(to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def to_hash
              {
                :type => type,
                :description => description,
                :deprecation => deprecation.nil? ? nil : deprecation.to_hash,
                :attributes => attributes.map { |o| o.to_hash },
                :default => default,
                :discriminator_value => discriminator_value
              }
            end

          end

          # Wrapper class to support the union type[response_code] datatype[integer]
          class ResponseCodeIntegerWrapper < ResponseCode

            attr_reader :value

            def initialize(incoming={})
              super(:__discriminator__ => ResponseCode::Types::RESPONSE_CODE_INTEGER_WRAPPER)
              opts = HttpClient::Helper.symbolize_keys(incoming)
              HttpClient::Preconditions.require_keys(opts, [:value], 'ResponseCodeIntegerWrapper')
              @value = HttpClient::Preconditions.assert_class('value', opts.delete(:value), Integer)
            end

            def to_json
              JSON.dump(to_hash)
            end

            def copy(incoming={})
              ResponseCodeIntegerWrapper.new(subtype_to_hash.merge(HttpClient::Helper.symbolize_keys(incoming)))
            end

            def subtype_to_hash
              {
                :value => value
              }
            end

          end

        end

        # ===== END OF SERVICE DEFINITION =====
        module HttpClient

          class HttpHandler

            # Returns a client instance to use
            #
            # @param base_uri The base URI for this API
            # @param path the Requested full http path (including any query strings)
            def instance(base_uri, path)
              raise "Override in subclass"
            end

          end

          class HttpHandlerInstance

            # Executes a request. The provided request object will be an
            # instance of Net::HTTP (e.g. Net::HTTP::Get)
            def execute(request)
              raise "Override in subclass"
            end

          end

          class DefaultHttpHandler < HttpHandler

            def instance(base_uri, path)
              DefaultHttpHandlerInstance.new(base_uri)
            end

          end

          class DefaultHttpHandlerInstance < HttpHandlerInstance

            attr_reader :client

            def initialize(base_uri)
              @base_uri = Preconditions.assert_class('base_uri', base_uri, URI)
              @client = Net::HTTP.new(@base_uri.host, @base_uri.port)
              if @base_uri.scheme == "https"
                configure_ssl
              end
            end

            def execute(request)
              response = begin
                           @client.request(request)
                         rescue SocketError => e
                           raise StandardError.new("Error accessing uri[#{full_uri(request.path)}]: #{e}")
                         end

              case response
              when Net::HTTPSuccess
                response.body
              else
                body = response.body rescue nil
                raise HttpClient::ServerError.new(response.code.to_i, response.message, :body => body, :uri => full_uri(request.path).to_s)
              end
            end

            def full_uri(path)
              path.start_with?(@base_uri.to_s) ? path : File.join(@base_uri.to_s, path)
            end

            # Called to configure SSL if the base uri requires it
            def configure_ssl
              @client.use_ssl = true
              @client.verify_mode = OpenSSL::SSL::VERIFY_PEER
              @client.cert_store = OpenSSL::X509::Store.new
              @client.cert_store.set_default_paths
            end

          end

          class Request

            attr_reader :base_uri, :path, :full_uri

            def initialize(http_handler, base_uri, path)
              @http_handler = http_handler
              @base_uri = Preconditions.assert_class('base_uri', base_uri, URI)
              @path = Preconditions.assert_class('path', path, String)
              @full_uri = @base_uri.to_s + @path
              @params = nil
              @body = nil
              @auth = nil
              @headers = {}
              @header_keys_lower_case = []
            end

            def with_header(name, value)
              Preconditions.check_not_blank('name', name, "Header name is required")
              Preconditions.check_not_blank('value', value, "Header value is required")
              Preconditions.check_state(!@headers.has_key?(name),
                                        "Duplicate header named[%s]" % name)
              @headers[name] = value
              @header_keys_lower_case << name.downcase
              self
            end

            def with_auth(auth)
              Preconditions.assert_class('auth', auth, HttpClient::Authorization)
              Preconditions.check_state(@auth.nil?, "auth previously set")

              if auth.scheme.name == AuthScheme::BASIC.name
                @auth = auth
              else
                raise "Auth Scheme[#{auth.scheme.name}] not supported"
              end
              self
            end

            def with_query(params)
              Preconditions.assert_class('params', params, Hash)
              Preconditions.check_state(@params.nil?, "Already have query parameters")
              @params = params
              self
            end

            # Wrapper to set Content-Type header to application/json and set
            # the provided json document as the body
            def with_json(json)
              @headers['Content-Type'] ||= 'application/json; charset=UTF-8'
              with_body(json)
            end

            def with_body(body)
              Preconditions.check_not_blank('body', body)
              @body = body
              self
            end

            def get(&block)
              do_request(Net::HTTP::Get, &block)
            end

            def delete(&block)
              do_request(Net::HTTP::Delete, &block)
            end

            def options(&block)
              do_request(Net::HTTP::Options, &block)
            end

            def post(&block)
              do_request(Net::HTTP::Post, &block)
            end

            def put(&block)
              do_request(Net::HTTP::Put, &block)
            end

            class PATCH < Net::HTTP::Put
              METHOD = "PATCH"
            end

            def patch(&block)
              do_request(PATCH, &block)
            end

            def do_request(klass)
              Preconditions.assert_class('klass', klass, Class)

              uri = @full_uri.dup
              if q = to_query(@params)
                uri += "?%s" % q
              end

              request = klass.send(:new, uri)

              # DEBUG curl = ['curl']
              # DEBUG if klass != Net::HTTP::Get
              # DEBUG  curl << "-X%s" % klass.name.split("::").last.upcase
              # DEBUG end

              if @body
                # DEBUG tmpfile = "/tmp/rest_client.tmp"
                # DEBUG File.open(tmpfile, "w") { |os| os << @body.to_s }
                # DEBUG curl << "-d@%s" % tmpfile
                request.body = @body
              end

              if @auth
                # DEBUG curl << "-u \"%s:%s\"" % [@auth.username, @auth.password]
                Preconditions.check_state(!@header_keys_lower_case.include?("authorization"),
                                          "Cannot specify both an Authorization header and an auth instance")
                user_pass = "%s:%s" % [@auth.username, @auth.password]
                encoded = Base64.encode64(user_pass).to_s.split("\n").map(&:strip).join
                request.add_field("Authorization", "Basic %s" % encoded)
              end

              @headers.each { |key, value|
                # DEBUG curl <<  "-H \"%s: %s\"" % [key, value]
                request.add_field(key, value)
              }

              # DEBUG curl << "'%s%s'" % [@base_uri, path]
              # DEBUG puts curl.join(" ")

              raw_response = @http_handler.instance(@base_uri, request.path).execute(request)
              response = raw_response.to_s == "" ? nil : JSON.parse(raw_response)

              if block_given?
                yield response
              else
                response
              end
            end

            private
            def to_query(params={})
              parts = (params || {}).map { |k,v|
                if v.is_a?(Enumerable)
                  v.map { |el| "%s=%s" % [k, CGI.escape(el.to_s)] }
                else
                  "%s=%s" % [k, CGI.escape(v.to_s)]
                end
              }
              parts.empty? ? nil : parts.join("&")
            end

          end

          class ServerError < StandardError

            attr_reader :code, :details, :body, :uri

            def initialize(code, details, incoming={})
              opts = HttpClient::Helper.symbolize_keys(incoming)
              @code = HttpClient::Preconditions.assert_class('code', code, Integer)
              @details = HttpClient::Preconditions.assert_class('details', details, String)
              @body = HttpClient::Preconditions.assert_class_or_nil('body', opts.delete(:body), String)
              @uri = HttpClient::Preconditions.assert_class_or_nil('uri', opts.delete(:uri), String)
              HttpClient::Preconditions.assert_empty_opts(opts)
              super(self.message)
            end

            def message
              m = "%s %s" % [@code, @details]
              if @body
                m << ": %s" % @body
              end
              m
            end

            def body_json
              @body ? JSON.parse(@body) : nil
            end

          end

          class PreconditionException < StandardError

            attr_reader :message

            def initialize(message)
              super(message)
              @message = message
            end

          end

          module Preconditions

            def Preconditions.check_argument(expression, error_message=nil)
              if !expression
                raise PreconditionException.new(error_message || "check_argument failed")
              end
              nil
            end

            def Preconditions.check_state(expression, error_message=nil)
              if !expression
                raise PreconditionException.new(error_message || "check_state failed")
              end
              nil
            end

            def Preconditions.check_not_nil(field_name, reference, error_message=nil)
              if reference.nil?
                raise PreconditionException.new(error_message || "argument for %s cannot be nil" % field_name)
              end
              reference
            end

            def Preconditions.check_not_blank(field_name, reference, error_message=nil)
              if reference.to_s.strip == ""
                raise PreconditionException.new(error_message || "argument for %s cannot be blank" % field_name)
              end
              reference
            end

            # Throws an error if opts is not empty. Useful when parsing
            # arguments to a function
            def Preconditions.assert_empty_opts(opts)
              if !opts.empty?
                raise PreconditionException.new("Invalid opts: #{opts.keys.inspect}\n#{opts.inspect}")
              end
            end

            # Requires that the provided hash has the specified keys.
            # @param fields A list of symbols
            def Preconditions.require_keys(hash, fields, error_prefix=nil)
              missing = fields.select { |f| !hash.has_key?(f) }
              if !missing.empty?
                msg = "Missing required fields: " + missing.join(", ")
                raise PreconditionException.new(error_prefix.empty? ? msg : "#{error_prefix}: #{msg}")
              end
            end

            # Asserts that value is not nill and is_?(klass). Returns
            # value. Common use is
            #
            # amount = Preconditions.assert_class('amount', amount, BigDecimal)
            def Preconditions.assert_class(field_name, value, klass)
              Preconditions.check_not_nil('field_name', field_name)
              Preconditions.check_not_nil('klass', klass)
              Preconditions.check_not_nil('value', value, "Value for %s cannot be nil. Expected an instance of class %s" % [field_name, klass.name])
              Preconditions.check_state(value.is_a?(klass),
                                        "Value for #{field_name} is of type[#{value.class}] - class[#{klass}] is required. value[#{value.inspect.to_s}]")
              value
            end

            def Preconditions.assert_class_or_nil(field_name, value, klass)
              if !value.nil?
                Preconditions.assert_class(field_name, value, klass)
              end
            end

            def Preconditions.assert_boolean(field_name, value)
              Preconditions.check_not_nil('field_name', field_name)
              Preconditions.check_not_nil('value', value, "Value for %s cannot be nil. Expected an instance of TrueClass or FalseClass" % field_name)
              Preconditions.check_state(value.is_a?(TrueClass) || value.is_a?(FalseClass),
                                        "Value for #{field_name} is of type[#{value.class}] - class[TrueClass or FalseClass] is required. value[#{value.inspect.to_s}]")
              value
            end

            def Preconditions.assert_boolean_or_nil(field_name, value)
              if !value.nil?
                Preconditions.assert_boolean(field_name, value)
              end
            end

            def Preconditions.assert_collection_of_class(field_name, values, klass)
              Preconditions.assert_class(field_name, values, Array)
              values.each { |v| Preconditions.assert_class(field_name, v, klass) }
            end

            def Preconditions.assert_hash_of_class(field_name, hash, klass)
              Preconditions.assert_class(field_name, hash, Hash)
              values.each { |k, v| Preconditions.assert_class(field_name, v, klass) }
            end

          end

          class AuthScheme

            attr_reader :name

            def initialize(name)
              @name = HttpClient::Preconditions.check_not_blank('name', name)
            end

            BASIC = AuthScheme.new("basic") unless defined?(BASIC)

          end

          class Authorization

            attr_reader :scheme, :username, :password

            def initialize(scheme, username, opts={})
              @scheme = HttpClient::Preconditions.assert_class('schema', scheme, AuthScheme)
              @username = HttpClient::Preconditions.check_not_blank('username', username, "username is required")
              @password = HttpClient::Preconditions.assert_class_or_nil('password', opts.delete(:password), String)
              HttpClient::Preconditions.assert_empty_opts(opts)
            end

            def Authorization.basic(username, password=nil)
              Authorization.new(AuthScheme::BASIC, username, :password => password)
            end

          end

          module Helper

            def Helper.symbolize_keys(hash)
              Preconditions.assert_class('hash', hash, Hash)
              new_hash = {}
              hash.each { |k, v|
                new_hash[k.to_sym] = v
              }
              new_hash
            end

            def Helper.to_big_decimal(value)
              value ? BigDecimal(value.to_s) : nil
            end

            def Helper.to_object(value)
              value ? (value.is_a?(Hash) ? value : JSON.parse(value)) : nil
            end

            def Helper.to_uuid(value)
              Preconditions.check_state(value.nil? || value.match(/^\w\w\w\w\w\w\w\w\-\w\w\w\w\-\w\w\w\w\-\w\w\w\w\-\w\w\w\w\w\w\w\w\w\w\w\w$/),
                                        "Invalid guid[%s]" % value)
              value
            end

            def Helper.to_date_iso8601(value)
              if value.is_a?(Date)
                value
              elsif value
                Date.parse(value.to_s)
              else
                nil
              end
            end

            def Helper.to_date_time_iso8601(value)
              if value.is_a?(DateTime)
                value
              elsif value
                DateTime.parse(value.to_s)
              else
                nil
              end
            end

            def Helper.date_iso8601_to_string(value)
              value.nil? ? nil : value.strftime('%Y-%m-%d')
            end

            def Helper.date_time_iso8601_to_string(value)
              value.nil? ? nil : value.strftime('%Y-%m-%dT%H:%M:%S%z')
            end

            TRUE_STRINGS = ['t', 'true', 'y', 'yes', 'on', '1', 'trueclass'] unless defined?(TRUE_STRINGS)
            FALSE_STRINGS = ['f', 'false', 'n', 'no', 'off', '0', 'falseclass'] unless defined?(FALSE_STRINGS)

            def Helper.to_boolean(field_name, value)
              string = value.to_s.strip.downcase
              if TRUE_STRINGS.include?(string)
                true
              elsif FALSE_STRINGS.include?(string)
                false
              elsif string != ""
                raise PreconditionException.new("Unsupported boolean value[#{string}]. For true, must be one of: #{TRUE_STRINGS.inspect}. For false, must be one of: #{FALSE_STRINGS.inspect}")
              else
                nil
              end
            end

          end

        end
      end
    end
  end
end