Welcome to the "trac"-ing site of soap4r!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

root/branches/1_5/lib/soap/rpc/element.rb

Revision 2014, 7.8 kB (checked in by nahi, 3 weeks ago)
  • sort XML attributes in XML instance. 'xml*'s are first. closes #495.
  • -W warning cleanups. now 'rake test' and 'rake coverage' works.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # SOAP4R - RPC element definition.
2 # Copyright (C) 2000-2007  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
3
4 # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
5 # redistribute it and/or modify it under the same terms of Ruby's license;
6 # either the dual license version in 2003, or any later version.
7
8
9 require 'soap/baseData'
10
11
12 module SOAP
13
14 # Add method definitions for RPC to common definition in element.rb
15 class SOAPBody < SOAPStruct
16   public
17
18   def request
19     root_node
20   end
21
22   def response
23     root = root_node
24     if !@is_fault
25       if root.nil?
26         nil
27       elsif root.is_a?(SOAPBasetype)
28         root
29       else
30         # Initial element is [retval].
31         root[0]
32       end
33     else
34       root
35     end
36   end
37
38   def outparams
39     root = root_node
40     if !@is_fault and !root.nil? and !root.is_a?(SOAPBasetype)
41       op = root[1..-1]
42       op = nil if op && op.empty?
43       op
44     else
45       nil
46     end
47   end
48
49   def fault
50     if @is_fault
51       self['fault']
52     else
53       nil
54     end
55   end
56
57   def fault=(fault)
58     @is_fault = true
59     add('fault', fault)
60   end
61 end
62
63
64 module RPC
65
66
67 class RPCError < Error; end
68 class MethodDefinitionError < RPCError; end
69 class ParameterError < RPCError; end
70
71 class SOAPMethod < SOAPStruct
72   RETVAL = 'retval'
73   IN = 'in'
74   OUT = 'out'
75   INOUT = 'inout'
76
77   attr_reader :param_def
78   attr_reader :inparam
79   attr_reader :outparam
80   attr_reader :retval_name
81   attr_reader :retval_class_name
82
83   def initialize(qname, param_def = nil)
84     super(nil)
85     @elename = qname
86     @encodingstyle = nil
87
88     @param_def = param_def
89
90     @signature = []
91     @inparam_names = []
92     @inoutparam_names = []
93     @outparam_names = []
94
95     @inparam = {}
96     @outparam = {}
97     @retval_name = nil
98     @retval_class_name = nil
99
100     init_param(@param_def) if @param_def
101   end
102
103   def have_member
104     true
105   end
106
107   def have_outparam?
108     @outparam_names.size > 0
109   end
110
111   def input_params
112     collect_params(IN, INOUT)
113   end
114
115   def output_params
116     collect_params(OUT, INOUT)
117   end
118
119   def input_param_types
120     collect_param_types(IN, INOUT)
121   end
122
123   def output_param_types
124     collect_param_types(OUT, INOUT)
125   end
126
127   def set_param(params)
128     params.each do |param, data|
129       @inparam[param] = data
130       data.elename = XSD::QName.new(data.elename.namespace, param)
131       data.parent = self
132     end
133   end
134
135   def set_outparam(params)
136     params.each do |param, data|
137       @outparam[param] = data
138       data.elename = XSD::QName.new(data.elename.namespace, param)
139     end
140   end
141
142   def get_paramtypes(names)
143     types = []
144     @signature.each do |io_type, name, type_qname|
145       if type_qname && idx = names.index(name)
146         types[idx] = type_qname
147       end
148     end
149     types
150   end
151
152   def SOAPMethod.param_count(param_def, *type)
153     count = 0
154     param_def.each do |io_type, name, param_type|
155       if type.include?(io_type)
156         count += 1
157       end
158     end
159     count
160   end
161
162   def SOAPMethod.derive_rpc_param_def(obj, name, *param)
163     if param.size == 1 and param[0].is_a?(Array)
164       return param[0]
165     end
166     if param.empty?
167       method = obj.method(name)
168       param_names = (1..method.arity.abs).collect { |i| "p#{i}" }
169     else
170       param_names = param
171     end
172     create_rpc_param_def(param_names)
173   end
174
175   def SOAPMethod.create_rpc_param_def(param_names)
176     param_def = []
177     param_names.each do |param_name|
178       param_def.push([IN, param_name, nil])
179     end
180     param_def.push([RETVAL, 'return', nil])
181     param_def
182   end
183
184   def SOAPMethod.create_doc_param_def(req_qnames, res_qnames)
185     req_qnames = [req_qnames] if req_qnames.is_a?(XSD::QName)
186     res_qnames = [res_qnames] if res_qnames.is_a?(XSD::QName)
187     param_def = []
188     # req_qnames and res_qnames can be nil
189     if req_qnames
190       req_qnames.each do |qname|
191         param_def << [IN, qname.name, [nil, qname.namespace, qname.name]]
192       end
193     end
194     if res_qnames
195       res_qnames.each do |qname|
196         param_def << [OUT, qname.name, [nil, qname.namespace, qname.name]]
197       end
198     end
199     param_def
200   end
201
202 private
203
204   def collect_param_types(*type)
205     names = []
206     @signature.each do |io_type, name, type_qname|
207       names << type_qname if type.include?(io_type)
208     end
209     names
210   end
211
212   def collect_params(*type)
213     names = []
214     @signature.each do |io_type, name, type_qname|
215       names << name if type.include?(io_type)
216     end
217     names
218   end
219
220   def init_param(param_def)
221     param_def.each do |io_type, name, param_type|
222       mapped_class, nsdef, namedef = SOAPMethod.parse_param_type(param_type)
223       if nsdef && namedef
224         type_qname = XSD::QName.new(nsdef, namedef)
225       elsif mapped_class
226         type_qname = TypeMap.key(mapped_class)
227       end
228       case io_type
229       when IN
230         @signature.push([IN, name, type_qname])
231         @inparam_names.push(name)
232       when OUT
233         @signature.push([OUT, name, type_qname])
234         @outparam_names.push(name)
235       when INOUT
236         @signature.push([INOUT, name, type_qname])
237         @inoutparam_names.push(name)
238       when RETVAL
239         if @retval_name
240           raise MethodDefinitionError.new('duplicated retval')
241         end
242         @retval_name = name
243         @retval_class_name = mapped_class
244       else
245         raise MethodDefinitionError.new("unknown type: #{io_type}")
246       end
247     end
248   end
249
250   def self.parse_param_type(param_type)
251     mapped_class, nsdef, namedef = param_type
252     # the first element of typedef in param_def can be a String like
253     # "::SOAP::SOAPStruct" or "CustomClass[]".  turn this String to a class if
254     # we can.
255     if mapped_class.is_a?(String)
256       if /\[\]\Z/ =~ mapped_class
257         # when '[]' is added, ignore this.
258         mapped_class = nil
259       else
260         mapped_class = Mapping.class_from_name(mapped_class)
261       end
262     end
263     [mapped_class, nsdef, namedef]
264   end
265 end
266
267
268 class SOAPMethodRequest < SOAPMethod
269   attr_accessor :soapaction
270
271   def SOAPMethodRequest.create_request(qname, *params)
272     param_def = []
273     param_value = []
274     i = 0
275     params.each do |param|
276       param_name = "p#{i}"
277       i += 1
278       param_def << [IN, param_name, nil]
279       param_value << [param_name, param]
280     end
281     param_def << [RETVAL, 'return', nil]
282     o = new(qname, param_def)
283     o.set_param(param_value)
284     o
285   end
286
287   def initialize(qname, param_def = nil, soapaction = nil)
288     super(qname, param_def)
289     @soapaction = soapaction
290   end
291
292   def each
293     input_params.each do |name|
294       unless @inparam[name]
295         raise ParameterError.new("parameter: #{name} was not given")
296       end
297       yield(name, @inparam[name])
298     end
299   end
300
301   def dup
302     req = self.class.new(@elename.dup, @param_def, @soapaction)
303     req.encodingstyle = @encodingstyle
304     req
305   end
306
307   def create_method_response(response_name = nil)
308     response_name ||=
309       XSD::QName.new(@elename.namespace, @elename.name + 'Response')
310     SOAPMethodResponse.new(response_name, @param_def)
311   end
312 end
313
314
315 class SOAPMethodResponse < SOAPMethod
316
317   def initialize(qname, param_def = nil)
318     super(qname, param_def)
319     @retval = nil
320   end
321
322   def retval
323     @retval
324   end
325
326   def retval=(retval)
327     @retval = retval
328     @retval.elename = @retval.elename.dup_name(@retval_name || 'return')
329     retval.parent = self
330     retval
331   end
332
333   def each
334     if @retval_name and !@retval.is_a?(SOAPVoid)
335       yield(@retval_name, @retval)
336     end
337
338     output_params.each do |name|
339       unless @outparam[name]
340         raise ParameterError.new("parameter: #{name} was not given")
341       end
342       yield(name, @outparam[name])
343     end
344   end
345 end
346
347
348 # To return(?) void explicitly.
349 #  def foo(input_var)
350 #    ...
351 #    return SOAP::RPC::SOAPVoid.new
352 #  end
353 class SOAPVoid < XSD::XSDAnySimpleType
354   include SOAPBasetype
355   extend SOAPModuleUtils
356   Name = XSD::QName.new(Mapping::RubyCustomTypeNamespace, nil)
357
358 public
359   def initialize()
360     @elename = Name
361     @id = nil
362     @precedents = []
363     @parent = nil
364   end
365 end
366
367
368 end
369 end
Note: See TracBrowser for help on using the browser.