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,59 @@
|
|
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 generator base class
|
21
|
+
|
22
|
+
require 'savon'
|
23
|
+
require 'erb'
|
24
|
+
|
25
|
+
module AdsCommon
|
26
|
+
module Build
|
27
|
+
class SavonAbstractGenerator
|
28
|
+
def initialize(args)
|
29
|
+
if self.class() == AdsCommon::Build::SavonAbstractGenerator
|
30
|
+
raise NoMethodError, "Tried to instantiate an abstract class"
|
31
|
+
end
|
32
|
+
@require_path = args[:require_path]
|
33
|
+
@service_name = args[:service_name]
|
34
|
+
@module_name = args[:module_name]
|
35
|
+
@namespace = args[:namespace]
|
36
|
+
@generator_stamp = "Code generated by AdsCommon library %s on %s." %
|
37
|
+
[AdsCommon::ApiConfig::ADS_COMMON_VERSION,
|
38
|
+
Time.now.strftime("%Y-%m-%d %H:%M:%S")]
|
39
|
+
prepare_modules_string()
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_code()
|
43
|
+
code = ERB.new(get_code_template(), 0, '%<>')
|
44
|
+
code.result(binding)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_code_template()
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def prepare_modules_string()
|
52
|
+
modules_count = @module_name.scan(/::/).length
|
53
|
+
@modules_open_string = 'module ' + @module_name.gsub(/::/, '; module ')
|
54
|
+
@modules_close_string = 'end; ' * modules_count
|
55
|
+
@modules_close_string += 'end'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,136 @@
|
|
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
|
+
# Generates the wrappers for API services. Only used during the
|
21
|
+
# 'rake generate' step of library setup.
|
22
|
+
|
23
|
+
gem 'savon', '~>0.8.5'
|
24
|
+
require 'savon'
|
25
|
+
|
26
|
+
require 'ads_common/build/savon_service_generator'
|
27
|
+
require 'ads_common/build/savon_registry'
|
28
|
+
require 'ads_common/build/savon_registry_generator'
|
29
|
+
require 'ads_common/errors'
|
30
|
+
|
31
|
+
module AdsCommon
|
32
|
+
module Build
|
33
|
+
|
34
|
+
# Contains the methods that handle wrapper code generation.
|
35
|
+
class SavonGenerator
|
36
|
+
|
37
|
+
# Create a new generator for given WSDL
|
38
|
+
#
|
39
|
+
# Args:
|
40
|
+
# wsdl_url local or remote URL to pull WSDL data
|
41
|
+
# code_path local path to store generated files
|
42
|
+
# service_name a service name to generate stubs from
|
43
|
+
# module_name a fully-qualified module name
|
44
|
+
def initialize(wsdl_url, code_path, service_name, module_name)
|
45
|
+
@wsdl_url = wsdl_url
|
46
|
+
@code_path = code_path
|
47
|
+
@service_name = service_name
|
48
|
+
@generator_args = {
|
49
|
+
:service_name => service_name,
|
50
|
+
:module_name => module_name,
|
51
|
+
:require_path => @code_path.sub(/^lib\//, '')
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Pull, parse and generate wrapper for WSDL on given URL
|
57
|
+
#
|
58
|
+
# Args:
|
59
|
+
# none, instance variables are used.
|
60
|
+
#
|
61
|
+
# Returns:
|
62
|
+
# none
|
63
|
+
def process_wsdl()
|
64
|
+
client = Savon::Client.new {|wsdl| wsdl.document = @wsdl_url }
|
65
|
+
begin
|
66
|
+
@generator_args[:namespace] = client.wsdl.namespace
|
67
|
+
do_process_wsdl_client(client)
|
68
|
+
rescue AdsCommon::Errors::Error => e
|
69
|
+
error_msg = "An unrecoverable error occured during code generation"
|
70
|
+
error_msg += " for service [%s]: %s" % [@wsdl_url, e]
|
71
|
+
# TODO log properly
|
72
|
+
raise AdsCommon::Errors::BuildError, error_msg
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# Generate code for given Savon client
|
79
|
+
def do_process_wsdl_client(client)
|
80
|
+
service_file_name = @service_name.to_s.snakecase
|
81
|
+
|
82
|
+
wsdl = client.wsdl
|
83
|
+
check_service(wsdl)
|
84
|
+
|
85
|
+
wrapper_file_name = "%s/%s.rb" % [@code_path, service_file_name]
|
86
|
+
write_wrapper(wsdl, wrapper_file_name)
|
87
|
+
|
88
|
+
registry_file_name = "%s/%s_registry.rb" %
|
89
|
+
[@code_path, service_file_name]
|
90
|
+
write_registry(wsdl, registry_file_name)
|
91
|
+
end
|
92
|
+
|
93
|
+
def check_service(wsdl)
|
94
|
+
if wsdl.endpoint.nil? || wsdl.namespace.nil?
|
95
|
+
raise AdsCommon::Errors::BuildError,
|
96
|
+
'WSDL could not be retrieved or parsed.'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Generates wrapper file
|
101
|
+
def write_wrapper(wsdl, file_name)
|
102
|
+
wrapper_file = create_new_file(file_name)
|
103
|
+
generator = SavonServiceGenerator.new(@generator_args)
|
104
|
+
generator.add_actions(wsdl.soap_actions.dup)
|
105
|
+
wrapper_file.write(generator.generate_code())
|
106
|
+
wrapper_file.close
|
107
|
+
end
|
108
|
+
|
109
|
+
# Generates registry file
|
110
|
+
def write_registry(wsdl, file_name)
|
111
|
+
registry_file = create_new_file(file_name)
|
112
|
+
generator = SavonRegistryGenerator.new(@generator_args)
|
113
|
+
registry = SavonRegistry.new(wsdl)
|
114
|
+
generator.add_exceptions(registry.soap_exceptions.dup)
|
115
|
+
generator.add_methods(registry.soap_methods.dup)
|
116
|
+
generator.add_types(registry.soap_types.dup)
|
117
|
+
registry_file.write(generator.generate_code())
|
118
|
+
registry_file.close
|
119
|
+
end
|
120
|
+
|
121
|
+
# Creates a new file on specified path, overwriting existing one if it
|
122
|
+
# exists
|
123
|
+
def create_new_file(file_name)
|
124
|
+
puts "Creating %s..." % [file_name]
|
125
|
+
make_dir_for_path(file_name)
|
126
|
+
new_file = File.new(file_name, File::WRONLY|File::TRUNC|File::CREAT)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Creates a directory for the file path specified if not exists
|
130
|
+
def make_dir_for_path(path)
|
131
|
+
dir_name = File.dirname(path)
|
132
|
+
Dir.mkdir(dir_name) if !File.directory?(dir_name)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,236 @@
|
|
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
|
+
# Registry object for Savon backend. Used on generation step as parsed
|
21
|
+
# representation of WSDL for API stubs generation.
|
22
|
+
|
23
|
+
require 'savon'
|
24
|
+
require 'rexml/document'
|
25
|
+
|
26
|
+
module AdsCommon
|
27
|
+
module Build
|
28
|
+
STANDARD_TYPES = ['long', 'boolean', 'int', 'string', 'double']
|
29
|
+
|
30
|
+
# Contains the methods that extracts WSDL data.
|
31
|
+
class SavonRegistry
|
32
|
+
attr_reader :soap_exceptions
|
33
|
+
attr_reader :soap_methods
|
34
|
+
attr_reader :soap_types
|
35
|
+
|
36
|
+
# Initializes the instance.
|
37
|
+
# Args:
|
38
|
+
# wsdl - string containing wsdl to parse.
|
39
|
+
def initialize(wsdl)
|
40
|
+
do_process_wsdl(wsdl)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Generate code for given Savon client.
|
46
|
+
def do_process_wsdl(wsdl)
|
47
|
+
doc = REXML::Document.new(wsdl.to_xml)
|
48
|
+
@raw_types = []
|
49
|
+
@soap_exceptions = extract_exceptions(doc)
|
50
|
+
sort_exceptions()
|
51
|
+
@soap_methods = extract_methods(doc)
|
52
|
+
@soap_types = extract_types(doc)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extracts exceptions list with basic properties from ComplexTypes list.
|
56
|
+
def extract_exceptions(doc)
|
57
|
+
exceptions = []
|
58
|
+
ctypes = get_complex_types(doc)
|
59
|
+
raw_exceptions = exceptions_from_ctypes(ctypes)
|
60
|
+
raw_exceptions.each do |raw_exception|
|
61
|
+
exceptions << {:name => raw_exception.attributes['name'],
|
62
|
+
:doc => get_element_doc(raw_exception),
|
63
|
+
:base => get_element_base(raw_exception),
|
64
|
+
:fields => get_element_fields(raw_exception)}
|
65
|
+
end
|
66
|
+
return exceptions
|
67
|
+
end
|
68
|
+
|
69
|
+
# Extracts ComplexTypes from XML into an array.
|
70
|
+
def get_complex_types(doc)
|
71
|
+
complex_types = []
|
72
|
+
REXML::XPath.each(doc, '//schema/complexType') do |ctype|
|
73
|
+
complex_types << ctype
|
74
|
+
end
|
75
|
+
return complex_types
|
76
|
+
end
|
77
|
+
|
78
|
+
# Helper function to find Exceptions (by name) from all types.
|
79
|
+
def exceptions_from_ctypes(ctypes)
|
80
|
+
exceptions = []
|
81
|
+
ctypes.each do |ctype|
|
82
|
+
if ctype.attributes['name'].match('.+Exception$')
|
83
|
+
exceptions << ctype
|
84
|
+
end
|
85
|
+
end
|
86
|
+
return exceptions
|
87
|
+
end
|
88
|
+
|
89
|
+
# Extracts methods and parameters from XML.
|
90
|
+
def extract_methods(doc)
|
91
|
+
methods = []
|
92
|
+
iface = REXML::XPath.first(doc, 'descendant::wsdl:portType')
|
93
|
+
REXML::XPath.each(iface, 'descendant::wsdl:operation') do |operation|
|
94
|
+
methods << {:name => operation.attributes['name'].to_s.snakecase,
|
95
|
+
:input => extract_input_parameters(operation, doc),
|
96
|
+
:output => extract_output_parameters(operation, doc)}
|
97
|
+
# This could be used to include documentation from wsdl.
|
98
|
+
# :doc => get_element_doc(operation, 'wsdl')}
|
99
|
+
end
|
100
|
+
return methods
|
101
|
+
end
|
102
|
+
|
103
|
+
# Extracts input parameters of given method as an array.
|
104
|
+
def extract_input_parameters(op_node, doc)
|
105
|
+
result = []
|
106
|
+
op_name = op_node.attributes['name'].to_s
|
107
|
+
doc.each_element_with_attribute('name', op_name, 0,
|
108
|
+
'//schema/element') do |method_node|
|
109
|
+
seq_node = REXML::XPath.first(method_node, 'complexType/sequence')
|
110
|
+
result = get_element_fields(seq_node)
|
111
|
+
process_method_field_types(result)
|
112
|
+
end
|
113
|
+
return result
|
114
|
+
end
|
115
|
+
|
116
|
+
# Extracts output parameter name and fields.
|
117
|
+
def extract_output_parameters(op_node, doc)
|
118
|
+
output_element = REXML::XPath.first(op_node, 'descendant::wsdl:output')
|
119
|
+
output_name = (output_element.nil?) ? nil :
|
120
|
+
output_element.attribute('name').to_s
|
121
|
+
output_fields = []
|
122
|
+
doc.each_element_with_attribute('name', output_name, 0,
|
123
|
+
'//schema/element') do |response_node|
|
124
|
+
seq_node = REXML::XPath.first(response_node, 'complexType/sequence')
|
125
|
+
output_fields = get_element_fields(seq_node)
|
126
|
+
process_method_field_types(output_fields)
|
127
|
+
end
|
128
|
+
result = {:name => output_name.snakecase, :fields => output_fields}
|
129
|
+
return result
|
130
|
+
end
|
131
|
+
|
132
|
+
# Checks all fields are of standard type or included in raw_types.
|
133
|
+
def process_method_field_types(fields)
|
134
|
+
fields.each do |field|
|
135
|
+
field_type = field[:type]
|
136
|
+
next if STANDARD_TYPES.include?(field_type)
|
137
|
+
@raw_types << field_type unless @raw_types.include?(field_type)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Gets element base defined as an attribute in sibling.
|
142
|
+
def get_element_base(root)
|
143
|
+
base_element = REXML::XPath.first(root, 'complexContent/extension')
|
144
|
+
base = (base_element.nil?) ? nil :
|
145
|
+
base_element.attribute('base').to_s.gsub(/^.+:/, '')
|
146
|
+
return base
|
147
|
+
end
|
148
|
+
|
149
|
+
# Gets element documentation text.
|
150
|
+
def get_element_doc(root, namespace = nil)
|
151
|
+
key = 'documentation'
|
152
|
+
key = "%s:%s" % [namespace, key] if namespace
|
153
|
+
doc_element = REXML::XPath.first(root, "descendant::%s" % key)
|
154
|
+
doc = (doc_element.nil?) ? '' :
|
155
|
+
REXML::Text.unnormalize(doc_element.get_text.to_s)
|
156
|
+
return doc
|
157
|
+
end
|
158
|
+
|
159
|
+
# Gets subfields defined as elements under given root.
|
160
|
+
def get_element_fields(root)
|
161
|
+
fields = []
|
162
|
+
REXML::XPath.each(root, 'descendant::element') do |element|
|
163
|
+
fields << {:name => element.attribute('name').to_s.snakecase,
|
164
|
+
:type => element.attribute('type').to_s.gsub(/^.+:/, ''),
|
165
|
+
:min_occurs => attribute_to_int(element.attribute('minOccurs')),
|
166
|
+
:max_occurs => attribute_to_int(element.attribute('maxOccurs'))}
|
167
|
+
end
|
168
|
+
return fields
|
169
|
+
end
|
170
|
+
|
171
|
+
# Extracts definition of all types. If a non standard undefined type is
|
172
|
+
# found it process it recursively.
|
173
|
+
# Special case for extensions - types with a base class.
|
174
|
+
def extract_types(doc)
|
175
|
+
types = []
|
176
|
+
@raw_types.each do |raw_type|
|
177
|
+
doc.each_element_with_attribute('name', raw_type, 0,
|
178
|
+
'//schema/complexType') do |type_node|
|
179
|
+
type = {:name => raw_type, :fields => []}
|
180
|
+
ext_node = REXML::XPath.first(type_node, 'complexContent/extension')
|
181
|
+
if ext_node
|
182
|
+
base_type = ext_node.attribute('base').to_s.gsub(/^.+:/, '')
|
183
|
+
type[:base] = base_type
|
184
|
+
@raw_types << base_type unless @raw_types.include?(base_type)
|
185
|
+
seq_node = REXML::XPath.first(ext_node, 'sequence')
|
186
|
+
fields = get_element_fields(seq_node)
|
187
|
+
process_method_field_types(fields)
|
188
|
+
type[:fields] += fields
|
189
|
+
end
|
190
|
+
seq_node = REXML::XPath.first(type_node, 'sequence')
|
191
|
+
if seq_node
|
192
|
+
fields = get_element_fields(seq_node)
|
193
|
+
process_method_field_types(fields)
|
194
|
+
type[:fields] += fields
|
195
|
+
end
|
196
|
+
types << type
|
197
|
+
end
|
198
|
+
end
|
199
|
+
return types
|
200
|
+
end
|
201
|
+
|
202
|
+
# Simple converter for int values.
|
203
|
+
def attribute_to_int(attribute)
|
204
|
+
return attribute.value.eql?('unbounded') ? nil : attribute.value.to_i
|
205
|
+
end
|
206
|
+
|
207
|
+
# Reorders exceptions so that base ones always come before derived.
|
208
|
+
def sort_exceptions()
|
209
|
+
@ordered_exceptions = []
|
210
|
+
@soap_exceptions.each {|exception| do_include_exception(exception)}
|
211
|
+
@soap_exceptions = @ordered_exceptions
|
212
|
+
end
|
213
|
+
|
214
|
+
# Includes exception into ordered_exceptions if not already there and
|
215
|
+
# makes sure its base is already included.
|
216
|
+
def do_include_exception(exception)
|
217
|
+
return if find_exception(exception, @ordered_exceptions)
|
218
|
+
if exception[:base].nil?
|
219
|
+
@ordered_exceptions.push(exception)
|
220
|
+
else
|
221
|
+
base = find_exception(exception[:base], @soap_exceptions)
|
222
|
+
do_include_exception(base)
|
223
|
+
@ordered_exceptions.push(exception)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Finds object (exception) by name attribute in a list.
|
228
|
+
def find_exception(exception, list)
|
229
|
+
list.each do |e|
|
230
|
+
return e if (e.eql?(exception) || e[:name].eql?(exception))
|
231
|
+
end
|
232
|
+
return nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,139 @@
|
|
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 registry generation for Savon backend
|
21
|
+
|
22
|
+
require 'savon'
|
23
|
+
require 'ads_common/build/savon_abstract_generator'
|
24
|
+
require 'pp'
|
25
|
+
|
26
|
+
module AdsCommon
|
27
|
+
module Build
|
28
|
+
class SavonRegistryGenerator < SavonAbstractGenerator
|
29
|
+
REGISTRY_TEMPLATE = %q{<% %>
|
30
|
+
#!/usr/bin/ruby
|
31
|
+
# This is auto-generated code, changes will be overwritten.
|
32
|
+
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
|
33
|
+
# License:: Licensed under the Apache License,Version 2.0 (the "License").
|
34
|
+
#
|
35
|
+
# <%= @generator_stamp %>
|
36
|
+
|
37
|
+
require 'savon'
|
38
|
+
|
39
|
+
<%= @modules_open_string %>
|
40
|
+
|
41
|
+
class <%= @service_name %>Registry
|
42
|
+
<%= @service_name.upcase %>_METHODS = <%= format_signature(@methods) %>
|
43
|
+
<%= @service_name.upcase %>_TYPES = <%= format_signature(@types) %>
|
44
|
+
|
45
|
+
def self.get_method_signature(method_name)
|
46
|
+
return <%= @service_name.upcase %>_METHODS[method_name.to_sym]
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.get_type_signature(type_name)
|
50
|
+
return <%= @service_name.upcase %>_TYPES[type_name.to_sym]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
<% @exceptions.each do |exception| %>
|
54
|
+
<% array_fields = [] %>
|
55
|
+
|
56
|
+
<% doc_lines = format_doc(exception[:doc]) %>
|
57
|
+
<% doc_lines.each do |doc_line| %>
|
58
|
+
# <%= doc_line %>
|
59
|
+
<% end %>
|
60
|
+
<% base_text = (exception[:base].nil?) ? @default_exception_base : exception[:base] %>
|
61
|
+
class <%= exception[:name] %> < <%= base_text %>
|
62
|
+
<% exception[:fields].each do |field| %>
|
63
|
+
attr_reader :<%= field[:name] %> # <%= field[:type] %>
|
64
|
+
<% array_fields << field[:name] if field[:max_occurs].nil? || (field[:max_occurs] > 1) %>
|
65
|
+
<% end %>
|
66
|
+
<% if !(array_fields.empty?) %>
|
67
|
+
def initialize(exception_fault)
|
68
|
+
@array_fields = [] if !defined?(@array_fields)
|
69
|
+
<% array_fields.each do |field| %>
|
70
|
+
@array_fields << '<%= field.to_s %>'
|
71
|
+
<% end %>
|
72
|
+
super(exception_fault)
|
73
|
+
end
|
74
|
+
<% end %>
|
75
|
+
end
|
76
|
+
<% end %>
|
77
|
+
<%= @modules_close_string %>
|
78
|
+
|
79
|
+
}.gsub(/^ /, '')
|
80
|
+
|
81
|
+
def initialize(args)
|
82
|
+
super(args)
|
83
|
+
@exceptions = []
|
84
|
+
@methods = []
|
85
|
+
@types = []
|
86
|
+
@default_exception_base = "%s::Errors::ApiException" %
|
87
|
+
@module_name.split('::').first
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_code_template()
|
91
|
+
REGISTRY_TEMPLATE
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_exceptions(exceptions)
|
95
|
+
@exceptions += exceptions
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_methods(methods)
|
99
|
+
@methods += methods
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_types(types)
|
103
|
+
@types += types
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Multi-line documentation formatter. Used to format text extracted from
|
109
|
+
# XML into stripped multi-line text.
|
110
|
+
def format_doc(doc)
|
111
|
+
res = []
|
112
|
+
doc.split(/\n/).each do |line|
|
113
|
+
line = line.strip();
|
114
|
+
res << line if !(line.empty?)
|
115
|
+
end
|
116
|
+
return res
|
117
|
+
end
|
118
|
+
|
119
|
+
# Prepares a hash string based on array of hashes passed.
|
120
|
+
def format_signature(objects_array)
|
121
|
+
objects_hash = get_hash_for_names_array(objects_array)
|
122
|
+
return PP.singleline_pp(objects_hash, '')
|
123
|
+
end
|
124
|
+
|
125
|
+
# Converts an array of hashes to a hash based on ":name" fields:
|
126
|
+
# [{:name => 'foo', :data => 'bar'}] => {:foo => {:data => 'bar'}}
|
127
|
+
def get_hash_for_names_array(input)
|
128
|
+
output = {}
|
129
|
+
input.each do |e|
|
130
|
+
key = e[:name].to_sym
|
131
|
+
value = e.dup
|
132
|
+
value.delete(:name)
|
133
|
+
output[key] = value
|
134
|
+
end
|
135
|
+
return output
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|