/tools/Ruby/lib/ruby/1.8/soap/mapping/factory.rb

http://github.com/agross/netopenspace · Ruby · 355 lines · 303 code · 39 blank · 13 comment · 30 complexity · c88391e35217d51026725eb45270f419 MD5 · raw file

  1. # SOAP4R - Mapping factory.
  2. # Copyright (C) 2000, 2001, 2002, 2003 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. module SOAP
  7. module Mapping
  8. class Factory
  9. include TraverseSupport
  10. def initialize
  11. # nothing to do
  12. end
  13. def obj2soap(soap_class, obj, info, map)
  14. raise NotImplementError.new
  15. # return soap_obj
  16. end
  17. def soap2obj(obj_class, node, info, map)
  18. raise NotImplementError.new
  19. # return convert_succeeded_or_not, obj
  20. end
  21. def setiv2obj(obj, node, map)
  22. return if node.nil?
  23. if obj.is_a?(Array)
  24. setiv2ary(obj, node, map)
  25. else
  26. setiv2struct(obj, node, map)
  27. end
  28. end
  29. def setiv2soap(node, obj, map)
  30. if obj.class.class_variables.include?('@@schema_element')
  31. obj.class.class_eval('@@schema_element').each do |name, info|
  32. type, qname = info
  33. if qname
  34. elename = qname.name
  35. else
  36. elename = Mapping.name2elename(name)
  37. end
  38. node.add(elename,
  39. Mapping._obj2soap(obj.instance_variable_get('@' + name), map))
  40. end
  41. else
  42. # should we sort instance_variables?
  43. obj.instance_variables.each do |var|
  44. name = var.sub(/^@/, '')
  45. elename = Mapping.name2elename(name)
  46. node.add(elename,
  47. Mapping._obj2soap(obj.instance_variable_get(var), map))
  48. end
  49. end
  50. end
  51. private
  52. def setiv2ary(obj, node, map)
  53. node.each do |name, value|
  54. Array.instance_method(:<<).bind(obj).call(Mapping._soap2obj(value, map))
  55. end
  56. end
  57. def setiv2struct(obj, node, map)
  58. vars = {}
  59. node.each do |name, value|
  60. vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
  61. end
  62. Mapping.set_attributes(obj, vars)
  63. end
  64. end
  65. class StringFactory_ < Factory
  66. def initialize(allow_original_mapping = false)
  67. super()
  68. @allow_original_mapping = allow_original_mapping
  69. end
  70. def obj2soap(soap_class, obj, info, map)
  71. if !@allow_original_mapping and !obj.instance_variables.empty?
  72. return nil
  73. end
  74. begin
  75. unless XSD::Charset.is_ces(obj, Thread.current[:SOAPExternalCES])
  76. return nil
  77. end
  78. encoded = XSD::Charset.encoding_conv(obj,
  79. Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
  80. soap_obj = soap_class.new(encoded)
  81. rescue XSD::ValueSpaceError
  82. return nil
  83. end
  84. mark_marshalled_obj(obj, soap_obj)
  85. soap_obj
  86. end
  87. def soap2obj(obj_class, node, info, map)
  88. obj = Mapping.create_empty_object(obj_class)
  89. decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding,
  90. Thread.current[:SOAPExternalCES])
  91. obj.replace(decoded)
  92. mark_unmarshalled_obj(node, obj)
  93. return true, obj
  94. end
  95. end
  96. class BasetypeFactory_ < Factory
  97. def initialize(allow_original_mapping = false)
  98. super()
  99. @allow_original_mapping = allow_original_mapping
  100. end
  101. def obj2soap(soap_class, obj, info, map)
  102. if !@allow_original_mapping and !obj.instance_variables.empty?
  103. return nil
  104. end
  105. soap_obj = nil
  106. begin
  107. soap_obj = soap_class.new(obj)
  108. rescue XSD::ValueSpaceError
  109. return nil
  110. end
  111. if @allow_original_mapping
  112. # Basetype except String should not be multiref-ed in SOAP/1.1.
  113. mark_marshalled_obj(obj, soap_obj)
  114. end
  115. soap_obj
  116. end
  117. def soap2obj(obj_class, node, info, map)
  118. obj = node.data
  119. mark_unmarshalled_obj(node, obj)
  120. return true, obj
  121. end
  122. end
  123. class DateTimeFactory_ < Factory
  124. def initialize(allow_original_mapping = false)
  125. super()
  126. @allow_original_mapping = allow_original_mapping
  127. end
  128. def obj2soap(soap_class, obj, info, map)
  129. if !@allow_original_mapping and
  130. Time === obj and !obj.instance_variables.empty?
  131. return nil
  132. end
  133. soap_obj = nil
  134. begin
  135. soap_obj = soap_class.new(obj)
  136. rescue XSD::ValueSpaceError
  137. return nil
  138. end
  139. mark_marshalled_obj(obj, soap_obj)
  140. soap_obj
  141. end
  142. def soap2obj(obj_class, node, info, map)
  143. if node.respond_to?(:to_obj)
  144. obj = node.to_obj(obj_class)
  145. return false if obj.nil?
  146. mark_unmarshalled_obj(node, obj)
  147. return true, obj
  148. else
  149. return false
  150. end
  151. end
  152. end
  153. class Base64Factory_ < Factory
  154. def obj2soap(soap_class, obj, info, map)
  155. return nil unless obj.instance_variables.empty?
  156. soap_obj = soap_class.new(obj)
  157. mark_marshalled_obj(obj, soap_obj) if soap_obj
  158. soap_obj
  159. end
  160. def soap2obj(obj_class, node, info, map)
  161. obj = node.string
  162. mark_unmarshalled_obj(node, obj)
  163. return true, obj
  164. end
  165. end
  166. class URIFactory_ < Factory
  167. def obj2soap(soap_class, obj, info, map)
  168. soap_obj = soap_class.new(obj)
  169. mark_marshalled_obj(obj, soap_obj) if soap_obj
  170. soap_obj
  171. end
  172. def soap2obj(obj_class, node, info, map)
  173. obj = node.data
  174. mark_unmarshalled_obj(node, obj)
  175. return true, obj
  176. end
  177. end
  178. class ArrayFactory_ < Factory
  179. def initialize(allow_original_mapping = false)
  180. super()
  181. @allow_original_mapping = allow_original_mapping
  182. end
  183. # [[1], [2]] is converted to Array of Array, not 2-D Array.
  184. # To create M-D Array, you must call Mapping.ary2md.
  185. def obj2soap(soap_class, obj, info, map)
  186. if !@allow_original_mapping and !obj.instance_variables.empty?
  187. return nil
  188. end
  189. arytype = Mapping.obj2element(obj)
  190. if arytype.name
  191. arytype.namespace ||= RubyTypeNamespace
  192. else
  193. arytype = XSD::AnyTypeName
  194. end
  195. soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
  196. mark_marshalled_obj(obj, soap_obj)
  197. obj.each do |item|
  198. soap_obj.add(Mapping._obj2soap(item, map))
  199. end
  200. soap_obj
  201. end
  202. def soap2obj(obj_class, node, info, map)
  203. obj = Mapping.create_empty_object(obj_class)
  204. mark_unmarshalled_obj(node, obj)
  205. node.soap2array(obj) do |elem|
  206. elem ? Mapping._soap2obj(elem, map) : nil
  207. end
  208. return true, obj
  209. end
  210. end
  211. class TypedArrayFactory_ < Factory
  212. def initialize(allow_original_mapping = false)
  213. super()
  214. @allow_original_mapping = allow_original_mapping
  215. end
  216. def obj2soap(soap_class, obj, info, map)
  217. if !@allow_original_mapping and !obj.instance_variables.empty?
  218. return nil
  219. end
  220. arytype = info[:type] || info[0]
  221. soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
  222. mark_marshalled_obj(obj, soap_obj)
  223. obj.each do |var|
  224. soap_obj.add(Mapping._obj2soap(var, map))
  225. end
  226. soap_obj
  227. end
  228. def soap2obj(obj_class, node, info, map)
  229. if node.rank > 1
  230. return false
  231. end
  232. arytype = info[:type] || info[0]
  233. unless node.arytype == arytype
  234. return false
  235. end
  236. obj = Mapping.create_empty_object(obj_class)
  237. mark_unmarshalled_obj(node, obj)
  238. node.soap2array(obj) do |elem|
  239. elem ? Mapping._soap2obj(elem, map) : nil
  240. end
  241. return true, obj
  242. end
  243. end
  244. class TypedStructFactory_ < Factory
  245. def obj2soap(soap_class, obj, info, map)
  246. type = info[:type] || info[0]
  247. soap_obj = soap_class.new(type)
  248. mark_marshalled_obj(obj, soap_obj)
  249. if obj.class <= SOAP::Marshallable
  250. setiv2soap(soap_obj, obj, map)
  251. else
  252. setiv2soap(soap_obj, obj, map)
  253. end
  254. soap_obj
  255. end
  256. def soap2obj(obj_class, node, info, map)
  257. type = info[:type] || info[0]
  258. unless node.type == type
  259. return false
  260. end
  261. obj = Mapping.create_empty_object(obj_class)
  262. mark_unmarshalled_obj(node, obj)
  263. setiv2obj(obj, node, map)
  264. return true, obj
  265. end
  266. end
  267. MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map')
  268. class HashFactory_ < Factory
  269. def initialize(allow_original_mapping = false)
  270. super()
  271. @allow_original_mapping = allow_original_mapping
  272. end
  273. def obj2soap(soap_class, obj, info, map)
  274. if !@allow_original_mapping and !obj.instance_variables.empty?
  275. return nil
  276. end
  277. if !obj.default.nil? or
  278. (obj.respond_to?(:default_proc) and obj.default_proc)
  279. return nil
  280. end
  281. soap_obj = SOAPStruct.new(MapQName)
  282. mark_marshalled_obj(obj, soap_obj)
  283. obj.each do |key, value|
  284. elem = SOAPStruct.new
  285. elem.add("key", Mapping._obj2soap(key, map))
  286. elem.add("value", Mapping._obj2soap(value, map))
  287. # ApacheAxis allows only 'item' here.
  288. soap_obj.add("item", elem)
  289. end
  290. soap_obj
  291. end
  292. def soap2obj(obj_class, node, info, map)
  293. unless node.type == MapQName
  294. return false
  295. end
  296. if node.class == SOAPStruct and node.key?('default')
  297. return false
  298. end
  299. obj = Mapping.create_empty_object(obj_class)
  300. mark_unmarshalled_obj(node, obj)
  301. if node.class == SOAPStruct
  302. node.each do |key, value|
  303. obj[Mapping._soap2obj(value['key'], map)] =
  304. Mapping._soap2obj(value['value'], map)
  305. end
  306. else
  307. node.each do |value|
  308. obj[Mapping._soap2obj(value['key'], map)] =
  309. Mapping._soap2obj(value['value'], map)
  310. end
  311. end
  312. return true, obj
  313. end
  314. end
  315. end
  316. end