class SOAP::EncodingStyle::SOAPHandler

Constants

Namespace
NilLiteralMap
RootLiteralMap

Public Class Methods

new(charset = nil) click to toggle source
Calls superclass method SOAP::EncodingStyle::Handler::new
# File lib/soap/encodingstyle/soapHandler.rb, line 21
def initialize(charset = nil)
  super(charset)
  @refpool = []
  @idpool = []
  @textbuf = []
  @is_first_top_ele = true
end

Public Instance Methods

decode_epilogue() click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 220
def decode_epilogue
  decode_resolve_id
end
decode_parent(parent, node) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 224
def decode_parent(parent, node)
  return unless 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
  else
    raise EncodingStyleError.new("illegal parent: #{parent.node}")
  end
end
decode_prologue() click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 214
def decode_prologue
  @refpool.clear
  @idpool.clear
  @is_first_top_ele = true
end
decode_tag(ns, elename, attrs, parent) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 152
def decode_tag(ns, elename, attrs, parent)
  @textbuf.clear
  is_nil, type, arytype, root, offset, position, href, id =
    extract_attrs(ns, attrs)
  o = nil
  if is_nil
    o = SOAPNil.decode(elename)
  elsif href
    o = SOAPReference.decode(elename, href)
    @refpool << o
  elsif @decode_typemap
    o = decode_tag_by_wsdl(ns, elename, type, parent.node, arytype, attrs)
  else
    o = decode_tag_by_type(ns, elename, type, parent.node, arytype, attrs)
  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
decode_tag_end(ns, node) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 189
def decode_tag_end(ns, node)
  textbufstr = @textbuf.join
  @textbuf.clear
  o = node.node
  if o.is_a?(SOAPUnknown)
    newnode = if /\A\s*\z/ =~ textbufstr
      o.as_struct
    else
      o.as_string
    end
    if newnode.id
      @idpool << newnode
    end
    node.replace_node(newnode)
    o = node.node
  end
  decode_textbuf(o, textbufstr)
  # unlink definedtype
  o.definedtype = nil
end
decode_text(ns, text) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 210
def decode_text(ns, text)
  @textbuf << text
end
encode_data(generator, ns, data, parent) click to toggle source

encode interface.

