mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
8c2fb77787
commit
db9445103c
145 changed files with 20938 additions and 0 deletions
232
lib/soap/encodingstyle/aspDotNetHandler.rb
Normal file
232
lib/soap/encodingstyle/aspDotNetHandler.rb
Normal file
|
|
@ -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
|
||||
111
lib/soap/encodingstyle/handler.rb
Normal file
111
lib/soap/encodingstyle/handler.rb
Normal file
|
|
@ -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
|
||||
218
lib/soap/encodingstyle/literalHandler.rb
Normal file
218
lib/soap/encodingstyle/literalHandler.rb
Normal file
|
|
@ -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
|
||||
548
lib/soap/encodingstyle/soapHandler.rb
Normal file
548
lib/soap/encodingstyle/soapHandler.rb
Normal file
|
|
@ -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.
|
||||
# <SOAP-ENC:Array ...> => type Array in SOAP-ENC.
|
||||
# <Country xmlns="foo"> => 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue