From db9445103c082a306ba085f7677da02ea94b8841 Mon Sep 17 00:00:00 2001 From: nahi Date: Wed, 24 Sep 2003 15:18:44 +0000 Subject: * 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 --- lib/soap/encodingstyle/aspDotNetHandler.rb | 232 ++++++++++++ lib/soap/encodingstyle/handler.rb | 111 ++++++ lib/soap/encodingstyle/literalHandler.rb | 218 ++++++++++++ lib/soap/encodingstyle/soapHandler.rb | 548 +++++++++++++++++++++++++++++ 4 files changed, 1109 insertions(+) create mode 100644 lib/soap/encodingstyle/aspDotNetHandler.rb create mode 100644 lib/soap/encodingstyle/handler.rb create mode 100644 lib/soap/encodingstyle/literalHandler.rb create mode 100644 lib/soap/encodingstyle/soapHandler.rb (limited to 'lib/soap/encodingstyle') diff --git a/lib/soap/encodingstyle/aspDotNetHandler.rb b/lib/soap/encodingstyle/aspDotNetHandler.rb new file mode 100644 index 0000000000..fdce42a48a --- /dev/null +++ b/lib/soap/encodingstyle/aspDotNetHandler.rb @@ -0,0 +1,232 @@ +=begin +SOAP4R - ASP.NET EncodingStyle handler library +Copyright (C) 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 + + +require 'soap/encodingstyle/handler' + + +module SOAP +module EncodingStyle + + +class ASPDotNetHandler < Handler + Namespace = 'http://tempuri.org/ASP.NET' + add_handler + + def initialize(charset = nil) + super(charset) + @textbuf = '' + @decode_typemap = nil + end + + + ### + ## encode interface. + # + def encode_data(buf, ns, qualified, data, parent, indent = '') + attrs = {} + name = if qualified and data.elename.namespace + SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace) + ns.name(data.elename) + else + data.elename.name + end + + case data + when SOAPRawString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << data.to_s + when XSD::XSDString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(@charset ? + XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s) + when XSD::XSDAnySimpleType + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(data.to_s) + when SOAPStruct + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.each do |key, value| + if !value.elename.namespace + value.elename.namespace = data.elename.namespace + end + yield(value, true) + end + when SOAPArray + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.traverse do |child, *rank| + data.position = nil + yield(child, true) + end + else + raise EncodingStyleError.new("Unknown object:#{ data } in this encodingSt +yle.") + end + end + + def encode_data_end(buf, ns, qualified, data, parent, indent = "") + name = if qualified and data.elename.namespace + ns.name(data.elename) + else + data.elename.name + end + cr = data.is_a?(SOAPCompoundtype) + SOAPGenerator.encode_tag_end(buf, name, indent, cr) + end + + + ### + ## decode interface. + # + class SOAPTemporalObject + attr_accessor :parent + + def initialize + @parent = nil + end + end + + class SOAPUnknown < SOAPTemporalObject + def initialize(handler, elename) + super() + @handler = handler + @elename = elename + end + + def as_struct + o = SOAPStruct.decode(@elename, XSD::AnyTypeName) + o.parent = @parent + o.type.name = @name + @handler.decode_parent(@parent, o) + o + end + + def as_string + o = SOAPString.decode(@elename) + o.parent = @parent + @handler.decode_parent(@parent, o) + o + end + + def as_nil + o = SOAPNil.decode(@elename) + o.parent = @parent + @handler.decode_parent(@parent, o) + o + end + end + + def decode_tag(ns, elename, attrs, parent) + # ToDo: check if @textbuf is empty... + @textbuf = '' + o = SOAPUnknown.new(self, elename) + o.parent = parent + o + end + + def decode_tag_end(ns, node) + o = node.node + if o.is_a?(SOAPUnknown) + newnode = o.as_string +# if /\A\s*\z/ =~ @textbuf +# o.as_struct +# else +# o.as_string +# end + node.replace_node(newnode) + o = node.node + end + + decode_textbuf(o) + @textbuf = '' + end + + def decode_text(ns, text) + # @textbuf is set at decode_tag_end. + @textbuf << text + end + + def decode_prologue + end + + def decode_epilogue + end + + def decode_parent(parent, node) + case parent.node + when SOAPUnknown + newparent = parent.node.as_struct + node.parent = newparent + parent.replace_node(newparent) + decode_parent(parent, node) + + when SOAPStruct + data = parent.node[node.elename.name] + case data + when nil + parent.node.add(node.elename.name, node) + when SOAPArray + name, type_ns = node.elename.name, node.type.namespace + data.add(node) + node.elename, node.type.namespace = name, type_ns + else + parent.node[node.elename.name] = SOAPArray.new + name, type_ns = data.elename.name, data.type.namespace + parent.node[node.elename.name].add(data) + data.elename.name, data.type.namespace = name, type_ns + name, type_ns = node.elename.name, node.type.namespace + parent.node[node.elename.name].add(node) + node.elename.name, node.type.namespace = name, type_ns + end + + when SOAPArray + if node.position + parent.node[*(decode_arypos(node.position))] = node + parent.node.sparse = true + else + parent.node.add(node) + end + + when SOAPBasetype + raise EncodingStyleError.new("SOAP base type must not have a child.") + + else + # SOAPUnknown does not have parent. + # raise EncodingStyleError.new("Illegal parent: #{ parent }.") + end + end + +private + + def decode_textbuf(node) + if node.is_a?(XSD::XSDString) + if @charset + node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset)) + else + node.set(@textbuf) + end + else + # Nothing to do... + end + end +end + +ASPDotNetHandler.new + + +end +end diff --git a/lib/soap/encodingstyle/handler.rb b/lib/soap/encodingstyle/handler.rb new file mode 100644 index 0000000000..1ab9d86ec5 --- /dev/null +++ b/lib/soap/encodingstyle/handler.rb @@ -0,0 +1,111 @@ +=begin +SOAP4R - EncodingStyle handler library +Copyright (C) 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 + + +require 'soap/soap' +require 'soap/baseData' +require 'soap/element' + + +module SOAP +module EncodingStyle + + +class Handler + @@handlers = {} + + class EncodingStyleError < Error; end + + class << self + def uri + self::Namespace + end + + def handler(uri) + @@handlers[uri] + end + + def each + @@handlers.each do |key, value| + yield(value) + end + end + + private + + def add_handler + @@handlers[self.uri] = self + end + end + + attr_reader :charset + attr_accessor :generate_explicit_type + def decode_typemap=(complextypes) + @decode_typemap = complextypes + end + + def initialize(charset) + @charset = charset + @generate_explicit_type = true + @decode_typemap = nil + end + + ### + ## encode interface. + # + # Returns a XML instance as a string. + def encode_data(buf, ns, qualified, data, parent, indent) + raise NotImplementError.new('Method encode_data must be defined in derived class.') + end + + def encode_data_end(buf, ns, qualified, data, parent, indent) + raise NotImplementError.new('Method encode_data must be defined in derived class.') + end + + def encode_prologue + end + + def encode_epilogue + end + + ### + ## decode interface. + # + # Returns SOAP/OM data. + def decode_tag(ns, name, attrs, parent) + raise NotImplementError.new('Method decode_tag must be defined in derived class.') + end + + def decode_tag_end(ns, name) + raise NotImplementError.new('Method decode_tag_end must be defined in derived class.') + end + + def decode_text(ns, text) + raise NotImplementError.new('Method decode_text must be defined in derived class.') + end + + def decode_prologue + end + + def decode_epilogue + end +end + + +end +end diff --git a/lib/soap/encodingstyle/literalHandler.rb b/lib/soap/encodingstyle/literalHandler.rb new file mode 100644 index 0000000000..b5d0d464d7 --- /dev/null +++ b/lib/soap/encodingstyle/literalHandler.rb @@ -0,0 +1,218 @@ +=begin +SOAP4R - XML Literal EncodingStyle handler library +Copyright (C) 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 + + +require 'soap/encodingstyle/handler' + + +module SOAP +module EncodingStyle + + +class LiteralHandler < Handler + Namespace = SOAP::LiteralNamespace + add_handler + + def initialize(charset = nil) + super(charset) + @textbuf = '' + end + + + ### + ## encode interface. + # + def encode_data(buf, ns, qualified, data, parent, indent = '') + attrs = {} + name = if qualified and data.elename.namespace + SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace) + ns.name(data.elename) + else + data.elename.name + end + + case data + when SOAPRawString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << data.to_s + when XSD::XSDString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(@charset ? + XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s) + when XSD::XSDAnySimpleType + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(data.to_s) + when SOAPStruct + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.each do |key, value| + value.elename.namespace = data.elename.namespace if !value.elename.namespace + yield(value, true) + end + when SOAPArray + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.traverse do |child, *rank| + data.position = nil + yield(child, true) + end + when SOAPElement + SOAPGenerator.encode_tag(buf, name, attrs.update(data.extraattr), + indent) + buf << data.text if data.text + data.each do |key, value| + value.elename.namespace = data.elename.namespace if !value.elename.namespace + #yield(value, data.qualified) + yield(value, qualified) + end + else + raise EncodingStyleError.new("Unknown object:#{ data } in this encodingStyle.") + end + end + + def encode_data_end(buf, ns, qualified, data, parent, indent) + name = if qualified and data.elename.namespace + ns.name(data.elename) + else + data.elename.name + end + SOAPGenerator.encode_tag_end(buf, name, indent) + end + + + ### + ## decode interface. + # + class SOAPTemporalObject + attr_accessor :parent + + def initialize + @parent = nil + end + end + + class SOAPUnknown < SOAPTemporalObject + def initialize(handler, elename) + super() + @handler = handler + @elename = elename + end + + def as_struct + o = SOAPStruct.decode(@elename, XSD::AnyTypeName) + o.parent = @parent + @handler.decode_parent(@parent, o) + o + end + + def as_string + o = SOAPString.decode(@elename) + o.parent = @parent + @handler.decode_parent(@parent, o) + o + end + + def as_nil + o = SOAPNil.decode(@elename) + o.parent = @parent + @handler.decode_parent(@parent, o) + o + end + end + + def decode_tag(ns, elename, attrs, parent) + # ToDo: check if @textbuf is empty... + @textbuf = '' + o = SOAPUnknown.new(self, elename) + o.parent = parent + o + end + + def decode_tag_end(ns, node) + o = node.node + if o.is_a?(SOAPUnknown) + newnode = if /\A\s*\z/ =~ @textbuf + o.as_struct + else + o.as_string + end + node.replace_node(newnode) + o = node.node + end + + decode_textbuf(o) + @textbuf = '' + end + + def decode_text(ns, text) + # @textbuf is set at decode_tag_end. + @textbuf << text + end + + def decode_prologue + end + + def decode_epilogue + end + + def decode_parent(parent, node) + case parent.node + when SOAPUnknown + newparent = parent.node.as_struct + node.parent = newparent + parent.replace_node(newparent) + decode_parent(parent, node) + + when SOAPStruct + parent.node.add(node.name, node) + + when SOAPArray + if node.position + parent.node[*(decode_arypos(node.position))] = node + parent.node.sparse = true + else + parent.node.add(node) + end + + when SOAPBasetype + raise EncodingStyleError.new("SOAP base type must not have a child.") + + else + # SOAPUnknown does not have parent. + # raise EncodingStyleError.new("Illegal parent: #{ parent }.") + end + end + +private + + def decode_textbuf(node) + if node.is_a?(XSD::XSDString) + if @charset + node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset)) + else + node.set(@textbuf) + end + else + # Nothing to do... + end + end +end + +LiteralHandler.new + + +end +end diff --git a/lib/soap/encodingstyle/soapHandler.rb b/lib/soap/encodingstyle/soapHandler.rb new file mode 100644 index 0000000000..b1b5072e49 --- /dev/null +++ b/lib/soap/encodingstyle/soapHandler.rb @@ -0,0 +1,548 @@ +=begin +SOAP4R - SOAP EncodingStyle handler library +Copyright (C) 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 + + +require 'soap/encodingstyle/handler' + + +module SOAP +module EncodingStyle + + +class SOAPHandler < Handler + Namespace = SOAP::EncodingNamespace + add_handler + + def initialize(charset = nil) + super(charset) + @refpool = [] + @idpool = [] + @textbuf = '' + @is_first_top_ele = true + end + + + ### + ## encode interface. + # + def encode_data(buf, ns, qualified, data, parent, indent = '') + attrs = encode_attrs(ns, qualified, data, parent) + + if parent && parent.is_a?(SOAPArray) && parent.position + attrs[ns.name(AttrPositionName)] = '[' << parent.position.join(',') << ']' + end + + name = nil + if qualified and data.elename.namespace + SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace) + name = ns.name(data.elename) + else + name = data.elename.name + end + + if data.respond_to?(:encode) + SOAPGenerator.encode_tag(buf, name, attrs, indent) + return data.encode(buf, ns, attrs, indent) + end + + case data + when SOAPReference + attrs['href'] = '#' << data.refid + SOAPGenerator.encode_tag(buf, name, attrs, indent) + when SOAPRawString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << data.to_s + when XSD::XSDString + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(@charset ? + XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s) + when XSD::XSDAnySimpleType + SOAPGenerator.encode_tag(buf, name, attrs, indent) + buf << SOAPGenerator.encode_str(data.to_s) + when SOAPStruct + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.each do |key, value| + yield(value, false) + end + when SOAPArray + SOAPGenerator.encode_tag(buf, name, attrs, indent) + data.traverse do |child, *rank| + data.position = data.sparse ? rank : nil + yield(child, false) + end + else + raise EncodingStyleError.new( + "Unknown object:#{ data } in this encodingStyle.") + end + end + + def encode_data_end(buf, ns, qualified, data, parent, indent = '') + name = if qualified and data.elename.namespace + ns.name(data.elename) + else + data.elename.name + end + cr = data.is_a?(SOAPCompoundtype) + SOAPGenerator.encode_tag_end(buf, name, indent, cr) + end + + + ### + ## decode interface. + # + class SOAPTemporalObject + attr_accessor :parent + attr_accessor :position + attr_accessor :id + attr_accessor :root + + def initialize + @parent = nil + @position = nil + @id = nil + @root = nil + end + end + + class SOAPUnknown < SOAPTemporalObject + attr_reader :type + attr_accessor :definedtype + attr_reader :extraattr + + def initialize(handler, elename, type, extraattr) + super() + @handler = handler + @elename = elename + @type = type + @extraattr = extraattr + @definedtype = nil + end + + def as_struct + o = SOAPStruct.decode(@elename, @type) + o.id = @id + o.root = @root + o.parent = @parent + o.position = @position + o.extraattr.update(@extraattr) + @handler.decode_parent(@parent, o) + o + end + + def as_string + o = SOAPString.decode(@elename) + o.id = @id + o.root = @root + o.parent = @parent + o.position = @position + o.extraattr.update(@extraattr) + @handler.decode_parent(@parent, o) + o + end + + def as_nil + o = SOAPNil.decode(@elename) + o.id = @id + o.root = @root + o.parent = @parent + o.position = @position + o.extraattr.update(@extraattr) + @handler.decode_parent(@parent, o) + o + end + end + + def decode_tag(ns, elename, attrs, parent) + # ToDo: check if @textbuf is empty... + @textbuf = '' + is_nil, type, arytype, root, offset, position, href, id, extraattr = + decode_attrs(ns, attrs) + o = nil + if is_nil + o = SOAPNil.decode(elename) + elsif href + o = SOAPReference.decode(elename, href) + @refpool << o + elsif @decode_typemap && + (parent.node.class != SOAPBody || @is_first_top_ele) + # multi-ref element should be parsed by decode_tag_by_type. + @is_first_top_ele = false + o = decode_tag_by_wsdl(ns, elename, type, parent.node, arytype, extraattr) + else + o = decode_tag_by_type(ns, elename, type, parent.node, arytype, extraattr) + end + + if o.is_a?(SOAPArray) + if offset + o.offset = decode_arypos(offset) + o.sparse = true + else + o.sparse = false + end + end + + o.parent = parent + o.id = id + o.root = root + o.position = position + + unless o.is_a?(SOAPTemporalObject) + @idpool << o if o.id + decode_parent(parent, o) + end + o + end + + def decode_tag_end(ns, node) + o = node.node + if o.is_a?(SOAPUnknown) + newnode = if /\A\s*\z/ =~ @textbuf + o.as_struct + else + o.as_string + end + if newnode.id + @idpool << newnode + end + node.replace_node(newnode) + o = node.node + end + if o.is_a?(SOAPCompoundtype) + o.definedtype = nil + end + + decode_textbuf(o) + @textbuf = '' + end + + def decode_text(ns, text) + # @textbuf is set at decode_tag_end. + @textbuf << text + end + + def decode_prologue + @refpool.clear + @idpool.clear + @is_first_top_ele = true + end + + def decode_epilogue + decode_resolve_id + end + + def decode_parent(parent, node) + case parent.node + when SOAPUnknown + newparent = parent.node.as_struct + node.parent = newparent + if newparent.id + @idpool << newparent + end + parent.replace_node(newparent) + decode_parent(parent, node) + + when SOAPStruct + parent.node.add(node.elename.name, node) + node.parent = parent.node + + when SOAPArray + if node.position + parent.node[*(decode_arypos(node.position))] = node + parent.node.sparse = true + else + parent.node.add(node) + end + node.parent = parent.node + + when SOAPBasetype + raise EncodingStyleError.new("SOAP base type must not have a child.") + + else + raise EncodingStyleError.new("Illegal parent: #{ parent.node }.") + end + end + +private + + def content_ranksize(typename) + typename.scan(/\[[\d,]*\]$/)[0] + end + + def content_typename(typename) + typename.sub(/\[,*\]$/, '') + end + + def create_arytype(ns, data) + XSD::QName.new(data.arytype.namespace, + content_typename(data.arytype.name) << '[' << data.size.join(',') << ']') + end + + def encode_attrs(ns, qualified, data, parent) + return {} if data.is_a?(SOAPReference) + attrs = {} + + if !parent || parent.encodingstyle != EncodingNamespace + if @generate_explicit_type + SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace) + SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace) + attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace + end + data.encodingstyle = EncodingNamespace + end + + if data.is_a?(SOAPNil) + attrs[ns.name(XSD::AttrNilName)] = XSD::NilValue + elsif @generate_explicit_type + if data.type.namespace + SOAPGenerator.assign_ns(attrs, ns, data.type.namespace) + end + if data.is_a?(SOAPArray) + if data.arytype.namespace + SOAPGenerator.assign_ns(attrs, ns, data.arytype.namespace) + end + attrs[ns.name(AttrArrayTypeName)] = ns.name(create_arytype(ns, data)) + if data.type.name + attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type) + end + elsif parent && parent.is_a?(SOAPArray) && (parent.arytype == data.type) + # No need to add. + elsif !data.type.namespace + # No need to add. + else + attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type) + end + end + + data.extraattr.each do |key, value| + SOAPGenerator.assign_ns(attrs, ns, key.namespace) + attrs[ns.name(key)] = value # ns.name(value) ? + end + if data.id + attrs['id'] = data.id + end + attrs + end + + def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr) + if parent.class == SOAPBody + # Unqualified name is allowed here. + type = @decode_typemap[elename] || @decode_typemap.find_name(elename.name) + unless type + raise EncodingStyleError.new("Unknown operation '#{ elename }'.") + end + o = SOAPStruct.new(elename) + o.definedtype = type + return o + end + + if parent.type == XSD::AnyTypeName + return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, + extraattr) + end + + # parent.definedtype is nil means the parent is SOAPUnknown. SOAPUnknown is + # generated by decode_tag_by_type when its type is anyType. + parenttype = parent.definedtype || @decode_typemap[parent.type] + unless parenttype + raise EncodingStyleError.new("Unknown type '#{ parent.type }'.") + end + typename = parenttype.child_type(elename) + if typename + if (klass = TypeMap[typename]) + return klass.decode(elename) + elsif typename == XSD::AnyTypeName + return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, + extraattr) + end + end + + type = if typename + @decode_typemap[typename] + else + parenttype.child_defined_complextype(elename) + end + unless type + raise EncodingStyleError.new("Unknown type '#{ typename }'.") + end + + case type.compoundtype + when :TYPE_STRUCT + o = SOAPStruct.decode(elename, typename) + o.definedtype = type + return o + when :TYPE_ARRAY + expected_arytype = type.find_arytype + actual_arytype = if arytypestr + XSD::QName.new(expected_arytype.namespace, + content_typename(expected_arytype.name) << + content_ranksize(arytypestr)) + else + expected_arytype + end + o = SOAPArray.decode(elename, typename, actual_arytype) + o.definedtype = type + return o + end + return nil + end + + def decode_tag_by_type(ns, elename, typestr, parent, arytypestr, extraattr) + if arytypestr + type = typestr ? ns.parse(typestr) : ValueArrayName + node = SOAPArray.decode(elename, type, ns.parse(arytypestr)) + node.extraattr.update(extraattr) + return node + end + + type = nil + if typestr + type = ns.parse(typestr) + elsif parent.is_a?(SOAPArray) + type = parent.arytype + else + # Since it's in dynamic(without any type) encoding process, + # assumes entity as its type itself. + # => type Array in SOAP-ENC. + # => type Country in foo. + type = elename + end + + if (klass = TypeMap[type]) + klass.decode(elename) + else + # Unknown type... Struct or String + SOAPUnknown.new(self, elename, type, extraattr) + end + end + + def decode_textbuf(node) + case node + when XSD::XSDHexBinary, XSD::XSDBase64Binary + node.set_encoded(@textbuf) + when XSD::XSDString + if @charset + node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset)) + else + node.set(@textbuf) + end + when SOAPNil + # Nothing to do. + when SOAPBasetype + node.set(@textbuf) + else + # Nothing to do... + end + end + + NilLiteralMap = { + 'true' => true, + '1' => true, + 'false' => false, + '0' => false + } + RootLiteralMap = { + '1' => 1, + '0' => 0 + } + def decode_attrs(ns, attrs) + is_nil = false + type = nil + arytype = nil + root = nil + offset = nil + position = nil + href = nil + id = nil + extraattr = {} + + attrs.each do |key, value| + qname = ns.parse(key) + case qname.namespace + when XSD::InstanceNamespace + case qname.name + when XSD::NilLiteral + is_nil = NilLiteralMap[value] or + raise EncodingStyleError.new("Cannot accept attribute value: #{ value } as the value of xsi:#{ XSD::NilLiteral } (expected 'true', 'false', '1', or '0').") + next + when XSD::AttrType + type = value + next + end + when EncodingNamespace + case qname.name + when AttrArrayType + arytype = value + next + when AttrRoot + root = RootLiteralMap[value] or + raise EncodingStyleError.new( + "Illegal root attribute value: #{ value }.") + next + when AttrOffset + offset = value + next + when AttrPosition + position = value + next + end + end + if key == 'href' + href = value + next + elsif key == 'id' + id = value + next + end + extraattr[qname] = value + end + + return is_nil, type, arytype, root, offset, position, href, id, extraattr + end + + def decode_arypos(position) + /^\[(.+)\]$/ =~ position + $1.split(',').collect { |s| s.to_i } + end + + def decode_resolve_id + count = @refpool.length # To avoid infinite loop + while !@refpool.empty? && count > 0 + @refpool = @refpool.find_all { |ref| + o = @idpool.find { |item| + ('#' << item.id == ref.refid) + } + unless o + raise EncodingStyleError.new("Unresolved reference: #{ ref.refid }.") + end + if o.is_a?(SOAPReference) + true + else + ref.__setobj__(o) + false + end + } + count -= 1 + end + end +end + +SOAPHandler.new + + +end +end -- cgit v1.2.3