<?xml version="1.0" ?>
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" 
"dtd/kdex.dtd" [
 <!ENTITY kwsdl_compiler "<application>kwsdl_compiler</application>">
 <!ENTITY kappname "&kwsdl_compiler;">
 <!ENTITY package "kdepim">
 <!ENTITY % addindex "IGNORE">
 <!ENTITY % English "INCLUDE" > <!-- change language only here -->  
]>

<book lang="&language;">
<bookinfo>
<title>The &kwsdl_compiler; Handbook</title>
<authorgroup>
<author>
<firstname>Tobias</firstname>
<surname>Koenig</surname>
<affiliation>
<address><email>tokoe@kde.org</email></address>
</affiliation>
</author>
<author>
<firstname>Will</firstname>
<surname>Stephenson</surname>
<affiliation>
<address><email>wstephenson@kde.org</email></address>
</affiliation>
</author>

<!-- TRANS:ROLES_OF_TRANSLATORS -->
</authorgroup>

<date>2008-07-30</date>
<releaseinfo>0.2</releaseinfo>

<legalnotice>
&FDLNotice;
</legalnotice>

<abstract>
<para>&kwsdl_compiler; is a tool to generate KDE/C++ code from a WSDL (Web Service Description Language) file
for communication with a web service.</para>
</abstract>

<keywordset>
<keyword>KDE</keyword>
<keyword>kwsdl_compiler</keyword>
<keyword>WSDL</keyword>
<keyword>SOAP</keyword>
<keyword>webservice</keyword>
</keywordset>
</bookinfo>

<chapter id="introduction">
<title>Introduction</title>

<para>
Webservices are services provided by more and more software components for platform independend
information interchange and encapsulating of business logic. The functionality of a webservice is
described by its WSDL (Web Service Description Language) file which is available from the provider
of this service.
To use a webservice one has to marshal the request in a XML document which is sent to the server
via HTTP and demarshal the response (also a XML document) returned by the server.
This can be done manually, however since the WSDL fully describes the interface of a webservice,
the code for marshalling, demarshalling and communication be generated automatically.
</para>

<para>
&kwsdl_compiler; is the tool which does this automatic code generation for KDE. The generated code
makes use of a couple of KDE features, e.g. KIO slaves for communication which brings the advantage of
SSL support and cookie handling.
At the moment &kwsdl_compiler; only generates code for a client stub (the part which uses the webservice),
but in later versions it is planned to support generation of server stubs (the webservice itself) as well.
</para>
</chapter>

<chapter id="using-kwsdl_compiler">
<title>Using &kwsdl_compiler;</title>

<sect1 id="getting-started">
<title>Getting Started</title>

<para>
&kwsdl_compiler; is a command line tool because it is mainly used during the development of an
application and should be well integrated into KDE's build system.
</para>

<para>
The simplest usage of &kwsdl_compiler; is to start it with the url of the WSDL file as its argument:
</para>
<screen><command>kwsdl_compiler <replaceable>http://url/to/wsdl/file</replaceable></command></screen>
<para>
In this case &kwsdl_compiler; will create two files (kwsdl_generated.h and kwsdl_generated.cpp) in the current
working directory, which contain the generated code of this webservice.
</para>
<para>
If you want the generated files to be in another directory, use the <option>-d</option> or <option>--outputDirectory</option>
argument:
</para>
<screen><command>kwsdl_compiler -d <replaceable>gen_project/</replaceable> <replaceable>http://url/to/wsdl/file</replaceable></command></screen>
</sect1>

<sect1 id="configuration-file">
<title>The Configuration File</title>

<para>
For easier integration into the build process, &kwsdl_compiler; supports the usage of a configuration file, which
contains all settings for a flexible code generation. The configuration file which should be used can be passed
to &kwsdl_compiler; with the <option>-c</option> argument.
</para>
<screen><command>kwsdl_compiler -c <replaceable>myproject.kwsdlcfg</replaceable></command></screen>
<para>
Example:
</para>
<programlisting>
&lt;kwsdlcfg&gt;
 &lt;wsdlUrl&gt;http://myserver/apis/ws/seller.wsdl&lt;/wsdlUrl&gt;
 &lt;outputFileName&gt;ws_seller&lt;/outputFileName&gt;
 &lt;outputDirectory&gt;gen_project&lt;/outputDirectory&gt;
 &lt;namespaceMapping prefix="ms" uri="urn:MySeller"/&gt;
 &lt;namespaceMapping prefix="ys" uri="urn:YourSeller"/&gt;
&lt;/kwsdlcfg&gt;
</programlisting>

