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 20
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 211
def decode_epilogue
  decode_resolve_id
end
decode_parent(parent, node) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 215
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 205
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 145
def decode_tag(ns, elename, attrs, parent)
  @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
    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
decode_tag_end(ns, node) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 182
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
  decode_textbuf(o)
  # unlink definedtype
  o.definedtype = nil
end
decode_text(ns, text) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 201
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 32
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 73
def encode_data_end(generator, ns, data, parent)
  name = generator.encode_name_end(ns, data)
  cr = data.is_a?(SOAPCompoundtype)
  generator.encode_tag_end(name, cr)
end

Private Instance Methods

content_ranksize(typename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 244
def content_ranksize(typename)
  typename.scan(/\[[\d,]*\]$/)[0]
end
content_typename(typename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 248
def content_typename(typename)
  typename.sub(/\[,*\]$/, '')
end
create_arytype(ns, data) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 252
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 549
def decode_arypos(position)
  /^\[(.+)\]$/ =~ position
  $1.split(',').collect { |s| s.to_i }
end
decode_attr_value(ns, qname, value) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 539
def decode_attr_value(ns, qname, value)
  if /\A#/ =~ value
    o = SOAPReference.decode(nil, value)
    @refpool << o
    o
  else
    value
  end
end
decode_attrs(ns, attrs) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 483
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
    qname = ns.parse_local(key)
    extraattr[qname] = decode_attr_value(ns, qname, value)
  end

  return is_nil, type, arytype, root, offset, position, href, id, extraattr
end
decode_basetype(klass, elename) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 380
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 390
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 384
def decode_defined_simpletype(elename, typename, typedef, arytypestr)
  o = decode_basetype(TypeMap[typedef.base], elename)
  o.definedtype = typedef
  o
end
decode_definedtype(elename, typename, typedef, arytypestr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 369
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_resolve_id() click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 554
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, extraattr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 420
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])
    node = decode_basetype(klass, elename)
    node.extraattr.update(extraattr)
    return node
  end

  # Unknown type... Struct or String
  SOAPUnknown.new(self, elename, type, extraattr)
end
decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 313
def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
  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.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,
      extraattr)
  end

  if parent.type == XSD::AnyTypeName
    return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
      extraattr)
  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,
      extraattr)
  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,
      extraattr)
  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) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 451
def decode_textbuf(node)
  case node
  when XSD::XSDHexBinary, XSD::XSDBase64Binary
    node.set_encoded(@textbuf)
  when XSD::XSDString
    if @charset
      @textbuf = XSD::Charset.encoding_from_xml(@textbuf, @charset)
    end
    if node.definedtype
      node.definedtype.check_lexical_format(@textbuf)
    end
    node.set(@textbuf)
  when SOAPNil
    # Nothing to do.
  when SOAPBasetype
    node.set(@textbuf)
  else
    # Nothing to do...
  end
  @textbuf = ''
end
encode_attr_value(generator, ns, qname, value) click to toggle source
# File lib/soap/encodingstyle/soapHandler.rb, line 303
def encode_attr_value(generator, ns, qname, value)
  if value.is_a?(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 257
def encode_attrs(generator, ns, data, parent)
  attrs = {}
  return attrs if data.is_a?(SOAPReference)

  if !parent || parent.encodingstyle != EncodingNamespace
    if @generate_explicit_type
      SOAPGenerator.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
      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
      SOAPGenerator.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|
    SOAPGenerator.assign_ns(attrs, ns, key.namespace)
    attrs[ns.name(key)] = encode_attr_value(generator, ns, key, value)
  end
  if data.id
    attrs['id'] = data.id
  end
  attrs
end