X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/286a7152f2984ca4704b4174a4c6cadca793c28e..f736ac4d9735600af24d8b71dd7b1fa40b4b055e:/lib/google/api_client/discovery.rb diff --git a/lib/google/api_client/discovery.rb b/lib/google/api_client/discovery.rb index 88a0a6ef82..bb01d67ce7 100644 --- a/lib/google/api_client/discovery.rb +++ b/lib/google/api_client/discovery.rb @@ -13,565 +13,7 @@ # limitations under the License. -require 'json' -require 'addressable/uri' -require 'addressable/template' - -require 'google/inflection' -require 'google/api_client/errors' - -module Google - class APIClient - ## - # A service that has been described by a discovery document. - class API - - ## - # Creates a description of a particular version of a service. - # - # @param [String] api - # The identifier for the service. Note that while this frequently - # matches the first segment of all of the service's RPC names, this - # should not be assumed. There is no requirement that these match. - # @param [String] version - # The identifier for the service version. - # @param [Hash] api_description - # The section of the discovery document that applies to this service - # version. - # - # @return [Google::APIClient::API] The constructed service object. - def initialize(document_base, discovery_document) - @document_base = Addressable::URI.parse(document_base) - @discovery_document = discovery_document - metaclass = (class <String representation of the service's state. - # - # @return [String] The service's state, as a String. - def inspect - sprintf( - "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.name - ) - end - end - - ## - # A resource that has been described by a discovery document. - class Resource - - ## - # Creates a description of a particular version of a resource. - # - # @param [Addressable::URI] base - # The base URI for the service. - # @param [String] resource_name - # The identifier for the resource. - # @param [Hash] resource_description - # The section of the discovery document that applies to this resource. - # - # @return [Google::APIClient::Resource] The constructed resource object. - def initialize(rest_base, resource_name, discovery_document) - @rest_base = rest_base - @name = resource_name - @discovery_document = discovery_document - metaclass = (class <String representation of the resource's state. - # - # @return [String] The resource's state, as a String. - def inspect - sprintf( - "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.name - ) - end - end - - ## - # A method that has been described by a discovery document. - class Method - - ## - # Creates a description of a particular method. - # - # @param [Addressable::URI] rest_base - # The base URI for the service. - # @param [String] method_name - # The identifier for the method. - # @param [Hash] method_description - # The section of the discovery document that applies to this method. - # - # @return [Google::APIClient::Method] The constructed method object. - def initialize(rest_base, method_name, discovery_document) - @rest_base = rest_base - @name = method_name - @discovery_document = discovery_document - end - - ## - # Returns the identifier for the method. - # - # @return [String] The method identifier. - attr_reader :name - - ## - # Returns the parsed section of the discovery document that applies to - # this method. - # - # @return [Hash] The method description. - attr_reader :description - - ## - # Returns the base URI for the method. - # - # @return [Addressable::URI] - # The base URI that this method will be joined to. - attr_reader :rest_base - - ## - # Updates the method with the new base. - # - # @param [Addressable::URI, #to_str, String] new_base - # The new base URI to use for the method. - def rest_base=(new_rest_base) - @rest_base = Addressable::URI.parse(new_rest_base) - @uri_template = nil - end - - ## - # Returns the RPC name for the method. - # - # @return [String] The RPC name. - def rpc_method - return @discovery_document['rpcMethod'] - end - - ## - # Returns the URI template for the method. A parameter list can be - # used to expand this into a URI. - # - # @return [Addressable::Template] The URI template. - def uri_template - # TODO(bobaman) We shouldn't be calling #to_s here, this should be - # a join operation on a URI, but we have to treat these as Strings - # because of the way the discovery document provides the URIs. - # This should be fixed soon. - return @uri_template ||= Addressable::Template.new( - self.rest_base + @discovery_document['restPath'] - ) - end - - ## - # Normalizes parameters, converting to the appropriate types. - # - # @param [Hash, Array] parameters - # The parameters to normalize. - # - # @return [Hash] The normalized parameters. - def normalize_parameters(parameters={}) - # Convert keys to Strings when appropriate - if parameters.kind_of?(Hash) || parameters.kind_of?(Array) - # Is a Hash or an Array a better return type? Do we ever need to - # worry about the same parameter being sent twice with different - # values? - parameters = parameters.inject({}) do |accu, (k, v)| - k = k.to_s if k.kind_of?(Symbol) - k = k.to_str if k.respond_to?(:to_str) - unless k.kind_of?(String) - raise TypeError, "Expected String, got #{k.class}." - end - accu[k] = v - accu - end - else - raise TypeError, - "Expected Hash or Array, got #{parameters.class}." - end - return parameters - end - - ## - # Expands the method's URI template using a parameter list. - # - # @param [Hash, Array] parameters - # The parameter list to use. - # - # @return [Addressable::URI] The URI after expansion. - def generate_uri(parameters={}) - parameters = self.normalize_parameters(parameters) - self.validate_parameters(parameters) - template_variables = self.uri_template.variables - uri = self.uri_template.expand(parameters) - query_parameters = parameters.reject do |k, v| - template_variables.include?(k) - end - if query_parameters.size > 0 - uri.query_values = (uri.query_values || {}).merge(query_parameters) - end - # Normalization is necessary because of undesirable percent-escaping - # during URI template expansion - return uri.normalize - end - - ## - # Generates an HTTP request for this method. - # - # @param [Hash, Array] parameters - # The parameters to send. - # @param [String, StringIO] body The body for the HTTP request. - # @param [Hash, Array] headers The HTTP headers for the request. - # - # @return [Array] The generated HTTP request. - def generate_request(parameters={}, body='', headers=[]) - if body.respond_to?(:string) - body = body.string - elsif body.respond_to?(:to_str) - body = body.to_str - else - raise TypeError, "Expected String or StringIO, got #{body.class}." - end - if !headers.kind_of?(Array) && !headers.kind_of?(Hash) - raise TypeError, "Expected Hash or Array, got #{headers.class}." - end - method = @discovery_document['httpMethod'] || 'GET' - uri = self.generate_uri(parameters) - headers = headers.to_a if headers.kind_of?(Hash) - return [method, uri.to_str, headers, [body]] - end - - ## - # Returns a Hash of the parameter descriptions for - # this method. - # - # @return [Hash] The parameter descriptions. - def parameter_descriptions - @parameter_descriptions ||= ( - @discovery_document['parameters'] || {} - ).inject({}) { |h,(k,v)| h[k]=v; h } - end - - ## - # Returns an Array of the parameters for this method. - # - # @return [Array] The parameters. - def parameters - @parameters ||= (( - @discovery_document['parameters'] || {} - ).inject({}) { |h,(k,v)| h[k]=v; h }).keys - end - - ## - # Returns an Array of the required parameters for this - # method. - # - # @return [Array] The required parameters. - # - # @example - # # A list of all required parameters. - # method.required_parameters - def required_parameters - @required_parameters ||= ((self.parameter_descriptions.select do |k, v| - v['required'] - end).inject({}) { |h,(k,v)| h[k]=v; h }).keys - end - - ## - # Returns an Array of the optional parameters for this - # method. - # - # @return [Array] The optional parameters. - # - # @example - # # A list of all optional parameters. - # method.optional_parameters - def optional_parameters - @optional_parameters ||= ((self.parameter_descriptions.reject do |k, v| - v['required'] - end).inject({}) { |h,(k,v)| h[k]=v; h }).keys - end - - ## - # Verifies that the parameters are valid for this method. Raises an - # exception if validation fails. - # - # @param [Hash, Array] parameters - # The parameters to verify. - # - # @return [NilClass] nil if validation passes. - def validate_parameters(parameters={}) - parameters = self.normalize_parameters(parameters) - required_variables = ((self.parameter_descriptions.select do |k, v| - v['required'] - end).inject({}) { |h,(k,v)| h[k]=v; h }).keys - missing_variables = required_variables - parameters.keys - if missing_variables.size > 0 - raise ArgumentError, - "Missing required parameters: #{missing_variables.join(', ')}." - end - parameters.each do |k, v| - if self.parameter_descriptions[k] - enum = self.parameter_descriptions[k]['enum'] - if enum && !enum.include?(v) - raise ArgumentError, - "Parameter '#{k}' has an invalid value: #{v}. " + - "Must be one of #{enum.inspect}." - end - pattern = self.parameter_descriptions[k]['pattern'] - if pattern - regexp = Regexp.new("^#{pattern}$") - if v !~ regexp - raise ArgumentError, - "Parameter '#{k}' has an invalid value: #{v}. " + - "Must match: /^#{pattern}$/." - end - end - end - end - return nil - end - - ## - # Returns a String representation of the method's state. - # - # @return [String] The method's state, as a String. - def inspect - sprintf( - "#<%s:%#0x NAME:%s>", - self.class.to_s, self.object_id, self.rpc_method - ) - end - end - end -end +require 'google/api_client/discovery/api' +require 'google/api_client/discovery/resource' +require 'google/api_client/discovery/method' +require 'google/api_client/discovery/schema'