diff options
author | nahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-09-24 15:18:44 +0000 |
---|---|---|
committer | nahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-09-24 15:18:44 +0000 |
commit | db9445103c082a306ba085f7677da02ea94b8841 (patch) | |
tree | a311d59f031ae5def87f68be71ed1f58abadc031 /lib/soap/mapping/mapping.rb | |
parent | 8c2fb77787d1f20b4c19c9c52552856c339b86e9 (diff) | |
download | ruby-db9445103c082a306ba085f7677da02ea94b8841.tar.gz |
* lib/soap/* (29 files): SOAP4R added.
* lib/wsdl/* (42 files): WSDL4R added.
* lib/xsd/* (12 files): XSD4R added.
* test/soap/* (16 files): added.
* test/wsdl/* (2 files): added.
* test/xsd/* (3 files): added.
* sample/soap/* (27 files): added.
* sample/wsdl/* (13 files): added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4591 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/soap/mapping/mapping.rb')
-rw-r--r-- | lib/soap/mapping/mapping.rb | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/lib/soap/mapping/mapping.rb b/lib/soap/mapping/mapping.rb new file mode 100644 index 0000000000..19eca5dab0 --- /dev/null +++ b/lib/soap/mapping/mapping.rb @@ -0,0 +1,218 @@ +=begin +SOAP4R - Ruby type mapping utility. +Copyright (C) 2000, 2001, 2003 NAKAMURA Hiroshi. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PRATICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 675 Mass +Ave, Cambridge, MA 02139, USA. +=end + + +module SOAP + + +module Mapping + RubyTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/1.6' + RubyTypeInstanceNamespace = + 'http://www.ruby-lang.org/xmlns/ruby/type-instance' + RubyCustomTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/custom' + ApacheSOAPTypeNamespace = 'http://xml.apache.org/xml-soap' + + + # TraverseSupport breaks Thread.current[:SOAPMarshalDataKey]. + module TraverseSupport + def mark_marshalled_obj(obj, soap_obj) + Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj + end + + def mark_unmarshalled_obj(node, obj) + # node.id is not Object#id but SOAPReference#id + Thread.current[:SOAPMarshalDataKey][node.id] = obj + end + end + + + def self.obj2soap(obj, registry = nil, type = nil) + registry ||= Mapping::DefaultRegistry + Thread.current[:SOAPMarshalDataKey] = {} + soap_obj = _obj2soap(obj, registry, type) + Thread.current[:SOAPMarshalDataKey] = nil + soap_obj + end + + def self.soap2obj(node, registry = nil) + registry ||= Mapping::DefaultRegistry + Thread.current[:SOAPMarshalDataKey] = {} + obj = _soap2obj(node, registry) + Thread.current[:SOAPMarshalDataKey] = nil + obj + end + + def self.ary2soap(ary, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil) + registry ||= Mapping::DefaultRegistry + type = XSD::QName.new(type_ns, typename) + soap_ary = SOAPArray.new(ValueArrayName, 1, type) + Thread.current[:SOAPMarshalDataKey] = {} + ary.each do |ele| + soap_ary.add(_obj2soap(ele, registry, type)) + end + Thread.current[:SOAPMarshalDataKey] = nil + soap_ary + end + + def self.ary2md(ary, rank, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil) + registry ||= Mapping::DefaultRegistry + type = XSD::QName.new(type_ns, typename) + md_ary = SOAPArray.new(ValueArrayName, rank, type) + Thread.current[:SOAPMarshalDataKey] = {} + add_md_ary(md_ary, ary, [], registry) + Thread.current[:SOAPMarshalDataKey] = nil + md_ary + end + + def self.fault2exception(e, registry = nil) + registry ||= Mapping::DefaultRegistry + detail = if e.detail + soap2obj(e.detail, registry) || "" + else + "" + end + if detail.is_a?(Mapping::SOAPException) + begin + raise detail.to_e + rescue Exception => e2 + detail.set_backtrace(e2) + raise + end + else + e.detail = detail + e.set_backtrace( + if detail.is_a?(Array) + detail + else + [detail.to_s] + end + ) + raise + end + end + + def self._obj2soap(obj, registry, type = nil) + if referent = Thread.current[:SOAPMarshalDataKey][obj.__id__] + soap_obj = SOAPReference.new + soap_obj.__setobj__(referent) + soap_obj + else + registry.obj2soap(obj.class, obj, type) + end + end + + def self._soap2obj(node, registry) + 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) + end + end + return registry.soap2obj(node.class, node) + end + + + # Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here. + # Caution: '.' is not allowed here. + # To follow XML spec., it should be NCName. + # (denied chars) => .[0-F][0-F] + # ex. a.b => a.2eb + # + def self.name2elename(name) + name.gsub(/([^a-zA-Z0-9:_\-]+)/n) { + '.' << $1.unpack('H2' * $1.size).join('.') + }.gsub(/::/n, '..') + end + + def self.elename2name(name) + name.gsub(/\.\./n, '::').gsub(/((?:\.[0-9a-fA-F]{2})+)/n) { + [$1.delete('.')].pack('H*') + } + end + + def self.class_from_name(name) + if /^[A-Z]/ !~ name + 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 + end + klass + end + + def self.class2qname(klass) + name = if klass.class_variables.include?("@@schema_type") + klass.class_eval("@@schema_type") + else + nil + end + namespace = if klass.class_variables.include?("@@schema_ns") + klass.class_eval("@@schema_ns") + else + nil + end + XSD::QName.new(namespace, name) + end + + def self.class2element(klass) + type = Mapping.class2qname(klass) + type.name ||= Mapping.name2elename(klass.name) + type.namespace ||= RubyCustomTypeNamespace + type + end + + def self.obj2element(obj) + name = namespace = nil + ivars = obj.instance_variables + if ivars.include?("@schema_type") + name = obj.instance_eval("@schema_type") + end + if ivars.include?("@schema_ns") + namespace = obj.instance_eval("@schema_ns") + end + if !name or !namespace + class2qname(obj.class) + else + XSD::QName.new(namespace, name) + end + end + + class << Mapping + private + def add_md_ary(md_ary, ary, indices, registry) + for idx in 0..(ary.size - 1) + if ary[idx].is_a?(Array) + add_md_ary(md_ary, ary[idx], indices + [idx], registry) + else + md_ary[*(indices + [idx])] = _obj2soap(ary[idx], registry) + end + end + end + end +end + + +end |