1 | # WSDL4R - Creating driver code from WSDL.
|
---|
2 | # Copyright (C) 2002, 2003, 2005 NAKAMURA, Hiroshi <[email protected]>.
|
---|
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 'wsdl/info'
|
---|
10 | require 'wsdl/soap/classDefCreatorSupport'
|
---|
11 | require 'soap/rpc/element'
|
---|
12 |
|
---|
13 |
|
---|
14 | module WSDL
|
---|
15 | module SOAP
|
---|
16 |
|
---|
17 |
|
---|
18 | class MethodDefCreator
|
---|
19 | include ClassDefCreatorSupport
|
---|
20 |
|
---|
21 | attr_reader :definitions
|
---|
22 |
|
---|
23 | def initialize(definitions)
|
---|
24 | @definitions = definitions
|
---|
25 | @simpletypes = @definitions.collect_simpletypes
|
---|
26 | @complextypes = @definitions.collect_complextypes
|
---|
27 | @elements = @definitions.collect_elements
|
---|
28 | @types = []
|
---|
29 | end
|
---|
30 |
|
---|
31 | def dump(porttype)
|
---|
32 | @types.clear
|
---|
33 | result = ""
|
---|
34 | operations = @definitions.porttype(porttype).operations
|
---|
35 | binding = @definitions.porttype_binding(porttype)
|
---|
36 | operations.each do |operation|
|
---|
37 | op_bind = binding.operations[operation.name]
|
---|
38 | next unless op_bind # no binding is defined
|
---|
39 | next unless op_bind.soapoperation # not a SOAP operation binding
|
---|
40 | result << ",\n" unless result.empty?
|
---|
41 | result << dump_method(operation, op_bind).chomp
|
---|
42 | end
|
---|
43 | return result, @types
|
---|
44 | end
|
---|
45 |
|
---|
46 | def collect_rpcparameter(operation)
|
---|
47 | result = operation.inputparts.collect { |part|
|
---|
48 | collect_type(part.type)
|
---|
49 | param_set(::SOAP::RPC::SOAPMethod::IN, part.name, rpcdefinedtype(part))
|
---|
50 | }
|
---|
51 | outparts = operation.outputparts
|
---|
52 | if outparts.size > 0
|
---|
53 | retval = outparts[0]
|
---|
54 | collect_type(retval.type)
|
---|
55 | result << param_set(::SOAP::RPC::SOAPMethod::RETVAL, retval.name,
|
---|
56 | rpcdefinedtype(retval))
|
---|
57 | cdr(outparts).each { |part|
|
---|
58 | collect_type(part.type)
|
---|
59 | result << param_set(::SOAP::RPC::SOAPMethod::OUT, part.name,
|
---|
60 | rpcdefinedtype(part))
|
---|
61 | }
|
---|
62 | end
|
---|
63 | result
|
---|
64 | end
|
---|
65 |
|
---|
66 | def collect_documentparameter(operation)
|
---|
67 | param = []
|
---|
68 | operation.inputparts.each do |input|
|
---|
69 | param << param_set(::SOAP::RPC::SOAPMethod::IN, input.name,
|
---|
70 | documentdefinedtype(input), elementqualified(input))
|
---|
71 | end
|
---|
72 | operation.outputparts.each do |output|
|
---|
73 | param << param_set(::SOAP::RPC::SOAPMethod::OUT, output.name,
|
---|
74 | documentdefinedtype(output), elementqualified(output))
|
---|
75 | end
|
---|
76 | param
|
---|
77 | end
|
---|
78 |
|
---|
79 | private
|
---|
80 |
|
---|
81 | def dump_method(operation, binding)
|
---|
82 | name = safemethodname(operation.name.name)
|
---|
83 | name_as = operation.name.name
|
---|
84 | style = binding.soapoperation_style
|
---|
85 | inputuse = binding.input.soapbody_use
|
---|
86 | outputuse = binding.output.soapbody_use
|
---|
87 | namespace = binding.input.soapbody.namespace
|
---|
88 | if style == :rpc
|
---|
89 | qname = XSD::QName.new(namespace, name_as)
|
---|
90 | paramstr = param2str(collect_rpcparameter(operation))
|
---|
91 | else
|
---|
92 | qname = nil
|
---|
93 | paramstr = param2str(collect_documentparameter(operation))
|
---|
94 | end
|
---|
95 | if paramstr.empty?
|
---|
96 | paramstr = '[]'
|
---|
97 | else
|
---|
98 | paramstr = "[ " << paramstr.split(/\r?\n/).join("\n ") << " ]"
|
---|
99 | end
|
---|
100 | definitions = <<__EOD__
|
---|
101 | #{ndq(binding.soapaction)},
|
---|
102 | #{dq(name)},
|
---|
103 | #{paramstr},
|
---|
104 | { :request_style => #{sym(style.id2name)}, :request_use => #{sym(inputuse.id2name)},
|
---|
105 | :response_style => #{sym(style.id2name)}, :response_use => #{sym(outputuse.id2name)} }
|
---|
106 | __EOD__
|
---|
107 | if style == :rpc
|
---|
108 | return <<__EOD__
|
---|
109 | [ #{qname.dump},
|
---|
110 | #{definitions}]
|
---|
111 | __EOD__
|
---|
112 | else
|
---|
113 | return <<__EOD__
|
---|
114 | [ #{definitions}]
|
---|
115 | __EOD__
|
---|
116 | end
|
---|
117 | end
|
---|
118 |
|
---|
119 | def rpcdefinedtype(part)
|
---|
120 | if mapped = basetype_mapped_class(part.type)
|
---|
121 | ['::' + mapped.name]
|
---|
122 | elsif definedtype = @simpletypes[part.type]
|
---|
123 | ['::' + basetype_mapped_class(definedtype.base).name]
|
---|
124 | elsif definedtype = @elements[part.element]
|
---|
125 | #['::SOAP::SOAPStruct', part.element.namespace, part.element.name]
|
---|
126 | ['nil', part.element.namespace, part.element.name]
|
---|
127 | elsif definedtype = @complextypes[part.type]
|
---|
128 | case definedtype.compoundtype
|
---|
129 | when :TYPE_STRUCT, :TYPE_EMPTY # ToDo: empty should be treated as void.
|
---|
130 | type = create_class_name(part.type)
|
---|
131 | [type, part.type.namespace, part.type.name]
|
---|
132 | when :TYPE_MAP
|
---|
133 | [Hash.name, part.type.namespace, part.type.name]
|
---|
134 | when :TYPE_ARRAY
|
---|
135 | arytype = definedtype.find_arytype || XSD::AnyTypeName
|
---|
136 | ns = arytype.namespace
|
---|
137 | name = arytype.name.sub(/\[(?:,)*\]$/, '')
|
---|
138 | type = create_class_name(XSD::QName.new(ns, name))
|
---|
139 | [type + '[]', ns, name]
|
---|
140 | else
|
---|
141 | raise NotImplementedError.new("must not reach here")
|
---|
142 | end
|
---|
143 | else
|
---|
144 | raise RuntimeError.new("part: #{part.name} cannot be resolved")
|
---|
145 | end
|
---|
146 | end
|
---|
147 |
|
---|
148 | def documentdefinedtype(part)
|
---|
149 | if mapped = basetype_mapped_class(part.type)
|
---|
150 | ['::' + mapped.name, nil, part.name]
|
---|
151 | elsif definedtype = @simpletypes[part.type]
|
---|
152 | ['::' + basetype_mapped_class(definedtype.base).name, nil, part.name]
|
---|
153 | elsif definedtype = @elements[part.element]
|
---|
154 | ['::SOAP::SOAPElement', part.element.namespace, part.element.name]
|
---|
155 | elsif definedtype = @complextypes[part.type]
|
---|
156 | ['::SOAP::SOAPElement', part.type.namespace, part.type.name]
|
---|
157 | else
|
---|
158 | raise RuntimeError.new("part: #{part.name} cannot be resolved")
|
---|
159 | end
|
---|
160 | end
|
---|
161 |
|
---|
162 | def elementqualified(part)
|
---|
163 | if mapped = basetype_mapped_class(part.type)
|
---|
164 | false
|
---|
165 | elsif definedtype = @simpletypes[part.type]
|
---|
166 | false
|
---|
167 | elsif definedtype = @elements[part.element]
|
---|
168 | definedtype.elementform == 'qualified'
|
---|
169 | elsif definedtype = @complextypes[part.type]
|
---|
170 | false
|
---|
171 | else
|
---|
172 | raise RuntimeError.new("part: #{part.name} cannot be resolved")
|
---|
173 | end
|
---|
174 | end
|
---|
175 |
|
---|
176 | def param_set(io_type, name, type, ele = nil)
|
---|
177 | [io_type, name, type, ele]
|
---|
178 | end
|
---|
179 |
|
---|
180 | def collect_type(type)
|
---|
181 | # ignore inline type definition.
|
---|
182 | return if type.nil?
|
---|
183 | return if @types.include?(type)
|
---|
184 | @types << type
|
---|
185 | return unless @complextypes[type]
|
---|
186 | @complextypes[type].each_element do |element|
|
---|
187 | collect_type(element.type)
|
---|
188 | end
|
---|
189 | end
|
---|
190 |
|
---|
191 | def param2str(params)
|
---|
192 | params.collect { |param|
|
---|
193 | io, name, type, ele = param
|
---|
194 | unless ele.nil?
|
---|
195 | "[#{dq(io)}, #{dq(name)}, #{type2str(type)}, #{ele2str(ele)}]"
|
---|
196 | else
|
---|
197 | "[#{dq(io)}, #{dq(name)}, #{type2str(type)}]"
|
---|
198 | end
|
---|
199 | }.join(",\n")
|
---|
200 | end
|
---|
201 |
|
---|
202 | def type2str(type)
|
---|
203 | if type.size == 1
|
---|
204 | "[#{dq(type[0])}]"
|
---|
205 | else
|
---|
206 | "[#{dq(type[0])}, #{ndq(type[1])}, #{dq(type[2])}]"
|
---|
207 | end
|
---|
208 | end
|
---|
209 |
|
---|
210 | def ele2str(ele)
|
---|
211 | qualified = ele
|
---|
212 | if qualified
|
---|
213 | "true"
|
---|
214 | else
|
---|
215 | "false"
|
---|
216 | end
|
---|
217 | end
|
---|
218 |
|
---|
219 | def cdr(ary)
|
---|
220 | result = ary.dup
|
---|
221 | result.shift
|
---|
222 | result
|
---|
223 | end
|
---|
224 | end
|
---|
225 |
|
---|
226 |
|
---|
227 | end
|
---|
228 | end
|
---|