<para>Explanation:</para>
<variablelist>
<varlistentry>
<term>wsdlUrl</term>
<listitem><para>The url of the WSDL file of the webservice. This entry can be omitted when the url is passed as command line argument.</para></listitem>
</varlistentry>
<varlistentry>
<term>outputFileName</term>
<listitem><para>The name of the generated file. So when outputFileName is set to 'foobar', the files 'foobar.h' and 'foobar.cpp' will be generated. If this entry is omitted, the generated code is saved in 'kwsdl_generated.h' and 'kwsdl_generated.cpp'.</para></listitem>
</varlistentry>
<varlistentry>
<term>outputDirectory</term>
<listitem><para>The directory where the generated code should be stored. If this entry is omitted the current working directory is used.</para></listitem>
</varlistentry>
<varlistentry>
<term>namespaceMapping</term>
<listitem><para>Types defined in the WSDL file can be namespaced, so the classes in the generated code will be namespaced as well. To avoid meaningless namespaces like 'ns1', this entry allows to assign a prefix to a namespace URI.</para></listitem>
</varlistentry>
</variablelist>

<para>
So the above example configuration file would cause &kwsdl_compiler; to load the WSDL file from
http://myserver/apis/ws/seller.wsdl, parse it and store the generated code as ws_seller.h and ws_seller.cpp in the
directory gen_project/. If seller.wsdl contains a type definition with the name 'Request' which
is in namespace urn:MySeller, a class MS__Request will be generated.
</para>
</sect1>
</chapter>

<chapter id="advanced-usage">
<title>Advanced Usage</title>
<para>This chapter is not complete yet, it mainly summarizes some ideas which features could be added to
&kwsdl_compiler; in future.</para>

<sect1 id="custom-transport">
<title>Use Custom Transport Class</title>
<para>
&kwsdl_compiler; is built in a modular way, so that you can easily exchange single parts, like the
transport layer for example. There are two builtin types of transport, one for KDE (uses KIO slaves)
and one Qt only. The KDE transport is used as default, however you can switch to other transports
by using the 'transport' configuration file entry:
</para>
<screen>&lt;transport&gt;TransportType&lt;/transport&gt;</screen>
<para>
TransportType can be one of the following strings:
<variablelist>
<varlistentry>
<term>KDE</term>
<listitem><para>The default type which uses the full featured KIO HTTP slave.</para></listitem>
</varlistentry>
<varlistentry>
<term>Qt</term>
<listitem><para>An Qt only solution without SSL and cookie support.</para></listitem>
</varlistentry>
<varlistentry>
<term>Custom</term>
<listitem><para>Using this type allows you to use your own transport class (see below).</para></listitem>
</varlistentry>
</variablelist>
</para>

<para>
With the 'Custom' transport type set you can create your own Transport class which will
be used by the autogenerated code for the communication. The class must derive from QObject and provide the
interface of the Transport class:
</para>

<programlisting>
class Transport : public QObject
{
  Q_OBJECT

  public:
    /**
      Constructs a new Transport which communicates
      with the webservice at the given @param url.
     */
    Transport( const QString &amp;url );

    /**
      Sends a valid SOAP @param message to the webservice.

      @param message The SOAP message in xml format.
      @param header An additional SOAP header.
     */
    void query( const QString &amp;message, const QString &amp;header );

  signals:
    /**
      This signal is emitted whenever the query was successful, otherwise
      @see error() is emitted.

      @param result The result of the query in xml format (SOAP message).
     */
    void result( const QString &amp;result );

    /**
      This signal is emitted whenever an error occured during transmission.

      @param msg An i18n'ed error message.
     */
    void error( const QString &amp;msg );
};
</programlisting>
<para>To actually integrate the custom transport into your project, just rename your class 'Transport'
and put the declaration into a file with the name 'transport.h'.
The autogenerated code will include this file and make use of it.</para>
</sect1>
</chapter>

<chapter id="example">
<title>Example</title>
<para>This chapter provides an example how to access the GoogleSearch webservice. The WSDL file of this service can
be downloaded at http://apis.google.com.  However Google no longer distributes the secret api key needed to successfully make calls, which makes this example useful for theory only.  After retrieving the WSDL we create a configuration file
for our project.</para>

<programlisting>
&lt;kwsdlcfg&gt;
 &lt;wsdlUrl&gt;GoogleSearch.wsdl&lt;/wsdlUrl&gt;
 &lt;namespaceMapping prefix="ggs" uri="urn:GoogleSearch"/&gt;
&lt;/kwsdlcfg&gt;
</programlisting>

