=head1 NAME

XML::Compile::SOAP - base-class for SOAP implementations

=head1 INHERITANCE

 XML::Compile::SOAP is extended by
   XML::Compile::SOAP::SOAP11
   XML::Compile::SOAP::SOAP12

=head1 SYNOPSIS

 use XML::Compile::SOAP::SOAP11;
 use XML::Compile::Util qw/pack_type/;

 # There are quite some differences between SOAP1.1 and 1.2
 my $soap   = XML::Compile::SOAP::SOAP11->new;

 # load extra schemas always explicitly
 $soap->schemas->importDefinitions(...);

 my $h1type = pack_type $myns, $sometype;
 my $b1type = "{$myns}$othertype";  # less clean

 # Request, answer, and call usually created via WSDL
 my $request = $soap->compile
   ('CLIENT', 'INPUT'               # client to server
   , header   => [ h1 => $h1type ]
   , body     => [ b1 => $b1type ]
   , destination    => [ h1 => 'NEXT' ]
   , mustUnderstand => 'h1'
   );

 my $answer = $soap->compile
   ('CLIENT', 'OUTPUT'              # server to client
   , header   => [ h2 => $h2type ]
   , body     => [ b2 => $b2type ]
   , headerfault => [ ... ]
   , fault    => [ ... ]
   );

 my $call  = $soap->call($request, $answer, address => $endpoint);

 my $result = $call->(h1 => ..., b1 => ...);
 print $result->{h2}->{...};
 print $result->{b2}->{...};

=head1 DESCRIPTION

**WARNING** Implementation not finished: not usable!!

