PageRenderTime 309ms CodeModel.GetById 275ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/Ruby/lib/ruby/1.8/wsdl/soap/classDefCreator.rb

http://github.com/agross/netopenspace
Ruby | 314 lines | 274 code | 26 blank | 14 comment | 31 complexity | 5d6534ed42177d8a9436e1c33f0500bf MD5 | raw file
  1# WSDL4R - Creating class definition from WSDL
  2# Copyright (C) 2002, 2003, 2004  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
  9require 'wsdl/data'
 10require 'wsdl/soap/classDefCreatorSupport'
 11require 'xsd/codegen'
 12
 13
 14module WSDL
 15module SOAP
 16
 17
 18class ClassDefCreator
 19  include ClassDefCreatorSupport
 20
 21  def initialize(definitions)
 22    @elements = definitions.collect_elements
 23    @simpletypes = definitions.collect_simpletypes
 24    @complextypes = definitions.collect_complextypes
 25    @faulttypes = nil
 26    if definitions.respond_to?(:collect_faulttypes)
 27      @faulttypes = definitions.collect_faulttypes
 28    end
 29  end
 30
 31  def dump(type = nil)
 32    result = "require 'xsd/qname'\n"
 33    if type
 34      result = dump_classdef(type.name, type)
 35    else
 36      str = dump_element
 37      unless str.empty?
 38        result << "\n" unless result.empty?
 39        result << str
 40      end
 41      str = dump_complextype
 42      unless str.empty?
 43        result << "\n" unless result.empty?
 44        result << str
 45      end
 46      str = dump_simpletype
 47      unless str.empty?
 48        result << "\n" unless result.empty?
 49        result << str
 50      end
 51    end
 52    result
 53  end
 54
 55private
 56
 57  def dump_element
 58    @elements.collect { |ele|
 59      if ele.local_complextype
 60        dump_classdef(ele.name, ele.local_complextype,
 61          ele.elementform == 'qualified')
 62      elsif ele.local_simpletype
 63        dump_simpletypedef(ele.name, ele.local_simpletype)
 64      else
 65        nil
 66      end
 67    }.compact.join("\n")
 68  end
 69
 70  def dump_simpletype
 71    @simpletypes.collect { |type|
 72      dump_simpletypedef(type.name, type)
 73    }.compact.join("\n")
 74  end
 75
 76  def dump_complextype
 77    @complextypes.collect { |type|
 78      case type.compoundtype
 79      when :TYPE_STRUCT, :TYPE_EMPTY
 80        dump_classdef(type.name, type)
 81      when :TYPE_ARRAY
 82        dump_arraydef(type)
 83      when :TYPE_SIMPLE
 84        dump_simpleclassdef(type)
 85      when :TYPE_MAP
 86        # mapped as a general Hash
 87        nil
 88      else
 89        raise RuntimeError.new(
 90          "unknown kind of complexContent: #{type.compoundtype}")
 91      end
 92    }.compact.join("\n")
 93  end
 94
 95  def dump_simpletypedef(qname, simpletype)
 96    if !simpletype.restriction or simpletype.restriction.enumeration.empty?
 97      return nil
 98    end
 99    c = XSD::CodeGen::ModuleDef.new(create_class_name(qname))
