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

root/branches/1_5/lib/soap/mapping/wsdlencodedregistry.rb

Revision 1971, 5.8 kB (checked in by nahi, 1 year ago)
  • cache the result of XSD::CodeGen?#{safeconstname|safevarname} while mapping.
  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1 # SOAP4R - WSDL encoded mapping registry.
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 '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 < EncodedRegistry
21   attr_reader :definedelements
22   attr_reader :definedtypes
23
24   def initialize(definedtypes = XSD::NamedElements::Empty)
25     super()
26     @definedtypes = definedtypes
27     # @definedelements = definedelements  needed?
28     # For mapping AnyType element.
29     @rubytype_factory = RubytypeFactory.new(
30       :allow_untyped_struct => true,
31       :allow_original_mapping => true
32     )
33   end
34
35   def obj2soap(obj, qname = nil)
36     soap_obj = nil
37     if type = @definedtypes[qname]
38       soap_obj = obj2typesoap(obj, type)
39     else
40       soap_obj = any2soap(obj, qname)
41     end
42     return soap_obj if soap_obj
43     if @excn_handler_obj2soap
44       soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
45         Mapping._obj2soap(yield_obj, self)
46       }
47       return soap_obj if soap_obj
48     end
49     if qname
50       raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
51     else
52       raise MappingError.new("cannot map #{obj.class.name} to SOAP/OM")
53     end
54   end
55
56   # map anything for now: must refer WSDL while mapping.  [ToDo]
57   def soap2obj(node, obj_class = nil)
58     cause = nil
59     begin
60       unless obj_class
61         typestr = Mapping.safeconstname(node.elename.name)
62         obj_class = Mapping.class_from_name(typestr)
63       end
64       return Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
65     rescue MappingError
66       cause = $!
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", cause)
77   end
78
79 private
80
81   def any2soap(obj, qname)
82     ele = nil
83     if obj.nil?
84       ele = SOAPNil.new
85     elsif qname.nil? or qname == XSD::AnyTypeName
86       ele = @rubytype_factory.obj2soap(nil, obj, nil, self)
87     elsif obj.is_a?(XSD::NSDBase)
88       ele = soap2soap(obj, qname)
89     elsif type = TypeMap[qname]
90       ele = base2soap(obj, type)
91     end
92     add_attributes2soap(obj, ele) unless ele.nil?
93     ele
94   end
95
96   def soap2soap(obj, type_qname)
97     if obj.is_a?(SOAPBasetype)
98       obj
99     elsif obj.is_a?(SOAPStruct) && (type = @definedtypes[type_qname])
100       soap_obj = obj
101       mark_marshalled_obj(obj, soap_obj)
102       elements2soap(obj, soap_obj, type.elements)
103       soap_obj
104     elsif obj.is_a?(SOAPArray) && (type = @definedtypes[type_qname])
105       soap_obj = obj
106       contenttype = type.child_type
107       mark_marshalled_obj(obj, soap_obj)
108       obj.replace do |ele|
109         Mapping._obj2soap(ele, self, contenttype)
110       end
111       soap_obj
112     else
113       nil
114     end
115   end
116
117   def obj2typesoap(obj, type)
118     if type.is_a?(::WSDL::XMLSchema::SimpleType)
119       simpleobj2soap(obj, type)
120     else
121       complexobj2soap(obj, type)
122     end
123   end
124
125   def simpleobj2soap(obj, type)
126     type.check_lexical_format(obj)
127     return SOAPNil.new if obj.nil?      # TODO: check nillable.
128     if type.base
129       ele = base2soap(obj, TypeMap[type.base])
130       ele.type = type.name
131     elsif type.list
132       value = obj.is_a?(Array) ? obj.join(" ") : obj.to_s
133       ele = base2soap(value, SOAP::SOAPString)
134     else
135       raise MappingError.new("unsupported simpleType: #{type}")
136     end
137     ele
138   end
139
140   def complexobj2soap(obj, type)
141     case type.compoundtype
142     when :TYPE_STRUCT
143       struct2soap(obj, type.name, type)
144     when :TYPE_ARRAY
145       array2soap(obj, type.name, type)
146     when :TYPE_MAP
147       map2soap(obj, type.name, type)
148     when :TYPE_SIMPLE
149       simpleobj2soap(obj, type.simplecontent)
150     when :TYPE_EMPTY
151       raise MappingError.new("should be empty") unless obj.nil?
152       SOAPNil.new
153     else
154       raise MappingError.new("unknown compound type: #{type.compoundtype}")
155     end
156   end
157
158   def struct2soap(obj, type_qname, type)
159     return SOAPNil.new if obj.nil?      # ToDo: check nillable.
160     soap_obj = SOAPStruct.new(type_qname)
161     mark_marshalled_obj(obj, soap_obj)
162     elements2soap(obj, soap_obj, type.elements)
163     soap_obj
164   end
165
166   def array2soap(obj, type_qname, type)
167     return SOAPNil.new if obj.nil?      # ToDo: check nillable.
168     arytype = type.child_type
169     soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
170     unless obj.nil?
171       mark_marshalled_obj(obj, soap_obj)
172       obj.each do |item|
173         soap_obj.add(Mapping._obj2soap(item, self, arytype))
174       end
175     end
176     soap_obj
177   end
178
179   MapKeyName = XSD::QName.new(nil, "key")
180   MapValueName = XSD::QName.new(nil, "value")
181   def map2soap(obj, type_qname, type)
182     return SOAPNil.new if obj.nil?      # ToDo: check nillable.
183     keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
184     valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
185     soap_obj = SOAPStruct.new(MapQName)
186     unless obj.nil?
187       mark_marshalled_obj(obj, soap_obj)
188       obj.each do |key, value|
189         elem = SOAPStruct.new
190         elem.add("key", Mapping._obj2soap(key, self, keytype))
191         elem.add("value", Mapping._obj2soap(value, self, valuetype))
192         # ApacheAxis allows only 'item' here.
193         soap_obj.add("item", elem)
194       end
195     end
196     soap_obj
197   end
198
199   def elements2soap(obj, soap_obj, elements)
200     elements.each do |element|
201       name = element.name.name
202       child_obj = Mapping.get_attribute(obj, name)
203       soap_obj.add(name,
204         Mapping._obj2soap(child_obj, self, element.type || element.name))
205     end
206   end
207 end
208
209
210 end
211 end
Note: See TracBrowser for help on using the browser.