# File lib/soap/encodingstyle/soapHandler.rb, line 33
def encode_data(generator, ns, data, parent)
  attrs = encode_attrs(generator, ns, data, parent)
  if parent && parent.is_a?(SOAPArray) && parent.position
    attrs[ns.name(AttrPositionName)] = "[#{parent.position.join(',')}]"
  end
  name = generator.encode_name(ns, data, attrs)
  case data
  when SOAPReference
    attrs['href'] = data.refidstr
    generator.encode_tag(name, attrs)
  when SOAPExternalReference
    data.referred
    attrs['href'] = data.refidstr
    generator.encode_tag(name, attrs)
  when SOAPRawString
    generator.encode_tag(name, attrs)
    generator.encode_rawstring(data.to_s)
  when XSD::XSDString
    generator.encode_tag(name, attrs)
    generator.encode_string(@charset ?
      XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
  when XSD::XSDAnySimpleType
    generator.encode_tag(name, attrs)
    generator.encode_string(data.to_s)
  when SOAPStruct
    generator.encode_tag(name, attrs)
    data.each do |key, value|
      generator.encode_child(ns, value, data)
    end
  when SOAPArray
    generator.encode_tag(name, attrs)
    data.traverse do |child, *rank|
      data.position = data.sparse ? rank : nil
      generator.encode_child(ns, child, data)
    end
  else
    raise EncodingStyleError.new(
      "unknown object:#{data} in this encodingStyle")
  end
end
encode_data_end(generator, ns, data, parent) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 74
def encode_data_end(generator, ns, data, parent)
  name = generator.encode_name_end(ns, data)
  cr = (data.is_a?(SOAPCompoundtype) and data.have_member)
  generator.encode_tag_end(name, cr)
end

Private Instance Methods

content_ranksize(typename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 253
def content_ranksize(typename)
  typename.scan(/\[[\d,]*\]$/)[0]
end
content_typename(typename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 257
def content_typename(typename)
  typename.sub(/\[,*\]$/, '')
end
create_arytype(ns, data) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 261
def create_arytype(ns, data)
  XSD::QName.new(data.arytype.namespace,
    content_typename(data.arytype.name) + "[#{data.size.join(',')}]")
end
decode_arypos(position) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 526
def decode_arypos(position)
  /^\[(.+)\]$/ =~ position
  $1.split(',').collect { |s| s.to_i }
end
decode_basetype(klass, elename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 394
def decode_basetype(klass, elename)
  klass.decode(elename)
end
decode_defined_complextype(elename, typename, typedef, arytypestr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 408
def decode_defined_complextype(elename, typename, typedef, arytypestr)
  case typedef.compoundtype
  when :TYPE_STRUCT, :TYPE_MAP
    o = SOAPStruct.decode(elename, typename)
    o.definedtype = typedef
    return o
  when :TYPE_ARRAY
    expected_arytype = typedef.find_arytype
    if arytypestr
      actual_arytype = XSD::QName.new(expected_arytype.namespace,
        content_typename(expected_arytype.name) <<
        content_ranksize(arytypestr))
      o = SOAPArray.decode(elename, typename, actual_arytype)
    else
      o = SOAPArray.new(typename, 1, expected_arytype)
      o.elename = elename
    end
    o.definedtype = typedef
    return o
  when :TYPE_EMPTY
    o = SOAPNil.decode(elename)
    o.definedtype = typedef
    return o
  else
    raise RuntimeError.new(
      "Unknown kind of complexType: #{typedef.compoundtype}")
  end
  nil
end
decode_defined_simpletype(elename, typename, typedef, arytypestr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 398
def decode_defined_simpletype(elename, typename, typedef, arytypestr)
  if typedef.base
    o = decode_basetype(TypeMap[typedef.base], elename)
    o.definedtype = typedef
    o
  else
    raise RuntimeError.new("unsupported simpleType: #{typedef}")
  end
end
decode_definedtype(elename, typename, typedef, arytypestr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 383
def decode_definedtype(elename, typename, typedef, arytypestr)
  unless typedef
    raise EncodingStyleError.new("unknown type '#{typename}'")
  end
  if typedef.is_a?(::WSDL::XMLSchema::SimpleType)
    decode_defined_simpletype(elename, typename, typedef, arytypestr)
  else
    decode_defined_complextype(elename, typename, typedef, arytypestr)
  end
end
decode_ref_value(ns, value) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 516
def decode_ref_value(ns, value)
  if /\A#/ =~ value
    o = SOAPReference.decode(nil, value)
    @refpool << o
    o
  else
    value
  end
end
decode_resolve_id() click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 531
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
      }
      if o.is_a?(SOAPReference)
        true # link of link.
      elsif o
        ref.__setobj__(o)
        false
      elsif o = ref.rootnode.external_content[ref.refid]
        ref.__setobj__(o)
        false
      else
        raise EncodingStyleError.new("unresolved reference: #{ref.refid}")
      end
    }
    count -= 1
  end
end
decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 438
def decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs)
  if arytypestr
    type = typestr ? ns.parse(typestr) : ValueArrayName
    node = SOAPArray.decode(elename, type, ns.parse(arytypestr))
    node.extraattr.update(attrs)
    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]
    node = decode_basetype(klass, elename)
    node.extraattr.update(attrs)
    return node
  end

  # Unknown type... Struct or String
  SOAPUnknown.new(self, elename, type, attrs)
end
decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, attrs) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 330
def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, attrs)
  o = nil
  if parent.class == SOAPBody
    # root element: should branch by root attribute?
    if @is_first_top_ele
      # Unqualified name is allowed here.
      @is_first_top_ele = false
      type = @decode_typemap[elename] ||
        @decode_typemap.find_name(elename.name)
      if type
        o = SOAPStruct.new(elename)
        o.elename = elename
        o.definedtype = type
        return o
      end
    end
    # multi-ref element.
    if typestr
      typename = ns.parse(typestr)
      typedef = @decode_typemap[typename]
      if typedef
        return decode_definedtype(elename, typename, typedef, arytypestr)
      end
    end
    return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs)
  end

  if parent.type == XSD::AnyTypeName
    return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs)
  end

  # parent.definedtype == 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
    return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs)
  end

  definedtype_name = parenttype.child_type(elename)
  if definedtype_name and (klass = TypeMap[definedtype_name])
    return decode_basetype(klass, elename)
  elsif definedtype_name == XSD::AnyTypeName
    return decode_tag_by_type(ns, elename, typestr, parent, arytypestr, attrs)
  end

  if definedtype_name
    typedef = @decode_typemap[definedtype_name]
  else
    typedef = parenttype.child_defined_complextype(elename)
  end
  decode_definedtype(elename, definedtype_name, typedef, arytypestr)
