=begin
SOAP4R - SOAP elements library
Copyright (C) 2000, 2001 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/baseData'


module SOAP


###
## SOAP elements
#
class SOAPFault < SOAPStruct
  include SOAPCompoundtype

public

  def faultcode
    self[ 'faultcode' ]
  end

  def faultstring
    self[ 'faultstring' ]
  end

  def faultactor
    self[ 'faultactor' ]
  end

  def detail
    self[ 'detail' ]
  end

  def faultcode=( rhs )
    self[ 'faultcode' ] = rhs
  end

  def faultstring=( rhs )
    self[ 'faultstring' ] = rhs
  end

  def faultactor=( rhs )
    self[ 'faultactor' ] = rhs
  end

  def detail=( rhs )
    self[ 'detail' ] = rhs
  end

  def initialize( faultCode = nil, faultString = nil, faultActor = nil, detail = nil )
    super( self.type.to_s )
    @namespace = EnvelopeNamespace
    @name = 'Fault'
    @encodingStyle = EncodingNamespace

    if faultCode
      self.faultcode = faultCode
      self.faultstring = faultString
      self.faultactor = faultActor
      self.detail = detail
      self.faultcode.name = 'faultcode' if self.faultcode
      self.faultstring.name = 'faultstring' if self.faultstring
      self.faultactor.name = 'faultactor' if self.faultactor
      self.detail.name = 'detail' if self.detail
    end
  end

  def encode( buf, ns )
    attrs = {}
    if !ns.assigned?( EnvelopeNamespace )
      tag = ns.assign( EnvelopeNamespace )
      attrs[ 'xmlns:' << tag ] = EnvelopeNamespace
    end
    if !ns.assigned?( EncodingNamespace )
      tag = ns.assign( EncodingNamespace )
      attrs[ 'xmlns:' << tag ] = EncodingNamespace
    end
    attrs[ ns.name( EnvelopeNamespace, AttrEncodingStyle ) ] =
      EncodingNamespace
    name = ns.name( @namespace, @name )
    SOAPGenerator.encodeTag( buf, name, attrs, true )
    yield( self.faultcode, false )
    yield( self.faultstring, false)
    yield( self.faultactor, false )
    yield( self.detail, false ) if self.detail
    SOAPGenerator.encodeTagEnd( buf, name, true )
  end
end


class SOAPBody < SOAPStruct

public

  def initialize( data = nil, isFault = false )
    super( self.type.to_s )
    @namespace = EnvelopeNamespace
    @name = 'Body'
    @encodingStyle = nil
    @data = []
    @data << data if data
    @isFault = isFault
  end

  def encode( buf, ns )
    name = ns.name( @namespace, @name )
    SOAPGenerator.encodeTag( buf, name, nil, true )
    if @isFault
      yield( @data, true )
    else
      @data.each do | data |
	yield( data, true )
      end
    end
    SOAPGenerator.encodeTagEnd( buf, name, true )
  end

  def rootNode
    @data.each do | node |
      if node.root == 1
	return node
      end
    end
    # No specified root...
    @data.each do | node |
      if node.root != 0
	return node
      end
    end

    raise SOAPParser::FormatDecodeError.new( 'No root element.' )
  end
end


class SOAPHeaderItem < NSDBase
  include SOAPCompoundtype

public

  attr_accessor :content
  attr_accessor :mustUnderstand
  attr_accessor :encodingStyle

  def initialize( content, mustUnderstand = true, encodingStyle = nil )
    super( self.type.to_s )
    @content = content
    @mustUnderstand = mustUnderstand
    @encodingStyle = encodingStyle || LiteralNamespace
  end

  def encode( buf, ns )
    @content.attr[ ns.name( EnvelopeNamespace, AttrMustUnderstand ) ] =
      ( @mustUnderstand ? '1' : '0' )
    if @encodingStyle
      @content.attr[ ns.name( EnvelopeNamespace, AttrEncodingStyle ) ] =
      	@encodingStyle
    end
    @content.encodingStyle = @encodingStyle if !@content.encodingStyle
    yield( @content, true )
  end
end


class SOAPHeader < SOAPArray
  def initialize()
    super( self.type.to_s, 1 )	# rank == 1
    @namespace = EnvelopeNamespace
    @name = 'Header'
    @encodingStyle = nil
  end

  def encode( buf, ns )
    name = ns.name( @namespace, @name )
    SOAPGenerator.encodeTag( buf, name, nil, true )
    @data.each do | data |
      yield( data, true )
    end
    SOAPGenerator.encodeTagEnd( buf, name, true )
  end

  def length
    @data.length
  end
end


class SOAPEnvelope < NSDBase
  include SOAPCompoundtype

  attr_accessor :header
  attr_accessor :body
  attr_reader :refPool
  attr_reader :idPool

  def initialize( initHeader = nil, initBody = nil )
    super( self.type.to_s )
    @namespace = EnvelopeNamespace
    @name = 'Envelope'
    @encodingStyle = nil
    @header = initHeader
    @body = initBody
    @refPool = []
    @idPool = []
  end

  def encode( buf, ns )
    attrs = {}
    tag = ns.assign( EnvelopeNamespace, SOAPNamespaceTag )
    attrs[ 'xmlns:' << tag ] = EnvelopeNamespace
    tag = ns.assign( XSD::Namespace, XSDNamespaceTag )
    attrs[ 'xmlns:' << tag ] = XSD::Namespace
    tag = ns.assign( XSD::InstanceNamespace, XSINamespaceTag )
    attrs[ 'xmlns:' << tag ] = XSD::InstanceNamespace

    name = ns.name( @namespace, @name )
    SOAPGenerator.encodeTag( buf, name, attrs, true )

    yield( @header, true ) if @header and @header.length > 0
    yield( @body, true )

    SOAPGenerator.encodeTagEnd( buf, name, true )
  end
end


end
