source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/baseData.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.7 KB
Line 
1# soap/baseData.rb: SOAP4R - Base type library
2# Copyright (C) 2000, 2001, 2003-2005 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 'xsd/datatypes'
10require 'soap/soap'
11
12
13module SOAP
14
15
16###
17## Mix-in module for SOAP base type classes.
18#
19module SOAPModuleUtils
20 include SOAP
21
22public
23
24 def decode(elename)
25 d = self.new
26 d.elename = elename
27 d
28 end
29end
30
31
32###
33## for SOAP type(base and compound)
34#
35module SOAPType
36 attr_accessor :encodingstyle
37 attr_accessor :elename
38 attr_accessor :id
39 attr_reader :precedents
40 attr_accessor :root
41 attr_accessor :parent
42 attr_accessor :position
43 attr_reader :extraattr
44 attr_accessor :definedtype
45
46 def initialize(*arg)
47 super
48 @encodingstyle = nil
49 @elename = XSD::QName::EMPTY
50 @id = nil
51 @precedents = []
52 @root = false
53 @parent = nil
54 @position = nil
55 @definedtype = nil
56 @extraattr = {}
57 end
58
59 def inspect
60 if self.is_a?(XSD::NSDBase)
61 sprintf("#<%s:0x%x %s %s>", self.class.name, __id__, self.elename, self.type)
62 else
63 sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
64 end
65 end
66
67 def rootnode
68 node = self
69 while node = node.parent
70 break if SOAPEnvelope === node
71 end
72 node
73 end
74end
75
76
77###
78## for SOAP base type
79#
80module SOAPBasetype
81 include SOAPType
82 include SOAP
83
84 def initialize(*arg)
85 super
86 end
87end
88
89
90###
91## for SOAP compound type
92#
93module SOAPCompoundtype
94 include SOAPType
95 include SOAP
96
97 def initialize(*arg)
98 super
99 end
100end
101
102
103###
104## Convenience datatypes.
105#
106class SOAPReference < XSD::NSDBase
107 include SOAPBasetype
108 extend SOAPModuleUtils
109
110public
111
112 attr_accessor :refid
113
114 # Override the definition in SOAPBasetype.
115 def initialize(obj = nil)
116 super()
117 @type = XSD::QName::EMPTY
118 @refid = nil
119 @obj = nil
120 __setobj__(obj) if obj
121 end
122
123 def __getobj__
124 @obj
125 end
126
127 def __setobj__(obj)
128 @obj = obj
129 @refid = @obj.id || SOAPReference.create_refid(@obj)
130 @obj.id = @refid unless @obj.id
131 @obj.precedents << self
132 # Copies NSDBase information
133 @obj.type = @type unless @obj.type
134 end
135
136 # Why don't I use delegate.rb?
137 # -> delegate requires target object type at initialize time.
138 # Why don't I use forwardable.rb?
139 # -> forwardable requires a list of forwarding methods.
140 #
141 # ToDo: Maybe I should use forwardable.rb and give it a methods list like
142 # delegate.rb...
143 #
144 def method_missing(msg_id, *params)
145 if @obj
146 @obj.send(msg_id, *params)
147 else
148 nil
149 end
150 end
151
152 def refidstr
153 '#' + @refid
154 end
155
156 def self.create_refid(obj)
157 'id' + obj.__id__.to_s
158 end
159
160 def self.decode(elename, refidstr)
161 if /\A#(.*)\z/ =~ refidstr
162 refid = $1
163 elsif /\Acid:(.*)\z/ =~ refidstr
164 refid = $1
165 else
166 raise ArgumentError.new("illegal refid #{refidstr}")
167 end
168 d = super(elename)
169 d.refid = refid
170 d
171 end
172end
173
174
175class SOAPExternalReference < XSD::NSDBase
176 include SOAPBasetype
177 extend SOAPModuleUtils
178
179 def initialize
180 super()
181 @type = XSD::QName::EMPTY
182 end
183
184 def referred
185 rootnode.external_content[external_contentid] = self
186 end
187
188 def refidstr
189 'cid:' + external_contentid
190 end
191
192private
193
194 def external_contentid
195 raise NotImplementedError.new
196 end
197end
198
199
200class SOAPNil < XSD::XSDNil
201 include SOAPBasetype
202 extend SOAPModuleUtils
203end
204
205# SOAPRawString is for sending raw string. In contrast to SOAPString,
206# SOAP4R does not do XML encoding and does not convert its CES. The string it
207# holds is embedded to XML instance directly as a 'xsd:string'.
208class SOAPRawString < XSD::XSDString
209 include SOAPBasetype
210 extend SOAPModuleUtils
211end
212
213
214###
215## Basic datatypes.
216#
217class SOAPAnySimpleType < XSD::XSDAnySimpleType
218 include SOAPBasetype
219 extend SOAPModuleUtils
220end
221
222class SOAPString < XSD::XSDString
223 include SOAPBasetype
224 extend SOAPModuleUtils
225end
226
227class SOAPBoolean < XSD::XSDBoolean
228 include SOAPBasetype
229 extend SOAPModuleUtils
230end
231
232class SOAPDecimal < XSD::XSDDecimal
233 include SOAPBasetype
234 extend SOAPModuleUtils
235end
236
237class SOAPFloat < XSD::XSDFloat
238 include SOAPBasetype
239 extend SOAPModuleUtils
240end
241
242class SOAPDouble < XSD::XSDDouble
243 include SOAPBasetype
244 extend SOAPModuleUtils
245end
246
247class SOAPDuration < XSD::XSDDuration
248 include SOAPBasetype
249 extend SOAPModuleUtils
250end
251
252class SOAPDateTime < XSD::XSDDateTime
253 include SOAPBasetype
254 extend SOAPModuleUtils
255end
256
257class SOAPTime < XSD::XSDTime
258 include SOAPBasetype
259 extend SOAPModuleUtils
260end
261
262class SOAPDate < XSD::XSDDate
263 include SOAPBasetype
264 extend SOAPModuleUtils
265end
266
267class SOAPGYearMonth < XSD::XSDGYearMonth
268 include SOAPBasetype
269 extend SOAPModuleUtils
270end
271
272class SOAPGYear < XSD::XSDGYear
273 include SOAPBasetype
274 extend SOAPModuleUtils
275end
276
277class SOAPGMonthDay < XSD::XSDGMonthDay
278 include SOAPBasetype
279 extend SOAPModuleUtils
280end
281
282class SOAPGDay < XSD::XSDGDay
283 include SOAPBasetype
284 extend SOAPModuleUtils
285end
286
287class SOAPGMonth < XSD::XSDGMonth
288 include SOAPBasetype
289 extend SOAPModuleUtils
290end
291
292class SOAPHexBinary < XSD::XSDHexBinary
293 include SOAPBasetype
294 extend SOAPModuleUtils
295end
296
297class SOAPBase64 < XSD::XSDBase64Binary
298 include SOAPBasetype
299 extend SOAPModuleUtils
300 Type = QName.new(EncodingNamespace, Base64Literal)
301
302public
303 # Override the definition in SOAPBasetype.
304 def initialize(value = nil)
305 super(value)
306 @type = Type
307 end
308
309 def as_xsd
310 @type = XSD::XSDBase64Binary::Type
311 end
312end
313
314class SOAPAnyURI < XSD::XSDAnyURI
315 include SOAPBasetype
316 extend SOAPModuleUtils
317end
318
319class SOAPQName < XSD::XSDQName
320 include SOAPBasetype
321 extend SOAPModuleUtils
322end
323
324
325class SOAPInteger < XSD::XSDInteger
326 include SOAPBasetype
327 extend SOAPModuleUtils
328end
329
330class SOAPNonPositiveInteger < XSD::XSDNonPositiveInteger
331 include SOAPBasetype
332 extend SOAPModuleUtils
333end
334
335class SOAPNegativeInteger < XSD::XSDNegativeInteger
336 include SOAPBasetype
337 extend SOAPModuleUtils
338end
339
340class SOAPLong < XSD::XSDLong
341 include SOAPBasetype
342 extend SOAPModuleUtils
343end
344
345class SOAPInt < XSD::XSDInt
346 include SOAPBasetype
347 extend SOAPModuleUtils
348end
349
350class SOAPShort < XSD::XSDShort
351 include SOAPBasetype
352 extend SOAPModuleUtils
353end
354
355class SOAPByte < XSD::XSDByte
356 include SOAPBasetype
357 extend SOAPModuleUtils
358end
359
360class SOAPNonNegativeInteger < XSD::XSDNonNegativeInteger
361 include SOAPBasetype
362 extend SOAPModuleUtils
363end
364
365class SOAPUnsignedLong < XSD::XSDUnsignedLong
366 include SOAPBasetype
367 extend SOAPModuleUtils
368end
369
370class SOAPUnsignedInt < XSD::XSDUnsignedInt
371 include SOAPBasetype
372 extend SOAPModuleUtils
373end
374
375class SOAPUnsignedShort < XSD::XSDUnsignedShort
376 include SOAPBasetype
377 extend SOAPModuleUtils
378end
379
380class SOAPUnsignedByte < XSD::XSDUnsignedByte
381 include SOAPBasetype
382 extend SOAPModuleUtils
383end
384
385class SOAPPositiveInteger < XSD::XSDPositiveInteger
386 include SOAPBasetype
387 extend SOAPModuleUtils
388end
389
390
391###
392## Compound datatypes.
393#
394class SOAPStruct < XSD::NSDBase
395 include SOAPCompoundtype
396 include Enumerable
397
398public
399
400 def initialize(type = nil)
401 super()
402 @type = type || XSD::QName::EMPTY
403 @array = []
404 @data = []
405 end
406
407 def to_s()
408 str = ''
409 self.each do |key, data|
410 str << "#{key}: #{data}\n"
411 end
412 str
413 end
414
415 def add(name, value)
416 add_member(name, value)
417 end
418
419 def [](idx)
420 if idx.is_a?(Range)
421 @data[idx]
422 elsif idx.is_a?(Integer)
423 if (idx > @array.size)
424 raise ArrayIndexOutOfBoundsError.new('In ' << @type.name)
425 end
426 @data[idx]
427 else
428 if @array.include?(idx)
429 @data[@array.index(idx)]
430 else
431 nil
432 end
433 end
434 end
435
436 def []=(idx, data)
437 if @array.include?(idx)
438 data.parent = self if data.respond_to?(:parent=)
439 @data[@array.index(idx)] = data
440 else
441 add(idx, data)
442 end
443 end
444
445 def key?(name)
446 @array.include?(name)
447 end
448
449 def members
450 @array
451 end
452
453 def to_obj
454 hash = {}
455 proptype = {}
456 each do |k, v|
457 value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
458 case proptype[k]
459 when :single
460 hash[k] = [hash[k], value]
461 proptype[k] = :multi
462 when :multi
463 hash[k] << value
464 else
465 hash[k] = value
466 proptype[k] = :single
467 end
468 end
469 hash
470 end
471
472 def each
473 idx = 0
474 while idx < @array.length
475 yield(@array[idx], @data[idx])
476 idx += 1
477 end
478 end
479
480 def replace
481 members.each do |member|
482 self[member] = yield(self[member])
483 end
484 end
485
486 def self.decode(elename, type)
487 s = SOAPStruct.new(type)
488 s.elename = elename
489 s
490 end
491
492private
493
494 def add_member(name, value = nil)
495 value = SOAPNil.new() if value.nil?
496 @array.push(name)
497 value.elename = value.elename.dup_name(name)
498 @data.push(value)
499 value.parent = self if value.respond_to?(:parent=)
500 value
501 end
502end
503
504
505# SOAPElement is not typed so it is not derived from NSDBase.
506class SOAPElement
507 include Enumerable
508
509 attr_accessor :encodingstyle
510
511 attr_accessor :elename
512 attr_accessor :id
513 attr_reader :precedents
514 attr_accessor :root
515 attr_accessor :parent
516 attr_accessor :position
517 attr_accessor :extraattr
518
519 attr_accessor :qualified
520
521 def initialize(elename, text = nil)
522 if !elename.is_a?(XSD::QName)
523 elename = XSD::QName.new(nil, elename)
524 end
525 @encodingstyle = LiteralNamespace
526 @elename = elename
527 @id = nil
528 @precedents = []
529 @root = false
530 @parent = nil
531 @position = nil
532 @extraattr = {}
533
534 @qualified = nil
535
536 @array = []
537 @data = []
538 @text = text
539 end
540
541 def inspect
542 sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
543 end
544
545 # Text interface.
546 attr_accessor :text
547 alias data text
548
549 # Element interfaces.
550 def add(value)
551 add_member(value.elename.name, value)
552 end
553
554 def [](idx)
555 if @array.include?(idx)
556 @data[@array.index(idx)]
557 else
558 nil
559 end
560 end
561
562 def []=(idx, data)
563 if @array.include?(idx)
564 data.parent = self if data.respond_to?(:parent=)
565 @data[@array.index(idx)] = data
566 else
567 add(data)
568 end
569 end
570
571 def key?(name)
572 @array.include?(name)
573 end
574
575 def members
576 @array
577 end
578
579 def to_obj
580 if members.empty?
581 @text
582 else
583 hash = {}
584 proptype = {}
585 each do |k, v|
586 value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
587 case proptype[k]
588 when :single
589 hash[k] = [hash[k], value]
590 proptype[k] = :multi
591 when :multi
592 hash[k] << value
593 else
594 hash[k] = value
595 proptype[k] = :single
596 end
597 end
598 hash
599 end
600 end
601
602 def each
603 idx = 0
604 while idx < @array.length
605 yield(@array[idx], @data[idx])
606 idx += 1
607 end
608 end
609
610 def self.decode(elename)
611 o = SOAPElement.new(elename)
612 o
613 end
614
615 def self.from_obj(obj, namespace = nil)
616 o = SOAPElement.new(nil)
617 case obj
618 when nil
619 o.text = nil
620 when Hash
621 obj.each do |elename, value|
622 if value.is_a?(Array)
623 value.each do |subvalue|
624 child = from_obj(subvalue, namespace)
625 child.elename = to_elename(elename, namespace)
626 o.add(child)
627 end
628 else
629 child = from_obj(value, namespace)
630 child.elename = to_elename(elename, namespace)
631 o.add(child)
632 end
633 end
634 else
635 o.text = obj.to_s
636 end
637 o
638 end
639
640 def self.to_elename(obj, namespace = nil)
641 if obj.is_a?(XSD::QName)
642 obj
643 elsif /\A(.+):([^:]+)\z/ =~ obj.to_s
644 XSD::QName.new($1, $2)
645 else
646 XSD::QName.new(namespace, obj.to_s)
647 end
648 end
649
650private
651
652 def add_member(name, value)
653 add_accessor(name)
654 @array.push(name)
655 @data.push(value)
656 value.parent = self if value.respond_to?(:parent=)
657 value
658 end
659
660 if RUBY_VERSION > "1.7.0"
661 def add_accessor(name)
662 methodname = name
663 if self.respond_to?(methodname)
664 methodname = safe_accessor_name(methodname)
665 end
666 Mapping.define_singleton_method(self, methodname) do
667 @data[@array.index(name)]
668 end
669 Mapping.define_singleton_method(self, methodname + '=') do |value|
670 @data[@array.index(name)] = value
671 end
672 end
673 else
674 def add_accessor(name)
675 methodname = safe_accessor_name(name)
676 instance_eval <<-EOS
677 def #{methodname}
678 @data[@array.index(#{name.dump})]
679 end
680
681 def #{methodname}=(value)
682 @data[@array.index(#{name.dump})] = value
683 end
684 EOS
685 end
686 end
687
688 def safe_accessor_name(name)
689 "var_" << name.gsub(/[^a-zA-Z0-9_]/, '')
690 end
691end
692
693
694class SOAPArray < XSD::NSDBase
695 include SOAPCompoundtype
696 include Enumerable
697
698public
699
700 attr_accessor :sparse
701
702 attr_reader :offset, :rank
703 attr_accessor :size, :size_fixed
704 attr_reader :arytype
705
706 def initialize(type = nil, rank = 1, arytype = nil)
707 super()
708 @type = type || ValueArrayName
709 @rank = rank
710 @data = Array.new
711 @sparse = false
712 @offset = Array.new(rank, 0)
713 @size = Array.new(rank, 0)
714 @size_fixed = false
715 @position = nil
716 @arytype = arytype
717 end
718
719 def offset=(var)
720 @offset = var
721 @sparse = true
722 end
723
724 def add(value)
725 self[*(@offset)] = value
726 end
727
728 def [](*idxary)
729 if idxary.size != @rank
730 raise ArgumentError.new("given #{idxary.size} params does not match rank: #{@rank}")
731 end
732
733 retrieve(idxary)
734 end
735
736 def []=(*idxary)
737 value = idxary.slice!(-1)
738
739 if idxary.size != @rank
740 raise ArgumentError.new("given #{idxary.size} params(#{idxary})" +
741 " does not match rank: #{@rank}")
742 end
743
744 idx = 0
745 while idx < idxary.size
746 if idxary[idx] + 1 > @size[idx]
747 @size[idx] = idxary[idx] + 1
748 end
749 idx += 1
750 end
751
752 data = retrieve(idxary[0, idxary.size - 1])
753 data[idxary.last] = value
754
755 if value.is_a?(SOAPType)
756 value.elename = ITEM_NAME
757 # Sync type
758 unless @type.name
759 @type = XSD::QName.new(value.type.namespace,
760 SOAPArray.create_arytype(value.type.name, @rank))
761 end
762 value.type ||= @type
763 end
764
765 @offset = idxary
766 value.parent = self if value.respond_to?(:parent=)
767 offsetnext
768 end
769
770 def each
771 @data.each do |data|
772 yield(data)
773 end
774 end
775
776 def to_a
777 @data.dup
778 end
779
780 def replace
781 @data = deep_map(@data) do |ele|
782 yield(ele)
783 end
784 end
785
786 def deep_map(ary, &block)
787 ary.collect do |ele|
788 if ele.is_a?(Array)
789 deep_map(ele, &block)
790 else
791 new_obj = block.call(ele)
792 new_obj.elename = ITEM_NAME
793 new_obj
794 end
795 end
796 end
797
798 def include?(var)
799 traverse_data(@data) do |v, *rank|
800 if v.is_a?(SOAPBasetype) && v.data == var
801 return true
802 end
803 end
804 false
805 end
806
807 def traverse
808 traverse_data(@data) do |v, *rank|
809 unless @sparse
810 yield(v)
811 else
812 yield(v, *rank) if v && !v.is_a?(SOAPNil)
813 end
814 end
815 end
816
817 def soap2array(ary)
818 traverse_data(@data) do |v, *position|
819 iteary = ary
820 rank = 1
821 while rank < position.size
822 idx = position[rank - 1]
823 if iteary[idx].nil?
824 iteary = iteary[idx] = Array.new
825 else
826 iteary = iteary[idx]
827 end
828 rank += 1
829 end
830 if block_given?
831 iteary[position.last] = yield(v)
832 else
833 iteary[position.last] = v
834 end
835 end
836 end
837
838 def position
839 @position
840 end
841
842private
843
844 ITEM_NAME = XSD::QName.new(nil, 'item')
845
846 def retrieve(idxary)
847 data = @data
848 rank = 1
849 while rank <= idxary.size
850 idx = idxary[rank - 1]
851 if data[idx].nil?
852 data = data[idx] = Array.new
853 else
854 data = data[idx]
855 end
856 rank += 1
857 end
858 data
859 end
860
861 def traverse_data(data, rank = 1)
862 idx = 0
863 while idx < ranksize(rank)
864 if rank < @rank
865 traverse_data(data[idx], rank + 1) do |*v|
866 v[1, 0] = idx
867 yield(*v)
868 end
869 else
870 yield(data[idx], idx)
871 end
872 idx += 1
873 end
874 end
875
876 def ranksize(rank)
877 @size[rank - 1]
878 end
879
880 def offsetnext
881 move = false
882 idx = @offset.size - 1
883 while !move && idx >= 0
884 @offset[idx] += 1
885 if @size_fixed
886 if @offset[idx] < @size[idx]
887 move = true
888 else
889 @offset[idx] = 0
890 idx -= 1
891 end
892 else
893 move = true
894 end
895 end
896 end
897
898 # Module function
899
900public
901
902 def self.decode(elename, type, arytype)
903 typestr, nofary = parse_type(arytype.name)
904 rank = nofary.count(',') + 1
905 plain_arytype = XSD::QName.new(arytype.namespace, typestr)
906 o = SOAPArray.new(type, rank, plain_arytype)
907 size = []
908 nofary.split(',').each do |s|
909 if s.empty?
910 size.clear
911 break
912 else
913 size << s.to_i
914 end
915 end
916 unless size.empty?
917 o.size = size
918 o.size_fixed = true
919 end
920 o.elename = elename
921 o
922 end
923
924private
925
926 def self.create_arytype(typename, rank)
927 "#{typename}[" << ',' * (rank - 1) << ']'
928 end
929
930 TypeParseRegexp = Regexp.new('^(.+)\[([\d,]*)\]$')
931
932 def self.parse_type(string)
933 TypeParseRegexp =~ string
934 return $1, $2
935 end
936end
937
938
939require 'soap/mapping/typeMap'
940
941
942end
Note: See TracBrowser for help on using the repository browser.