This module handles the SOAP protocol.  The first implementation is
SOAP1.1 (F<http://www.w3.org/TR/2000/NOTE-SOAP-20000508/>), which is still
most often used.  The SOAP1.2 definition (F<http://www.w3.org/TR/soap12/>)
are different; this module tries to define a sufficiently
abstract interface to hide the protocol differences.

=head2 Limitations

On the moment, the following limitations exist:

=over 4

=item .

Only qualified header and body elements are supported.

=item .

Only document/literal use is supported, not XML-RPC.

=back

=head1 METHODS

=head2 Constructors

$obj-E<gt>B<new>(OPTIONS)

=over 4

 Option     --Default
 encoding_ns  <required>
 envelope_ns  <required>
 media_type   application/soap+xml
 schemas      created internally

. encoding_ns => URI

. envelope_ns => URI

. media_type => MIMETYPE

. schemas => C<XML::Compile::Schema> object

=over 4

Use this when you have already processed some schema definitions.  Otherwise,
you can add schemas later with C<< $soap->schames->importDefinitions() >>

=back

=back

=head2 Accessors

$obj-E<gt>B<encodingNS>

=over 4

=back

$obj-E<gt>B<envelopeNS>

=over 4

=back

$obj-E<gt>B<schemas>

=over 4

Returns the L<XML::Compile::Schema|XML::Compile::Schema> object which contains the
knowledge about the types.

=back

=head2 SOAPAction

$obj-E<gt>B<compile>(('CLIENT'|'SERVER'),('INPUT'|'OUTPUT'), OPTIONS)

=over 4

The payload is defined explicitly, where all headers and bodies are
specified as ARRAY containing key-value pairs (ENTRIES).  When you
have a WSDL file, these ENTRIES are generated automatically.

As role, you specify whether your application is a C<CLIENT> (creates
INPUT messages to the server, accepts OUTPUT messages), or a
C<SERVER> (accepting INPUT queries, producing OUTPUT messages).
The combination of the first and second parameter determine whether
an XML reader or XML writer is to be created.
NB: a C<CLIENT> C<INPUT> message is a message which is sent by
the client as input to the server, according the WSDL terminology
definition.

To make your life easy, the ENTRIES use a label (a free to choose key,
the I<part> in WSDL terminology), to ease relation of your data with
the type where it belongs to.  The type of an entry (the value) is
defines as an C<any> type in the schema and therefore you will need
to explicitly specify the type of the element to be processed.

 Option        --Default
 body            undef
 destination     []
 fault           []
 header          undef
 mustUnderstand  []
 role            ULTIMATE
 roles           []

. body => ENTRIES

. destination => ARRAY

=over 4

Writers only.  Indicate who the target of the header entry is.
By default, the end-point is the destination of each header element.

The ARRAY contains a LIST of key-value pairs, specifing an entry label
followed by an I<actor> (soap1.1) or I<role> (soap1.2) URI.  You may use
the predefined actors/roles, like 'NEXT'.  See L<roleAbbreviation()|XML::Compile::SOAP/"SOAPAction">.

=back

. fault => ENTRIES

=over 4

The SOAP1.1 and SOAP1.2 protocols define fault entries in the
answer.  Both have a location to add your own additional
information: the type(-processor) is to specified here, but the
returned information structure is larger and differs per SOAP
implementation.

=back

. header => ENTRIES

=over 4

ARRAY of PAIRS, defining a nice LABEL (free of choice but unique)
and an element reference.  The LABEL will appear in your code only, to
refer to the element in a simple way.

=back

. mustUnderstand => STRING|ARRAY-OF-STRING

=over 4

Writers only.  The specified header entry labels specify which elements
must be understood by the destination.  These elements will get the
C<mustUnderstand> attribute set to C<1> (soap1.1) or C<true> (soap1.2).

=back

. role => URI|ARRAY-OF-URI

=over 4

Readers only.
One or more URIs, specifying the role(s) you application has in the
process.  Only when your role contains C<ULTIMATE>, the body is
parsed.  Otherwise, the body is returned as uninterpreted XML tree.
You should not use the role C<NEXT>, because every intermediate
node is a C<NEXT>.

All understood headers are parsed when the C<actor> (soap1.1) or
C<role> (soap1.2) attribute address the specified URI.  When other
headers emerge which are not understood but carry the C<mustUnderstood>
attribute, an fault is returned automatically.  In that case, the
call to the compiled subroutine will return C<undef>.

=back

. roles => ARRAY-OF-URI

=over 4

Alternative for option C<role>

=back

=back

$obj-E<gt>B<direction>(ROLE, INOUT)

=over 4

Based on the ROLE of the application (C<CLIENT> or C<SERVER>) and the 
direction indication (C<INPUT> or C<OUTPUT> from the WSDL), this
returns whether a C<READER> or C<WRITER> needs to be generated.

=back

$obj-E<gt>B<roleAbbreviation>(STRING)

=over 4

Translates actor/role/destination abbreviations into URIs. Various
SOAP protocol versions have different pre-defined URIs, which can
be abbreviated for readibility.  Returns the unmodified STRING in
all other cases.

=back

=head1 DETAILS

=head2 Do it yourself, no WSDL

Does this all look too complicated?  It isn't that bad.  The following
example is used as test-case t/82soap11.t, directly taken from the SOAP11
specs section 1.3 example 1.

 # for simplification
 my $TestNS   = 'http://test-types';
 my $SchemaNS = 'http://www.w3.org/2001/XMLSchema';

First, the schema (hopefully someone else created for you, because they
can be quite hard to create correctly) is in file C<myschema.xsd>

 <schema targetNamespace="$TestNS"
   xmlns="$SchemaNS">

 <element name="GetLastTradePrice">
   <complexType>
      <all>
        <element name="symbol" type="string"/>
      </all>
   </complexType>
 </element>

 <element name="GetLastTradePriceResponse">
   <complexType>
      <all>
         <element name="price" type="float"/>
      </all>
   </complexType>
 </element>

 <element name="Transaction" type="int"/>
 </schema>

Ok, now the program you create the request:

 use XML::Compile::SOAP::SOAP11;
 use XML::Compile::Util  qw/pack_type/;

 my $soap   = XML::Compile::SOAP::SOAP11->new;
 $soap->schemas->importDefinitions('myschema.xsd');

 my $get_price = $soap->compile
  ( 'CLIENT', 'INPUT'
  , header => [ transaction => pack_type($TestNS, 'Transaction') ]
  , body =>   [ request => pack_type($TestNS, 'GetLastTradePrice') ]
  , mustUnderstand => 'transaction'
  , destination => [ 'transaction' => 'NEXT http://actor' ]
  );

C<INPUT> is used in the WSDL terminology, indicating this message is
an input message for the server.  This C<$get_price> is a WRITER.  Above
is done only once in the initialization phase of your program.

At run-time, you have to call the CODE reference with a
data-structure which is compatible with the schema structure.
(See L<XML::Compile::Schema::template()|XML::Compile::Schema/"Compilers"> if you have no clue how it should
look)  So: let's send this:

 # insert your data
 my %data_in =
   ( Header => {transaction => 5}
   , Body   => {request => {symbol => 'DIS'}}
   );

 # create a XML::LibXML tree
 my $xml  = $get_price->(\%data_in, 'UTF-8');
 print $xml->toString;

And the output is:

 <SOAP-ENV:Envelope
    xmlns:x0="http://test-types"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header>
     <x0:Transaction
       mustUnderstand="1"
       actor="http://schemas.xmlsoap.org/soap/actor/next http://actor">
         5
     </x0:Transaction>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
     <x0:GetLastTradePrice>
       <symbol>DIS</symbol>
     </x0:GetLastTradePrice>
   </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>

Some transport protocol will sent this data from the client to the
server.  See XML::Compile::SOAP::HTTP, as one example.

On the SOAP server side, we will parse the message.  The string C<$soap>
contains the XML.  The program looks like this:

 my $server = $soap->compile       # create once
  ( 'SERVER', 'INPUT'
  , header => [ transaction => pack_type($TestNS, 'Transaction') ]
  , body =>   [ request => pack_type($TestNS, 'GetLastTradePrice') ]
  );

 my $data_out = $server->($soap);  # call often

Now, the C<$data_out> reference on the server, is stucturally exactly 
equivalent to the C<%data_in> from the client.

=head1 DIAGNOSTICS

Error: an input message does not have faults

=over 4

=back

Error: headerfault does only exist in SOAP1.1

=over 4

=back

Error: message is INPUT or OUTPUT, not $inout

=over 4

=back

Error: option 'destination' only for writers

=over 4

=back

Error: option 'mustUnderstand' only for writers

=over 4

=back

Error: option 'role' only for readers

=over 4

=back

Error: option 'roles' only for readers

=over 4

=back

Error: role must be CLIENT or SERVER, not $role

=over 4

=back

=head1 SEE ALSO

This module is part of XML-Compile distribution version 0.51,
built on August 10, 2007. Website: F<http://perl.overmeer.net/xml-compile/>

=head1 LICENSE

Copyrights 2006-2007 by Mark Overmeer. For other contributors see ChangeLog.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://www.perl.com/perl/misc/Artistic.html>

