source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/registry.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 16.0 KB
Line 
1# SOAP4R - Mapping registry.
2# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <[email protected]>.
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 'soap/baseData'
10require 'soap/mapping/mapping'
11require 'soap/mapping/typeMap'
12require 'soap/mapping/factory'
13require 'soap/mapping/rubytypeFactory'
14
15
16module SOAP
17
18
19module Marshallable
20 # @@type_ns = Mapping::RubyCustomTypeNamespace
21end
22
23
24module Mapping
25
26
27module MappedException; end
28
29
30RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')
31RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends')
32RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars')
33
34
35# Inner class to pass an exception.
36class SOAPException; include Marshallable
37 attr_reader :excn_type_name, :cause
38 def initialize(e)
39 @excn_type_name = Mapping.name2elename(e.class.to_s)
40 @cause = e
41 end
42
43 def to_e
44 if @cause.is_a?(::Exception)
45 @cause.extend(::SOAP::Mapping::MappedException)
46 return @cause
47 elsif @cause.respond_to?(:message) and @cause.respond_to?(:backtrace)
48 e = RuntimeError.new(@cause.message)
49 e.set_backtrace(@cause.backtrace)
50 return e
51 end
52 klass = Mapping.class_from_name(Mapping.elename2name(@excn_type_name.to_s))
53 if klass.nil? or not klass <= ::Exception
54 return RuntimeError.new(@cause.inspect)
55 end
56 obj = klass.new(@cause.message)
57 obj.extend(::SOAP::Mapping::MappedException)
58 obj
59 end
60end
61
62
63# For anyType object: SOAP::Mapping::Object not ::Object
64class Object; include Marshallable
65 def initialize
66 @__xmlele_type = {}
67 @__xmlele = []
68 @__xmlattr = {}
69 end
70
71 def inspect
72 sprintf("#<%s:0x%x%s>", self.class.name, __id__,
73 @__xmlele.collect { |name, value| " #{name}=#{value.inspect}" }.join)
74 end
75
76 def __xmlattr
77 @__xmlattr
78 end
79
80 def __xmlele
81 @__xmlele
82 end
83
84 def [](qname)
85 unless qname.is_a?(XSD::QName)
86 qname = XSD::QName.new(nil, qname)
87 end
88 @__xmlele.each do |k, v|
89 return v if k == qname
90 end
91 # fallback
92 @__xmlele.each do |k, v|
93 return v if k.name == qname.name
94 end
95 nil
96 end
97
98 def []=(qname, value)
99 unless qname.is_a?(XSD::QName)
100 qname = XSD::QName.new(nil, qname)
101 end
102 found = false
103 @__xmlele.each do |pair|
104 if pair[0] == qname
105 found = true
106 pair[1] = value
107 end
108 end
109 unless found
110 __define_attr_accessor(qname)
111 @__xmlele << [qname, value]
112 end
113 @__xmlele_type[qname] = :single
114 end
115
116 def __add_xmlele_value(qname, value)
117 found = false
118 @__xmlele.map! do |k, v|
119 if k == qname
120 found = true
121 [k, __set_xmlele_value(k, v, value)]
122 else
123 [k, v]
124 end
125 end
126 unless found
127 __define_attr_accessor(qname)
128 @__xmlele << [qname, value]
129 @__xmlele_type[qname] = :single
130 end
131 value
132 end
133
134private
135
136 if RUBY_VERSION > "1.7.0"
137 def __define_attr_accessor(qname)
138 name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
139 Mapping.define_attr_accessor(self, name,
140 proc { self[qname] },
141 proc { |value| self[qname] = value })
142 end
143 else
144 def __define_attr_accessor(qname)
145 name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
146 instance_eval <<-EOS
147 def #{name}
148 self[#{qname.dump}]
149 end
150
151 def #{name}=(value)
152 self[#{qname.dump}] = value
153 end
154 EOS
155 end
156 end
157
158 def __set_xmlele_value(key, org, value)
159 case @__xmlele_type[key]
160 when :multi
161 org << value
162 org
163 when :single
164 @__xmlele_type[key] = :multi
165 [org, value]
166 else
167 raise RuntimeError.new("unknown type")
168 end
169 end
170end
171
172
173class MappingError < Error; end
174
175
176class Registry
177 class Map
178 def initialize(registry)
179 @obj2soap = {}
180 @soap2obj = {}
181 @registry = registry
182 end
183
184 def obj2soap(obj)
185 klass = obj.class
186 if map = @obj2soap[klass]
187 map.each do |soap_class, factory, info|
188 ret = factory.obj2soap(soap_class, obj, info, @registry)
189 return ret if ret
190 end
191 end
192 ancestors = klass.ancestors
193 ancestors.delete(klass)
194 ancestors.delete(::Object)
195 ancestors.delete(::Kernel)
196 ancestors.each do |klass|
197 if map = @obj2soap[klass]
198 map.each do |soap_class, factory, info|
199 if info[:derived_class]
200 ret = factory.obj2soap(soap_class, obj, info, @registry)
201 return ret if ret
202 end
203 end
204 end
205 end
206 nil
207 end
208
209 def soap2obj(node, klass = nil)
210 if map = @soap2obj[node.class]
211 map.each do |obj_class, factory, info|
212 next if klass and obj_class != klass
213 conv, obj = factory.soap2obj(obj_class, node, info, @registry)
214 return true, obj if conv
215 end
216 end
217 return false, nil
218 end
219
220 # Give priority to former entry.
221 def init(init_map = [])
222 clear
223 init_map.reverse_each do |obj_class, soap_class, factory, info|
224 add(obj_class, soap_class, factory, info)
225 end
226 end
227
228 # Give priority to latter entry.
229 def add(obj_class, soap_class, factory, info)
230 info ||= {}
231 (@obj2soap[obj_class] ||= []).unshift([soap_class, factory, info])
232 (@soap2obj[soap_class] ||= []).unshift([obj_class, factory, info])
233 end
234
235 def clear
236 @obj2soap.clear
237 @soap2obj.clear
238 end
239
240 def find_mapped_soap_class(target_obj_class)
241 map = @obj2soap[target_obj_class]
242 map.empty? ? nil : map[0][1]
243 end
244
245 def find_mapped_obj_class(target_soap_class)
246 map = @soap2obj[target_soap_class]
247 map.empty? ? nil : map[0][0]
248 end
249 end
250
251 StringFactory = StringFactory_.new
252 BasetypeFactory = BasetypeFactory_.new
253 DateTimeFactory = DateTimeFactory_.new
254 ArrayFactory = ArrayFactory_.new
255 Base64Factory = Base64Factory_.new
256 URIFactory = URIFactory_.new
257 TypedArrayFactory = TypedArrayFactory_.new
258 TypedStructFactory = TypedStructFactory_.new
259
260 HashFactory = HashFactory_.new
261
262 SOAPBaseMap = [
263 [::NilClass, ::SOAP::SOAPNil, BasetypeFactory],
264 [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
265 [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
266 [::String, ::SOAP::SOAPString, StringFactory],
267 [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
268 [::Date, ::SOAP::SOAPDate, DateTimeFactory],
269 [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
270 [::Time, ::SOAP::SOAPTime, DateTimeFactory],
271 [::Float, ::SOAP::SOAPDouble, BasetypeFactory,
272 {:derived_class => true}],
273 [::Float, ::SOAP::SOAPFloat, BasetypeFactory,
274 {:derived_class => true}],
275 [::Integer, ::SOAP::SOAPInt, BasetypeFactory,
276 {:derived_class => true}],
277 [::Integer, ::SOAP::SOAPLong, BasetypeFactory,
278 {:derived_class => true}],
279 [::Integer, ::SOAP::SOAPInteger, BasetypeFactory,
280 {:derived_class => true}],
281 [::Integer, ::SOAP::SOAPShort, BasetypeFactory,
282 {:derived_class => true}],
283 [::Integer, ::SOAP::SOAPByte, BasetypeFactory,
284 {:derived_class => true}],
285 [::Integer, ::SOAP::SOAPNonPositiveInteger, BasetypeFactory,
286 {:derived_class => true}],
287 [::Integer, ::SOAP::SOAPNegativeInteger, BasetypeFactory,
288 {:derived_class => true}],
289 [::Integer, ::SOAP::SOAPNonNegativeInteger, BasetypeFactory,
290 {:derived_class => true}],
291 [::Integer, ::SOAP::SOAPPositiveInteger, BasetypeFactory,
292 {:derived_class => true}],
293 [::Integer, ::SOAP::SOAPUnsignedLong, BasetypeFactory,
294 {:derived_class => true}],
295 [::Integer, ::SOAP::SOAPUnsignedInt, BasetypeFactory,
296 {:derived_class => true}],
297 [::Integer, ::SOAP::SOAPUnsignedShort, BasetypeFactory,
298 {:derived_class => true}],
299 [::Integer, ::SOAP::SOAPUnsignedByte, BasetypeFactory,
300 {:derived_class => true}],
301 [::URI::Generic, ::SOAP::SOAPAnyURI, URIFactory,
302 {:derived_class => true}],
303 [::String, ::SOAP::SOAPBase64, Base64Factory],
304 [::String, ::SOAP::SOAPHexBinary, Base64Factory],
305 [::String, ::SOAP::SOAPDecimal, BasetypeFactory],
306 [::String, ::SOAP::SOAPDuration, BasetypeFactory],
307 [::String, ::SOAP::SOAPGYearMonth, BasetypeFactory],
308 [::String, ::SOAP::SOAPGYear, BasetypeFactory],
309 [::String, ::SOAP::SOAPGMonthDay, BasetypeFactory],
310 [::String, ::SOAP::SOAPGDay, BasetypeFactory],
311 [::String, ::SOAP::SOAPGMonth, BasetypeFactory],
312 [::String, ::SOAP::SOAPQName, BasetypeFactory],
313
314 [::Hash, ::SOAP::SOAPArray, HashFactory],
315 [::Hash, ::SOAP::SOAPStruct, HashFactory],
316
317 [::Array, ::SOAP::SOAPArray, ArrayFactory,
318 {:derived_class => true}],
319
320 [::SOAP::Mapping::SOAPException,
321 ::SOAP::SOAPStruct, TypedStructFactory,
322 {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
323 ]
324
325 RubyOriginalMap = [
326 [::NilClass, ::SOAP::SOAPNil, BasetypeFactory],
327 [::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory],
328 [::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
329 [::String, ::SOAP::SOAPString, StringFactory],
330 [::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
331 [::Date, ::SOAP::SOAPDate, DateTimeFactory],
332 [::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
333 [::Time, ::SOAP::SOAPTime, DateTimeFactory],
334 [::Float, ::SOAP::SOAPDouble, BasetypeFactory,
335 {:derived_class => true}],
336 [::Float, ::SOAP::SOAPFloat, BasetypeFactory,
337 {:derived_class => true}],
338 [::Integer, ::SOAP::SOAPInt, BasetypeFactory,
339 {:derived_class => true}],
340 [::Integer, ::SOAP::SOAPLong, BasetypeFactory,
341 {:derived_class => true}],
342 [::Integer, ::SOAP::SOAPInteger, BasetypeFactory,
343 {:derived_class => true}],
344 [::Integer, ::SOAP::SOAPShort, BasetypeFactory,
345 {:derived_class => true}],
346 [::Integer, ::SOAP::SOAPByte, BasetypeFactory,
347 {:derived_class => true}],
348 [::Integer, ::SOAP::SOAPNonPositiveInteger, BasetypeFactory,
349 {:derived_class => true}],
350 [::Integer, ::SOAP::SOAPNegativeInteger, BasetypeFactory,
351 {:derived_class => true}],
352 [::Integer, ::SOAP::SOAPNonNegativeInteger, BasetypeFactory,
353 {:derived_class => true}],
354 [::Integer, ::SOAP::SOAPPositiveInteger, BasetypeFactory,
355 {:derived_class => true}],
356 [::Integer, ::SOAP::SOAPUnsignedLong, BasetypeFactory,
357 {:derived_class => true}],
358 [::Integer, ::SOAP::SOAPUnsignedInt, BasetypeFactory,
359 {:derived_class => true}],
360 [::Integer, ::SOAP::SOAPUnsignedShort, BasetypeFactory,
361 {:derived_class => true}],
362 [::Integer, ::SOAP::SOAPUnsignedByte, BasetypeFactory,
363 {:derived_class => true}],
364 [::URI::Generic, ::SOAP::SOAPAnyURI, URIFactory,
365 {:derived_class => true}],
366 [::String, ::SOAP::SOAPBase64, Base64Factory],
367 [::String, ::SOAP::SOAPHexBinary, Base64Factory],
368 [::String, ::SOAP::SOAPDecimal, BasetypeFactory],
369 [::String, ::SOAP::SOAPDuration, BasetypeFactory],
370 [::String, ::SOAP::SOAPGYearMonth, BasetypeFactory],
371 [::String, ::SOAP::SOAPGYear, BasetypeFactory],
372 [::String, ::SOAP::SOAPGMonthDay, BasetypeFactory],
373 [::String, ::SOAP::SOAPGDay, BasetypeFactory],
374 [::String, ::SOAP::SOAPGMonth, BasetypeFactory],
375 [::String, ::SOAP::SOAPQName, BasetypeFactory],
376
377 [::Hash, ::SOAP::SOAPArray, HashFactory],
378 [::Hash, ::SOAP::SOAPStruct, HashFactory],
379
380 # Does not allow Array's subclass here.
381 [::Array, ::SOAP::SOAPArray, ArrayFactory],
382
383 [::SOAP::Mapping::SOAPException,
384 ::SOAP::SOAPStruct, TypedStructFactory,
385 {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
386 ]
387
388 attr_accessor :default_factory
389 attr_accessor :excn_handler_obj2soap
390 attr_accessor :excn_handler_soap2obj
391
392 def initialize(config = {})
393 @config = config
394 @map = Map.new(self)
395 if @config[:allow_original_mapping]
396 @allow_original_mapping = true
397 @map.init(RubyOriginalMap)
398 else
399 @allow_original_mapping = false
400 @map.init(SOAPBaseMap)
401 end
402 @allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
403 @config[:allow_untyped_struct] : true
404 @rubytype_factory = RubytypeFactory.new(
405 :allow_untyped_struct => @allow_untyped_struct,
406 :allow_original_mapping => @allow_original_mapping
407 )
408 @default_factory = @rubytype_factory
409 @excn_handler_obj2soap = nil
410 @excn_handler_soap2obj = nil
411 end
412
413 def add(obj_class, soap_class, factory, info = nil)
414 @map.add(obj_class, soap_class, factory, info)
415 end
416 alias set add
417
418 # general Registry ignores type_qname
419 def obj2soap(obj, type_qname = nil)
420 soap = _obj2soap(obj)
421 if @allow_original_mapping
422 addextend2soap(soap, obj)
423 end
424 soap
425 end
426
427 def soap2obj(node, klass = nil)
428 obj = _soap2obj(node, klass)
429 if @allow_original_mapping
430 addextend2obj(obj, node.extraattr[RubyExtendName])
431 addiv2obj(obj, node.extraattr[RubyIVarName])
432 end
433 obj
434 end
435
436 def find_mapped_soap_class(obj_class)
437 @map.find_mapped_soap_class(obj_class)
438 end
439
440 def find_mapped_obj_class(soap_class)
441 @map.find_mapped_obj_class(soap_class)
442 end
443
444private
445
446 def _obj2soap(obj)
447 ret = nil
448 if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
449 obj.replace do |ele|
450 Mapping._obj2soap(ele, self)
451 end
452 return obj
453 elsif obj.is_a?(SOAPBasetype)
454 return obj
455 end
456 begin
457 ret = @map.obj2soap(obj) ||
458 @default_factory.obj2soap(nil, obj, nil, self)
459 return ret if ret
460 rescue MappingError
461 end
462 if @excn_handler_obj2soap
463 ret = @excn_handler_obj2soap.call(obj) { |yield_obj|
464 Mapping._obj2soap(yield_obj, self)
465 }
466 return ret if ret
467 end
468 raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
469 end
470
471 # Might return nil as a mapping result.
472 def _soap2obj(node, klass = nil)
473 if node.extraattr.key?(RubyTypeName)
474 conv, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
475 return obj if conv
476 else
477 conv, obj = @map.soap2obj(node, klass)
478 return obj if conv
479 conv, obj = @default_factory.soap2obj(nil, node, nil, self)
480 return obj if conv
481 end
482 if @excn_handler_soap2obj
483 begin
484 return @excn_handler_soap2obj.call(node) { |yield_node|
485 Mapping._soap2obj(yield_node, self)
486 }
487 rescue Exception
488 end
489 end
490 raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
491 end
492
493 def addiv2obj(obj, attr)
494 return unless attr
495 vars = {}
496 attr.__getobj__.each do |name, value|
497 vars[name] = Mapping._soap2obj(value, self)
498 end
499 Mapping.set_attributes(obj, vars)
500 end
501
502 if RUBY_VERSION >= '1.8.0'
503 def addextend2obj(obj, attr)
504 return unless attr
505 attr.split(/ /).reverse_each do |mstr|
506 obj.extend(Mapping.module_from_name(mstr))
507 end
508 end
509 else
510 # (class < false; self; end).ancestors includes "TrueClass" under 1.6...
511 def addextend2obj(obj, attr)
512 return unless attr
513 attr.split(/ /).reverse_each do |mstr|
514 m = Mapping.module_from_name(mstr)
515 obj.extend(m)
516 end
517 end
518 end
519
520 def addextend2soap(node, obj)
521 return if obj.is_a?(Symbol) or obj.is_a?(Fixnum)
522 list = (class << obj; self; end).ancestors - obj.class.ancestors
523 unless list.empty?
524 node.extraattr[RubyExtendName] = list.collect { |c|
525 if c.name.empty?
526 raise TypeError.new("singleton can't be dumped #{ obj }")
527 end
528 c.name
529 }.join(" ")
530 end
531 end
532
533end
534
535
536DefaultRegistry = Registry.new
537RubyOriginalRegistry = Registry.new(:allow_original_mapping => true)
538
539
540end
541end
Note: See TracBrowser for help on using the repository browser.