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

root/trunk/lib/soap/rpc/element.rb

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