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

root/branches/1_5/lib/wsdl/soap/mappingRegistryCreatorSupport.rb

Revision 1980, 11.6 kB (checked in by nahi, 1 year ago)
Line 
1 # WSDL4R - Creating MappingRegistry support.
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 'wsdl/soap/classDefCreatorSupport'
10
11
12 module WSDL
13 module SOAP
14
15
16 # requires @defined_const = {}, @dump_with_inner, @modulepath
17 module MappingRegistryCreatorSupport
18   include ClassDefCreatorSupport
19   include XSD::CodeGen
20
21   def dump_with_inner
22     @dump_with_inner = []
23     @dump_with_inner.unshift(yield)
24     @dump_with_inner.join("\n")
25   end
26
27   def dump_complextypedef(mpath, qname, typedef, as_element = nil, opt = {})
28     case typedef.compoundtype
29     when :TYPE_STRUCT, :TYPE_EMPTY
30       dump_complex_typemap(mpath, qname, typedef, as_element, opt)
31     when :TYPE_ARRAY
32       dump_array_typemap(mpath, qname, typedef, as_element, opt)
33     when :TYPE_SIMPLE
34       dump_simple_typemap(mpath, qname, typedef, as_element, opt)
35     when :TYPE_MAP
36       # mapped as a general Hash
37       nil
38     else
39       raise RuntimeError.new(
40         "unknown kind of complexContent: #{typedef.compoundtype}")
41     end
42   end
43
44   def dump_array_typemap(mpath, qname, typedef, as_element, opt)
45     if typedef.find_soapenc_arytype
46       if opt[:encoded]
47         dump_encoded_array_typemap(mpath, qname, typedef, as_element, opt)
48       end
49     else
50       dump_literal_array_typemap(mpath, qname, typedef, as_element, opt)
51     end
52   end
53
54   def dump_complex_typemap(mpath, qname, typedef, as_element, opt)
55     var = {}
56     define_dump_class(var, mpath, qname, typedef, as_element, opt)
57     schema_ns = (var[:schema_name] || var[:schema_type]).namespace
58     if var[:schema_type] and typedef.base
59       var[:schema_basetype] = typedef.base
60     end
61     parentmodule = var[:class]
62     parsed_element =
63       parse_elements(typedef.elements, qname.namespace, parentmodule, opt)
64     if typedef.choice?
65       parsed_element.unshift(:choice)
66     end
67     var[:schema_element] = dump_schema_element_definition(parsed_element, 2)
68     unless typedef.attributes.empty?
69       var[:schema_attribute] = define_attribute(typedef.attributes)
70     end
71     assign_const(schema_ns, 'Ns')
72     dump_entry(@varname, var)
73   end
74
75   def dump_simple_typemap(mpath, qname, typedef, as_element, opt)
76     var = {}
77     define_dump_class(var, mpath, qname, typedef, as_element, opt)
78     schema_ns = (var[:schema_name] || var[:schema_type]).namespace
79     unless typedef.attributes.empty?
80       var[:schema_attribute] = define_attribute(typedef.attributes)
81     end
82     assign_const(schema_ns, 'Ns')
83     dump_entry(@varname, var)
84   end
85
86   def dump_schema_element_definition(definition, indent = 0)
87     return '[]' if definition.empty?
88     sp = ' ' * indent
89     if definition[0] == :choice
90       definition.shift
91       "[ :choice,\n" +
92         dump_schema_element(definition, indent + 2) + "\n" + sp + "]"
93     elsif definition[0].is_a?(::Array)
94       "[\n" +
95         dump_schema_element(definition, indent + 2) + "\n" + sp + "]"
96     else
97       varname, name, type, occurrence = definition
98       '[' + [
99         varname.dump,
100         dump_type(name, type),
101         dump_occurrence(occurrence)
102       ].compact.join(', ') + ']'
103     end
104   end
105
106   def dump_schema_element(schema_element, indent = 0)
107     sp = ' ' * indent
108     delimiter = ",\n" + sp
109     sp + schema_element.collect { |definition|
110       dump_schema_element_definition(definition, indent)
111     }.join(delimiter)
112   end
113
114   def dump_type(name, type)
115     if name
116       assign_const(name.namespace, 'Ns')
117       '[' + ndq(type) + ', ' + dqname(name) + ']'
118     else
119       ndq(type)
120     end
121   end
122
123   def dump_occurrence(occurrence)
124     if occurrence and occurrence != [1, 1] # default
125       minoccurs, maxoccurs = occurrence
126       maxoccurs ||= 'nil'
127       "[#{minoccurs}, #{maxoccurs}]"
128     end
129   end
130
131   def parse_elements(elements, base_namespace, mpath, opt)
132     schema_element = []
133     any = false
134     elements.each do |element|
135       case element
136       when XMLSchema::Any
137         # only 1 <any/> is allowed for now.
138         raise RuntimeError.new("duplicated 'any'") if any
139         any = true
140         varname = 'any' # not used
141         eleqname = XSD::AnyTypeName
142         type = nil
143         occurrence = nil
144         schema_element << [varname, eleqname, type, occurrence]
145       when XMLSchema::Element
146         next if element.ref == SchemaName
147         typebase = @modulepath
148         if element.anonymous_type?
149           child_opt = {
150             :qualified => (element.elementform == 'qualified'),
151             :is_anonymous => true
152           }
153           @dump_with_inner << dump_complextypedef(mpath, element.name, element.local_complextype, nil, child_opt)
154           typebase = mpath
155         end
156         type = create_type_name(typebase, element)
157         name = name_element(element).name
158         varname = safevarname(name)
159         if element.map_as_array?
160           if type
161             type += '[]'
162           else
163             type = '[]'
164           end
165         end
166         # nil means @@schema_ns + varname
167         eleqname = element.name || element.ref
168         if eleqname && varname == name && eleqname.namespace == base_namespace
169           eleqname = nil
170         end
171         occurrence = [element.minoccurs, element.maxoccurs]
172         schema_element << [varname, eleqname, type, occurrence]
173       when WSDL::XMLSchema::Sequence
174         child_schema_element =
175           parse_elements(element.elements, base_namespace, mpath, opt)
176         schema_element << child_schema_element
177       when WSDL::XMLSchema::Choice
178         child_schema_element =
179           parse_elements(element.elements, base_namespace, mpath, opt)
180         if !element.map_as_array?
181           # choice + maxOccurs="unbounded" is treated just as 'all' now.
182           child_schema_element.unshift(:choice)
183         end
184         schema_element << child_schema_element
185       when WSDL::XMLSchema::Group
186         if element.content.nil?
187           warn("no group definition found: #{element}")
188           next
189         end
190         child_schema_element =
191           parse_elements(element.content.elements, base_namespace, mpath, opt)
192         schema_element.concat(child_schema_element)
193       else
194         raise RuntimeError.new("unknown type: #{element}")
195       end
196     end
197     schema_element
198   end
199
200   def define_attribute(attributes)
201     schema_attribute = []
202     attributes.each do |attribute|
203       name = name_attribute(attribute)
204       if klass = attribute_basetype(attribute)
205         type = klass.name
206       else
207         warn("unresolved attribute type #{attribute.type} for #{name}")
208         type = nil
209       end
210       schema_attribute << [name, type]
211     end
212     "{\n    " +
213       schema_attribute.collect { |name, type|
214         assign_const(name.namespace, 'Ns')
215         dqname(name) + ' => ' + ndq(type)
216       }.join(",\n    ") +
217     "\n  }"
218   end
219
220   def dump_entry(regname, var)
221     "#{regname}.register(\n  " +
222       [
223         dump_entry_item(var, :class),
224         dump_entry_item(var, :soap_class),
225         dump_entry_item(var, :schema_name, :qname),
226         dump_entry_item(var, :schema_type, :qname),
227         dump_entry_item(var, :is_anonymous),
228         dump_entry_item(var, :schema_basetype, :qname),
229         dump_entry_item(var, :schema_qualified),
230         dump_entry_item(var, :schema_element),
231         dump_entry_item(var, :schema_attribute)
232       ].compact.join(",\n  ") +
233     "\n)\n"
234   end
235
236   def dump_entry_item(var, key, dump_type = :none)
237     if var.key?(key)
238       case dump_type
239       when :none
240         ":#{key} => #{var[key]}"
241       when :string
242         if @defined_const.key?(var[key])
243           ":#{key} => #{@defined_const[var[key]]}"
244         else
245           ":#{key} => #{ndq(var[key])}"
246         end
247       when :qname
248         qname = var[key]
249         if @defined_const.key?(qname.namespace)
250           ns = @defined_const[qname.namespace]
251         else
252           ns = ndq(qname.namespace)
253         end
254         ":#{key} => XSD::QName.new(#{ns}, #{ndq(qname.name)})"
255       else
256         raise "Unknown dump type: #{dump_type}"
257       end
258     end
259   end
260
261   def dump_simpletypedef(mpath, qname, simpletype, as_element = nil, opt = {})
262     if simpletype.restriction
263       dump_simpletypedef_restriction(mpath, qname, simpletype, as_element, opt)
264     elsif simpletype.list
265       dump_simpletypedef_list(mpath, qname, simpletype, as_element, opt)
266     elsif simpletype.union
267       dump_simpletypedef_union(mpath, qname, simpletype, as_element, opt)
268     else
269       raise RuntimeError.new("unknown kind of simpletype: #{simpletype}")
270     end
271   end
272
273   def dump_simpletypedef_restriction(mpath, qname, typedef, as_element, opt)
274     restriction = typedef.restriction
275     unless restriction.enumeration?
276       # not supported.  minlength?
277       return nil
278     end
279     var = {}
280     define_dump_class(var, mpath, qname, typedef, as_element, opt)
281     schema_ns = (var[:schema_name] || var[:schema_type]).namespace
282     assign_const(schema_ns, 'Ns')
283     dump_entry(@varname, var)
284   end
285
286   def dump_simpletypedef_list(mpath, qname, typedef, as_element, opt)
287     nil
288   end
289
290   def dump_simpletypedef_union(mpath, qname, typedef, as_element, opt)
291     nil
292   end
293
294   DEFAULT_ITEM_NAME = XSD::QName.new(nil, 'item')
295
296   def dump_literal_array_typemap(mpath, qname, typedef, as_element, opt)
297     var = {}
298     define_dump_class(var, mpath, qname, typedef, as_element, opt)
299     schema_ns = (var[:schema_name] || var[:schema_type]).namespace
300     parsed_element =
301       parse_elements(typedef.elements, qname.namespace, var[:class], opt)
302     if parsed_element.empty?
303       parsed_element = [create_array_element_definition(typedef, mpath)]
304     end
305     var[:schema_element] = dump_schema_element_definition(parsed_element, 2)
306     assign_const(schema_ns, 'Ns')
307     dump_entry(@varname, var)
308   end
309
310   def dump_encoded_array_typemap(mpath, qname, typedef, as_element, opt)
311     arytype = typedef.find_arytype || XSD::AnyTypeName
312     type = XSD::QName.new(arytype.namespace, arytype.name.sub(/\[(?:,)*\]$/, ''))
313     return <<__EOD__
314 #{@varname}.set(
315   #{mapped_class_name(qname, mpath)},
316   ::SOAP::SOAPArray,
317   ::SOAP::Mapping::EncodedRegistry::TypedArrayFactory,
318   { :type => #{dqname(type)} }
319 )
320 __EOD__
321   end
322
323   # used when "soapenc:arrayType" definition
324   def create_array_element_definition(typedef, mpath)
325     child_type = typedef.child_type
326     child_element = typedef.find_aryelement
327     if child_type == XSD::AnyTypeName
328       type = nil
329     elsif child_element
330       if klass = element_basetype(child_element)
331         type = klass.name
332       else
333         typename = child_element.type || child_element.name
334         type = mapped_class_name(typename, mpath)
335       end
336     elsif child_type
337       type = mapped_class_name(child_type, mpath)
338     else
339       type = nil
340     end
341     occurrence = [0, nil]
342     if child_element and child_element.name
343       if child_element.map_as_array?
344         type << '[]' if type
345         occurrence = [child_element.minoccurs, child_element.maxoccurs]
346       end
347       child_element_name = child_element.name
348     else
349       child_element_name = DEFAULT_ITEM_NAME
350     end
351     [child_element_name.name, child_element_name, type, occurrence]
352   end
353
354   def define_dump_class(var, mpath, qname, typedef, as_element, opt)
355     var[:class] = mapped_class_name(qname, mpath)
356     if as_element
357       var[:schema_name] = as_element
358       schema_ns = as_element.namespace
359     elsif typedef.name.nil?
360       var[:schema_name] = qname
361       schema_ns = qname.namespace
362     else
363       var[:schema_type] = qname
364       schema_ns = qname.namespace
365     end
366     var[:is_anonymous] = opt[:is_anonymous] if opt.key?(:is_anonymous)
367     # true, false, or nil
368     if opt.key?(:qualified)
369       var[:schema_qualified] = opt[:qualified].to_s
370     end
371   end
372 end
373
374
375 end
376 end
Note: See TracBrowser for help on using the browser.