Fixed issue with ambiguous reference.
[arvados.git] / lib / google / api_client / result.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 module Google
16   class APIClient
17     ##
18     # This class wraps a result returned by an API call.
19     class Result
20       def initialize(reference, request, response)
21         @reference = reference
22         @request = request
23         @response = response
24       end
25
26       attr_reader :reference
27
28       attr_reader :request
29
30       attr_reader :response
31
32       def status
33         return @response[0]
34       end
35
36       def headers
37         return @response[1]
38       end
39
40       def body
41         return @body ||= (begin
42           response_body = @response[2]
43           merged_body = (response_body.inject(StringIO.new) do |accu, chunk|
44             accu.write(chunk)
45             accu
46           end).string
47         end)
48       end
49
50       def data
51         return @data ||= (begin
52           _, content_type = self.headers.detect do |h, v|
53             h.downcase == 'Content-Type'.downcase
54           end
55           media_type = content_type[/^([^;]*);?.*$/, 1].strip.downcase
56           data = self.body
57           case media_type
58           when 'application/json'
59             data = ::JSON.parse(data)
60             # Strip data wrapper, if present
61             data = data['data'] if data.has_key?('data')
62           else
63             raise ArgumentError,
64               "Content-Type not supported for parsing: #{media_type}"
65           end
66           if @reference.api_method && @reference.api_method.response_schema
67             # Automatically parse using the schema designated for the
68             # response of this API method.
69             data = @reference.api_method.response_schema.new(data)
70             data
71           else
72             # Otherwise, return the raw unparsed value.
73             # This value must be indexable like a Hash.
74             data
75           end
76         end)
77       end
78
79       def pagination_type
80         return :token
81       end
82
83       def page_token_param
84         return "pageToken"
85       end
86
87       def next_page_token
88         if self.data.respond_to?(:next_page_token)
89           return self.data.next_page_token
90         elsif self.data.respond_to?(:[])
91           return self.data["nextPageToken"]
92         else
93           raise TypeError, "Data object did not respond to #next_page_token."
94         end
95       end
96
97       def next_page
98         merged_parameters = Hash[self.reference.parameters].merge({
99           self.page_token_param => self.next_page_token
100         })
101         # Because References can be coerced to Hashes, we can merge them,
102         # preserving all context except the API method parameters that we're
103         # using for pagination.
104         return Google::APIClient::Reference.new(
105           Hash[self.reference].merge(:parameters => merged_parameters)
106         )
107       end
108
109       def prev_page_token
110         if self.data.respond_to?(:prev_page_token)
111           return self.data.prev_page_token
112         elsif self.data.respond_to?(:[])
113           return self.data["prevPageToken"]
114         else
115           raise TypeError, "Data object did not respond to #next_page_token."
116         end
117       end
118
119       def prev_page
120         merged_parameters = Hash[self.reference.parameters].merge({
121           self.page_token_param => self.prev_page_token
122         })
123         # Because References can be coerced to Hashes, we can merge them,
124         # preserving all context except the API method parameters that we're
125         # using for pagination.
126         return Google::APIClient::Reference.new(
127           Hash[self.reference].merge(:parameters => merged_parameters)
128         )
129       end
130     end
131   end
132 end