100    c.comment = "#{qname}"
101    const = {}
102    simpletype.restriction.enumeration.each do |value|
103      constname = safeconstname(value)
104      const[constname] ||= 0
105      if (const[constname] += 1) > 1
106        constname += "_#{const[constname]}"
107      end
108      c.def_const(constname, ndq(value))
109    end
110    c.dump
111  end
112
113  def dump_simpleclassdef(type_or_element)
114    qname = type_or_element.name
115    base = create_class_name(type_or_element.simplecontent.base)
116    c = XSD::CodeGen::ClassDef.new(create_class_name(qname), base)
117    c.comment = "#{qname}"
118    c.dump
119  end
120
121  def dump_classdef(qname, typedef, qualified = false)
122    if @faulttypes and @faulttypes.index(qname)
123      c = XSD::CodeGen::ClassDef.new(create_class_name(qname),
124        '::StandardError')
125    else
126      c = XSD::CodeGen::ClassDef.new(create_class_name(qname))
127    end
128    c.comment = "#{qname}"
129    c.def_classvar('schema_type', ndq(qname.name))
130    c.def_classvar('schema_ns', ndq(qname.namespace))
131    c.def_classvar('schema_qualified', dq('true')) if qualified
132    schema_element = []
133    init_lines = ''
134    params = []
135    typedef.each_element do |element|
136      if element.type == XSD::AnyTypeName
137        type = nil
138      elsif klass = element_basetype(element)
139        type = klass.name
140      elsif element.type
141        type = create_class_name(element.type)
142      else
143        type = nil      # means anyType.
144        # do we define a class for local complexType from it's name?
145        #   type = create_class_name(element.name)
146        # <element>
147        #   <complexType>
148        #     <seq...>
149        #   </complexType>
150        # </element>
151      end
152      name = name_element(element).name
153      attrname = safemethodname?(name) ? name : safemethodname(name)
154      varname = safevarname(name)
155      c.def_attr(attrname, true, varname)
156      init_lines << "@#{varname} = #{varname}\n"
157      if element.map_as_array?
158        params << "#{varname} = []"
159        type << '[]' if type
160      else
161        params << "#{varname} = nil"
162      end
163      # nil means @@schema_ns + varname
164      eleqname =
165        (varname == name && element.name.namespace == qname.namespace) ?
166        nil : element.name
167      schema_element << [varname, eleqname, type]
168    end
169    unless typedef.attributes.empty?
170      define_attribute(c, typedef.attributes)
171      init_lines << "@__xmlattr = {}\n"
172    end
173    c.def_classvar('schema_element',
174      '[' +
175        schema_element.collect { |varname, name, type|
176          '[' +
177            (
178              if name
179                varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
180              else
181                varname.dump + ', ' + ndq(type)
182              end
183            ) +
184          ']'
185        }.join(', ') +
186      ']'
187    )
188    c.def_method('initialize', *params) do
189      init_lines
190    end
191    c.dump
192  end
193
194  def element_basetype(ele)
195    if klass = basetype_class(ele.type)
196      klass
197    elsif ele.local_simpletype
198      basetype_class(ele.local_simpletype.base)
199    else
200      nil
201    end
202  end
203
204  def attribute_basetype(attr)
205    if klass = basetype_class(attr.type)
206      klass
207    elsif attr.local_simpletype
208      basetype_class(attr.local_simpletype.base)
209    else
210      nil
211    end
212  end
213
214  def basetype_class(type)
215    return nil if type.nil?
216    if simpletype = @simpletypes[type]
217      basetype_mapped_class(simpletype.base)
218    else
219      basetype_mapped_class(type)
220    end
221  end
222
223  def define_attribute(c, attributes)
224    schema_attribute = []
225    attributes.each do |attribute|
226      name = name_attribute(attribute)
227      if klass = attribute_basetype(attribute)
228        type = klass.name
229      else
230        type = nil
231      end
232      methodname = safemethodname('xmlattr_' + name.name)
233      c.def_method(methodname) do <<-__EOD__
234          (@__xmlattr ||= {})[#{dqname(name)}]
235        __EOD__
236      end
237      c.def_method(methodname + '=', 'value') do <<-__EOD__
238          (@__xmlattr ||= {})[#{dqname(name)}] = value
239        __EOD__
240      end
241      schema_attribute << [name, type]
242    end
243    c.def_classvar('schema_attribute',
244      '{' +
245        schema_attribute.collect { |name, type|
246          dqname(name) + ' => ' + ndq(type)
247        }.join(', ') +
248      '}'
249    )
250  end
251
252  def name_element(element)
253    return element.name if element.name 
254    return element.ref if element.ref
255    raise RuntimeError.new("cannot define name of #{element}")
256  end
257
258  def name_attribute(attribute)
259    return attribute.name if attribute.name 
260    return attribute.ref if attribute.ref
261    raise RuntimeError.new("cannot define name of #{attribute}")
262  end
263
264  DEFAULT_ITEM_NAME = XSD::QName.new(nil, 'item')
265
266  def dump_arraydef(complextype)
267    qname = complextype.name
268    c = XSD::CodeGen::ClassDef.new(create_class_name(qname), '::Array')
269    c.comment = "#{qname}"
270    child_type = complextype.child_type
271    c.def_classvar('schema_type', ndq(child_type.name))
272    c.def_classvar('schema_ns', ndq(child_type.namespace))
273    child_element = complextype.find_aryelement
274    schema_element = []
275    if child_type == XSD::AnyTypeName
276      type = nil
277    elsif child_element and (klass = element_basetype(child_element))
278      type = klass.name
279    elsif child_type
280      type = create_class_name(child_type)
281    else
282      type = nil
283    end
284    if child_element
285      if child_element.map_as_array?
286        type << '[]' if type
287      end
288      child_element_name = child_element.name
289    else
290      child_element_name = DEFAULT_ITEM_NAME
291    end
292    schema_element << [child_element_name.name, child_element_name, type]
293    c.def_classvar('schema_element',
294      '[' +
295        schema_element.collect { |varname, name, type|
296          '[' +
297            (
298              if name
299                varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
300              else
301                varname.dump + ', ' + ndq(type)
302              end
303            ) +
304          ']'
305        }.join(', ') +
306      ']'
307    )
308    c.dump
309  end
310end
311
312
313end
314end