<para>which we store as googlesearch.kwsdlcfg.</para>
<para>Now we let &kwsdl_compiler; generate the code for us:</para>
<screen><command>kwsdl_compiler -c <replaceable>googlesearch.kwsdlcfg</replaceable></command></screen>
<para>Two new files (kwsdl_generated.h and kwsdl_generated.cpp) will be in the current working directory now.
To actually use the webservice we have to write some glue code, which makes use of the generated code.</para>

<para>main.h</para>
<programlisting>
#ifndef MAIN_H
#define MAIN_H

#include "kwsdl_generated.h"

class KWSDLTest : public QObject
{
  Q_OBJECT

  public:
    KWSDLTest();
    ~KWSDLTest();

    void run();

  private slots:
    /**
      Slot which is called when the doGoogleSearch call was successful.
     */
    void googleSearch( GGS__GoogleSearchResult *_return );

    /**
      Slot which is called when an error occured.
     */
    void googleSearchError( SoapFault *fault );

  private:
    GoogleSearchService mService;
};

#endif
</programlisting>

<para>main.cpp</para>
<programlisting>
#include "main.h"
#include &lt;kaboutdata.h&gt;
#include &lt;kapplication.h&gt;
#include &lt;kcmdlineargs.h&gt;
#include &lt;kdebug.h&gt;

KWSDLTest::KWSDLTest()
{
  // connect the signals of the generated code with our slots

  // return value
  connect( &amp;mService, SIGNAL( doGoogleSearchResponse( GGS__GoogleSearchResult* ) ),
           this, SLOT( googleSearch( GGS__GoogleSearchResult* ) ) );

  // error
  connect( &amp;mService, SIGNAL( doGoogleSearchError( SoapFault* ) ),
           this, SLOT( googleSearchError( SoapFault* ) ) );
}

KWSDLTest::~KWSDLTest()
{
}

void KWSDLTest::run()
{
  // do actually call the service
  mService.doGoogleSearch( new QString( "secret key from google" ),
        new QString( "kwsdl" ), new int( 0 ),
        new int( 10 ), new bool( false ),
        new QString(), new bool( true ),
        new QString(), new QString(), new QString() );
}

void KWSDLTest::googleSearch( GGS__GoogleSearchResult *_return )
{
  // extract and show the search result

  GGS__ResultElementArray* resultArray = _return-&gt;resultElements();
  QList&lt;GGS__ResultElement*&gt; *list = resultArray-&gt;items();
  QList&lt;GGS__ResultElement*&gt;::ConstIterator it;
  foreach ( GGS__ResultElement* element, *list ) {
    kDebug() &lt;&lt; "url=" &lt;&lt; *element-&gt;uRL();
  }

  delete _return;

  kapp-&gt;quit();
}

void KWSDLTest::googleSearchError( SoapFault *fault )
{
  // show error message

  kDebug() &lt;&lt; "googleSearchError (" &lt;&lt; fault-&gt;description() &lt;&lt; ")";

  delete fault;

  kapp-&gt;quit();
}

int main( int argc, char **argv )
{
  KAboutData aboutData( "googlesearch", 0, ki18n( "Google Search" ),
        "0.1", ki18n( "Google Search" ), KAboutData::License_LGPL );

  KCmdLineArgs::init( argc, argv, &amp;aboutData );

  KApplication app;

  KWSDLTest test;
  test.run();

  return app.exec();
}

#include "main.moc"
</programlisting>

</chapter>

<chapter id="command-line">
<title>Command Line Options</title>
<para>&kwsdl_compiler; supports some command-line arguments, which can be
used to influence the code generation:</para>

<variablelist>
<varlistentry>
<term><command>kwsdl_compiler</command> <option>-c, --configfile &lt;file&gt;</option></term>
<listitem><para>Uses the given file as configuration file.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>kwsdl_compiler</command> <option>-d, --outputDirectory &lt;directory&gt;</option></term>
<listitem><para>Save the generated code in the given directory.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>kwsdl_compiler</command> <option>&lt;wsdl&gt;</option></term>
<listitem><para>Generate code for the given wsdl.</para></listitem>
</varlistentry>
</variablelist>
</chapter>

<chapter id="credits">
<title>Credits and License</title>

<para>&kwsdl_compiler; - The &kde; WSDL compiler</para>

<para>Copyright (c) 2005 - 2006, Tobias Koenig <email>tokoe@kde.org</email></para>
<para>Copyright (c) 2008, Will Stephenson <email>wstephenson@kde.org</email></para>

&underFDL;               <!-- FDL: do not remove -->
</chapter>
</book>

