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