google-ads-common 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|