google-ads-common 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +68 -0
- data/Rakefile +128 -0
- data/lib/ads_common/api.rb +183 -0
- data/lib/ads_common/api_config.rb +284 -0
- data/lib/ads_common/auth/base_handler.rb +53 -0
- data/lib/ads_common/auth/client_login_handler.rb +180 -0
- data/lib/ads_common/build/rake_common.rb +339 -0
- data/lib/ads_common/build/savon_abstract_generator.rb +59 -0
- data/lib/ads_common/build/savon_generator.rb +136 -0
- data/lib/ads_common/build/savon_registry.rb +236 -0
- data/lib/ads_common/build/savon_registry_generator.rb +139 -0
- data/lib/ads_common/build/savon_service_generator.rb +130 -0
- data/lib/ads_common/build/soap4r_generator.rb +565 -0
- data/lib/ads_common/config.rb +122 -0
- data/lib/ads_common/credential_handler.rb +72 -0
- data/lib/ads_common/errors.rb +70 -0
- data/lib/ads_common/http.rb +75 -0
- data/lib/ads_common/logger.rb +68 -0
- data/lib/ads_common/savon_headers/simple_header_handler.rb +148 -0
- data/lib/ads_common/soap4r_headers/nested_header_handler.rb +50 -0
- data/lib/ads_common/soap4r_headers/single_header_handler.rb +44 -0
- data/lib/ads_common/soap4r_patches.rb +210 -0
- data/lib/ads_common/soap4r_response_handler.rb +89 -0
- metadata +141 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Author:: api.dklimkin@gmail.com (Danial Klimkin)
|
4
|
+
#
|
5
|
+
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# License:: Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
16
|
+
# implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
# Code template for wrappers generation for Savon backend
|
21
|
+
|
22
|
+
require 'savon'
|
23
|
+
require 'ads_common/build/savon_abstract_generator'
|
24
|
+
|
25
|
+
module AdsCommon
|
26
|
+
module Build
|
27
|
+
class SavonServiceGenerator < SavonAbstractGenerator
|
28
|
+
SERVICE_TEMPLATE = %q{<% %>
|
29
|
+
#!/usr/bin/ruby
|
30
|
+
# This is auto-generated code, changes will be overwritten.
|
31
|
+
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
|
32
|
+
# License:: Licensed under the Apache License,Version 2.0 (the "License").
|
33
|
+
#
|
34
|
+
# <%= @generator_stamp %>
|
35
|
+
|
36
|
+
require 'savon'
|
37
|
+
require '<%= @require_path %>/<%= @service_name.to_s.snakecase %>_registry'
|
38
|
+
|
39
|
+
<%= @modules_open_string %>
|
40
|
+
|
41
|
+
class <%= @service_name %>
|
42
|
+
attr_accessor :headerhandler, :wiredump_dev, :options
|
43
|
+
def initialize(endpoint)
|
44
|
+
@headerhandler = []
|
45
|
+
@wiredump_dev = nil
|
46
|
+
@options = {}
|
47
|
+
@client = Savon::Client.new do |wsdl|
|
48
|
+
wsdl.namespace = '<%= @namespace %>'
|
49
|
+
wsdl.endpoint = endpoint
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
<% @actions.each do |action| %>
|
54
|
+
def <%= action %>(args = nil)
|
55
|
+
validate_args(:<%= action %>, args)
|
56
|
+
response = @client.request(:<%= action %>) {|soap|
|
57
|
+
set_headers(soap, args)
|
58
|
+
}
|
59
|
+
handle_errors(response)
|
60
|
+
return extract_result(response, '<%= action %>')
|
61
|
+
end
|
62
|
+
<% end %>
|
63
|
+
private
|
64
|
+
|
65
|
+
def validate_args(action_symbol, args = nil)
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_headers(soap, args)
|
70
|
+
@headerhandler.each { |handler| handler.prepare_soap(soap, args) }
|
71
|
+
end
|
72
|
+
|
73
|
+
# Extracts the finest results possible for the given result. Returns
|
74
|
+
# the response itself in worst case (contents unknown).
|
75
|
+
def extract_result(response, action_name)
|
76
|
+
method = <%= @service_name %>Registry::get_method_signature(action_name)
|
77
|
+
action = method[:output][:name].to_sym
|
78
|
+
result = response.to_hash
|
79
|
+
result = result[action] if result.include?(action)
|
80
|
+
result = result[:rval] if result.include?(:rval)
|
81
|
+
return result
|
82
|
+
end
|
83
|
+
|
84
|
+
# Checks for errors in response and raises appropriate exception
|
85
|
+
def handle_errors(response)
|
86
|
+
if response.soap_fault?
|
87
|
+
exception = exception_for_soap_fault(response)
|
88
|
+
raise exception
|
89
|
+
end
|
90
|
+
|
91
|
+
if response.http_error?
|
92
|
+
raise AdsCommon::Errors::HttpError,
|
93
|
+
"HTTP Error occurred: %s" % response.http_error
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Finds an exception object for a given response
|
98
|
+
def exception_for_soap_fault(response)
|
99
|
+
begin
|
100
|
+
exception_fault =
|
101
|
+
response.to_hash[:fault][:detail][:api_exception_fault]
|
102
|
+
exception_name = exception_fault[:application_exception_type]
|
103
|
+
exception_class = <%= @module_name %>::const_get(exception_name)
|
104
|
+
return exception_class.new(exception_fault)
|
105
|
+
rescue Exception => e
|
106
|
+
return AdsCommon::Errors::ApiException.new(
|
107
|
+
"Failed to resolve exception (%s)\n SOAP fault: %s" %
|
108
|
+
[e.message, response.soap_fault])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
<%= @modules_close_string %>
|
113
|
+
|
114
|
+
}.gsub(/^ /, '')
|
115
|
+
|
116
|
+
def initialize(args)
|
117
|
+
super(args)
|
118
|
+
@actions = []
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_actions(actions)
|
122
|
+
@actions += actions
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_code_template()
|
126
|
+
SERVICE_TEMPLATE
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,565 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Author:: api.sgomes@gmail.com (Sérgio Gomes)
|
4
|
+
#
|
5
|
+
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# License:: Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
16
|
+
# implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
# Generates the wrappers for API services. Only used during the
|
21
|
+
# 'rake generate' step of library setup.
|
22
|
+
|
23
|
+
module AdsCommon
|
24
|
+
module Build
|
25
|
+
|
26
|
+
# Contains the methods that handle wrapper code generation.
|
27
|
+
module Soap4rGenerator
|
28
|
+
ARRAY_CLASSNAME = 'SOAP::SOAPArray'
|
29
|
+
|
30
|
+
# Should be overriden for specific APIs, to contain the API config
|
31
|
+
# module.
|
32
|
+
def api_config
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# Should be overriden for specific APIs, to contain the extension config
|
37
|
+
# module.
|
38
|
+
def extension_config
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Should be overriden for specific APIs, to contain an instance of
|
43
|
+
# AdsCommon::Config with the configs for the appropriate library.
|
44
|
+
def config
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# Converts from camelCase names to underscore_separated names.
|
49
|
+
#
|
50
|
+
# Args:
|
51
|
+
# - text: the text to be converted
|
52
|
+
#
|
53
|
+
def underscore(text)
|
54
|
+
text.gsub(/[a-z0-9][A-Z]/) do |match|
|
55
|
+
match[0,1] + '_' + match[1,1].downcase
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generate the wrapper class for a given service.
|
60
|
+
# These classes make it easier to invoke the API methods, by removing the
|
61
|
+
# need to instance a <MethodName> object, instead allowing passing of the
|
62
|
+
# call parameters directly.
|
63
|
+
#
|
64
|
+
# Args:
|
65
|
+
# - version: the API version (as an integer)
|
66
|
+
# - service: the service name (as a string)
|
67
|
+
#
|
68
|
+
# Returns:
|
69
|
+
# The Ruby code for the class, as a string.
|
70
|
+
#
|
71
|
+
def generate_wrapper_class(version, service)
|
72
|
+
wrapper = service.to_s + "Wrapper"
|
73
|
+
module_name = api_config.module_name(version, service)
|
74
|
+
driver = api_config.interface_name(version, service)
|
75
|
+
driver_class = eval(driver)
|
76
|
+
api_name = api_config.api_name
|
77
|
+
|
78
|
+
registry =
|
79
|
+
eval("#{module_name}::DefaultMappingRegistry::LiteralRegistry")
|
80
|
+
|
81
|
+
class_def = <<-EOS
|
82
|
+
# This file was automatically generated during the "rake generate" step of
|
83
|
+
# library setup.
|
84
|
+
require '#{api_config.api_path}/#{version}/#{service}Driver.rb'
|
85
|
+
|
86
|
+
module #{api_name}
|
87
|
+
module #{version.to_s.upcase}
|
88
|
+
module #{service}
|
89
|
+
|
90
|
+
# Wrapper class for the #{version.to_s} #{service} service.
|
91
|
+
# This class is automatically generated.
|
92
|
+
class #{wrapper}
|
93
|
+
|
94
|
+
# Holds the API object to which the wrapper belongs.
|
95
|
+
attr_reader :api
|
96
|
+
|
97
|
+
# Version and service utility fields.
|
98
|
+
attr_reader :version, :service
|
99
|
+
|
100
|
+
REGISTRY = #{module_name}::DefaultMappingRegistry::LiteralRegistry
|
101
|
+
# This takes advantage of the code generated by soap4r to get the
|
102
|
+
# correct namespace for a given service. It accesses one of the fields
|
103
|
+
# in the description of the service's methods, which indicates the
|
104
|
+
# namespace.
|
105
|
+
# Since we're using a fixed version of soap4r (1.5.8), and this is
|
106
|
+
# automatically generated as part of the stub generation, it will
|
107
|
+
# always point to what we want.
|
108
|
+
NAMESPACE = '#{driver_class::Methods[0][2][0][2][1]}'
|
109
|
+
|
110
|
+
# Holds a shortcut to the parent module.
|
111
|
+
# Use this to avoid typing the full class name when creating classes
|
112
|
+
# belonging to this service, e.g.
|
113
|
+
# service_object.module::ClassName
|
114
|
+
# instead of
|
115
|
+
# #{api_name}::#{version.to_s.upcase}::#{service}::ClassName
|
116
|
+
# This will make it easier to migrate your code between API versions.
|
117
|
+
attr_reader :module
|
118
|
+
|
119
|
+
public
|
120
|
+
|
121
|
+
# Constructor for #{wrapper}.
|
122
|
+
#
|
123
|
+
# Args:
|
124
|
+
# - driver: SOAP::RPC::Driver object with the remote SOAP methods for
|
125
|
+
# this service
|
126
|
+
# - api: the API object to which the wrapper belongs
|
127
|
+
#
|
128
|
+
def initialize(driver, api)
|
129
|
+
@driver = driver
|
130
|
+
@api = api
|
131
|
+
@module = #{api_name}::#{version.to_s.upcase}::#{service}
|
132
|
+
@version = :#{version}
|
133
|
+
@service = :#{service}
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns the namespace for this service.
|
137
|
+
def namespace
|
138
|
+
return NAMESPACE
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# Converts from underscore_separated names to camelCase names.
|
144
|
+
#
|
145
|
+
# Args:
|
146
|
+
# - text: the text to be converted
|
147
|
+
#
|
148
|
+
def camel_case(text)
|
149
|
+
text.gsub(/_\\w/) {|match| match[1..-1].upcase}
|
150
|
+
end
|
151
|
+
|
152
|
+
# Converts from camelCase names to underscore_separated names.
|
153
|
+
#
|
154
|
+
# Args:
|
155
|
+
# - text: the text to be converted
|
156
|
+
#
|
157
|
+
def underscore(text)
|
158
|
+
text.gsub(/[a-z0-9][A-Z]/) do |match|
|
159
|
+
match[0,1] + '_' + match[1,1].downcase
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Validates whether an object is of the correct type.
|
164
|
+
# This method is invoked by the hash to object converter during
|
165
|
+
# runtime to check the type validity of every object.
|
166
|
+
#
|
167
|
+
# Args:
|
168
|
+
# - object: the hash "object" being evaluated
|
169
|
+
# - type: the expected type (the class object itself)
|
170
|
+
#
|
171
|
+
# Returns:
|
172
|
+
# nil, upon success
|
173
|
+
#
|
174
|
+
# Raises:
|
175
|
+
# - ArgumentError: in case of an unexpected type
|
176
|
+
#
|
177
|
+
def validate_object(object, type)
|
178
|
+
return nil if object.is_a? type
|
179
|
+
|
180
|
+
wsdl_type_obj = type.new
|
181
|
+
|
182
|
+
if object.is_a? Hash
|
183
|
+
xsi_type = object[:xsi_type] or object['xsi_type']
|
184
|
+
if xsi_type
|
185
|
+
begin
|
186
|
+
subtype = @module.class_eval(xsi_type)
|
187
|
+
user_type_obj = subtype.new
|
188
|
+
rescue
|
189
|
+
raise ArgumentError, "Specified xsi_type '" + xsi_type +
|
190
|
+
"' is unknown"
|
191
|
+
end
|
192
|
+
unless user_type_obj.is_a? type
|
193
|
+
raise ArgumentError, "Specified xsi_type '" + xsi_type +
|
194
|
+
"' is not a subclass of " + type.to_s
|
195
|
+
end
|
196
|
+
else
|
197
|
+
object.each do |key, value|
|
198
|
+
if key.to_s != 'xsi_type'
|
199
|
+
if !wsdl_type_obj.respond_to?(camel_case(key.to_s).to_sym)
|
200
|
+
raise ArgumentError, "Unknown property '" + key.to_s +
|
201
|
+
"' for type " + type.to_s
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
return nil
|
208
|
+
end
|
209
|
+
|
210
|
+
# Sets a property on a real (soap4r-generated) object.
|
211
|
+
#
|
212
|
+
# Args:
|
213
|
+
# - object: the object being modified
|
214
|
+
# - property: the property being set
|
215
|
+
# - value: the value it's being set to
|
216
|
+
#
|
217
|
+
def set_object_property(object, property, value)
|
218
|
+
begin
|
219
|
+
object.send(property.to_s + '=', value)
|
220
|
+
rescue
|
221
|
+
object_class = object.class.name.split('::').last
|
222
|
+
error = AdsCommon::Errors::MissingPropertyError.new(
|
223
|
+
property, object_class)
|
224
|
+
message = "'Missing property `" + property.to_s +
|
225
|
+
"' for object class `" + object_class + "'"
|
226
|
+
raise(error, message)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
public
|
231
|
+
|
232
|
+
# Converts dynamic objects (property hashes) into real soap4r objects.
|
233
|
+
# This is meant to be called when setting properties on a class, so
|
234
|
+
# the method receives an optional parameter specifying the class and
|
235
|
+
# property. This way, it's possible to determine the default type for
|
236
|
+
# the object if none is provided.
|
237
|
+
#
|
238
|
+
# Args:
|
239
|
+
# - object: the object being converted
|
240
|
+
# - parent_class: the class whose property is being set
|
241
|
+
# - property: the property being set
|
242
|
+
#
|
243
|
+
def convert_to_object(object, parent_class = nil, property = nil)
|
244
|
+
property = camel_case(property.to_s) if property
|
245
|
+
if object.is_a? Hash
|
246
|
+
# Process a hash.
|
247
|
+
specified_class = object[:xsi_type] or object['xsi_type']
|
248
|
+
default_class = nil
|
249
|
+
# Determine default class for this object, given the property
|
250
|
+
# being set.
|
251
|
+
if parent_class and property
|
252
|
+
parent = REGISTRY.schema_definition_from_class(parent_class)
|
253
|
+
element = parent.elements.entries.find do |entry|
|
254
|
+
entry.varname.to_s == property.to_s
|
255
|
+
end
|
256
|
+
default_class = element.mapped_class if element
|
257
|
+
end
|
258
|
+
validate_object(object, default_class)
|
259
|
+
real_class = nil
|
260
|
+
if specified_class
|
261
|
+
real_class = @module.class_eval(specified_class)
|
262
|
+
else
|
263
|
+
real_class = default_class
|
264
|
+
end
|
265
|
+
# Instance real object.
|
266
|
+
real_object = real_class.new
|
267
|
+
# Set each of its properties.
|
268
|
+
object.each do |entry, value|
|
269
|
+
entry = entry.to_s
|
270
|
+
unless entry == 'xsi_type'
|
271
|
+
if @api.config.read('service.use_ruby_names')
|
272
|
+
entry = camel_case(entry)
|
273
|
+
end
|
274
|
+
if value.is_a? Hash
|
275
|
+
# Recurse.
|
276
|
+
set_object_property(real_object, entry,
|
277
|
+
convert_to_object(value, real_class, entry))
|
278
|
+
elsif value.is_a? Array
|
279
|
+
set_object_property(real_object, entry,
|
280
|
+
value.map do |item|
|
281
|
+
# Recurse.
|
282
|
+
convert_to_object(item, real_class, entry)
|
283
|
+
end
|
284
|
+
)
|
285
|
+
else
|
286
|
+
set_object_property(real_object, entry, value)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
return real_object
|
291
|
+
elsif object.is_a? Array
|
292
|
+
# Process an array
|
293
|
+
return object.map do |entry|
|
294
|
+
# Recurse.
|
295
|
+
convert_to_object(entry, parent_class, property)
|
296
|
+
end
|
297
|
+
else
|
298
|
+
return object
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# Converts real soap4r objects into dynamic ones (property hashes).
|
303
|
+
# This is meant to be called for return objects of remote calls.
|
304
|
+
#
|
305
|
+
# Args:
|
306
|
+
# - object: the object being converted
|
307
|
+
#
|
308
|
+
def convert_from_object(object)
|
309
|
+
if object.class.name =~
|
310
|
+
/#{api_config.api_name}::#{version.to_s.upcase}::\\w+::\\w+/
|
311
|
+
# Handle soap4r object
|
312
|
+
object_class = REGISTRY.schema_definition_from_class(object.class)
|
313
|
+
if object_class.elements and !object_class.elements.entries.empty?
|
314
|
+
# Process complex object.
|
315
|
+
hash = {}
|
316
|
+
hash[:xsi_type] = object.class.name.split('::').last
|
317
|
+
object_class.elements.entries.each do |entry|
|
318
|
+
property = entry.varname.to_s
|
319
|
+
if object.respond_to? property and !property.include?('_Type')
|
320
|
+
value = object.send(property)
|
321
|
+
property_name = nil
|
322
|
+
if @api.config.read('service.use_ruby_names')
|
323
|
+
property_name = underscore(property).to_sym
|
324
|
+
else
|
325
|
+
property_name = property.to_sym
|
326
|
+
end
|
327
|
+
# Recurse.
|
328
|
+
hash[property_name] = convert_from_object(value) if value
|
329
|
+
end
|
330
|
+
end
|
331
|
+
return hash
|
332
|
+
else
|
333
|
+
# Process simple object.
|
334
|
+
parent = object.class.superclass
|
335
|
+
return parent.new(object)
|
336
|
+
end
|
337
|
+
elsif object.is_a? Array
|
338
|
+
# Handle arrays
|
339
|
+
return object.map do |entry|
|
340
|
+
# Recurse.
|
341
|
+
convert_from_object(entry)
|
342
|
+
end
|
343
|
+
else
|
344
|
+
# Handle native objects
|
345
|
+
return object
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
|
350
|
+
public
|
351
|
+
|
352
|
+
EOS
|
353
|
+
|
354
|
+
# Add service methods
|
355
|
+
methods = driver_class::Methods
|
356
|
+
module_name = api_config.module_name(version, service)
|
357
|
+
methods.each do |method|
|
358
|
+
name = method[1]
|
359
|
+
doc_link = doc_link(version, service, name)
|
360
|
+
method_def = <<-EOS
|
361
|
+
# Calls the {#{name}}[#{doc_link}] method of the #{service} service.
|
362
|
+
# Check {the online documentation for this method}[#{doc_link}].
|
363
|
+
EOS
|
364
|
+
|
365
|
+
begin
|
366
|
+
method_class = eval("#{module_name}::#{fix_case_up(name)}")
|
367
|
+
arguments =
|
368
|
+
registry.schema_definition_from_class(method_class).elements
|
369
|
+
rescue
|
370
|
+
method_class = nil
|
371
|
+
arguments = nil
|
372
|
+
end
|
373
|
+
|
374
|
+
if arguments and arguments.size > 0
|
375
|
+
method_def += <<-EOS
|
376
|
+
#
|
377
|
+
# Args:
|
378
|
+
EOS
|
379
|
+
end
|
380
|
+
|
381
|
+
if arguments
|
382
|
+
# Add list of arguments to the RDoc comment
|
383
|
+
arguments.each_with_index do |elem, index|
|
384
|
+
if type(elem) == ARRAY_CLASSNAME
|
385
|
+
method_def += <<-EOS
|
386
|
+
# - #{elem.varname}: #{type(elem)} of #{elem.mapped_class}
|
387
|
+
EOS
|
388
|
+
else
|
389
|
+
method_def += <<-EOS
|
390
|
+
# - #{elem.varname}: #{type(elem)}
|
391
|
+
EOS
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
begin
|
397
|
+
response_class =
|
398
|
+
eval("#{module_name}::#{fix_case_up(name)}Response")
|
399
|
+
returns =
|
400
|
+
registry.schema_definition_from_class(response_class).elements
|
401
|
+
|
402
|
+
if returns.size > 0
|
403
|
+
method_def += <<-EOS
|
404
|
+
#
|
405
|
+
# Returns:
|
406
|
+
EOS
|
407
|
+
end
|
408
|
+
|
409
|
+
# Add list of returns to the RDoc comment
|
410
|
+
returns.each_with_index do |elem, index|
|
411
|
+
if type(elem) == ARRAY_CLASSNAME
|
412
|
+
method_def += <<-EOS
|
413
|
+
# - #{elem.varname}: #{type(elem)} of #{elem.mapped_class}
|
414
|
+
EOS
|
415
|
+
else
|
416
|
+
method_def += <<-EOS
|
417
|
+
# - #{elem.varname}: #{type(elem)}
|
418
|
+
EOS
|
419
|
+
end
|
420
|
+
end
|
421
|
+
rescue
|
422
|
+
method_def += <<-EOS
|
423
|
+
#
|
424
|
+
# Returns:
|
425
|
+
EOS
|
426
|
+
end
|
427
|
+
|
428
|
+
arg_names = arguments ? arguments.map {|elem| elem.varname} : []
|
429
|
+
arg_list = arg_names.join(', ')
|
430
|
+
|
431
|
+
method_def += <<-EOS
|
432
|
+
#
|
433
|
+
# Raises:
|
434
|
+
# Error::ApiError (or a subclass thereof) if a SOAP fault occurs.
|
435
|
+
#
|
436
|
+
def #{name}(#{arg_list})
|
437
|
+
begin
|
438
|
+
arg_array = []
|
439
|
+
EOS
|
440
|
+
|
441
|
+
# Add validation for every argument
|
442
|
+
if arguments
|
443
|
+
arguments.each_with_index do |elem, index|
|
444
|
+
method_def += <<-EOS
|
445
|
+
validate_object(#{arg_names[index]}, #{type(elem)})
|
446
|
+
arg_array << convert_to_object(#{elem.varname}, #{method_class},
|
447
|
+
'#{elem.varname}')
|
448
|
+
EOS
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
method_def += <<-EOS
|
453
|
+
# Construct request object and make API call
|
454
|
+
EOS
|
455
|
+
|
456
|
+
if arguments
|
457
|
+
method_def += <<-EOS
|
458
|
+
obj = #{module_name}::#{fix_case_up(name)}.new(*arg_array)
|
459
|
+
reply = convert_from_object(@driver.#{name}(obj))
|
460
|
+
EOS
|
461
|
+
else
|
462
|
+
method_def += <<-EOS
|
463
|
+
reply = convert_from_object(@driver.#{name}())
|
464
|
+
EOS
|
465
|
+
end
|
466
|
+
|
467
|
+
method_def += <<-EOS
|
468
|
+
reply = reply[:rval] if reply.include?(:rval)
|
469
|
+
return reply
|
470
|
+
rescue SOAP::FaultError => fault
|
471
|
+
raise #{api_config.api_name}::Errors.create_api_exception(fault,
|
472
|
+
self)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
EOS
|
477
|
+
class_def += method_def
|
478
|
+
|
479
|
+
if name != underscore(name)
|
480
|
+
class_def += <<-EOS
|
481
|
+
alias #{underscore(name)} #{name}\n
|
482
|
+
|
483
|
+
EOS
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
# Add extension methods, if any
|
488
|
+
extensions = extension_config.extensions[[version, service]]
|
489
|
+
unless extensions.nil?
|
490
|
+
extensions.each do |ext|
|
491
|
+
params = extension_config.methods[ext].join(', ')
|
492
|
+
arglist = 'self'
|
493
|
+
arglist += ", #{params}" if params != ''
|
494
|
+
method_def = <<-EOS
|
495
|
+
# <i>Extension method</i> -- Calls the
|
496
|
+
# #{api_config.api_name}::Extensions.#{ext} method with +self+ as the
|
497
|
+
# first parameter.
|
498
|
+
def #{ext}(#{params})
|
499
|
+
return #{api_config.api_name}::Extensions.#{ext}(#{arglist})
|
500
|
+
end
|
501
|
+
|
502
|
+
EOS
|
503
|
+
class_def += method_def
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
class_def += <<-EOS
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
512
|
+
EOS
|
513
|
+
return class_def
|
514
|
+
end
|
515
|
+
|
516
|
+
# Helper method to fix a method name from lowerCamelCase to CamelCase.
|
517
|
+
#
|
518
|
+
# Args:
|
519
|
+
# - name: the method name
|
520
|
+
#
|
521
|
+
# Returns:
|
522
|
+
# The fixed name.
|
523
|
+
#
|
524
|
+
def fix_case_up(name)
|
525
|
+
return name[0, 1].upcase + name[1..-1]
|
526
|
+
end
|
527
|
+
|
528
|
+
# Helper method to create a link to a method's entry in the API online
|
529
|
+
# docs.
|
530
|
+
#
|
531
|
+
# Args:
|
532
|
+
# - version: the API version (as an integer)
|
533
|
+
# - service: the service name (as a string)
|
534
|
+
# - method: the method name (as a string)
|
535
|
+
#
|
536
|
+
# Returns:
|
537
|
+
# The URL to the method's entry in the documentation (as a string).
|
538
|
+
# +nil+ if none.
|
539
|
+
#
|
540
|
+
def doc_link(version, service, method)
|
541
|
+
return nil
|
542
|
+
end
|
543
|
+
|
544
|
+
# Helper method to return the expected type for a parameter, given the
|
545
|
+
# SchemaElementDefinition.
|
546
|
+
#
|
547
|
+
# Args:
|
548
|
+
# - element: SOAP::Mapping::SchemaElementDefinition element for the
|
549
|
+
# parameter (taken from the schema definition of the class)
|
550
|
+
#
|
551
|
+
# Returns:
|
552
|
+
# The full name for the expected parameter type (as a String)
|
553
|
+
#
|
554
|
+
def type(element)
|
555
|
+
# Check if it's an array
|
556
|
+
if element.as_array?
|
557
|
+
return ARRAY_CLASSNAME
|
558
|
+
else
|
559
|
+
return element.mapped_class
|
560
|
+
end
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|