Mostly doc updates, +remove support for method as string
[arvados.git] / lib / google / api_client / discovery / api.rb
1 # Copyright 2010 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15
16 require 'addressable/uri'
17
18 require 'google/inflection'
19 require 'google/api_client/discovery/resource'
20 require 'google/api_client/discovery/method'
21 require 'google/api_client/discovery/media'
22
23 module Google
24   class APIClient
25     ##
26     # A service that has been described by a discovery document.
27     class API
28
29       ##
30       # Creates a description of a particular version of a service.
31       #
32       # @param [String] document_base
33       #   Base URI for the service
34       # @param [Hash] discovery_document
35       #   The section of the discovery document that applies to this service
36       #   version.
37       #
38       # @return [Google::APIClient::API] The constructed service object.
39       def initialize(document_base, discovery_document)
40         @document_base = Addressable::URI.parse(document_base)
41         @discovery_document = discovery_document
42         metaclass = (class << self; self; end)
43         self.discovered_resources.each do |resource|
44           method_name = Google::INFLECTOR.underscore(resource.name).to_sym
45           if !self.respond_to?(method_name)
46             metaclass.send(:define_method, method_name) { resource }
47           end
48         end
49         self.discovered_methods.each do |method|
50           method_name = Google::INFLECTOR.underscore(method.name).to_sym
51           if !self.respond_to?(method_name)
52             metaclass.send(:define_method, method_name) { method }
53           end
54         end
55       end
56
57       ##
58       # Returns the id of the service.
59       #
60       # @return [String] The service id.
61       def id
62         return (
63           @discovery_document['id'] ||
64           "#{self.name}:#{self.version}"
65         )
66       end
67
68       ##
69       # Returns the identifier for the service.
70       #
71       # @return [String] The service identifier.
72       def name
73         return @discovery_document['name']
74       end
75
76       ##
77       # Returns the version of the service.
78       #
79       # @return [String] The service version.
80       def version
81         return @discovery_document['version']
82       end
83
84       ##
85       # Returns a human-readable title for the API.
86       #
87       # @return [Hash] The API title.
88       def title
89         return @discovery_document['title']
90       end
91
92       ##
93       # Returns a human-readable description of the API.
94       #
95       # @return [Hash] The API description.
96       def description
97         return @discovery_document['description']
98       end
99
100       ##
101       # Returns a URI for the API documentation.
102       #
103       # @return [Hash] The API documentation.
104       def documentation
105         return Addressable::URI.parse(@discovery_document['documentationLink'])
106       end
107
108       ##
109       # Returns true if this is the preferred version of this API.
110       #
111       # @return [TrueClass, FalseClass]
112       #   Whether or not this is the preferred version of this API.
113       def preferred
114         return !!@discovery_document['preferred']
115       end
116
117       ##
118       # Returns the list of API features.
119       #
120       # @return [Array]
121       #   The features supported by this API.
122       def features
123         return @discovery_document['features'] || []
124       end
125
126       ##
127       # Returns true if this API uses a data wrapper.
128       #
129       # @return [TrueClass, FalseClass]
130       #   Whether or not this API uses a data wrapper.
131       def data_wrapper?
132         return self.features.include?('dataWrapper')
133       end
134
135       ##
136       # Returns the base URI for the discovery document.
137       #
138       # @return [Addressable::URI] The base URI.
139       attr_reader :document_base
140
141       ##
142       # Returns the base URI for this version of the service.
143       #
144       # @return [Addressable::URI] The base URI that methods are joined to.
145       def method_base
146         if @discovery_document['basePath']
147           return @method_base ||= (
148             self.document_base.join(Addressable::URI.parse(@discovery_document['basePath']))
149           ).normalize
150         else
151           return nil
152         end
153       end
154
155       ##
156       # Updates the hierarchy of resources and methods with the new base.
157       #
158       # @param [Addressable::URI, #to_str, String] new_method_base
159       #   The new base URI to use for the service.
160       def method_base=(new_method_base)
161         @method_base = Addressable::URI.parse(new_method_base)
162         self.discovered_resources.each do |resource|
163           resource.method_base = @method_base
164         end
165         self.discovered_methods.each do |method|
166           method.method_base = @method_base
167         end
168       end
169
170       ##
171       # Returns the base URI for batch calls to this service.
172       #
173       # @return [Addressable::URI] The base URI that methods are joined to.
174       def batch_path
175         if @discovery_document['batchPath']
176           return @batch_path ||= (
177             self.document_base.join(Addressable::URI.parse('/' +
178                 @discovery_document['batchPath']))
179           ).normalize
180         else
181           return nil
182         end
183       end
184
185       ##
186       # A list of schemas available for this version of the API.
187       #
188       # @return [Hash] A list of {Google::APIClient::Schema} objects.
189       def schemas
190         return @schemas ||= (
191           (@discovery_document['schemas'] || []).inject({}) do |accu, (k, v)|
192             accu[k] = Google::APIClient::Schema.parse(self, v)
193             accu
194           end
195         )
196       end
197
198       ##
199       # Returns a schema for a kind value.
200       #
201       # @return [Google::APIClient::Schema] The associated Schema object.
202       def schema_for_kind(kind)
203         api_name, schema_name = kind.split('#', 2)
204         if api_name != self.name
205           raise ArgumentError,
206             "The kind does not match this API. " +
207             "Expected '#{self.name}', got '#{api_name}'."
208         end
209         for k, v in self.schemas
210           return v if k.downcase == schema_name.downcase
211         end
212         return nil
213       end
214
215       ##
216       # A list of resources available at the root level of this version of the
217       # API.
218       #
219       # @return [Array] A list of {Google::APIClient::Resource} objects.
220       def discovered_resources
221         return @discovered_resources ||= (
222           (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
223             accu << Google::APIClient::Resource.new(
224               self, self.method_base, k, v
225             )
226             accu
227           end
228         )
229       end
230
231       ##
232       # A list of methods available at the root level of this version of the
233       # API.
234       #
235       # @return [Array] A list of {Google::APIClient::Method} objects.
236       def discovered_methods
237         return @discovered_methods ||= (
238           (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
239             accu << Google::APIClient::Method.new(self, self.method_base, k, v)
240             accu
241           end
242         )
243       end
244
245       ##
246       # Allows deep inspection of the discovery document.
247       def [](key)
248         return @discovery_document[key]
249       end
250
251       ##
252       # Converts the service to a flat mapping of RPC names and method objects.
253       #
254       # @return [Hash] All methods available on the service.
255       #
256       # @example
257       #   # Discover available methods
258       #   method_names = client.discovered_api('buzz').to_h.keys
259       def to_h
260         return @hash ||= (begin
261           methods_hash = {}
262           self.discovered_methods.each do |method|
263             methods_hash[method.id] = method
264           end
265           self.discovered_resources.each do |resource|
266             methods_hash.merge!(resource.to_h)
267           end
268           methods_hash
269         end)
270       end
271
272       ##
273       # Returns a <code>String</code> representation of the service's state.
274       #
275       # @return [String] The service's state, as a <code>String</code>.
276       def inspect
277         sprintf(
278           "#<%s:%#0x ID:%s>", self.class.to_s, self.object_id, self.id
279         )
280       end
281     end
282   end
283 end