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