~ubuntu-branches/ubuntu/trusty/ruby1.9/trusty

« back to all changes in this revision

Viewing changes to lib/soap/mapping/wsdlencodedregistry.rb

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Hermann
  • Date: 2008-01-24 11:42:29 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20080124114229-jw2f87rdxlq6gp11
Tags: 1.9.0.0-2ubuntu1
* Merge from debian unstable, remaining changes:
  - Robustify check for target_os, fixing build failure on lpia.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# SOAP4R - WSDL encoded mapping registry.
2
 
# Copyright (C) 2000-2003, 2005  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 'xsd/qname'
10
 
require 'xsd/namedelements'
11
 
require 'soap/baseData'
12
 
require 'soap/mapping/mapping'
13
 
require 'soap/mapping/typeMap'
14
 
 
15
 
 
16
 
module SOAP
17
 
module Mapping
18
 
 
19
 
 
20
 
class WSDLEncodedRegistry < Registry
21
 
  include TraverseSupport
22
 
 
23
 
  attr_reader :definedelements
24
 
  attr_reader :definedtypes
25
 
  attr_accessor :excn_handler_obj2soap
26
 
  attr_accessor :excn_handler_soap2obj
27
 
 
28
 
  def initialize(definedtypes = XSD::NamedElements::Empty)
29
 
    @definedtypes = definedtypes
30
 
    # @definedelements = definedelements  needed?
31
 
    @excn_handler_obj2soap = nil
32
 
    @excn_handler_soap2obj = nil
33
 
    # For mapping AnyType element.
34
 
    @rubytype_factory = RubytypeFactory.new(
35
 
      :allow_untyped_struct => true,
36
 
      :allow_original_mapping => true
37
 
    )
38
 
    @schema_element_cache = {}
39
 
  end
40
 
 
41
 
  def obj2soap(obj, qname = nil)
42
 
    soap_obj = nil
43
 
    if type = @definedtypes[qname]
44
 
      soap_obj = obj2typesoap(obj, type)
45
 
    else
46
 
      soap_obj = any2soap(obj, qname)
47
 
    end
48
 
    return soap_obj if soap_obj
49
 
    if @excn_handler_obj2soap
50
 
      soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
51
 
        Mapping._obj2soap(yield_obj, self)
52
 
      }
53
 
      return soap_obj if soap_obj
54
 
    end
55
 
    if qname
56
 
      raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
57
 
    else
58
 
      raise MappingError.new("cannot map #{obj.class.name} to SOAP/OM")
59
 
    end
60
 
  end
61
 
 
62
 
  # map anything for now: must refer WSDL while mapping.  [ToDo]
63
 
  def soap2obj(node, obj_class = nil)
64
 
    begin
65
 
      return any2obj(node, obj_class)
66
 
    rescue MappingError
67
 
    end
68
 
    if @excn_handler_soap2obj
69
 
      begin
70
 
        return @excn_handler_soap2obj.call(node) { |yield_node|
71
 
            Mapping._soap2obj(yield_node, self)
72
 
          }
73
 
      rescue Exception
74
 
      end
75
 
    end
76
 
    raise MappingError.new("cannot map #{node.type.name} to Ruby object")
77
 
  end
78
 
 
79
 
private
80
 
 
81
 
  def any2soap(obj, qname)
82
 
    if obj.nil?
83
 
      SOAPNil.new
84
 
    elsif qname.nil? or qname == XSD::AnyTypeName
85
 
      @rubytype_factory.obj2soap(nil, obj, nil, self)
86
 
    elsif obj.is_a?(XSD::NSDBase)
87
 
      soap2soap(obj, qname)
88
 
    elsif (type = TypeMap[qname])
89
 
      base2soap(obj, type)
90
 
    else
91
 
      nil
92
 
    end
93
 
  end
94
 
 
95
 
  def soap2soap(obj, type_qname)
96
 
    if obj.is_a?(SOAPBasetype)
97
 
      obj
98
 
    elsif obj.is_a?(SOAPStruct) && (type = @definedtypes[type_qname])
99
 
      soap_obj = obj
100
 
      mark_marshalled_obj(obj, soap_obj)
101
 
      elements2soap(obj, soap_obj, type.content.elements)
102
 
      soap_obj
103
 
    elsif obj.is_a?(SOAPArray) && (type = @definedtypes[type_qname])
104
 
      soap_obj = obj
105
 
      contenttype = type.child_type
106
 
      mark_marshalled_obj(obj, soap_obj)
107
 
      obj.replace do |ele|
108
 
        Mapping._obj2soap(ele, self, contenttype)
109
 
      end
110
 
      soap_obj
111
 
    else
112
 
      nil
113
 
    end
114
 
  end
115
 
 
116
 
  def obj2typesoap(obj, type)
117
 
    if type.is_a?(::WSDL::XMLSchema::SimpleType)
118
 
      simpleobj2soap(obj, type)
119
 
    else
120
 
      complexobj2soap(obj, type)
121
 
    end
122
 
  end
123
 
 
124
 
  def simpleobj2soap(obj, type)
125
 
    type.check_lexical_format(obj)
126
 
    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
127
 
    o = base2soap(obj, TypeMap[type.base])
128
 
    o
129
 
  end
130
 
 
131
 
  def complexobj2soap(obj, type)
132
 
    case type.compoundtype
133
 
    when :TYPE_STRUCT
134
 
      struct2soap(obj, type.name, type)
135
 
    when :TYPE_ARRAY
136
 
      array2soap(obj, type.name, type)
