summaryrefslogtreecommitdiff
path: root/lib/soap/mapping/rubytypeFactory.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/mapping/rubytypeFactory.rb')
-rw-r--r--lib/soap/mapping/rubytypeFactory.rb377
1 files changed, 200 insertions, 177 deletions
diff --git a/lib/soap/mapping/rubytypeFactory.rb b/lib/soap/mapping/rubytypeFactory.rb
index 0a3f502dfe..3ebb799220 100644
--- a/lib/soap/mapping/rubytypeFactory.rb
+++ b/lib/soap/mapping/rubytypeFactory.rb
@@ -22,22 +22,28 @@ module Mapping
class RubytypeFactory < Factory
- TYPE_STRING = 'String'
- TYPE_ARRAY = 'Array'
- TYPE_REGEXP = 'Regexp'
- TYPE_RANGE = 'Range'
- TYPE_CLASS = 'Class'
- TYPE_MODULE = 'Module'
- TYPE_SYMBOL = 'Symbol'
- TYPE_STRUCT = 'Struct'
- TYPE_HASH = 'Map'
-
+ TYPE_STRING = XSD::QName.new(RubyTypeNamespace, 'String')
+ TYPE_TIME = XSD::QName.new(RubyTypeNamespace, 'Time')
+ TYPE_ARRAY = XSD::QName.new(RubyTypeNamespace, 'Array')
+ TYPE_REGEXP = XSD::QName.new(RubyTypeNamespace, 'Regexp')
+ TYPE_RANGE = XSD::QName.new(RubyTypeNamespace, 'Range')
+ TYPE_CLASS = XSD::QName.new(RubyTypeNamespace, 'Class')
+ TYPE_MODULE = XSD::QName.new(RubyTypeNamespace, 'Module')
+ TYPE_SYMBOL = XSD::QName.new(RubyTypeNamespace, 'Symbol')
+ TYPE_STRUCT = XSD::QName.new(RubyTypeNamespace, 'Struct')
+ TYPE_HASH = XSD::QName.new(RubyTypeNamespace, 'Map')
+
def initialize(config = {})
@config = config
@allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
@config[:allow_untyped_struct] : true
@allow_original_mapping = @config.key?(:allow_original_mapping) ?
@config[:allow_original_mapping] : false
+ @string_factory = StringFactory_.new(true)
+ @basetype_factory = BasetypeFactory_.new(true)
+ @datetime_factory = DateTimeFactory_.new(true)
+ @array_factory = ArrayFactory_.new(true)
+ @hash_factory = HashFactory_.new(true)
end
def obj2soap(soap_class, obj, info, map)
@@ -47,48 +53,83 @@ class RubytypeFactory < Factory
unless @allow_original_mapping
return nil
end
- unless XSD::Charset.is_ces(obj, $KCODE)
+ param = @string_factory.obj2soap(SOAPString, obj, info, map)
+ if obj.class != String
+ param.extraattr[RubyTypeName] = obj.class.name
+ end
+ addiv2soapattr(param, obj, map)
+ when Time
+ unless @allow_original_mapping
return nil
end
- encoded = XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding)
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRING))
- mark_marshalled_obj(obj, param)
- param.add('string', SOAPString.new(encoded))
- if obj.class != String
+ param = @datetime_factory.obj2soap(SOAPDateTime, obj, info, map)
+ if obj.class != Time
param.extraattr[RubyTypeName] = obj.class.name
end
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Array
unless @allow_original_mapping
return nil
end
- arytype = Mapping.obj2element(obj)
- if arytype.name
- arytype.namespace ||= RubyTypeNamespace
- else
- arytype = XSD::AnyTypeName
+ param = @array_factory.obj2soap(nil, obj, info, map)
+ if obj.class != Array
+ param.extraattr[RubyTypeName] = obj.class.name
end
- if obj.instance_variables.empty?
- param = SOAPArray.new(ValueArrayName, 1, arytype)
- mark_marshalled_obj(obj, param)
- obj.each do |var|
- param.add(Mapping._obj2soap(var, map))
- end
- else
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_ARRAY))
- mark_marshalled_obj(obj, param)
- ary = SOAPArray.new(ValueArrayName, 1, arytype)
- obj.each do |var|
- ary.add(Mapping._obj2soap(var, map))
- end
- param.add('array', ary)
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
+ when NilClass
+ unless @allow_original_mapping
+ return nil
end
- if obj.class != Array
+ param = @basetype_factory.obj2soap(SOAPNil, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when FalseClass, TrueClass
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPBoolean, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when Integer
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPInt, obj, info, map)
+ param ||= @basetype_factory.obj2soap(SOAPInteger, obj, info, map)
+ param ||= @basetype_factory.obj2soap(SOAPDecimal, obj, info, map)
+ addiv2soapattr(param, obj, map)
+ when Float
+ unless @allow_original_mapping
+ return nil
+ end
+ param = @basetype_factory.obj2soap(SOAPDouble, obj, info, map)
+ if obj.class != Float
param.extraattr[RubyTypeName] = obj.class.name
end
+ addiv2soapattr(param, obj, map)
+ when Hash
+ unless @allow_original_mapping
+ return nil
+ end
+ if obj.respond_to?(:default_proc) && obj.default_proc
+ raise TypeError.new("cannot dump hash with default proc")
+ end
+ param = SOAPStruct.new(TYPE_HASH)
+ mark_marshalled_obj(obj, param)
+ if obj.class != Hash
+ param.extraattr[RubyTypeName] = obj.class.name
+ end
+ obj.each do |key, value|
+ elem = SOAPStruct.new # Undefined type.
+ elem.add("key", Mapping._obj2soap(key, map))
+ elem.add("value", Mapping._obj2soap(value, map))
+ param.add("item", elem)
+ end
+ param.add('default', Mapping._obj2soap(obj.default, map))
+ addiv2soapattr(param, obj, map)
when Regexp
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_REGEXP))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_REGEXP)
mark_marshalled_obj(obj, param)
if obj.class != Regexp
param.extraattr[RubyTypeName] = obj.class.name
@@ -119,9 +160,12 @@ class RubytypeFactory < Factory
end
end
param.add('options', SOAPInt.new(options))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Range
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_RANGE))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_RANGE)
mark_marshalled_obj(obj, param)
if obj.class != Range
param.extraattr[RubyTypeName] = obj.class.name
@@ -129,57 +173,42 @@ class RubytypeFactory < Factory
param.add('begin', Mapping._obj2soap(obj.begin, map))
param.add('end', Mapping._obj2soap(obj.end, map))
param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?))
- addiv2soap(param, obj, map)
- when Hash
+ addiv2soapattr(param, obj, map)
+ when Class
unless @allow_original_mapping
return nil
end
- if obj.respond_to?(:default_proc) && obj.default_proc
- raise TypeError.new("cannot dump hash with default proc")
- end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_HASH))
- mark_marshalled_obj(obj, param)
- if obj.class != Hash
- param.extraattr[RubyTypeName] = obj.class.name
- end
- obj.each do |key, value|
- elem = SOAPStruct.new # Undefined type.
- elem.add("key", Mapping._obj2soap(key, map))
- elem.add("value", Mapping._obj2soap(value, map))
- param.add("item", elem)
- end
- param.add('default', Mapping._obj2soap(obj.default, map))
- addiv2soap(param, obj, map)
- when Class
if obj.name.empty?
raise TypeError.new("Can't dump anonymous class #{ obj }.")
end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_CLASS))
+ param = SOAPStruct.new(TYPE_CLASS)
mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Module
+ unless @allow_original_mapping
+ return nil
+ end
if obj.name.empty?
raise TypeError.new("Can't dump anonymous module #{ obj }.")
end
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_MODULE))
+ param = SOAPStruct.new(TYPE_MODULE)
mark_marshalled_obj(obj, param)
param.add('name', SOAPString.new(obj.name))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Symbol
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_SYMBOL))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_SYMBOL)
mark_marshalled_obj(obj, param)
param.add('id', SOAPString.new(obj.id2name))
- addiv2soap(param, obj, map)
- when Exception
- typestr = Mapping.name2elename(obj.class.to_s)
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
- mark_marshalled_obj(obj, param)
- param.add('message', Mapping._obj2soap(obj.message, map))
- param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when Struct
- param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, TYPE_STRUCT))
+ unless @allow_original_mapping
+ return nil
+ end
+ param = SOAPStruct.new(TYPE_STRUCT)
mark_marshalled_obj(obj, param)
param.add('type', ele_type = SOAPString.new(obj.class.to_s))
ele_member = SOAPStruct.new
@@ -188,29 +217,23 @@ class RubytypeFactory < Factory
Mapping._obj2soap(obj[member], map))
end
param.add('member', ele_member)
- addiv2soap(param, obj, map)
+ addiv2soapattr(param, obj, map)
when IO, Binding, Continuation, Data, Dir, File::Stat, MatchData, Method,
- Proc, Thread, ThreadGroup
+ Proc, Thread, ThreadGroup # from 1.8: Process::Status, UnboundMethod
return nil
when ::SOAP::Mapping::Object
param = SOAPStruct.new(XSD::AnyTypeName)
mark_marshalled_obj(obj, param)
- setiv2soap(param, obj, map) # addiv2soap?
- else
- if obj.class.name.empty?
- raise TypeError.new("Can't dump anonymous class #{ obj }.")
- end
- if check_singleton(obj)
- raise TypeError.new("singleton can't be dumped #{ obj }")
- end
- type = Mapping.class2element(obj.class)
- param = SOAPStruct.new(type)
+ addiv2soapattr(param, obj, map)
+ when Exception
+ typestr = Mapping.name2elename(obj.class.to_s)
+ param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
mark_marshalled_obj(obj, param)
- if obj.class <= Marshallable
- setiv2soap(param, obj, map)
- else
- setiv2soap(param, obj, map) # Should not be marshalled?
- end
+ param.add('message', Mapping._obj2soap(obj.message, map))
+ param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
+ addiv2soapattr(param, obj, map)
+ else
+ param = unknownobj2soap(soap_class, obj, info, map)
end
param
end
@@ -218,26 +241,42 @@ class RubytypeFactory < Factory
def soap2obj(obj_class, node, info, map)
rubytype = node.extraattr[RubyTypeName]
if rubytype or node.type.namespace == RubyTypeNamespace
- rubytype2obj(node, map, rubytype)
+ rubytype2obj(node, info, map, rubytype)
elsif node.type == XSD::AnyTypeName or node.type == XSD::AnySimpleTypeName
- anytype2obj(node, map)
+ anytype2obj(node, info, map)
else
- unknowntype2obj(node, map)
+ unknowntype2obj(node, info, map)
end
end
private
- def check_singleton(obj)
- unless singleton_methods_true(obj).empty?
- return true
+ def addiv2soapattr(node, obj, map)
+ return if obj.instance_variables.empty?
+ ivars = SOAPStruct.new # Undefined type.
+ setiv2soap(ivars, obj, map)
+ node.extraattr[RubyIVarName] = ivars
+ end
+
+ def unknownobj2soap(soap_class, obj, info, map)
+ if obj.class.name.empty?
+ raise TypeError.new("Can't dump anonymous class #{ obj }.")
end
singleton_class = class << obj; self; end
- if !singleton_class.instance_variables.empty? or
- !(singleton_class.ancestors - obj.class.ancestors).empty?
- return true
+ if !singleton_methods_true(obj).empty? or
+ !singleton_class.instance_variables.empty?
+ raise TypeError.new("singleton can't be dumped #{ obj }")
+ end
+ if !(singleton_class.ancestors - obj.class.ancestors).empty?
+ typestr = Mapping.name2elename(obj.class.to_s)
+ type = XSD::QName.new(RubyTypeNamespace, typestr)
+ else
+ type = Mapping.class2element(obj.class)
end
- false
+ param = SOAPStruct.new(type)
+ mark_marshalled_obj(obj, param)
+ setiv2soap(param, obj, map)
+ param
end
if RUBY_VERSION >= '1.8.0'
@@ -250,40 +289,54 @@ private
end
end
- def rubytype2obj(node, map, rubytype)
+ def rubytype2obj(node, info, map, rubytype)
+ klass = rubytype ? Mapping.class_from_name(rubytype) : nil
obj = nil
- case node.class
+ case node
when SOAPString
- obj = string2obj(node, map, rubytype)
- obj.replace(node.data)
+ return @string_factory.soap2obj(klass || String, node, info, map)
+ when SOAPDateTime
+ #return @datetime_factory.soap2obj(klass || Time, node, info, map)
+ klass ||= Time
+ t = node.to_time
+ arg = [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.usec]
+ obj = t.gmt? ? klass.gm(*arg) : klass.local(*arg)
+ mark_unmarshalled_obj(node, obj)
return true, obj
when SOAPArray
- obj = array2obj(node, map, rubytype)
- node.soap2array(obj) do |elem|
- elem ? Mapping._soap2obj(elem, map) : nil
- end
- return true, obj
+ return @array_factory.soap2obj(klass || Array, node, info, map)
+ when SOAPNil, SOAPBoolean, SOAPInt, SOAPInteger, SOAPDecimal, SOAPDouble
+ return @basetype_factory.soap2obj(nil, node, info, map)
+ when SOAPStruct
+ return rubytypestruct2obj(node, info, map, rubytype)
+ else
+ raise
end
+ end
- case node.type.name
- when TYPE_STRING
- obj = string2obj(node, map, rubytype)
- obj.replace(node['string'].data)
- setiv2obj(obj, node['ivars'], map)
- when TYPE_ARRAY
- obj = array2obj(node, map, rubytype)
- node['array'].soap2array(obj) do |elem|
- elem ? Mapping._soap2obj(elem, map) : nil
- end
- setiv2obj(obj, node['ivars'], map)
+ def rubytypestruct2obj(node, info, map, rubytype)
+ klass = rubytype ? Mapping.class_from_name(rubytype) : nil
+ obj = nil
+ case node.type
+ when TYPE_HASH
+ klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
+ obj = create_empty_object(klass)
+ mark_unmarshalled_obj(node, obj)
+ node.each do |key, value|
+ next unless key == 'item'
+ obj[Mapping._soap2obj(value['key'], map)] =
+ Mapping._soap2obj(value['value'], map)
+ end
+ if node.key?('default')
+ obj.default = Mapping._soap2obj(node['default'], map)
+ end
when TYPE_REGEXP
klass = rubytype ? Mapping.class_from_name(rubytype) : Regexp
obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj)
source = node['source'].string
options = node['options'].data || 0
- obj.instance_eval { initialize(source, options) }
- setiv2obj(obj, node['ivars'], map)
+ Regexp.instance_method(:initialize).bind(obj).call(source, options)
when TYPE_RANGE
klass = rubytype ? Mapping.class_from_name(rubytype) : Range
obj = create_empty_object(klass)
@@ -291,33 +344,13 @@ private
first = Mapping._soap2obj(node['begin'], map)
last = Mapping._soap2obj(node['end'], map)
exclude_end = node['exclude_end'].data
- obj.instance_eval { initialize(first, last, exclude_end) }
- setiv2obj(obj, node['ivars'], map)
- when TYPE_HASH
- unless @allow_original_mapping
- return false
- end
- klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
- obj = create_empty_object(klass)
- mark_unmarshalled_obj(node, obj)
- node.each do |key, value|
- next unless key == 'item'
- obj[Mapping._soap2obj(value['key'], map)] =
- Mapping._soap2obj(value['value'], map)
- end
- if node.key?('default')
- obj.default = Mapping._soap2obj(node['default'], map)
- end
- setiv2obj(obj, node['ivars'], map)
+ Range.instance_method(:initialize).bind(obj).call(first, last, exclude_end)
when TYPE_CLASS
obj = Mapping.class_from_name(node['name'].data)
- setiv2obj(obj, node['ivars'], map)
when TYPE_MODULE
obj = Mapping.class_from_name(node['name'].data)
- setiv2obj(obj, node['ivars'], map)
when TYPE_SYMBOL
obj = node['id'].data.intern
- setiv2obj(obj, node['ivars'], map)
when TYPE_STRUCT
typestr = Mapping.elename2name(node['type'].data)
klass = Mapping.class_from_name(typestr)
@@ -333,40 +366,15 @@ private
obj = create_empty_object(klass)
mark_unmarshalled_obj(node, obj)
node['member'].each do |name, value|
- obj[Mapping.elename2name(name)] =
- Mapping._soap2obj(value, map)
+ obj[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
end
- setiv2obj(obj, node['ivars'], map)
else
- conv, obj = exception2obj(node, map)
- unless conv
- return false
- end
- setiv2obj(obj, node['ivars'], map)
+ return unknowntype2obj(node, info, map)
end
return true, obj
end
- def exception2obj(node, map)
- typestr = Mapping.elename2name(node.type.name)
- klass = Mapping.class_from_name(typestr)
- if klass.nil?
- return false
- end
- unless klass <= Exception
- return false
- end
- message = Mapping._soap2obj(node['message'], map)
- backtrace = Mapping._soap2obj(node['backtrace'], map)
- obj = create_empty_object(klass)
- obj = obj.exception(message)
- mark_unmarshalled_obj(node, obj)
- obj.set_backtrace(backtrace)
- setiv2obj(obj, node['ivars'], map)
- return true, obj
- end
-
- def anytype2obj(node, map)
+ def anytype2obj(node, info, map)
case node
when SOAPBasetype
return true, node.data
@@ -383,22 +391,24 @@ private
end
end
- def unknowntype2obj(node, map)
+ def unknowntype2obj(node, info, map)
if node.is_a?(SOAPStruct)
- obj = struct2obj(node, map)
+ obj = unknownstruct2obj(node, info, map)
return true, obj if obj
if !@allow_untyped_struct
return false
end
- return anytype2obj(node, map)
+ return anytype2obj(node, info, map)
else
# Basetype which is not defined...
return false
end
end
- def struct2obj(node, map)
- obj = nil
+ def unknownstruct2obj(node, info, map)
+ unless node.type.name
+ return nil
+ end
typestr = Mapping.elename2name(node.type.name)
klass = Mapping.class_from_name(typestr)
if klass.nil?
@@ -407,6 +417,9 @@ private
if klass.nil?
return nil
end
+ if klass <= ::Exception
+ return exception2obj(klass, node, map)
+ end
klass_type = Mapping.class2qname(klass)
return nil unless node.type.match(klass_type)
obj = create_empty_object(klass)
@@ -415,6 +428,16 @@ private
obj
end
+ def exception2obj(klass, node, map)
+ message = Mapping._soap2obj(node['message'], map)
+ backtrace = Mapping._soap2obj(node['backtrace'], map)
+ obj = create_empty_object(klass)
+ obj = obj.exception(message)
+ mark_unmarshalled_obj(node, obj)
+ obj.set_backtrace(backtrace)
+ obj
+ end
+
# Only creates empty array. Do String#replace it with real string.
def array2obj(node, map, rubytype)
klass = rubytype ? Mapping.class_from_name(rubytype) : Array