end
decode_textbuf(node, textbufstr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 469
def decode_textbuf(node, textbufstr)
  case node
  when XSD::XSDHexBinary, XSD::XSDBase64Binary
    node.set_encoded(textbufstr)
  when XSD::XSDString
    if @charset
      textbufstr = XSD::Charset.encoding_from_xml(textbufstr, @charset)
    end
    if node.definedtype
      node.definedtype.check_lexical_format(textbufstr)
    end
    node.set(textbufstr)
  when SOAPNil
    # Nothing to do.
  when SOAPBasetype
    node.set(textbufstr)
  else
    # Nothing to do...
  end
end
encode_attr_value(generator, ns, qname, value) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 319
def encode_attr_value(generator, ns, qname, value)
  case value
  when SOAPType
    ref = SOAPReference.new(value)
    generator.add_reftarget(qname.name, value)
    ref.refidstr
  else
    value.to_s
  end
end
encode_attrs(generator, ns, data, parent) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 266
def encode_attrs(generator, ns, data, parent)
  attrs = {}
  return attrs if data.is_a?(SOAPReference)

  if !parent || parent.encodingstyle != EncodingNamespace
    if @generate_explicit_type
      Generator.assign_ns(attrs, ns, EnvelopeNamespace)
      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
      Generator.assign_ns(attrs, ns, data.type.namespace)
    end
    if data.is_a?(SOAPArray)
      if data.arytype.namespace
        Generator.assign_ns(attrs, ns, data.arytype.namespace)
      end
      Generator.assign_ns(attrs, ns, EncodingNamespace)
      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|
    keytag = key
    if key.is_a?(XSD::QName)
      keytag = encode_attr_key(attrs, ns, key)
    end
    if value.is_a?(XSD::QName)
      value = encode_qname(attrs, ns, value)
    else
      value = encode_attr_value(generator, ns, key, value)
    end
    attrs[keytag] = value
  end
  if data.id
    attrs['id'] = data.id
  end
  attrs
end
extract_attrs(ns, attrs) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 500
def extract_attrs(ns, attrs)
  is_nil = NilLiteralMap[attrs[XSD::AttrNilName]]
  type = attrs[XSD::AttrTypeName]
  arytype = attrs[AttrArrayTypeName]
  root = attrs[AttrRootName]
  offset = attrs[AttrOffsetName]
  position = attrs[AttrPositionName]
  href = attrs[AttrHrefName]
  id = attrs[AttrIdName]
  if attrs.key?(Mapping::RubyIVarName)
    attrs[Mapping::RubyIVarName] =
      decode_ref_value(ns, attrs[Mapping::RubyIVarName])
  end
  return is_nil, type, arytype, root, offset, position, href, id
end