137
 
    when :TYPE_MAP
138
 
      map2soap(obj, type.name, type)
139
 
    when :TYPE_SIMPLE
140
 
      simpleobj2soap(obj, type.simplecontent)
141
 
    when :TYPE_EMPTY
142
 
      raise MappingError.new("should be empty") unless obj.nil?
143
 
      SOAPNil.new
144
 
    else
145
 
      raise MappingError.new("unknown compound type: #{type.compoundtype}")
146
 
    end
147
 
  end
148
 
 
149
 
  def base2soap(obj, type)
150
 
    soap_obj = nil
151
 
    if type <= XSD::XSDString
152
 
      str = XSD::Charset.encoding_conv(obj.to_s,
153
 
        Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
154
 
      soap_obj = type.new(str)
155
 
      mark_marshalled_obj(obj, soap_obj)
156
 
    else
157
 
      soap_obj = type.new(obj)
158
 
    end
159
 
    soap_obj
160
 
  end
161
 
 
162
 
  def struct2soap(obj, type_qname, type)
163
 
    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
164
 
    soap_obj = SOAPStruct.new(type_qname)
165
 
    unless obj.nil?
166
 
      mark_marshalled_obj(obj, soap_obj)
167
 
      elements2soap(obj, soap_obj, type.content.elements)
168
 
    end
169
 
    soap_obj
170
 
  end
171
 
 
172
 
  def array2soap(obj, type_qname, type)
173
 
    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
174
 
    arytype = type.child_type
175
 
    soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
176
 
    unless obj.nil?
177
 
      mark_marshalled_obj(obj, soap_obj)
178
 
      obj.each do |item|
179
 
        soap_obj.add(Mapping._obj2soap(item, self, arytype))
180
 
      end
181
 
    end
182
 
    soap_obj
183
 
  end
184
 
 
185
 
  MapKeyName = XSD::QName.new(nil, "key")
186
 
  MapValueName = XSD::QName.new(nil, "value")
187
 
  def map2soap(obj, type_qname, type)
188
 
    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
189
 
    keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
190
 
    valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
191
 
    soap_obj = SOAPStruct.new(MapQName)
192
 
    unless obj.nil?
193
 
      mark_marshalled_obj(obj, soap_obj)
194
 
      obj.each do |key, value|
195
 
        elem = SOAPStruct.new
196
 
        elem.add("key", Mapping._obj2soap(key, self, keytype))
197
 
        elem.add("value", Mapping._obj2soap(value, self, valuetype))
198
 
        # ApacheAxis allows only 'item' here.
199
 
        soap_obj.add("item", elem)
200
 
      end
201
 
    end
202
 
    soap_obj
203
 
  end
204
 
 
205
 
  def elements2soap(obj, soap_obj, elements)
206
 
    elements.each do |element|
207
 
      name = element.name.name
208
 
      child_obj = Mapping.get_attribute(obj, name)
209
 
      soap_obj.add(name,
210
 
        Mapping._obj2soap(child_obj, self, element.type || element.name))
211
 
    end
212
 
  end
213
 
 
214
 
  def any2obj(node, obj_class)
215
 
    unless obj_class
216
 
      typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
217
 
      obj_class = Mapping.class_from_name(typestr)
218
 
    end
219
 
    if obj_class and obj_class.class_variables.include?('@@schema_element')
220
 
      soap2stubobj(node, obj_class)
221
 
    else
222
 
      Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
223
 
    end
224
 
  end
225
 
 
226
 
  def soap2stubobj(node, obj_class)
227
 
    obj = Mapping.create_empty_object(obj_class)
228
 
    unless node.is_a?(SOAPNil)
229
 
      add_elements2stubobj(node, obj)
230
 
    end
231
 
    obj
232
 
  end
233
 
 
234
 
  def add_elements2stubobj(node, obj)
235
 
    elements, as_array = schema_element_definition(obj.class)
236
 
    vars = {}
237
 
    node.each do |name, value|
238
 
      item = elements.find { |k, v| k.name == name }
239
 
      if item
240
 
        elename, class_name = item
241
 
        if klass = Mapping.class_from_name(class_name)
242
 
          # klass must be a SOAPBasetype or a class
243
 
          if klass.ancestors.include?(::SOAP::SOAPBasetype)
244
 
            if value.respond_to?(:data)
245
 
              child = klass.new(value.data).data
246
 
            else
247
 
              child = klass.new(nil).data
248
 
            end
249
 
          else
250
 
            child = Mapping._soap2obj(value, self, klass)
251
 
          end
252
 
        elsif klass = Mapping.module_from_name(class_name)
253
 
          # simpletype
254
 
          if value.respond_to?(:data)
255
 
            child = value.data
256
 
          else
257
 
            raise MappingError.new(
258
 
              "cannot map to a module value: #{class_name}")
259
 
          end
260
 
        else
261
 
          raise MappingError.new("unknown class: #{class_name}")
262
 
        end
263
 
      else      # untyped element is treated as anyType.
264
 
        child = Mapping._soap2obj(value, self)
265
 
      end
266
 
      vars[name] = child
267
 
    end
268
 
    Mapping.set_attributes(obj, vars)
269
 
  end
270
 
 
271
 
  # it caches @@schema_element.  this means that @@schema_element must not be
272
 
  # changed while a lifetime of a WSDLLiteralRegistry.
273
 
  def schema_element_definition(klass)
274
 
    @schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
275
 
  end
276
 
end
277
 
 
278
 
 
279
 
end
280
 
end