nogara-wash_out 0.5.2
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/.gitignore +9 -0
- data/.travis.yml +3 -0
- data/Appraisals +7 -0
- data/CHANGELOG.md +79 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +118 -0
- data/LICENSE +22 -0
- data/README.md +181 -0
- data/Rakefile +14 -0
- data/app/helpers/wash_out_helper.rb +64 -0
- data/app/views/wash_with_soap/error.builder +10 -0
- data/app/views/wash_with_soap/response.builder +13 -0
- data/app/views/wash_with_soap/wsdl.builder +68 -0
- data/gemfiles/rails-3.0.11.gemfile +8 -0
- data/gemfiles/rails-3.0.11.gemfile.lock +130 -0
- data/gemfiles/rails-3.1.3.gemfile +8 -0
- data/gemfiles/rails-3.1.3.gemfile.lock +141 -0
- data/init.rb +1 -0
- data/lib/wash_out.rb +35 -0
- data/lib/wash_out/dispatcher.rb +206 -0
- data/lib/wash_out/engine.rb +30 -0
- data/lib/wash_out/model.rb +25 -0
- data/lib/wash_out/param.rb +176 -0
- data/lib/wash_out/router.rb +36 -0
- data/lib/wash_out/soap.rb +40 -0
- data/lib/wash_out/type.rb +28 -0
- data/lib/wash_out/version.rb +3 -0
- data/lib/wash_out/wsse.rb +79 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +42 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +23 -0
- data/spec/dummy/config/environments/test.rb +30 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/httpi-rack.rb +46 -0
- data/spec/wash_out/dispatcher_spec.rb +65 -0
- data/spec/wash_out/param_spec.rb +26 -0
- data/spec/wash_out/type_spec.rb +23 -0
- data/spec/wash_out_spec.rb +686 -0
- data/wash_out.gemspec +21 -0
- metadata +183 -0
data/init.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'wash_out'
|
data/lib/wash_out.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'wash_out/engine'
|
|
2
|
+
require 'wash_out/param'
|
|
3
|
+
require 'wash_out/dispatcher'
|
|
4
|
+
require 'wash_out/soap'
|
|
5
|
+
require 'wash_out/router'
|
|
6
|
+
require 'wash_out/type'
|
|
7
|
+
require 'wash_out/model'
|
|
8
|
+
require 'wash_out/wsse'
|
|
9
|
+
|
|
10
|
+
module ActionDispatch::Routing
|
|
11
|
+
class Mapper
|
|
12
|
+
# Adds the routes for a SOAP endpoint at +controller+.
|
|
13
|
+
def wash_out(controller_name, options={})
|
|
14
|
+
options.reverse_merge!(@scope) if @scope
|
|
15
|
+
controller_class_name = [options[:module], controller_name].compact.join("/")
|
|
16
|
+
|
|
17
|
+
match "#{controller_name}/wsdl" => "#{controller_name}#_generate_wsdl", :via => :get, :format => false
|
|
18
|
+
match "#{controller_name}/action" => WashOut::Router.new(controller_class_name), :defaults => { :controller => controller_class_name, :action => '_action' }, :format => false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
Mime::Type.register "application/soap+xml", :soap
|
|
24
|
+
ActiveRecord::Base.send :extend, WashOut::Model if defined?(ActiveRecord)
|
|
25
|
+
|
|
26
|
+
ActionController::Renderers.add :soap do |what, options|
|
|
27
|
+
_render_soap(what, options)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module ActionView
|
|
31
|
+
class Base
|
|
32
|
+
cattr_accessor :washout_namespace
|
|
33
|
+
@@washout_namespace = false
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
require 'nori'
|
|
2
|
+
|
|
3
|
+
module WashOut
|
|
4
|
+
# The WashOut::Dispatcher module should be included in a controller acting
|
|
5
|
+
# as a SOAP endpoint. It includes actions for generating WSDL and handling
|
|
6
|
+
# SOAP requests.
|
|
7
|
+
module Dispatcher
|
|
8
|
+
# A SOAPError exception can be raised to return a correct SOAP error
|
|
9
|
+
# response.
|
|
10
|
+
class SOAPError < Exception; end
|
|
11
|
+
class ProgrammerError < Exception; end
|
|
12
|
+
|
|
13
|
+
# This filter parses the SOAP request and puts it into +params+ array.
|
|
14
|
+
def _parse_soap_parameters
|
|
15
|
+
# Do not interfere with project-space Nori setup
|
|
16
|
+
strip = Nori.strip_namespaces?
|
|
17
|
+
convert = Nori.convert_tags?
|
|
18
|
+
typecast = Nori.advanced_typecasting?
|
|
19
|
+
|
|
20
|
+
Nori.strip_namespaces = true
|
|
21
|
+
Nori.advanced_typecasting = false
|
|
22
|
+
|
|
23
|
+
if WashOut::Engine.snakecase_input
|
|
24
|
+
Nori.convert_tags_to { |tag| tag.snakecase.to_sym }
|
|
25
|
+
else
|
|
26
|
+
Nori.convert_tags_to { |tag| tag.to_sym }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
request_body = request.body.read
|
|
30
|
+
@_params = Nori.parse(request_body)
|
|
31
|
+
|
|
32
|
+
references = WashOut::Dispatcher.deep_select(@_params){|k,v| v.is_a?(Hash) && v.has_key?(:@id)}
|
|
33
|
+
|
|
34
|
+
unless references.blank?
|
|
35
|
+
replaces = {}; references.each{|r| replaces['#'+r[:@id]] = r}
|
|
36
|
+
@_params = WashOut::Dispatcher.deep_replace_href(@_params, replaces)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Reset Nori setup to project-space
|
|
40
|
+
Nori.strip_namespaces = strip
|
|
41
|
+
Nori.advanced_typecasting = typecast
|
|
42
|
+
Nori.convert_tags_to convert
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _authenticate_wsse
|
|
46
|
+
begin
|
|
47
|
+
xml_security = @_params.values_at(:envelope, :Envelope).compact.first
|
|
48
|
+
xml_security = xml_security.values_at(:header, :Header).compact.first
|
|
49
|
+
xml_security = xml_security.values_at(:security, :Security).compact.first
|
|
50
|
+
username_token = xml_security.values_at(:username_token, :UsernameToken).compact.first
|
|
51
|
+
rescue
|
|
52
|
+
username_token = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
WashOut::Wsse.authenticate username_token
|
|
56
|
+
|
|
57
|
+
request.env['WSSE_TOKEN'] = username_token.with_indifferent_access unless username_token.blank?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def _map_soap_parameters
|
|
61
|
+
soap_action = request.env['wash_out.soap_action']
|
|
62
|
+
action_spec = self.class.soap_actions[soap_action]
|
|
63
|
+
|
|
64
|
+
xml_data = @_params.values_at(:envelope, :Envelope).compact.first
|
|
65
|
+
xml_data = xml_data.values_at(:body, :Body).compact.first
|
|
66
|
+
xml_data = xml_data.values_at(soap_action.underscore.to_sym,
|
|
67
|
+
soap_action.to_sym).compact.first || {}
|
|
68
|
+
|
|
69
|
+
strip_empty_nodes = lambda{|hash|
|
|
70
|
+
hash.each do |key, value|
|
|
71
|
+
if value.is_a? Hash
|
|
72
|
+
value = value.delete_if{|key, value| key.to_s[0] == '@'}
|
|
73
|
+
|
|
74
|
+
if value.length > 0
|
|
75
|
+
hash[key] = strip_empty_nodes.call(value)
|
|
76
|
+
else
|
|
77
|
+
hash[key] = nil
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
hash
|
|
83
|
+
}
|
|
84
|
+
xml_data = strip_empty_nodes.call(xml_data)
|
|
85
|
+
@_params = HashWithIndifferentAccess.new
|
|
86
|
+
|
|
87
|
+
action_spec[:in].each do |param|
|
|
88
|
+
key = param.raw_name.to_sym
|
|
89
|
+
|
|
90
|
+
if xml_data.has_key? key
|
|
91
|
+
@_params[param.raw_name] = param.load(xml_data, key)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# This action generates the WSDL for defined SOAP methods.
|
|
97
|
+
def _generate_wsdl
|
|
98
|
+
@map = self.class.soap_actions
|
|
99
|
+
@namespace = WashOut::Engine.namespace
|
|
100
|
+
@name = controller_path.gsub('/', '_')
|
|
101
|
+
|
|
102
|
+
render :template => 'wash_with_soap/wsdl', :layout => false
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Render a SOAP response.
|
|
106
|
+
def _render_soap(result, options)
|
|
107
|
+
@namespace = WashOut::Engine.namespace
|
|
108
|
+
@operation = soap_action = request.env['wash_out.soap_action']
|
|
109
|
+
action_spec = self.class.soap_actions[soap_action][:out]
|
|
110
|
+
|
|
111
|
+
result = { 'value' => result } unless result.is_a? Hash
|
|
112
|
+
result = HashWithIndifferentAccess.new(result)
|
|
113
|
+
|
|
114
|
+
inject = lambda {|data, map|
|
|
115
|
+
result_spec = []
|
|
116
|
+
|
|
117
|
+
map.each_with_index do |param, i|
|
|
118
|
+
result_spec[i] = param.flat_copy
|
|
119
|
+
|
|
120
|
+
# Inline complex structure
|
|
121
|
+
if param.struct? && !param.multiplied
|
|
122
|
+
result_spec[i].map = inject.call(data[param.raw_name], param.map)
|
|
123
|
+
|
|
124
|
+
# Inline array of complex structures
|
|
125
|
+
elsif param.struct? && param.multiplied
|
|
126
|
+
if data.nil?
|
|
127
|
+
data = {} # when no data is given
|
|
128
|
+
elsif data.is_a?(Array)
|
|
129
|
+
raise ProgrammerError,
|
|
130
|
+
"SOAP response used #{data.inspect} (which is an Array), " +
|
|
131
|
+
"in the context where a Hash with key of '#{param.raw_name}' " +
|
|
132
|
+
"was expected."
|
|
133
|
+
end
|
|
134
|
+
data[param.raw_name] = [] unless data[param.raw_name].is_a?(Array)
|
|
135
|
+
result_spec[i].map = data[param.raw_name].map{|e| inject.call(e, param.map)}
|
|
136
|
+
|
|
137
|
+
else
|
|
138
|
+
val = data[param.raw_name]
|
|
139
|
+
if param.multiplied and val and not val.is_a?(Array)
|
|
140
|
+
raise ProgrammerError,
|
|
141
|
+
"SOAP response tried to use '#{val.inspect}' " +
|
|
142
|
+
"(which is of type #{val.class}), as the value for " +
|
|
143
|
+
"'#{param.raw_name}' (which expects an Array)."
|
|
144
|
+
end
|
|
145
|
+
result_spec[i].value = val
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
return result_spec
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
render :template => 'wash_with_soap/response',
|
|
153
|
+
:layout => false,
|
|
154
|
+
:locals => { :result => inject.call(result, action_spec) },
|
|
155
|
+
:content_type => 'text/xml'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# This action is a fallback for all undefined SOAP actions.
|
|
159
|
+
def _invalid_action
|
|
160
|
+
render_soap_error("Cannot find SOAP action mapping for #{request.env['wash_out.soap_action']}")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def _render_soap_exception(error)
|
|
164
|
+
render_soap_error(error.message)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Render a SOAP error response.
|
|
168
|
+
#
|
|
169
|
+
# Rails do not support sequental rescue_from handling, that is, rescuing an
|
|
170
|
+
# exception from a rescue_from handler. Hence this function is a public API.
|
|
171
|
+
def render_soap_error(message)
|
|
172
|
+
render :template => 'wash_with_soap/error', :status => 500,
|
|
173
|
+
:layout => false,
|
|
174
|
+
:locals => { :error_message => message },
|
|
175
|
+
:content_type => 'text/xml'
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def self.included(controller)
|
|
179
|
+
controller.send :rescue_from, SOAPError, :with => :_render_soap_exception
|
|
180
|
+
controller.send :helper, :wash_out
|
|
181
|
+
controller.send :before_filter, :_parse_soap_parameters, :except => [ :_generate_wsdl, :_invalid_action ]
|
|
182
|
+
controller.send :before_filter, :_authenticate_wsse, :except => [ :_generate_wsdl, :_invalid_action ]
|
|
183
|
+
controller.send :before_filter, :_map_soap_parameters, :except => [ :_generate_wsdl, :_invalid_action ]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def self.deep_select(hash, result=[], &blk)
|
|
187
|
+
result += Hash[hash.select(&blk)].values
|
|
188
|
+
|
|
189
|
+
hash.each do |key, value|
|
|
190
|
+
result = deep_select(value, result, &blk) if value.is_a? Hash
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
result
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def self.deep_replace_href(hash, replace)
|
|
197
|
+
return replace[hash[:@href]] if hash.has_key?(:@href)
|
|
198
|
+
|
|
199
|
+
hash.keys.each do |key, value|
|
|
200
|
+
hash[key] = deep_replace_href(hash[key], replace) if hash[key].is_a?(Hash)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
hash
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module WashOut
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
class << self
|
|
4
|
+
attr_accessor :namespace
|
|
5
|
+
attr_accessor :snakecase, :snakecase_input, :camelize_wsdl
|
|
6
|
+
attr_accessor :wsse_username, :wsse_password
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
self.namespace = 'urn:WashOut'
|
|
10
|
+
self.snakecase = nil
|
|
11
|
+
|
|
12
|
+
self.snakecase_input = false
|
|
13
|
+
self.camelize_wsdl = false
|
|
14
|
+
|
|
15
|
+
self.wsse_username = nil
|
|
16
|
+
self.wsse_password = nil
|
|
17
|
+
|
|
18
|
+
config.wash_out = ActiveSupport::OrderedOptions.new
|
|
19
|
+
|
|
20
|
+
initializer "wash_out.configuration" do |app|
|
|
21
|
+
app.config.wash_out.each do |key, value|
|
|
22
|
+
self.class.send "#{key}=", value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
unless self.class.snakecase.nil?
|
|
26
|
+
raise "Usage of wash_out.snakecase is deprecated. You should use wash_out.snakecase_input and wash_out.camelize_wsdl"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module WashOut
|
|
2
|
+
module Model
|
|
3
|
+
def wash_out_param_map
|
|
4
|
+
types = {
|
|
5
|
+
:text => :string,
|
|
6
|
+
:float => :double,
|
|
7
|
+
:decimal => :double,
|
|
8
|
+
:timestamp => :string
|
|
9
|
+
}
|
|
10
|
+
map = {}
|
|
11
|
+
|
|
12
|
+
columns_hash.each do |key, column|
|
|
13
|
+
type = column.type
|
|
14
|
+
type = types[type] if types.has_key?(type)
|
|
15
|
+
map[key] = type
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
map
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def wash_out_param_name
|
|
22
|
+
return name.underscore
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
module WashOut
|
|
2
|
+
class Param
|
|
3
|
+
attr_accessor :raw_name
|
|
4
|
+
attr_accessor :name
|
|
5
|
+
attr_accessor :map
|
|
6
|
+
attr_accessor :type
|
|
7
|
+
attr_accessor :multiplied
|
|
8
|
+
attr_accessor :value
|
|
9
|
+
attr_accessor :source_class
|
|
10
|
+
|
|
11
|
+
# Defines a WSDL parameter with name +name+ and type specifier +type+.
|
|
12
|
+
# The type specifier format is described in #parse_def.
|
|
13
|
+
def initialize(name, type, multiplied = false)
|
|
14
|
+
type ||= {}
|
|
15
|
+
|
|
16
|
+
@name = name.to_s
|
|
17
|
+
@raw_name = name.to_s
|
|
18
|
+
@map = {}
|
|
19
|
+
@multiplied = multiplied
|
|
20
|
+
|
|
21
|
+
if WashOut::Engine.camelize_wsdl.to_s == 'lower'
|
|
22
|
+
@name = @name.camelize(:lower)
|
|
23
|
+
elsif WashOut::Engine.camelize_wsdl
|
|
24
|
+
@name = @name.camelize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if type.is_a?(Symbol)
|
|
28
|
+
@type = type.to_s
|
|
29
|
+
elsif type.is_a?(Class)
|
|
30
|
+
@type = 'struct'
|
|
31
|
+
@map = self.class.parse_def(type.wash_out_param_map)
|
|
32
|
+
@source_class = type
|
|
33
|
+
else
|
|
34
|
+
@type = 'struct'
|
|
35
|
+
@map = self.class.parse_def(type)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Converts a generic externally derived Ruby value, such as String or
|
|
40
|
+
# Hash, to a native Ruby object according to the definition of this type.
|
|
41
|
+
def load(data, key)
|
|
42
|
+
if !data.has_key? key
|
|
43
|
+
raise WashOut::Dispatcher::SOAPError, "Required SOAP parameter '#{key}' is missing"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
data = data[key]
|
|
47
|
+
data = [data] if @multiplied && !data.is_a?(Array)
|
|
48
|
+
|
|
49
|
+
if struct?
|
|
50
|
+
if @multiplied
|
|
51
|
+
data.map do |x|
|
|
52
|
+
map_struct x do |param, data, elem|
|
|
53
|
+
param.load(data, elem)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
map_struct data do |param, data, elem|
|
|
58
|
+
param.load(data, elem)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
operation = case type
|
|
63
|
+
when 'string'; :to_s
|
|
64
|
+
when 'integer'; :to_i
|
|
65
|
+
when 'double'; :to_f
|
|
66
|
+
when 'boolean'; lambda { |v| v == 'true' }
|
|
67
|
+
when 'date'; :to_date
|
|
68
|
+
when 'datetime'; :to_datetime
|
|
69
|
+
when 'time'; :to_time
|
|
70
|
+
else raise RuntimeError, "Invalid WashOut simple type: #{type}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if operation.nil? || data.nil?
|
|
74
|
+
data
|
|
75
|
+
elsif @multiplied
|
|
76
|
+
data.map{|x| x.send(operation)}
|
|
77
|
+
elsif operation.is_a? Symbol
|
|
78
|
+
data.send(operation)
|
|
79
|
+
else
|
|
80
|
+
operation.call(data)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Checks if this Param defines a complex type.
|
|
86
|
+
def struct?
|
|
87
|
+
type == 'struct'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def classified?
|
|
91
|
+
!source_class.nil?
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def basic_type
|
|
95
|
+
return name unless classified?
|
|
96
|
+
return source_class.wash_out_param_name
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def xsd_type
|
|
100
|
+
return 'int' if type.to_s == 'integer'
|
|
101
|
+
return 'dateTime' if type.to_s == 'datetime'
|
|
102
|
+
return type
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns a WSDL namespaced identifier for this type.
|
|
106
|
+
def namespaced_type
|
|
107
|
+
struct? ? "tns:#{basic_type}" : "xsd:#{xsd_type}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Parses a +definition+. The format of the definition is best described
|
|
111
|
+
# by the following BNF-like grammar.
|
|
112
|
+
#
|
|
113
|
+
# simple_type := :string | :integer | :double | :boolean
|
|
114
|
+
# nested_type := type_hash | simple_type | WashOut::Param instance
|
|
115
|
+
# type_hash := { :parameter_name => nested_type, ... }
|
|
116
|
+
# definition := [ WashOut::Param, ... ] |
|
|
117
|
+
# type_hash |
|
|
118
|
+
# simple_type
|
|
119
|
+
#
|
|
120
|
+
# If a simple type is passed as the +definition+, a single Param is returned
|
|
121
|
+
# with the +name+ set to "value".
|
|
122
|
+
# If a WashOut::Param instance is passed as a +nested_type+, the corresponding
|
|
123
|
+
# +:parameter_name+ is ignored.
|
|
124
|
+
#
|
|
125
|
+
# This function returns an array of WashOut::Param objects.
|
|
126
|
+
def self.parse_def(definition)
|
|
127
|
+
raise RuntimeError, "[] should not be used in your params. Use nil if you want to mark empty set." if definition == []
|
|
128
|
+
return [] if definition == nil
|
|
129
|
+
|
|
130
|
+
if [Array, Symbol, Class].include?(definition.class)
|
|
131
|
+
definition = { :value => definition }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if definition.is_a? Hash
|
|
135
|
+
definition.map do |name, opt|
|
|
136
|
+
if opt.is_a? WashOut::Param
|
|
137
|
+
opt
|
|
138
|
+
elsif opt.is_a? Array
|
|
139
|
+
WashOut::Param.new(name, opt[0], true)
|
|
140
|
+
else
|
|
141
|
+
WashOut::Param.new(name, opt)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
else
|
|
145
|
+
raise RuntimeError, "Wrong definition: #{definition.inspect}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def flat_copy
|
|
150
|
+
copy = self.class.new(@name, @type.to_sym, @multiplied)
|
|
151
|
+
copy.raw_name = raw_name
|
|
152
|
+
copy
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
|
|
157
|
+
# Used to load an entire structure.
|
|
158
|
+
def map_struct(data)
|
|
159
|
+
unless data.is_a?(Hash)
|
|
160
|
+
raise WashOut::Dispatcher::SOAPError, "SOAP message structure is broken"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
data = data.with_indifferent_access
|
|
164
|
+
struct = {}.with_indifferent_access
|
|
165
|
+
|
|
166
|
+
# RUBY18 Enumerable#each_with_object is better, but 1.9 only.
|
|
167
|
+
@map.map do |param|
|
|
168
|
+
if data.has_key? param.raw_name
|
|
169
|
+
struct[param.raw_name] = yield param, data, param.raw_name
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
struct
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|