mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/{soap,wsdl,xsd}, test/{soap,wsdl,xsd}: imported soap4r/1.5.4.
== SOAP client and server == === for both client side and server side === * improved document/literal service support. style(rpc,document)/use(encoding, literal) combination are all supported. for the detail about combination, see test/soap/test_style.rb. * let WSDLEncodedRegistry#soap2obj map SOAP/OM to Ruby according to WSDL as well as obj2soap. closes #70. * let SOAP::Mapping::Object handle XML attribute for doc/lit service. you can set/get XML attribute via accessor methods which as a name 'xmlattr_' prefixed (<foo name="bar"/> -> Foo#xmlattr_name). === client side === * WSDLDriver capitalized name operation bug fixed. from 1.5.3-ruby1.8.2, operation which has capitalized name (such as KeywordSearchRequest in AWS) is defined as a method having uncapitalized name. (converted with GenSupport.safemethodname to handle operation name 'foo-bar'). it introduced serious incompatibility; in the past, it was defined as a capitalized. define capitalized method as well under that circumstance. * added new factory interface 'WSDLDriverFactory#create_rpc_driver' to create RPC::Driver, not WSDLDriver (RPC::Driver and WSDLDriver are merged). 'WSDLDriverFactory#create_driver' still creates WSDLDriver for compatibility but it warns that the method is deprecated. please use create_rpc_driver instead of create_driver. * allow to use an URI object as an endpoint_url even with net/http, not http-access2. === server side === * added mod_ruby support to SOAP::CGIStub. rename a CGI script server.cgi to server.rb and let mod_ruby's RubyHandler handles the script. CGIStub detects if it's running under mod_ruby environment or not. * added fcgi support to SOAP::CGIStub. see the sample at sample/soap/calc/server.fcgi. (almost same as server.cgi but has fcgi handler at the bottom.) * allow to return a SOAPFault object to respond customized SOAP fault. * added the interface 'generate_explicit_type' for server side (CGIStub, HTTPServer). call 'self.generate_explicit_type = true' if you want to return simplified XML even if it's rpc/encoded service. == WSDL == === WSDL definition === * improved XML Schema support such as extension, restriction, simpleType, complexType + simpleContent, ref, length, import, include. * reduced "unknown element/attribute" warnings (warn only 1 time for each QName). * importing XSD file at schemaLocation with xsd:import. === code generation from WSDL === * generator crashed when there's '-' in defined element/attribute name. * added ApacheMap WSDL definition. * sample/{soap,wsdl}: removed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@8502 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
15b7d43988
commit
991d0c409c
181 changed files with 3183 additions and 9380 deletions
|
@ -37,24 +37,28 @@ class Factory
|
|||
end
|
||||
|
||||
def setiv2soap(node, obj, map)
|
||||
# should we sort instance_variables?
|
||||
obj.instance_variables.each do |var|
|
||||
name = var.sub(/^@/, '')
|
||||
node.add(Mapping.name2elename(name),
|
||||
Mapping._obj2soap(obj.instance_variable_get(var), map))
|
||||
if obj.class.class_variables.include?('@@schema_element')
|
||||
obj.class.class_eval('@@schema_element').each do |name, info|
|
||||
type, qname = info
|
||||
if qname
|
||||
elename = qname.name
|
||||
else
|
||||
elename = Mapping.name2elename(name)
|
||||
end
|
||||
node.add(elename,
|
||||
Mapping._obj2soap(obj.instance_variable_get('@' + name), map))
|
||||
end
|
||||
else
|
||||
# should we sort instance_variables?
|
||||
obj.instance_variables.each do |var|
|
||||
name = var.sub(/^@/, '')
|
||||
elename = Mapping.name2elename(name)
|
||||
node.add(elename,
|
||||
Mapping._obj2soap(obj.instance_variable_get(var), map))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
||||
def mark_marshalled_obj(obj, soap_obj)
|
||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
||||
end
|
||||
|
||||
# It breaks Thread.current[:SOAPMarshalDataKey].
|
||||
def mark_unmarshalled_obj(node, obj)
|
||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setiv2ary(obj, node, map)
|
||||
|
@ -68,7 +72,7 @@ private
|
|||
node.each do |name, value|
|
||||
vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
|
||||
end
|
||||
Mapping.set_instance_vars(obj, vars)
|
||||
Mapping.set_attributes(obj, vars)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -156,20 +160,14 @@ class DateTimeFactory_ < Factory
|
|||
end
|
||||
|
||||
def soap2obj(obj_class, node, info, map)
|
||||
obj = nil
|
||||
if obj_class == Time
|
||||
obj = node.to_time
|
||||
if obj.nil?
|
||||
# Is out of range as a Time
|
||||
return false
|
||||
end
|
||||
elsif obj_class == Date
|
||||
obj = node.data
|
||||
if node.respond_to?(:to_obj)
|
||||
obj = node.to_obj(obj_class)
|
||||
return false if obj.nil?
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
else
|
||||
return false
|
||||
end
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
return true, obj
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SOAP4R - Ruby type mapping utility.
|
||||
# Copyright (C) 2000, 2001, 2003, 2004 NAKAMURA Hiroshi <nahi@ruby-lang.org>.
|
||||
# Copyright (C) 2000, 2001, 2003-2005 NAKAMURA Hiroshi <nahi@ruby-lang.org>.
|
||||
|
||||
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
||||
# redistribute it and/or modify it under the same terms of Ruby's license;
|
||||
|
@ -23,10 +23,12 @@ module Mapping
|
|||
# TraverseSupport breaks Thread.current[:SOAPMarshalDataKey].
|
||||
module TraverseSupport
|
||||
def mark_marshalled_obj(obj, soap_obj)
|
||||
raise if obj.nil?
|
||||
Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
|
||||
end
|
||||
|
||||
def mark_unmarshalled_obj(node, obj)
|
||||
return if obj.nil?
|
||||
# node.id is not Object#id but SOAPReference#id
|
||||
Thread.current[:SOAPMarshalDataKey][node.id] = obj
|
||||
end
|
||||
|
@ -41,10 +43,10 @@ module Mapping
|
|||
soap_obj
|
||||
end
|
||||
|
||||
def self.soap2obj(node, registry = nil)
|
||||
def self.soap2obj(node, registry = nil, klass = nil)
|
||||
registry ||= Mapping::DefaultRegistry
|
||||
Thread.current[:SOAPMarshalDataKey] = {}
|
||||
obj = _soap2obj(node, registry)
|
||||
obj = _soap2obj(node, registry, klass)
|
||||
Thread.current[:SOAPMarshalDataKey] = nil
|
||||
obj
|
||||
end
|
||||
|
@ -107,21 +109,21 @@ module Mapping
|
|||
elsif registry
|
||||
registry.obj2soap(obj, type)
|
||||
else
|
||||
raise MappingError.new("No mapping registry given.")
|
||||
raise MappingError.new("no mapping registry given")
|
||||
end
|
||||
end
|
||||
|
||||
def self._soap2obj(node, registry)
|
||||
def self._soap2obj(node, registry, klass = nil)
|
||||
if node.is_a?(SOAPReference)
|
||||
target = node.__getobj__
|
||||
# target.id is not Object#id but SOAPReference#id
|
||||
if referent = Thread.current[:SOAPMarshalDataKey][target.id]
|
||||
return referent
|
||||
else
|
||||
return _soap2obj(target, registry)
|
||||
return _soap2obj(target, registry, klass)
|
||||
end
|
||||
end
|
||||
return registry.soap2obj(node)
|
||||
return registry.soap2obj(node, klass)
|
||||
end
|
||||
|
||||
if Object.respond_to?(:allocate)
|
||||
|
@ -157,29 +159,6 @@ module Mapping
|
|||
end
|
||||
end
|
||||
|
||||
unless Object.respond_to?(:instance_variable_get)
|
||||
class Object
|
||||
def instance_variable_get(ivarname)
|
||||
instance_eval(ivarname)
|
||||
end
|
||||
|
||||
def instance_variable_set(ivarname, value)
|
||||
instance_eval("#{ivarname} = value")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.set_instance_vars(obj, values)
|
||||
values.each do |name, value|
|
||||
setter = name + "="
|
||||
if obj.respond_to?(setter)
|
||||
obj.__send__(setter, value)
|
||||
else
|
||||
obj.instance_variable_set('@' + name, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
|
||||
# Caution: '.' is not allowed here.
|
||||
# To follow XML spec., it should be NCName.
|
||||
|
@ -198,28 +177,51 @@ module Mapping
|
|||
}
|
||||
end
|
||||
|
||||
def self.class_from_name(name)
|
||||
if /^[A-Z]/ !~ name
|
||||
def self.const_from_name(name, lenient = false)
|
||||
const = ::Object
|
||||
name.sub(/\A::/, '').split('::').each do |const_str|
|
||||
if XSD::CodeGen::GenSupport.safeconstname?(const_str)
|
||||
if const.const_defined?(const_str)
|
||||
const = const.const_get(const_str)
|
||||
next
|
||||
end
|
||||
elsif lenient
|
||||
const_str = XSD::CodeGen::GenSupport.safeconstname(const_str)
|
||||
if const.const_defined?(const_str)
|
||||
const = const.const_get(const_str)
|
||||
next
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
klass = ::Object
|
||||
name.split('::').each do |klass_str|
|
||||
if klass.const_defined?(klass_str)
|
||||
klass = klass.const_get(klass_str)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
const
|
||||
end
|
||||
|
||||
def self.class_from_name(name, lenient = false)
|
||||
const = const_from_name(name, lenient)
|
||||
if const.is_a?(::Class)
|
||||
const
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.module_from_name(name, lenient = false)
|
||||
const = const_from_name(name, lenient)
|
||||
if const.is_a?(::Module)
|
||||
const
|
||||
else
|
||||
nil
|
||||
end
|
||||
klass
|
||||
end
|
||||
|
||||
def self.class2qname(klass)
|
||||
name = if klass.class_variables.include?("@@schema_type")
|
||||
name = if klass.class_variables.include?('@@schema_type')
|
||||
klass.class_eval('@@schema_type')
|
||||
else
|
||||
nil
|
||||
end
|
||||
namespace = if klass.class_variables.include?("@@schema_ns")
|
||||
namespace = if klass.class_variables.include?('@@schema_ns')
|
||||
klass.class_eval('@@schema_ns')
|
||||
else
|
||||
nil
|
||||
|
@ -250,19 +252,75 @@ module Mapping
|
|||
end
|
||||
end
|
||||
|
||||
def self.find_attribute(obj, attr_name)
|
||||
def self.define_singleton_method(obj, name, &block)
|
||||
sclass = (class << obj; self; end)
|
||||
sclass.__send__(:define_method, name, &block)
|
||||
end
|
||||
|
||||
def self.get_attribute(obj, attr_name)
|
||||
if obj.is_a?(::Hash)
|
||||
obj[attr_name] || obj[attr_name.intern]
|
||||
else
|
||||
name = ::XSD::CodeGen::GenSupport.safevarname(attr_name)
|
||||
if obj.respond_to?(name)
|
||||
obj.__send__(name)
|
||||
else
|
||||
name = XSD::CodeGen::GenSupport.safevarname(attr_name)
|
||||
if obj.instance_variables.include?('@' + name)
|
||||
obj.instance_variable_get('@' + name)
|
||||
elsif ((obj.is_a?(::Struct) or obj.is_a?(Marshallable)) and
|
||||
obj.respond_to?(name))
|
||||
obj.__send__(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.set_attributes(obj, values)
|
||||
if obj.is_a?(::SOAP::Mapping::Object)
|
||||
values.each do |attr_name, value|
|
||||
obj.__add_xmlele_value(attr_name, value)
|
||||
end
|
||||
else
|
||||
values.each do |attr_name, value|
|
||||
name = XSD::CodeGen::GenSupport.safevarname(attr_name)
|
||||
setter = name + "="
|
||||
if obj.respond_to?(setter)
|
||||
obj.__send__(setter, value)
|
||||
else
|
||||
obj.instance_variable_set('@' + name, value)
|
||||
begin
|
||||
define_attr_accessor(obj, name,
|
||||
proc { instance_variable_get('@' + name) },
|
||||
proc { |value| instance_variable_set('@' + name, value) })
|
||||
rescue TypeError
|
||||
# singleton class may not exist (e.g. Float)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.define_attr_accessor(obj, name, getterproc, setterproc = nil)
|
||||
define_singleton_method(obj, name, &getterproc)
|
||||
define_singleton_method(obj, name + '=', &setterproc) if setterproc
|
||||
end
|
||||
|
||||
def self.schema_element_definition(klass)
|
||||
return nil unless klass.class_variables.include?('@@schema_element')
|
||||
elements = {}
|
||||
as_array = []
|
||||
klass.class_eval('@@schema_element').each do |varname, definition|
|
||||
class_name, name = definition
|
||||
if /\[\]$/ =~ class_name
|
||||
class_name = class_name.sub(/\[\]$/, '')
|
||||
as_array << class_name
|
||||
end
|
||||
elements[name ? name.name : varname] = class_name
|
||||
end
|
||||
[elements, as_array]
|
||||
end
|
||||
|
||||
def self.schema_attribute_definition(klass)
|
||||
return nil unless klass.class_variables.include?('@@schema_attribute')
|
||||
klass.class_eval('@@schema_attribute')
|
||||
end
|
||||
|
||||
class << Mapping
|
||||
private
|
||||
def add_md_ary(md_ary, ary, indices, registry)
|
||||
|
|
|
@ -64,50 +64,105 @@ end
|
|||
# For anyType object: SOAP::Mapping::Object not ::Object
|
||||
class Object; include Marshallable
|
||||
def initialize
|
||||
@__soap_value_type = {}
|
||||
@__soap_value = {}
|
||||
@__xmlele_type = {}
|
||||
@__xmlele = []
|
||||
@__xmlattr = {}
|
||||
end
|
||||
|
||||
def [](name)
|
||||
@__soap_value[name]
|
||||
def inspect
|
||||
sprintf("#<%s:0x%x%s>", self.class.name, __id__,
|
||||
@__xmlele.collect { |name, value| " #{name}=#{value.inspect}" }.join)
|
||||
end
|
||||
|
||||
def []=(name, value)
|
||||
@__soap_value[name] = value
|
||||
def __xmlattr
|
||||
@__xmlattr
|
||||
end
|
||||
|
||||
def __soap_set_property(name, value)
|
||||
unless @__soap_value.key?(name)
|
||||
__define_attr_accessor(name)
|
||||
def __xmlele
|
||||
@__xmlele
|
||||
end
|
||||
|
||||
def [](qname)
|
||||
unless qname.is_a?(XSD::QName)
|
||||
qname = XSD::QName.new(nil, qname)
|
||||
end
|
||||
__soap_set_property_value(name, value)
|
||||
@__xmlele.each do |k, v|
|
||||
return v if k == qname
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
def []=(qname, value)
|
||||
unless qname.is_a?(XSD::QName)
|
||||
qname = XSD::QName.new(nil, qname)
|
||||
end
|
||||
found = false
|
||||
@__xmlele.each do |pair|
|
||||
if pair[0] == qname
|
||||
found = true
|
||||
pair[1] = value
|
||||
end
|
||||
end
|
||||
unless found
|
||||
__define_attr_accessor(qname)
|
||||
@__xmlele << [qname, value]
|
||||
end
|
||||
@__xmlele_type[qname] = :single
|
||||
end
|
||||
|
||||
def __soap_set_property_value(name, value)
|
||||
org = self[name]
|
||||
case @__soap_value_type[name]
|
||||
when :single
|
||||
self[name] = [org, value]
|
||||
@__soap_value_type[name] = :multi
|
||||
when :multi
|
||||
org << value
|
||||
else
|
||||
self[name] = value
|
||||
@__soap_value_type[name] = :single
|
||||
def __add_xmlele_value(qname, value)
|
||||
found = false
|
||||
@__xmlele.map! do |k, v|
|
||||
if k == qname
|
||||
found = true
|
||||
[k, __set_xmlele_value(k, v, value)]
|
||||
else
|
||||
[k, v]
|
||||
end
|
||||
end
|
||||
unless found
|
||||
__define_attr_accessor(qname)
|
||||
@__xmlele << [qname, value]
|
||||
@__xmlele_type[qname] = :single
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
def __define_attr_accessor(name)
|
||||
sclass = class << self; self; end
|
||||
sclass.__send__(:define_method, name, proc {
|
||||
self[name]
|
||||
})
|
||||
sclass.__send__(:define_method, name + '=', proc { |value|
|
||||
self[name] = value
|
||||
})
|
||||
private
|
||||
|
||||
if RUBY_VERSION > "1.7.0"
|
||||
def __define_attr_accessor(qname)
|
||||
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||
Mapping.define_attr_accessor(self, name,
|
||||
proc { self[qname] },
|
||||
proc { |value| self[qname] = value })
|
||||
end
|
||||
else
|
||||
def __define_attr_accessor(qname)
|
||||
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||
instance_eval <<-EOS
|
||||
def #{name}
|
||||
self[#{qname.dump}]
|
||||
end
|
||||
|
||||
def #{name}=(value)
|
||||
self[#{qname.dump}] = value
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
def __set_xmlele_value(key, org, value)
|
||||
case @__xmlele_type[key]
|
||||
when :multi
|
||||
org << value
|
||||
org
|
||||
when :single
|
||||
@__xmlele_type[key] = :multi
|
||||
[org, value]
|
||||
else
|
||||
raise RuntimeError.new("unknown type")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -123,7 +178,7 @@ class Registry
|
|||
@registry = registry
|
||||
end
|
||||
|
||||
def obj2soap(obj, type_qname = nil)
|
||||
def obj2soap(obj)
|
||||
klass = obj.class
|
||||
if map = @obj2soap[klass]
|
||||
map.each do |soap_class, factory, info|
|
||||
|
@ -131,7 +186,10 @@ class Registry
|
|||
return ret if ret
|
||||
end
|
||||
end
|
||||
ancestors = klass.ancestors[1..-3] # except itself, Object and Kernel
|
||||
ancestors = klass.ancestors
|
||||
ancestors.delete(klass)
|
||||
ancestors.delete(::Object)
|
||||
ancestors.delete(::Kernel)
|
||||
ancestors.each do |klass|
|
||||
if map = @obj2soap[klass]
|
||||
map.each do |soap_class, factory, info|
|
||||
|
@ -145,10 +203,10 @@ class Registry
|
|||
nil
|
||||
end
|
||||
|
||||
def soap2obj(node)
|
||||
klass = node.class
|
||||
if map = @soap2obj[klass]
|
||||
def soap2obj(node, klass = nil)
|
||||
if map = @soap2obj[node.class]
|
||||
map.each do |obj_class, factory, info|
|
||||
next if klass and obj_class != klass
|
||||
conv, obj = factory.soap2obj(obj_class, node, info, @registry)
|
||||
return true, obj if conv
|
||||
end
|
||||
|
@ -177,11 +235,13 @@ class Registry
|
|||
end
|
||||
|
||||
def find_mapped_soap_class(target_obj_class)
|
||||
@obj2soap[target_obj_class][0]
|
||||
map = @obj2soap[target_obj_class]
|
||||
map.empty? ? nil : map[0][1]
|
||||
end
|
||||
|
||||
def find_mapped_obj_class(target_soap_class)
|
||||
@soap2obj[target_soap_class][0]
|
||||
map = @soap2obj[target_soap_class]
|
||||
map.empty? ? nil : map[0][0]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -202,7 +262,6 @@ class Registry
|
|||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPString, StringFactory],
|
||||
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
||||
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
||||
|
@ -266,7 +325,6 @@ class Registry
|
|||
[::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory],
|
||||
[::String, ::SOAP::SOAPString, StringFactory],
|
||||
[::DateTime, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Date, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Date, ::SOAP::SOAPDate, DateTimeFactory],
|
||||
[::Time, ::SOAP::SOAPDateTime, DateTimeFactory],
|
||||
[::Time, ::SOAP::SOAPTime, DateTimeFactory],
|
||||
|
@ -354,17 +412,17 @@ class Registry
|
|||
end
|
||||
alias set add
|
||||
|
||||
# This mapping registry ignores type hint.
|
||||
# general Registry ignores type_qname
|
||||
def obj2soap(obj, type_qname = nil)
|
||||
soap = _obj2soap(obj, type_qname)
|
||||
soap = _obj2soap(obj)
|
||||
if @allow_original_mapping
|
||||
addextend2soap(soap, obj)
|
||||
end
|
||||
soap
|
||||
end
|
||||
|
||||
def soap2obj(node)
|
||||
obj = _soap2obj(node)
|
||||
def soap2obj(node, klass = nil)
|
||||
obj = _soap2obj(node, klass)
|
||||
if @allow_original_mapping
|
||||
addextend2obj(obj, node.extraattr[RubyExtendName])
|
||||
addiv2obj(obj, node.extraattr[RubyIVarName])
|
||||
|
@ -382,7 +440,7 @@ class Registry
|
|||
|
||||
private
|
||||
|
||||
def _obj2soap(obj, type_qname)
|
||||
def _obj2soap(obj)
|
||||
ret = nil
|
||||
if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
|
||||
obj.replace do |ele|
|
||||
|
@ -393,7 +451,7 @@ private
|
|||
return obj
|
||||
end
|
||||
begin
|
||||
ret = @map.obj2soap(obj, type_qname) ||
|
||||
ret = @map.obj2soap(obj) ||
|
||||
@default_factory.obj2soap(nil, obj, nil, self)
|
||||
return ret if ret
|
||||
rescue MappingError
|
||||
|
@ -408,12 +466,12 @@ private
|
|||
end
|
||||
|
||||
# Might return nil as a mapping result.
|
||||
def _soap2obj(node)
|
||||
def _soap2obj(node, klass = nil)
|
||||
if node.extraattr.key?(RubyTypeName)
|
||||
conv, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
|
||||
return obj if conv
|
||||
else
|
||||
conv, obj = @map.soap2obj(node)
|
||||
conv, obj = @map.soap2obj(node, klass)
|
||||
return obj if conv
|
||||
conv, obj = @default_factory.soap2obj(nil, node, nil, self)
|
||||
return obj if conv
|
||||
|
@ -435,14 +493,14 @@ private
|
|||
attr.__getobj__.each do |name, value|
|
||||
vars[name] = Mapping._soap2obj(value, self)
|
||||
end
|
||||
Mapping.set_instance_vars(obj, vars)
|
||||
Mapping.set_attributes(obj, vars)
|
||||
end
|
||||
|
||||
if RUBY_VERSION >= '1.8.0'
|
||||
def addextend2obj(obj, attr)
|
||||
return unless attr
|
||||
attr.split(/ /).reverse_each do |mstr|
|
||||
obj.extend(Mapping.class_from_name(mstr))
|
||||
obj.extend(Mapping.module_from_name(mstr))
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -450,8 +508,8 @@ private
|
|||
def addextend2obj(obj, attr)
|
||||
return unless attr
|
||||
attr.split(/ /).reverse_each do |mstr|
|
||||
m = Mapping.class_from_name(mstr)
|
||||
obj.extend(m) if m.class == Module
|
||||
m = Mapping.module_from_name(mstr)
|
||||
obj.extend(m)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SOAP4R - Ruby type mapping factory.
|
||||
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
# Copyright (C) 2000-2003, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
|
||||
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
||||
# redistribute it and/or modify it under the same terms of Ruby's license;
|
||||
|
@ -168,7 +168,7 @@ class RubytypeFactory < Factory
|
|||
return nil
|
||||
end
|
||||
if obj.to_s[0] == ?#
|
||||
raise TypeError.new("can't dump anonymous class #{ obj }")
|
||||
raise TypeError.new("can't dump anonymous class #{obj}")
|
||||
end
|
||||
param = SOAPStruct.new(TYPE_CLASS)
|
||||
mark_marshalled_obj(obj, param)
|
||||
|
@ -179,7 +179,7 @@ class RubytypeFactory < Factory
|
|||
return nil
|
||||
end
|
||||
if obj.to_s[0] == ?#
|
||||
raise TypeError.new("can't dump anonymous module #{ obj }")
|
||||
raise TypeError.new("can't dump anonymous module #{obj}")
|
||||
end
|
||||
param = SOAPStruct.new(TYPE_MODULE)
|
||||
mark_marshalled_obj(obj, param)
|
||||
|
@ -222,7 +222,12 @@ class RubytypeFactory < Factory
|
|||
when ::SOAP::Mapping::Object
|
||||
param = SOAPStruct.new(XSD::AnyTypeName)
|
||||
mark_marshalled_obj(obj, param)
|
||||
addiv2soapattr(param, obj, map)
|
||||
obj.__xmlele.each do |key, value|
|
||||
param.add(key.name, Mapping._obj2soap(value, map))
|
||||
end
|
||||
obj.__xmlattr.each do |key, value|
|
||||
param.extraattr[key] = value
|
||||
end
|
||||
when ::Exception
|
||||
typestr = Mapping.name2elename(obj.class.to_s)
|
||||
param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
|
||||
|
@ -258,12 +263,12 @@ private
|
|||
|
||||
def unknownobj2soap(soap_class, obj, info, map)
|
||||
if obj.class.name.empty?
|
||||
raise TypeError.new("can't dump anonymous class #{ obj }")
|
||||
raise TypeError.new("can't dump anonymous class #{obj}")
|
||||
end
|
||||
singleton_class = class << obj; self; end
|
||||
if !singleton_methods_true(obj).empty? or
|
||||
!singleton_class.instance_variables.empty?
|
||||
raise TypeError.new("singleton can't be dumped #{ obj }")
|
||||
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)
|
||||
|
@ -378,7 +383,11 @@ private
|
|||
obj = klass.new
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
node.each do |name, value|
|
||||
obj.__soap_set_property(name, Mapping._soap2obj(value, map))
|
||||
obj.__add_xmlele_value(XSD::QName.new(nil, name),
|
||||
Mapping._soap2obj(value, map))
|
||||
end
|
||||
unless node.extraattr.empty?
|
||||
obj.instance_variable_set('@__xmlattr', node.extraattr)
|
||||
end
|
||||
return true, obj
|
||||
else
|
||||
|
@ -387,7 +396,12 @@ private
|
|||
end
|
||||
|
||||
def unknowntype2obj(node, info, map)
|
||||
if node.is_a?(SOAPStruct)
|
||||
case node
|
||||
when SOAPBasetype
|
||||
return true, node.data
|
||||
when SOAPArray
|
||||
return @array_factory.soap2obj(Array, node, info, map)
|
||||
when SOAPStruct
|
||||
obj = unknownstruct2obj(node, info, map)
|
||||
return true, obj if obj
|
||||
if !@allow_untyped_struct
|
||||
|
@ -406,6 +420,9 @@ private
|
|||
end
|
||||
typestr = Mapping.elename2name(node.type.name)
|
||||
klass = Mapping.class_from_name(typestr)
|
||||
if klass.nil? and @allow_untyped_struct
|
||||
klass = Mapping.class_from_name(typestr, true) # lenient
|
||||
end
|
||||
if klass.nil?
|
||||
return nil
|
||||
end
|
||||
|
@ -414,7 +431,13 @@ private
|
|||
end
|
||||
klass_type = Mapping.class2qname(klass)
|
||||
return nil unless node.type.match(klass_type)
|
||||
obj = Mapping.create_empty_object(klass)
|
||||
obj = nil
|
||||
begin
|
||||
obj = Mapping.create_empty_object(klass)
|
||||
rescue
|
||||
# type name "data" tries Data.new which raises TypeError
|
||||
nil
|
||||
end
|
||||
mark_unmarshalled_obj(node, obj)
|
||||
setiv2obj(obj, node, map)
|
||||
obj
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# SOAP4R - WSDL encoded mapping registry.
|
||||
# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
# Copyright (C) 2000-2003, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
|
||||
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
||||
# redistribute it and/or modify it under the same terms of Ruby's license;
|
||||
# either the dual license version in 2003, or any later version.
|
||||
|
||||
|
||||
require 'xsd/qname'
|
||||
require 'xsd/namedelements'
|
||||
require 'soap/baseData'
|
||||
require 'soap/mapping/mapping'
|
||||
require 'soap/mapping/typeMap'
|
||||
|
@ -15,35 +17,33 @@ module SOAP
|
|||
module Mapping
|
||||
|
||||
|
||||
class WSDLEncodedRegistry
|
||||
class WSDLEncodedRegistry < Registry
|
||||
include TraverseSupport
|
||||
|
||||
attr_reader :definedelements
|
||||
attr_reader :definedtypes
|
||||
attr_accessor :excn_handler_obj2soap
|
||||
attr_accessor :excn_handler_soap2obj
|
||||
|
||||
def initialize(definedtypes, config = {})
|
||||
def initialize(definedtypes = XSD::NamedElements::Empty)
|
||||
@definedtypes = definedtypes
|
||||
@config = config
|
||||
# @definedelements = definedelements needed?
|
||||
@excn_handler_obj2soap = nil
|
||||
@excn_handler_soap2obj = nil
|
||||
# For mapping AnyType element.
|
||||
@rubytype_factory = RubytypeFactory.new(
|
||||
:allow_untyped_struct => true,
|
||||
:allow_original_mapping => true
|
||||
)
|
||||
@schema_element_cache = {}
|
||||
end
|
||||
|
||||
def obj2soap(obj, type_qname = nil)
|
||||
def obj2soap(obj, qname = nil)
|
||||
soap_obj = nil
|
||||
if obj.nil?
|
||||
soap_obj = SOAPNil.new
|
||||
elsif type_qname.nil? or type_qname == XSD::AnyTypeName
|
||||
soap_obj = @rubytype_factory.obj2soap(nil, obj, nil, self)
|
||||
elsif obj.is_a?(XSD::NSDBase)
|
||||
soap_obj = soap2soap(obj, type_qname)
|
||||
elsif type = @definedtypes[type_qname]
|
||||
soap_obj = obj2type(obj, type)
|
||||
elsif (type = TypeMap[type_qname])
|
||||
soap_obj = base2soap(obj, type)
|
||||
if type = @definedtypes[qname]
|
||||
soap_obj = obj2typesoap(obj, type)
|
||||
else
|
||||
soap_obj = any2soap(obj, qname)
|
||||
end
|
||||
return soap_obj if soap_obj
|
||||
if @excn_handler_obj2soap
|
||||
|
@ -52,15 +52,46 @@ class WSDLEncodedRegistry
|
|||
}
|
||||
return soap_obj if soap_obj
|
||||
end
|
||||
raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
|
||||
if qname
|
||||
raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
|
||||
else
|
||||
raise MappingError.new("cannot map #{obj.class.name} to SOAP/OM")
|
||||
end
|
||||
end
|
||||
|
||||
def soap2obj(node)
|
||||
raise RuntimeError.new("#{ self } is for obj2soap only.")
|
||||
# map anything for now: must refer WSDL while mapping. [ToDo]
|
||||
def soap2obj(node, obj_class = nil)
|
||||
begin
|
||||
return any2obj(node, obj_class)
|
||||
rescue MappingError
|
||||
end
|
||||
if @excn_handler_soap2obj
|
||||
begin
|
||||
return @excn_handler_soap2obj.call(node) { |yield_node|
|
||||
Mapping._soap2obj(yield_node, self)
|
||||
}
|
||||
rescue Exception
|
||||
end
|
||||
end
|
||||
raise MappingError.new("cannot map #{node.type.name} to Ruby object")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def any2soap(obj, qname)
|
||||
if obj.nil?
|
||||
SOAPNil.new
|
||||
elsif qname.nil? or qname == XSD::AnyTypeName
|
||||
@rubytype_factory.obj2soap(nil, obj, nil, self)
|
||||
elsif obj.is_a?(XSD::NSDBase)
|
||||
soap2soap(obj, qname)
|
||||
elsif (type = TypeMap[qname])
|
||||
base2soap(obj, type)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def soap2soap(obj, type_qname)
|
||||
if obj.is_a?(SOAPBasetype)
|
||||
obj
|
||||
|
@ -82,25 +113,22 @@ private
|
|||
end
|
||||
end
|
||||
|
||||
def obj2type(obj, type)
|
||||
def obj2typesoap(obj, type)
|
||||
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
||||
simple2soap(obj, type)
|
||||
simpleobj2soap(obj, type)
|
||||
else
|
||||
complex2soap(obj, type)
|
||||
complexobj2soap(obj, type)
|
||||
end
|
||||
end
|
||||
|
||||
def simple2soap(obj, type)
|
||||
o = base2soap(obj, TypeMap[type.base])
|
||||
if type.restriction.enumeration.empty?
|
||||
STDERR.puts("#{type.name}: simpleType which is not enum type not supported.")
|
||||
return o
|
||||
end
|
||||
def simpleobj2soap(obj, type)
|
||||
type.check_lexical_format(obj)
|
||||
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||
o = base2soap(obj, TypeMap[type.base])
|
||||
o
|
||||
end
|
||||
|
||||
def complex2soap(obj, type)
|
||||
def complexobj2soap(obj, type)
|
||||
case type.compoundtype
|
||||
when :TYPE_STRUCT
|
||||
struct2soap(obj, type.name, type)
|
||||
|
@ -108,8 +136,13 @@ private
|
|||
array2soap(obj, type.name, type)
|
||||
when :TYPE_MAP
|
||||
map2soap(obj, type.name, type)
|
||||
when :TYPE_SIMPLE
|
||||
simpleobj2soap(obj, type.simplecontent)
|
||||
when :TYPE_EMPTY
|
||||
raise MappingError.new("should be empty") unless obj.nil?
|
||||
SOAPNil.new
|
||||
else
|
||||
raise MappingError.new("Unknown compound type: #{ type.compoundtype }")
|
||||
raise MappingError.new("unknown compound type: #{type.compoundtype}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -126,18 +159,24 @@ private
|
|||
end
|
||||
|
||||
def struct2soap(obj, type_qname, type)
|
||||
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||
soap_obj = SOAPStruct.new(type_qname)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
elements2soap(obj, soap_obj, type.content.elements)
|
||||
unless obj.nil?
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
elements2soap(obj, soap_obj, type.content.elements)
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
||||
def array2soap(obj, type_qname, type)
|
||||
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||
arytype = type.child_type
|
||||
soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.each do |item|
|
||||
soap_obj.add(Mapping._obj2soap(item, self, arytype))
|
||||
unless obj.nil?
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.each do |item|
|
||||
soap_obj.add(Mapping._obj2soap(item, self, arytype))
|
||||
end
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
@ -145,16 +184,19 @@ private
|
|||
MapKeyName = XSD::QName.new(nil, "key")
|
||||
MapValueName = XSD::QName.new(nil, "value")
|
||||
def map2soap(obj, type_qname, type)
|
||||
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||
keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
|
||||
valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
|
||||
soap_obj = SOAPStruct.new(MapQName)
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.each do |key, value|
|
||||
elem = SOAPStruct.new
|
||||
elem.add("key", Mapping._obj2soap(key, self, keytype))
|
||||
elem.add("value", Mapping._obj2soap(value, self, valuetype))
|
||||
# ApacheAxis allows only 'item' here.
|
||||
soap_obj.add("item", elem)
|
||||
unless obj.nil?
|
||||
mark_marshalled_obj(obj, soap_obj)
|
||||
obj.each do |key, value|
|
||||
elem = SOAPStruct.new
|
||||
elem.add("key", Mapping._obj2soap(key, self, keytype))
|
||||
elem.add("value", Mapping._obj2soap(value, self, valuetype))
|
||||
# ApacheAxis allows only 'item' here.
|
||||
soap_obj.add("item", elem)
|
||||
end
|
||||
end
|
||||
soap_obj
|
||||
end
|
||||
|
@ -162,10 +204,64 @@ private
|
|||
def elements2soap(obj, soap_obj, elements)
|
||||
elements.each do |element|
|
||||
name = element.name.name
|
||||
child_obj = obj.instance_variable_get('@' + name)
|
||||
soap_obj.add(name, Mapping._obj2soap(child_obj, self, element.type))
|
||||
child_obj = Mapping.get_attribute(obj, name)
|
||||
soap_obj.add(name,
|
||||
Mapping._obj2soap(child_obj, self, element.type || element.name))
|
||||
end
|
||||
end
|
||||
|
||||
def any2obj(node, obj_class)
|
||||
unless obj_class
|
||||
typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
||||
obj_class = Mapping.class_from_name(typestr)
|
||||
end
|
||||
if obj_class and obj_class.class_variables.include?('@@schema_element')
|
||||
soap2stubobj(node, obj_class)
|
||||
else
|
||||
Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
|
||||
end
|
||||
end
|
||||
|
||||
def soap2stubobj(node, obj_class)
|
||||
obj = Mapping.create_empty_object(obj_class)
|
||||
unless node.is_a?(SOAPNil)
|
||||
add_elements2stubobj(node, obj)
|
||||
end
|
||||
obj
|
||||
end
|
||||
|
||||
def add_elements2stubobj(node, obj)
|
||||
elements, as_array = schema_element_definition(obj.class)
|
||||
vars = {}
|
||||
node.each do |name, value|
|
||||
if class_name = elements[name]
|
||||
if klass = Mapping.class_from_name(class_name)
|
||||
# klass must be a SOAPBasetype or a class
|
||||
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
||||
if value.respond_to?(:data)
|
||||
child = klass.new(value.data).data
|
||||
else
|
||||
child = klass.new(nil).data
|
||||
end
|
||||
else
|
||||
child = Mapping._soap2obj(value, self, klass)
|
||||
end
|
||||
else
|
||||
raise MappingError.new("unknown class: #{class_name}")
|
||||
end
|
||||
else # untyped element is treated as anyType.
|
||||
child = Mapping._soap2obj(value, self)
|
||||
end
|
||||
vars[name] = child
|
||||
end
|
||||
Mapping.set_attributes(obj, vars)
|
||||
end
|
||||
|
||||
# it caches @@schema_element. this means that @@schema_element must not be
|
||||
# changed while a lifetime of a WSDLLiteralRegistry.
|
||||
def schema_element_definition(klass)
|
||||
@schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SOAP4R - WSDL literal mapping registry.
|
||||
# Copyright (C) 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
# Copyright (C) 2004, 2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
||||
|
||||
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
||||
# redistribute it and/or modify it under the same terms of Ruby's license;
|
||||
|
@ -10,48 +10,55 @@ require 'soap/baseData'
|
|||
require 'soap/mapping/mapping'
|
||||
require 'soap/mapping/typeMap'
|
||||
require 'xsd/codegen/gensupport'
|
||||
require 'xsd/namedelements'
|
||||
|
||||
|
||||
module SOAP
|
||||
module Mapping
|
||||
|
||||
|
||||
class WSDLLiteralRegistry
|
||||
class WSDLLiteralRegistry < Registry
|
||||
attr_reader :definedelements
|
||||
attr_reader :definedtypes
|
||||
attr_accessor :excn_handler_obj2soap
|
||||
attr_accessor :excn_handler_soap2obj
|
||||
|
||||
def initialize(definedelements = nil, definedtypes = nil)
|
||||
@definedelements = definedelements
|
||||
def initialize(definedtypes = XSD::NamedElements::Empty,
|
||||
definedelements = XSD::NamedElements::Empty)
|
||||
@definedtypes = definedtypes
|
||||
@rubytype_factory = RubytypeFactory.new(:allow_original_mapping => false)
|
||||
@definedelements = definedelements
|
||||
@excn_handler_obj2soap = nil
|
||||
@excn_handler_soap2obj = nil
|
||||
@schema_element_cache = {}
|
||||
@schema_attribute_cache = {}
|
||||
end
|
||||
|
||||
def obj2soap(obj, qname)
|
||||
ret = nil
|
||||
if !@definedelements.nil? && ele = @definedelements[qname]
|
||||
ret = _obj2soap(obj, ele)
|
||||
elsif !@definedtypes.nil? && type = @definedtypes[qname]
|
||||
ret = obj2type(obj, type)
|
||||
soap_obj = nil
|
||||
if ele = @definedelements[qname]
|
||||
soap_obj = obj2elesoap(obj, ele)
|
||||
elsif type = @definedtypes[qname]
|
||||
soap_obj = obj2typesoap(obj, type)
|
||||
else
|
||||
ret = unknownobj2soap(obj, qname)
|
||||
soap_obj = any2soap(obj, qname)
|
||||
end
|
||||
return ret if ret
|
||||
return soap_obj if soap_obj
|
||||
if @excn_handler_obj2soap
|
||||
ret = @excn_handler_obj2soap.call(obj) { |yield_obj|
|
||||
soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
|
||||
Mapping._obj2soap(yield_obj, self)
|
||||
}
|
||||
return ret if ret
|
||||
return soap_obj if soap_obj
|
||||
end
|
||||
raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
|
||||
raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
|
||||
end
|
||||
|
||||
# node should be a SOAPElement
|
||||
def soap2obj(node)
|
||||
def soap2obj(node, obj_class = nil)
|
||||
unless obj_class.nil?
|
||||
raise MappingError.new("must not reach here")
|
||||
end
|
||||
begin
|
||||
return soapele2obj(node)
|
||||
return any2obj(node)
|
||||
rescue MappingError
|
||||
end
|
||||
if @excn_handler_soap2obj
|
||||
|
@ -62,108 +69,164 @@ class WSDLLiteralRegistry
|
|||
rescue Exception
|
||||
end
|
||||
end
|
||||
raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
|
||||
raise MappingError.new("cannot map #{node.type.name} to Ruby object")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _obj2soap(obj, ele)
|
||||
def obj2elesoap(obj, ele)
|
||||
o = nil
|
||||
if ele.type
|
||||
if type = @definedtypes[ele.type]
|
||||
o = obj2type(obj, type)
|
||||
o = obj2typesoap(obj, type)
|
||||
elsif type = TypeMap[ele.type]
|
||||
o = base2soap(obj, type)
|
||||
else
|
||||
raise MappingError.new("Cannot find type #{ele.type}.")
|
||||
raise MappingError.new("cannot find type #{ele.type}")
|
||||
end
|
||||
o.elename = ele.name
|
||||
elsif ele.local_complextype
|
||||
o = SOAPElement.new(ele.name)
|
||||
ele.local_complextype.each_element do |child_ele|
|
||||
o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name),
|
||||
child_ele))
|
||||
end
|
||||
o = obj2typesoap(obj, ele.local_complextype)
|
||||
o.elename = ele.name
|
||||
add_attributes2soap(obj, o)
|
||||
elsif ele.local_simpletype
|
||||
o = obj2typesoap(obj, ele.local_simpletype)
|
||||
o.elename = ele.name
|
||||
else
|
||||
raise MappingError.new('Illegal schema?')
|
||||
raise MappingError.new('illegal schema?')
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def obj2type(obj, type)
|
||||
def obj2typesoap(obj, type)
|
||||
if type.is_a?(::WSDL::XMLSchema::SimpleType)
|
||||
simple2soap(obj, type)
|
||||
simpleobj2soap(obj, type)
|
||||
else
|
||||
complex2soap(obj, type)
|
||||
complexobj2soap(obj, type)
|
||||
end
|
||||
end
|
||||
|
||||
def simple2soap(obj, type)
|
||||
o = base2soap(obj, TypeMap[type.base])
|
||||
if type.restriction.enumeration.empty?
|
||||
STDERR.puts(
|
||||
"#{type.name}: simpleType which is not enum type not supported.")
|
||||
return o
|
||||
end
|
||||
def simpleobj2soap(obj, type)
|
||||
type.check_lexical_format(obj)
|
||||
return SOAPNil.new if obj.nil? # ToDo: check nillable.
|
||||
o = base2soap(obj, TypeMap[type.base])
|
||||
o
|
||||
end
|
||||
|
||||
def complex2soap(obj, type)
|
||||
def complexobj2soap(obj, type)
|
||||
o = SOAPElement.new(type.name)
|
||||
type.each_element do |child_ele|
|
||||
o.add(_obj2soap(Mapping.find_attribute(obj, child_ele.name.name),
|
||||
child_ele))
|
||||
child = Mapping.get_attribute(obj, child_ele.name.name)
|
||||
if child.nil?
|
||||
if child_ele.nillable
|
||||
# ToDo: test
|
||||
# add empty element
|
||||
o.add(obj2elesoap(nil))
|
||||
elsif Integer(child_ele.minoccurs) == 0
|
||||
# nothing to do
|
||||
else
|
||||
raise MappingError.new("nil not allowed: #{child_ele.name.name}")
|
||||
end
|
||||
elsif child_ele.map_as_array?
|
||||
child.each do |item|
|
||||
o.add(obj2elesoap(item, child_ele))
|
||||
end
|
||||
else
|
||||
o.add(obj2elesoap(child, child_ele))
|
||||
end
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
def unknownobj2soap(obj, name)
|
||||
if obj.class.class_variables.include?('@@schema_element')
|
||||
ele = SOAPElement.new(name)
|
||||
add_elements2soap(obj, ele)
|
||||
add_attributes2soap(obj, ele)
|
||||
ele
|
||||
def any2soap(obj, qname)
|
||||
if obj.is_a?(SOAPElement)
|
||||
obj
|
||||
elsif obj.class.class_variables.include?('@@schema_element')
|
||||
stubobj2soap(obj, qname)
|
||||
elsif obj.is_a?(SOAP::Mapping::Object)
|
||||
mappingobj2soap(obj, qname)
|
||||
elsif obj.is_a?(Hash)
|
||||
ele = SOAPElement.from_obj(obj)
|
||||
ele.elename = name
|
||||
ele.elename = qname
|
||||
ele
|
||||
else
|
||||
# expected to be a basetype or an anyType.
|
||||
# SOAPStruct, etc. is used instead of SOAPElement.
|
||||
begin
|
||||
ele = Mapping.obj2soap(obj)
|
||||
ele.elename = qname
|
||||
ele
|
||||
rescue MappingError
|
||||
ele = SOAPElement.new(qname, obj.to_s)
|
||||
end
|
||||
if obj.respond_to?(:__xmlattr)
|
||||
obj.__xmlattr.each do |key, value|
|
||||
ele.extraattr[key] = value
|
||||
end
|
||||
end
|
||||
ele
|
||||
else # expected to be a basetype or an anyType.
|
||||
o = Mapping.obj2soap(obj)
|
||||
o.elename = name
|
||||
o
|
||||
end
|
||||
end
|
||||
|
||||
def stubobj2soap(obj, qname)
|
||||
ele = SOAPElement.new(qname)
|
||||
add_elements2soap(obj, ele)
|
||||
add_attributes2soap(obj, ele)
|
||||
ele
|
||||
end
|
||||
|
||||
def mappingobj2soap(obj, qname)
|
||||
ele = SOAPElement.new(qname)
|
||||
obj.__xmlele.each do |key, value|
|
||||
if value.is_a?(::Array)
|
||||
value.each do |item|
|
||||
ele.add(obj2soap(item, key))
|
||||
end
|
||||
else
|
||||
ele.add(obj2soap(value, key))
|
||||
end
|
||||
end
|
||||
obj.__xmlattr.each do |key, value|
|
||||
ele.extraattr[key] = value
|
||||
end
|
||||
ele
|
||||
end
|
||||
|
||||
def add_elements2soap(obj, ele)
|
||||
elements, as_array = schema_element_definition(obj.class)
|
||||
elements.each do |elename, type|
|
||||
child = Mapping.find_attribute(obj, elename)
|
||||
name = ::XSD::QName.new(nil, elename)
|
||||
if as_array.include?(type)
|
||||
child.each do |item|
|
||||
ele.add(obj2soap(item, name))
|
||||
if elements
|
||||
elements.each do |elename, type|
|
||||
child = Mapping.get_attribute(obj, elename)
|
||||
unless child.nil?
|
||||
name = XSD::QName.new(nil, elename)
|
||||
if as_array.include?(type)
|
||||
child.each do |item|
|
||||
ele.add(obj2soap(item, name))
|
||||
end
|
||||
else
|
||||
ele.add(obj2soap(child, name))
|
||||
end
|
||||
end
|
||||
else
|
||||
ele.add(obj2soap(child, name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_attributes2soap(obj, ele)
|
||||
attributes = schema_attribute_definition(obj.class)
|
||||
attributes.each do |attrname, param|
|
||||
attr = Mapping.find_attribute(obj, 'attr_' + attrname)
|
||||
ele.extraattr[attrname] = attr
|
||||
if attributes
|
||||
attributes.each do |qname, param|
|
||||
attr = obj.__send__('xmlattr_' +
|
||||
XSD::CodeGen::GenSupport.safevarname(qname.name))
|
||||
ele.extraattr[qname] = attr
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def base2soap(obj, type)
|
||||
soap_obj = nil
|
||||
if type <= ::XSD::XSDString
|
||||
soap_obj = type.new(::XSD::Charset.is_ces(obj, $KCODE) ?
|
||||
::XSD::Charset.encoding_conv(obj, $KCODE, ::XSD::Charset.encoding) :
|
||||
obj)
|
||||
if type <= XSD::XSDString
|
||||
soap_obj = type.new(XSD::Charset.is_ces(obj, $KCODE) ?
|
||||
XSD::Charset.encoding_conv(obj, $KCODE, XSD::Charset.encoding) : obj)
|
||||
else
|
||||
soap_obj = type.new(obj)
|
||||
end
|
||||
|
@ -176,35 +239,41 @@ private
|
|||
end
|
||||
klass = ::SOAP::Mapping::Object
|
||||
obj = klass.new
|
||||
node.each do |name, value|
|
||||
obj.__soap_set_property(name, Mapping.soap2obj(value))
|
||||
end
|
||||
obj
|
||||
end
|
||||
|
||||
def soapele2obj(node, obj_class = nil)
|
||||
def any2obj(node, obj_class = nil)
|
||||
unless obj_class
|
||||
typestr = ::XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
||||
typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
|
||||
obj_class = Mapping.class_from_name(typestr)
|
||||
end
|
||||
if obj_class and obj_class.class_variables.include?('@@schema_element')
|
||||
soapele2definedobj(node, obj_class)
|
||||
elsif node.is_a?(SOAPElement)
|
||||
node.to_obj
|
||||
soapele2stubobj(node, obj_class)
|
||||
elsif node.is_a?(SOAPElement) or node.is_a?(SOAPStruct)
|
||||
# SOAPArray for literal?
|
||||
soapele2plainobj(node)
|
||||
else
|
||||
result, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
|
||||
obj = Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
|
||||
add_attributes2plainobj(node, obj)
|
||||
obj
|
||||
end
|
||||
end
|
||||
|
||||
def soapele2definedobj(node, obj_class)
|
||||
def soapele2stubobj(node, obj_class)
|
||||
obj = Mapping.create_empty_object(obj_class)
|
||||
add_elements2obj(node, obj)
|
||||
add_attributes2obj(node, obj)
|
||||
add_elements2stubobj(node, obj)
|
||||
add_attributes2stubobj(node, obj)
|
||||
obj
|
||||
end
|
||||
|
||||
def add_elements2obj(node, obj)
|
||||
def soapele2plainobj(node)
|
||||
obj = anytype2obj(node)
|
||||
add_elements2plainobj(node, obj)
|
||||
add_attributes2plainobj(node, obj)
|
||||
obj
|
||||
end
|
||||
|
||||
def add_elements2stubobj(node, obj)
|
||||
elements, as_array = schema_element_definition(obj.class)
|
||||
vars = {}
|
||||
node.each do |name, value|
|
||||
|
@ -217,13 +286,13 @@ private
|
|||
child = klass.new(nil).data
|
||||
end
|
||||
else
|
||||
child = soapele2obj(value, klass)
|
||||
child = any2obj(value, klass)
|
||||
end
|
||||
else
|
||||
raise MappingError.new("Unknown class: #{class_name}")
|
||||
raise MappingError.new("unknown class: #{class_name}")
|
||||
end
|
||||
else # untyped element is treated as anyType.
|
||||
child = anytype2obj(value)
|
||||
child = any2obj(value)
|
||||
end
|
||||
if as_array.include?(class_name)
|
||||
(vars[name] ||= []) << child
|
||||
|
@ -231,48 +300,92 @@ private
|
|||
vars[name] = child
|
||||
end
|
||||
end
|
||||
Mapping.set_instance_vars(obj, vars)
|
||||
Mapping.set_attributes(obj, vars)
|
||||
end
|
||||
|
||||
def add_attributes2obj(node, obj)
|
||||
Mapping.set_instance_vars(obj, {'__soap_attribute' => {}})
|
||||
vars = {}
|
||||
attributes = schema_attribute_definition(obj.class)
|
||||
attributes.each do |attrname, class_name|
|
||||
attr = node.extraattr[::XSD::QName.new(nil, attrname)]
|
||||
next if attr.nil? or attr.empty?
|
||||
klass = Mapping.class_from_name(class_name)
|
||||
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
||||
child = klass.new(attr).data
|
||||
else
|
||||
child = attr
|
||||
def add_attributes2stubobj(node, obj)
|
||||
if attributes = schema_attribute_definition(obj.class)
|
||||
define_xmlattr(obj)
|
||||
attributes.each do |qname, class_name|
|
||||
attr = node.extraattr[qname]
|
||||
next if attr.nil? or attr.empty?
|
||||
klass = Mapping.class_from_name(class_name)
|
||||
if klass.ancestors.include?(::SOAP::SOAPBasetype)
|
||||
child = klass.new(attr).data
|
||||
else
|
||||
child = attr
|
||||
end
|
||||
obj.__xmlattr[qname] = child
|
||||
define_xmlattr_accessor(obj, qname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_elements2plainobj(node, obj)
|
||||
node.each do |name, value|
|
||||
obj.__add_xmlele_value(XSD::QName.new(nil, name), any2obj(value))
|
||||
end
|
||||
end
|
||||
|
||||
def add_attributes2plainobj(node, obj)
|
||||
return if node.extraattr.empty?
|
||||
define_xmlattr(obj)
|
||||
node.extraattr.each do |qname, value|
|
||||
obj.__xmlattr[qname] = value
|
||||
define_xmlattr_accessor(obj, qname)
|
||||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION > "1.7.0"
|
||||
def define_xmlattr_accessor(obj, qname)
|
||||
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||
Mapping.define_attr_accessor(obj, 'xmlattr_' + name,
|
||||
proc { @__xmlattr[qname] },
|
||||
proc { |value| @__xmlattr[qname] = value })
|
||||
end
|
||||
else
|
||||
def define_xmlattr_accessor(obj, qname)
|
||||
name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
|
||||
obj.instance_eval <<-EOS
|
||||
def #{name}
|
||||
@__xmlattr[#{qname.dump}]
|
||||
end
|
||||
|
||||
def #{name}=(value)
|
||||
@__xmlattr[#{qname.dump}] = value
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION > "1.7.0"
|
||||
def define_xmlattr(obj)
|
||||
obj.instance_variable_set('@__xmlattr', {})
|
||||
unless obj.respond_to?(:__xmlattr)
|
||||
Mapping.define_attr_accessor(obj, :__xmlattr, proc { @__xmlattr })
|
||||
end
|
||||
end
|
||||
else
|
||||
def define_xmlattr(obj)
|
||||
obj.instance_variable_set('@__xmlattr', {})
|
||||
unless obj.respond_to?(:__xmlattr)
|
||||
obj.instance_eval <<-EOS
|
||||
def __xmlattr
|
||||
@__xmlattr
|
||||
end
|
||||
EOS
|
||||
end
|
||||
vars['attr_' + attrname] = child
|
||||
end
|
||||
Mapping.set_instance_vars(obj, vars)
|
||||
end
|
||||
|
||||
# it caches @@schema_element. this means that @@schema_element must not be
|
||||
# changed while a lifetime of a WSDLLiteralRegistry.
|
||||
def schema_element_definition(klass)
|
||||
if @schema_element_cache.key?(klass)
|
||||
return @schema_element_cache[klass]
|
||||
end
|
||||
elements = {}
|
||||
as_array = []
|
||||
klass.class_eval('@@schema_element').each do |name, class_name|
|
||||
if /\[\]$/ =~ class_name
|
||||
class_name = class_name.sub(/\[\]$/, '')
|
||||
as_array << class_name
|
||||
end
|
||||
elements[name] = class_name
|
||||
end
|
||||
@schema_element_cache[klass] = [elements, as_array]
|
||||
return @schema_element_cache[klass]
|
||||
@schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
|
||||
end
|
||||
|
||||
def schema_attribute_definition(klass)
|
||||
attributes = klass.class_eval('@@schema_attribute')
|
||||
@schema_attribute_cache[klass] ||= Mapping.schema_attribute_definition(klass)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue