Index: /trunk/workshop/2010/building_wps_client_using_ol.rst
===================================================================
--- /trunk/workshop/2010/building_wps_client_using_ol.rst (revision 723)
+++ /trunk/workshop/2010/building_wps_client_using_ol.rst (revision 723)
@@ -0,0 +1,329 @@
+.. _building_wps_client_using_ol:
+
+Building a WPS client using OpenLayers
+######################################
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+The next step of our workshop is to connect to the OGR Services we have created
+from an OpenLayers map. This will allow to apply single or multiple geometries
+processes on user-selected polygons and to display the new generated geometries.
+
+Creating a simple map showing the dataset as WMS
+************************************************
+
+OpenLayers is also included in OSGeoLive default distribution, so it is convenient
+to use it for our needs. Please open ``/var/www/zoo-ogr.html`` using your favorite
+text editor and paste the following HTML snippet:
+
+.. code-block:: guess
+
+
+
+
+ ZOO WPS Client example
+
+
+
+
+
+
+
+
+
+The following JavaScript code must then be added in a ```` section within the
+```` one. This will setup a map showing the japanese regions data as WMS.
+
+.. code-block:: guess
+
+ var map, layer, select, hover, multi, control;
+
+ var typename="regions";
+ var main_url="http://localhost/cgi-bin/mapserv?map=/var/www/wfs.map";
+
+ function init(){
+ map = new OpenLayers.Map('map', {
+ controls: [
+ new OpenLayers.Control.PanZoom(),
+ new OpenLayers.Control.Permalink(),
+ new OpenLayers.Control.Navigation()
+ ]
+ });
+ layer = new OpenLayers.Layer.WMS(typename,main_url, {
+ layers: 'regions',
+ transparent: 'true',
+ format: 'image/png'
+ },
+ {
+ isBaseLayer: true,
+ visibility: true,
+ buffer: 0,
+ singleTile: true
+ }
+ );
+ map.addLayers([layer]);
+ map.setCenter(new OpenLayers.LonLat(138,33.5),5);
+ }
+
+Once done, please save your HTML file as ``zoo-ogr.html`` in your workshop directory,
+then copy it in ``/var/www`` and visualize it with your favorite Web browser using this link :
+``http://localhost/zoo-ogr.html``. You should obtain a map centered on the Japan with the WMS layer activated.
+
+.. image:: ./images/OL-JP-1.png
+ :width: 356px
+ :height: 280px
+ :align: center
+
+Fetching the data layer as WFS and adding selection controls
+************************************************************
+
+Before accessing the displayed data via WFS, you first have to create new vector layers
+dedicated to host the several interactions we are going to create. Please add the following
+lines within the ``init()`` function, and do not forget to add the newly created layer in
+the map.addLayers method:
+
+.. code-block:: guess
+
+ select = new OpenLayers.Layer.Vector("Selection", {
+ styleMap: new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"])
+ });
+
+ hover = new OpenLayers.Layer.Vector("Hover");
+ multi = new OpenLayers.Layer.Vector("Multi", { styleMap:
+ new OpenLayers.Style({
+ fillColor:"red",
+ fillOpacity:0.4,
+ strokeColor:"red",
+ strokeOpacity:1,
+ strokeWidth:2
+ })
+ });
+
+ map.addLayers([layer, select, hover, multi]);
+
+Then, you can now access the data by creating new controls to select polygons, as the
+following. Please note that ``OpenLayers.Protocol.WFS.fromWMSLayer`` is used to access
+geometries and that several state of selection are declared and append to the control variable.
+
+.. code-block:: guess
+
+ var protocol = OpenLayers.Protocol.WFS.fromWMSLayer(layer, {
+ featurePrefix: 'ms',
+ geometryName: 'msGeometry',
+ featureType: typename
+ });
+
+ control = new OpenLayers.Control.GetFeature({
+ protocol: protocol,
+ box: false,
+ hover: false,
+ multipleKey: "shiftKey",
+ toggleKey: "ctrlKey"
+ });
+ control.events.register("featureselected", this, function(e) {
+ select.addFeatures([e.feature]);
+ });
+ control.events.register("featureunselected", this, function(e) {
+ select.removeFeatures([e.feature]);
+ });
+ map.addControl(control);
+ control.activate();
+
+Please save your HTML file again. You should now be able to select a polygon only by
+clicking on it. The selected polygon should appear in blue color.
+
+.. image:: ./images/OL-JP-2.png
+ :width: 356px
+ :height: 280px
+ :align: center
+
+Calling the single geometry services from JavaScript
+****************************************************
+
+Now that everything is setup, we can go on and call our OGR ZOO services with JavaScript.
+Please add the following lines after the ``init()`` function, which will call the single
+geometry processes. You can notice that we use a specific ``parseMapServerId`` function
+which let us remove the unecessary white space returned as fid value.
+
+.. code-block:: guess
+
+ function parseMapServerId(){
+ var sf=arguments[0].split(".");
+ return sf[0]+"."+sf[1].replace(/ /g,'');
+ }
+
+ function simpleProcessing(aProcess) {
+ if (select.features.length == 0)
+ return alert("No feature selected!");
+ if(multi.features.length>=1)
+ multi.removeFeatures(multi.features);
+ var url = '/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&';
+ if (aProcess == 'Buffer') {
+ var dist = document.getElementById('bufferDist')?document.getElementById('bufferDist').value:'1';
+ if (isNaN(dist)) return alert("Distance is not a Number!");
+ url+='Identifier=Buffer&DataInputs=BufferDistance='+dist+'@datatype=interger;InputPolygon=Reference@xlink:href=';
+ } else
+ url += 'Identifier='+aProcess+'&DataInputs=InputPolygon=Reference@xlink:href=';
+ var xlink = control.protocol.url +"&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
+ xlink += '&typename='+control.protocol.featurePrefix;
+ xlink += ':'+control.protocol.featureType;
+ xlink += '&SRS='+control.protocol.srsName;
+ xlink += '&FeatureID='+parseMapServerId(select.features[0].fid);
+ url += encodeURIComponent(xlink);
+ url += '&RawDataOutput=Result@mimeType=application/json';
+
+ var request = new OpenLayers.Request.XMLHttpRequest();
+ request.open('GET',url,true);
+ request.onreadystatechange = function() {
+ if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
+ var GeoJSON = new OpenLayers.Format.GeoJSON();
+ var features = GeoJSON.read(request.responseText);
+ hover.removeFeatures(hover.features);
+ hover.addFeatures(features);
+ }
+ }
+ request.send();
+ }
+
+
+Then, some specific buttons must be added in the HTML, in order to be able to call
+the different processes we just declared. You can add them on top of the map by writing
+the following lines before the ````.
+
+.. code-block:: guess
+
+
+
Single geometry processing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Save your HTML file again. You should now be able to select a polygon and to launch a Buffer,
+ConvexHull, Boundary or Centroid on it by clicking one of the button. The result of the
+process should appear as GeoJSON layer on the map, in orange color.
+
+.. image:: ./images/OL-JP-3.png
+ :width: 536px
+ :height: 270px
+ :align: center
+
+Calling the multiples geometries processes from JavaScript
+**********************************************************
+
+Using the same technique, you can now write a function dedicated to the multiple geometries
+processes. Please add the following lines after the ``simpleProcessing()`` function, we will
+guide you during the exercise in section 5 on how to create such a function.
+
+.. code-block:: guess
+
+ function multiProcessing(aProcess) {
+ if (select.features.length == 0 || hover.features.length == 0)
+ return alert("No feature created!");
+ var url = '/cgi-bin/zoo_loader.cgi';
+ var xlink = control.protocol.url +"&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0";
+ xlink += '&typename='+control.protocol.featurePrefix;
+ xlink += ':'+control.protocol.featureType;
+ xlink += '&SRS='+control.protocol.srsName;
+ xlink += '&FeatureID='+parseMapServerId(select.features[0].fid);
+ var GeoJSON = new OpenLayers.Format.GeoJSON();
+ try {
+ var params = '';
+ params += ''+aProcess+'';
+ params += '';
+ params += '';
+ params += 'InputEntity1';
+ params += '';
+ params += '';
+ params += '';
+ params += 'InputEntity2';
+ params += '';
+ params += ' '+GeoJSON.write(hover.features[0].geometry)+' ';
+ params += '';
+ params += '';
+ params += '';
+ params += '';
+ params += '';
+ params += 'Result';
+ params += '';
+ params += '';
+ params += '';
+ } catch(e) {
+ alert(e);
+ return false;
+ }
+ var request = new OpenLayers.Request.XMLHttpRequest();
+ request.open('POST',url,true);
+ request.setRequestHeader('Content-Type','text/xml');
+ request.onreadystatechange = function() {
+ if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
+ var GeoJSON = new OpenLayers.Format.GeoJSON();
+ var features = GeoJSON.read(request.responseText);
+ multi.removeFeatures(multi.features);
+ multi.addFeatures(features);
+ }
+ }
+ request.send(params);
+ }
+
+Note that this time we didn't use the GET method to request the ZOO Kernel but a XML POST.
+We did that because if you use the GET method you will get error due to the HTTP GET method
+limitation based on the length of your request. Using JSON string representing the geometry
+will make your request longer.
+
+Once you get the functions to call your multiple geometries processes, you' must add some
+buttons to fire the request call. Here is the HTML code to add to your current ``zoo-ogr.html`` file :
+
+.. code-block:: guess
+
+
Multiple geometries processing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Please reload the page. You should then be able to run your multiple geometries services and
+you should get results displayed in red as shown by the following screenshots :
+
+
+.. image:: ./images/OL-JP-4.png
+ :width: 406px
+ :height: 140px
+.. image:: ./images/OL-JP-5.png
+ :width: 406px
+ :height: 140px
+.. image:: ./images/OL-JP-6.png
+ :width: 406px
+ :height: 140px
+.. image:: ./images/OL-JP-7.png
+ :width: 406px
+ :height: 140px
+
+It seems that something is missing in your Services Provider to get the same results …
+The multiple geometries Services ! This is what we are going to do together in the next section.
Index: /trunk/workshop/2010/exercise.rst
===================================================================
--- /trunk/workshop/2010/exercise.rst (revision 723)
+++ /trunk/workshop/2010/exercise.rst (revision 723)
@@ -0,0 +1,56 @@
+.. _exercise:
+
+Exercise
+########
+
+You know everything now about writting zcfg matadata files and get short pieces
+of code in ``service.c`` or ``ogr_service_provider.py`` depending if you choosen
+C or Python programming language respectively.
+
+The goal of this exercise is to implement the following multiple geometries services :
+
+ - Intersection
+ - Union
+ - Difference
+ - SymDifference
+
+C version
+*********
+
+Your are now invited to edit the source.c file you have created during this workshop
+to add the multiple geometries, using the following OGR C-API functions :
+
+ - `OGR_G_Intersection `__ (OGRGeometryH, OGRGeometryH)
+ - `OGR_G_Union `__ (OGRGeometryH, OGRGeometryH)
+ - `OGR_G_Difference `__ (OGRGeometryH, OGRGeometryH)
+ - `OGR_G_SymmetricDifference `__ (OGRGeometryH, OGRGeometryH)
+
+You can use the ``Boundary.zcfg`` file as example, rename the InputPolygon input
+to ``InputEntity1`` and add a similar input named ``IntputEntity2``. You are
+invited to update other values in the ZOO Metadata File to set the proper
+metadata informations.
+
+Python Version
+**************
+
+Your are invited to edit the ``ogr_ws_service_provider.py`` file you created
+during this workshop to add the multiple geometries using the following
+``osgeo.ogr`` Geometry methods applied on the first Geometry instance :
+
+ - Intersection(Geometry)
+ - Union(Geometry)
+ - Difference(Geometry)
+ - SymmetricDifference(Geometry)
+
+You can once again use the ``Boundary.zcfg`` file as example, rename the ``InputPolygon``
+input to ``InputEntity1`` and add a similar input named ``IntputEntity2``. You are
+invited to update other values in the ZOO metadata file to set the proper metadata
+informations.
+
+Testing your services
+*********************
+
+Once the multiple geometries Services are deployed on your local environment,
+please reload the ``zoo-ogr.html`` file created during the previous section
+from your browser and test your brand new ZOO Services.
+
Index: /trunk/workshop/2010/index.rst
===================================================================
--- /trunk/workshop/2010/index.rst (revision 723)
+++ /trunk/workshop/2010/index.rst (revision 723)
@@ -0,0 +1,29 @@
+.. _workshop-foss4g-japan-2010:
+
+
+ZOO-Project Workshop 2010
+======================================================
+
+:Original Title: **Practical Introduction to ZOO: The Open WPS Platform**
+:Author: Nicolas Bozon, Gérald Fenoy, Venkatesh Raghavan
+:Last Updated: $Date$
+:Events: FOSS4G 2010 Osaka / Tokyo / Beijing
+
+.. image:: ./images/foss4g2010tokyo.png
+ :width: 193px
+ :height: 100px
+
+.. image:: ./images/molamola_gps1.png
+ :width: 100px
+ :height: 100px
+
+**Workshop Table of Contents**
+
+.. toctree::
+ :maxdepth: 5
+
+ introduction
+ using_zoo_from_osgeolivevm
+ ogr_base_vect_ops
+ building_wps_client_using_ol
+ exercise
Index: /trunk/workshop/2010/introduction.rst
===================================================================
--- /trunk/workshop/2010/introduction.rst (revision 723)
+++ /trunk/workshop/2010/introduction.rst (revision 723)
@@ -0,0 +1,90 @@
+.. _introduction:
+
+Introduction
+======================================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+What is ZOO ?
+--------------------------------------------------------------------
+
+ZOO is a WPS (Web Processing Service) open source project recently released under a `MIT/X-11 `__ style license. It provides an OGC WPS compliant developer-friendly framework to create and chain WPS Web services. ZOO is made of three parts:
+
+ - `ZOO Kernel `__ : A powerful server-side C Kernel which makes it possible to manage and chain Web services coded in different programming languages.
+ - `ZOO Services `__ : A growing suite of example Web Services based on various open source libraries.
+ - `ZOO API `__ : A server-side JavaScript API able to call and chain the ZOO Services, which makes the development and chaining processes easier.
+
+ZOO is designed to make the service development easier by providing a powerful system
+able to understand and execute WPS compliant queries. It supports several programming
+languages, thus allowing you to create Web Services in your favorite one and from an
+already existing code. Further information on the project is available on the
+`ZOO Project official website `__ .
+
+How does ZOO works ?
+--------------------------------------------------------------------
+
+ZOO is based on a 'WPS Service Kernel' which constitutes the ZOO's core system
+(aka ZOO Kernel). The latter is able to load dynamic libraries and to handle them
+as on-demand Web services. The ZOO Kernel is written in C language, but supports
+several common programming languages for creating ZOO Services.
+
+A ZOO Service is a link composed of a ZOO metadata file (.zcfg) and the code for
+the corresponding implementation. The metadata file describes all the available
+functions which can be called using a WPS Exec Request, as well as the desired
+input/output. Services contain the algorithms and functions, and can now be
+implemented in C/C++, Fortran, Java, Python, Perl, PHP and JavaScript.
+
+ZOO Kernel works with Apache and can communicate with cartographic engines and
+Web mapping clients. It simply adds the WPS support to your spatial data infrastructure
+and your Web mapping application. It can use every GDAL/OGR supported formats as input
+data and create suitable vector or raster output for your cartographic engine and/or
+your web-mapping client application.
+
+What are we going to do in this workshop?
+--------------------------------------------------------------------
+
+This workshop aims to present the ZOO Project and its features, and to explain its
+capabilities regarding the `OGC WPS 1.0.0 specification `__.
+The participants will learn in 3 hours how to use ZOO Kernel, how to create
+ZOO Services and their configuration files and finally how to link the created
+Service with a client-side webmapping application. A pre-compiled ZOO 1.0 version
+is provided inside OSGeoLive, the OSGeo official Live DVD. For the sack of simplicity,
+an OSGeoLive Virtual Machine image disk is already installed on your computers.
+This will be used during this workshop, so the participants won't have to compile
+and install ZOO Kernel manually. Running and testing ZOO Kernel from this OSGeoLive
+image disk is thus the first step of the workshop, and every participants should
+get a working ZOO Kernel in less than 30 minutes.
+
+Once ZOO Kernel will be tested from a Web browser using GetCapabilities requests,
+participants will be invited to create an OGR based ZOO Service Provider aiming to
+enable simple spatial operations on vector data. Participants will first have to
+choose whether they will create the service using C or Python language. Every programming
+step of the ZOO Service Provider and the related Services will be each time detailed in
+C and Python. Once the ZOO Services will be ready and callable by ZOO Kernel, participants
+will finally learn how to use its different functions from an OpenLayers simple application.
+A sample dataset was providen by Orkney and included in the OSGeoLiveDVD, data are
+available trough OGC WMS/WFS WebServices using MapServer and will be displayed on a
+simple map and used as input data by the ZOO Services. Then, some specific selection
+and execution controls will be added in the JavaScript code in order to execute single
+and multiple geometries on the displayed polygons.
+
+Once again, the whole procedure will be organized step-by-step and detailed with
+numerous code snippets and their respective explanations. The instructors will check
+the ZOO Kernel functioning on each machine and will assist you while coding. Technical
+questions are of course welcome during the workshop.
+
+Usefull tips for reading :
+--------------------------------------------------------------------
+
+.. code-block:: guess
+
+ this is a code block
+
+.. warning:: This is a warning message.
+
+.. note:: This is an important note.
+
+
+**Let's go !**
Index: /trunk/workshop/2010/ogr_base_vect_ops.rst
===================================================================
--- /trunk/workshop/2010/ogr_base_vect_ops.rst (revision 723)
+++ /trunk/workshop/2010/ogr_base_vect_ops.rst (revision 723)
@@ -0,0 +1,1282 @@
+.. _ogr_base_vect_ops:
+
+Creating OGR based Web Services
+======================================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+--------------------------------------------------------------------
+
+In this part, we are going to create a ZOO ServicesProvider containing several Services
+based on the OGR C API or on the OGR Python module, which have also been placed in the
+ZOO installation on OSGeoLive. The intended goal is to use OGR and its GEOS based simple
+spatial functions as WPS Services.
+
+We will first start with the Boundary spatial function, which will be explained, codded
+and tested gradually as a ZOO Service. The same procedure will then be used to enable
+the Buffer, Centroid and Convex Hull functions. Once done, some multiple geometries processes
+such as Intersection, Union, Difference and Symetric Difference will be implemented through
+an `exercise <./exercise.html>`__ at the end of the workshop.
+
+As already said in the introduction, you have the choice to code your service in C or
+Python (or both!) during this workshop. Explanations will be based on the C part, but
+will be very helpful for those who will choose Python. Please decide according to your
+habits and preferences and tell your choice to the instructors. The results will be the
+same in both case.
+
+Preparing ZOO metadata file
+--------------------------------------------------------------------
+
+A ZOO Service is a combination of a ZOO metadata file (``.zcfg``) and the runtime module
+for the corresponding implementation, which is commonly called ZOO Service Provider. We
+will first prepare a ``.zcfg`` file step-by-step. Please open your preferred text editor
+and edit a file named ``Boundary.zcfg`` in your ``/home/user/zoows/sources/zoo-services/ws_sp``
+directory. First, you need to name the service between brackets at the top of the file, as the
+following
+
+::
+
+[Boundary]
+
+This name is very important, it is the name of the Service and so the name of the function
+defined in the Services Provider. A title and a brief abstract must then be added to inform
+clients on what the service can do:
+
+.. code-block:: guess
+
+ Title = Compute boundary.
+ Abstract = Returns the boundary of the geometry on which the method is invoked.
+
+Such metadata informations will be returned by a GetCapabilities request.
+
+You can also add other specific informations like the ``processVersion``. You can set if
+your ZOO Service can store its results, by setting the ``storeSupported`` parameter to
+true or false. You can also decide if the function can be run as a background task and
+inform on its current status, according to the ``statusSupported`` value :
+
+.. code-block:: guess
+
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+
+In the main section of the ZOO Service metadata file, you must also specify two important things:
+
+ - ``serviceProvider``, which is the name of the C shared library containing the Service function or the Python module name.
+ - ``serviceType``, which defines the programming language to be used for the Service. (value can be C or Python depending on what language you have decided to use)
+
+C ServicesProvider Example :
+
+.. code-block:: guess
+
+ serviceProvider=ogr_ws_service_provider.zo
+ serviceType=C
+
+In this case you will get an ``ogr_ws_service_provider.zo`` shared library containing
+the Boundary function, placed in the same directory than ZOO Kernel.
+
+Python ServicesProvider Example :
+
+.. code-block:: guess
+
+ serviceProvider=ogr_ws_service_provider
+ serviceType=Python
+
+In this case, you will get an ``ogr_ws_service_provider.py`` file containing the Python code of your Boundary function.
+
+In the main section you can also add any other metadata information, as the following:
+
+.. code-block:: guess
+
+
+ Title = Demo
+
+
+The main metadata informations have been declared, so you can now define data input
+which will be used by the ZOO Service. You can define any input needed by the Service.
+Please note that you can request ZOO Kernel using more data input than defined in
+the ``.zcfg`` file without any problem, those values will be passed to your service
+without filtering. In the Boundary Service example, a single polygon will be used as
+input, the one on which to apply the Boundary function.
+
+The data input declarations are included in a DataInputs block. They use the same
+syntax as the Service itself and the input name is between brackets. You can also
+fill a title, an abstract and a MetaData section for the input. You must set values
+for the ``minOccurs`` and ``maxOccurs`` parameters, as they will inform ZOO Kernel
+which parameters are required to be able to run the Service function.
+
+.. code-block:: none
+
+ [InputPolygon]
+ Title = Polygon to compute boundary
+ Abstract = URI to a set of GML that describes the polygon.
+ minOccurs = 1
+ maxOccurs = 1
+
+ Test = My test
+
+
+
+The metadata defines what type of data the Service supports. In the Boundary example,
+the input polygon can be provided as a GML file or as a JSON string. Next step is
+thus to define the default and supported input formats. Both formats should be declared
+in a LitteralData or ComplexData block depending on their types. For this first example
+we will use ComplexData blocks only.
+
+.. code-block:: guess
+
+
+
+ mimeType = text/xml
+ encoding = UTF-8
+
+
+ mimeType = application/json
+ encoding = UTF-8
+
+
+
+
+Then, the same metadata information must be defined for the output of the Service, inside a DataOutputs block, as the following:
+
+.. code-block:: none
+
+ [Result]
+ Title = The created geometry
+ Abstract = The geometry containing the boundary of the geometry on which the method was invoked.
+
+ Title = Result
+
+
+
+ mimeType = application/json
+ encoding = UTF-8
+
+
+ mimeType = text/xml
+ encoding = UTF-8
+
+
+
+A complete copy of this ``.zcfg`` file can be found at the following URL: http://zoo-project.org/trac/browser/trunk/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg.
+
+
+Once the ZOO metadata file is modified, you have to copy it in the same directory
+than your ZOO Kernel (so in your case ``/usr/lib/cgi-bin``). Then you should be
+able to run the following request :
+
+http://localhost/zoo/?Request=DescribeProcess&Service=WPS&Identifier=Boundary&version=1.0.0
+
+The returned ProcessDescriptions XML document should look like the following :
+
+.. image:: ./images/Practical-introduction-to-ZOO-5.png
+ :width: 456px
+ :height: 157px
+ :align: center
+
+Please note that the GetCapabilities and DescribeProcess only need a ``.zcfg``
+file to be completed. Simple, isn't it ? At this step, if you request ZOO Kernel
+for an Execute, you will get an ExceptionReport document as response, looking as the following :
+
+.. image:: ./images/Practical-introduction-to-ZOO-6.png
+ :width: 546px
+ :height: 80px
+ :align: center
+
+A similar error message will be returned if you try to run your Python Service :
+
+.. image:: ./images/Practical-introduction-to-ZOO-7.png
+ :width: 489px
+ :height: 87px
+ :align: center
+
+
+Implementing single geometry services
+------------------------------------------------------------------------------
+
+In order to learn the Services Provider creation and deployement step-by-step,
+we will first focus on creating a very simple one dedicated to the Boundary function.
+Similar procedure will then be used for the Buffer, Centroid and ConvexHull implementation.
+
+Your metadata is now ok, so you now must create the code of your Service. The most
+important thing you must be aware of when coding ZOO Services is that the function
+corresponding to your Service takes three parameters (internal maps datatype or
+`Python dictionaries `__)
+and returns an integer value representing the status of execution (SERVICE_FAILED or SERVICE_SUCCEEDED):
+
+ - ``conf`` : The main environment configuration (corresponding to the ``main.cfg`` content)
+ - ``inputs`` : The requested / default inputs
+ - ``outputs`` : The requested / default outputs
+
+Boundary
+..........................................................................................................................................................
+
+C Version
+*******************************************************************************************************
+
+As explained before, ZOO Kernel will pass the parameters to your Service function
+in a specific datatype called maps. In order to code your Service in C language,
+you also need to learn how to access this datatype in read/write mode.
+
+The maps are simple map named linked list containing a name, a content map and a
+pointer to the next map in the list (or NULL if there is no more map in the list).
+Here is the datatype definition as you can find in the zoo-kernel/service.h file:
+
+.. code-block:: c
+
+ typedef struct maps{
+ char* name;
+ struct map* content;
+ struct maps* next;
+ } maps;
+
+The map included in the maps is also a simple linked list and is used to store Key
+Value Pair values. A map is thus a couple of name and value and a pointer to the
+next map in the list. Here is the datatype definition you can find in the zoo-kernel/service.h file:
+
+.. code-block:: guess
+
+ typedef struct map{
+ char* name; /* The key */
+ char* value; /* The value */
+ struct map* next; /* Next couple */
+ } map;
+
+
+As partially or fully filled datastructures will be passed by the ZOO Kernel to
+your Services, this means that you do not need to deal with maps creation but
+directly with existing map, in other words the content of each maps. The first
+function you need to know is getMapFromMaps (defined in the zoo-kernel/service.h file)
+which let you access to a specific map of a maps.
+
+This function takes three parameters listed bellow:
+
+ - ``m`` : a maps pointer representing the maps used to search the specific map
+ - ``name`` : a char* representing the name of the map you are searching for
+ - ``key`` : a specific key in the map named name
+
+For example, the following syntax will be used to access the InputPolygon value
+map of a maps named inputs, your C code should be:
+
+.. code-block:: guess
+
+ map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+
+Once you get the map, you can access the name or the value fields, using the following syntax :
+
+.. code-block:: guess
+
+ tmp->name
+ tmp->value
+
+As you know how to read and access the map fields from a maps, you can now learn
+how to write in such a datastructure. This is done by using the simple setMapInMaps
+function once again defined in zoo-kernel/service.h. The setMapInMaps function takes four parameters :
+
+ - ``m`` : a maps pointer you want to update,
+ - ``ns`` : the name of the maps you want you want to update,
+ - ``n`` : the name of the map you want to add or update the value,
+ - ``v`` : the value you want to set for this map.
+
+Here is an example of how to add or edit the values of some map in the Result maps from outputs :
+
+.. code-block:: guess
+
+ setMapInMaps(outputs,"Result","value","Hello from the C World !");
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ setMapInMaps(outputs,"Result","encoding","UTF-8");
+
+
+Please note that the setMapInMaps function is able to create or update an existing map.
+Indeed, if a map called « value » allready exists, then its value will be updated automatically.
+
+Even if you will mainly use map from maps during this workshop, you can also add or
+update values in a map directly using the addToMap function defined in zoo-kernel/service.h.
+The addToMap function take three paramters :
+
+ - ``m`` : a map pointer you want to update,
+ - ``n`` : the name of the map you want to add or update the value,
+ - ``v`` : the value you want to set in this map.
+
+This datatype is really important cause it is used in every C based ZOO Services. It is
+also the same representation used in other languages but using their respectives datatypes.
+For Example in Python, the dictionaries datatype is used, so manipulation is much easier.
+
+Here is an example of the correspoding maps datatype used in Python language (this is a
+summarized version of the main configaration maps):
+
+.. code-block:: guess
+
+ main={
+ "main": {
+ "encoding": "utf-8",
+ "version": "1.0.0",
+ "serverAddress": "http://www.zoo-project.org/zoo/",
+ "lang": "fr-FR,en-CA"
+ },
+ "identification": {"title": "The Zoo WPS Development Server",
+ "abstract": "Development version of ZooWPS.",
+ "fees": "None",
+ "accessConstraints": "none",
+ "keywords": "WPS,GIS,buffer"
+ }
+ }
+
+As you know how to deal with maps and map, you are ready to code the first ZOO Service by using the OGR Boundary function.
+
+As already said in introduction we will use the MapServer WFS server available on
+OSGeoLive, so full WFS Response will be used as inputs values. As we will use the
+simple OGR Geometry functions like `OGR_G_GetBoundary `__,
+only the Geometry object will be used rather than a full WFS Response. The first
+thing to do is to write a function which will extract the geometry definition
+from the full WFS Response. We will call it createGeometryFromWFS.
+
+Here is the code of such a function:
+
+.. code-block:: guess
+
+ OGRGeometryH createGeometryFromWFS(maps* conf,char* inputStr){
+ xmlInitParser();
+ xmlDocPtr doc = xmlParseMemory(inputStr,strlen(inputStr));
+ xmlChar *xmlbuff;
+ int buffersize;
+ xmlXPathContextPtr xpathCtx;
+ xmlXPathObjectPtr xpathObj;
+ char * xpathExpr="/*/*/*/*/*[local-name()='Polygon' or local-name()='MultiPolygon']";
+ xpathCtx = xmlXPathNewContext(doc);
+ xpathObj = xmlXPathEvalExpression(BAD_CAST xpathExpr,xpathCtx);
+ if(!xpathObj->nodesetval){
+ errorException(conf, "Unable to parse Input Polygon","InvalidParameterValue");
+ exit(0);
+ }
+ int size = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
+ xmlDocPtr ndoc = xmlNewDoc(BAD_CAST "1.0");
+ for(int k=size-1;k>=0;k--){
+ xmlDocSetRootElement(ndoc, xpathObj->nodesetval->nodeTab[k]);
+ }
+ xmlDocDumpFormatMemory(ndoc, &xmlbuff, &buffersize, 1);
+ char *tmp=strdup(strstr((char*)xmlbuff,"?>")+2);
+ xmlXPathFreeObject(xpathObj);
+ xmlXPathFreeContext(xpathCtx);
+ xmlFree(xmlbuff);
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ OGRGeometryH res=OGR_G_CreateFromGML(tmp);
+ if(res==NULL){
+ errorException(conf, "Unable to call OGR_G_CreatFromGML","NoApplicableCode");
+ exit(0);
+ }
+ else
+ return res;
+ }
+
+
+The only thing we will focus on is the call to the errorException function used
+in the function body. This function is declared in the zoo-kernel/service_internal.h
+and defined in zoo-kernel/service_internal.c file. It takes three parameters as follow:
+
+ - the main environment maps,
+ - a char* representing the error message to display,
+ - a char* representing the error code (as defined in the WPS specification – Table 62).
+
+In other words, if the WFS response cannot be parsed properly, then you will return
+an ExceptionReport document informing the client that a problem occured.
+
+The function to extract the geometry object from a WFS Response is written, so you
+can now start defining the Boundary Service. Here is the full code for the Boundary Service:
+
+.. code-block:: guess
+
+ int Boundary(maps*& conf,maps*& inputs,maps*& outputs){
+ OGRGeometryH geometry,res;
+ map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+ if(tmp==NULL){
+ setMapInMaps(m,"lenv","message","Unable to parse InputPolygon");
+ return SERVICE_FAILED;
+ }
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0)
+ geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+ else
+ geometry=createGeometryFromWFS(conf,tmp->value);
+ if(geometry==NULL){
+ setMapInMaps(m,"lenv","message","Unable to parse InputPolygon");
+ return SERVICE_FAILED;
+ }
+ res=OGR_G_GetBoundary(geometry);
+ tmp1=getMapFromMaps(outputs,"Result","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0){
+ char *tmp=OGR_G_ExportToJson(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ free(tmp);
+ }
+ else{
+ char *tmp=OGR_G_ExportToGML(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ free(tmp);
+ }
+ outputs->next=NULL;
+ OGR_G_DestroyGeometry(geometry);
+ OGR_G_DestroyGeometry(res);
+ return SERVICE_SUCCEEDED;
+ }
+
+As you can see in the code above, the mimeType of the data inputs passed to our Service is first checked:
+
+.. code-block:: guess
+
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0)
+ geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+ else
+ geometry=createGeometryFromWFS(conf,tmp->value);
+
+Basically, if we get an input with a mimeType set to application/json, then we will
+use our ``OGR_G_CreateGeometryFromJson`` in other case, our ``createGeometryFromWFS`` local function.
+
+Please note that in some sense the data inputs are not really of the same kind.
+Indeed as we used directly ``OGR_G_CreateGeometryFromJson`` it means that the JSON
+string include only the geometry object and not the full GeoJSON string. Nevertheless,
+you can easily change this code to be able to use a full GeoJSON string, simply by
+creating a function which will extract the geometry object from the GeoJSON string
+(using the json-c library for instance, which is also used by the OGR GeoJSON Driver).
+
+Once you can access the input geometry object, you can use the ``OGR_G_GetBoundary``
+function and store the result in the res geometry variable. Then, you only have to
+store the value in the right format : GeoJSON per default or GML as we declared it as a supported output format.
+
+Please note that ZOO Kernel will give you pre-filled outputs values, so you will
+only have to fill the value for the key named value, even if in our example we
+override the mimeType using the text/plain value rather than the application/json
+(to show that we can also edit other fields of a map). Indeed, depending on the
+format requested by the client (or the default one) we will provide JSON or GML representation of the geometry.
+
+.. code-block:: guess
+
+ tmp1=getMapFromMaps(outputs,"Result","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0){
+ char *tmp=OGR_G_ExportToJson(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ free(tmp);
+ }
+ else{
+ char *tmp=OGR_G_ExportToGML(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ free(tmp);
+ }
+
+The Boundary ZOO Service is now implemented and you need to compile it to produce
+a Shared Library. As you just used functions defined in service.h (``getMapFromMaps``,
+``setMapInMaps`` and ``addToMap``), you must include this file in your C code. The
+same requirement is needed to be able to use the ``errorException`` function declared
+in ``zoo-kernel/service_internal.h``, you also must link your service object file to
+the ``zoo-kernel/service_internal.o`` in order to use ``errorException`` on runtime.
+You must then include the required files to access the libxml2 and OGR C-API.
+
+For the need of the Shared Library, you have to put your code in a block declared as
+extern "C". The final Service code should be stored in a service.c file located in
+the root of the Services Provider directory (so in ``/home/zoows/sources/zoo-services/ws_sp``).
+It should look like this:
+
+.. code-block:: guess
+
+ #include "ogr_api.h"
+ #include "service.h"
+ extern "C" {
+ #include
+ #include
+ #include
+ #include
+
+ }
+
+The full source code of your Service is now ready and you must produce the corresponding
+Service Shared Object by compiling the code as a Shared Library. This can be done using the following command:
+
+.. code-block:: guess
+
+ g++ $CFLAGS -shared -fpic -o cgi-env/!ServicesProvider.zo ./service.c $LDFLAGS
+
+Please note that the ``CFLAGS`` and ``LDFLAGS`` environment variables values must be set before.
+
+The ``CFLAGS`` must contain all the requested paths to find included headers, so the
+path to the directories where the ``ogr_api.h``, ``libxml2`` directory, ``service.h``
+and ``service_internal.h`` files are located. Thanks to the OSGeoLive environment,
+some of the provided tools can be used to retrieve those values : ``xml2-config`` and
+``gdal-config``, both used with the ``--cflags`` argument. They will produce the desired paths for you.
+
+If you follow the instructions to create your ZOO Services Provider main directory in
+``zoo-services``, then you should find the ZOO Kernel headers and source tree which is
+located in the ``../../zoo-kernel`` directory relatively to your current path (``/home/user/zoows/sources/zoo-services/ws_sp``).
+Note that you can also use a full path to the ``zoo-kernel`` directory but using relative
+path will let you move your sources tree somewhere else and keep your code compiling
+using exactly the same command line. So you must add a ``-I../../zoo-kernel`` to your
+``CFLAGS`` to make the compiler able to find the ``service.h`` and ``service_internal.h`` files.
+
+The full ``CFLAGS`` definition should look like this:
+
+.. code-block:: guess
+
+ CFLAGS=`gdal-config --cflags` `xml2-config --clfags` -I../../zoo-kernel/
+
+Once you get the included paths correctly set in your ``CFLAGS`` , it is time to concentrate
+on the library we have to link against (defined in the ``LDFLAGS`` environment variable).
+In order to link against the gdal and libxml2 libraries, you can use the same tools than
+above using the ``--libs`` argument rather than ``--cflags``. The full ``LDFLAGS``
+definition must look like this :
+
+.. code-block:: guess
+
+ LDFLAGS=`gdal-config --libs` `xml2-config --libs` ../../zoo-kernel/service_internal.o
+
+Let's now create a ``Makefile`` which will help you compiling your code over the time.
+Please write a short ``Makefile`` in the root of your ZOO Services Provider directory, containing the following lines:
+
+.. code-block:: guess
+
+ ZOO_SRC_ROOT=../../zoo-kernel/
+ CFLAGS=-I${ZOO_SRC_ROOT} `xml2-config --cflags` `gdal-config --cflags`
+ LDFLAGS=`xml2-config --libs` `gdal-config --libs`${ZOO_SRC_ROOT}/service_internal.o
+
+ cgi-env/ogr_ws_service_provider.zo: service.c
+ g++ ${CFLAGS} -shared -fpic -o cgi-env/ogr_ws_service_provider.zo ./service.c $ {LDFLAGS}
+ clean:
+ rm -f cgi-env/ogr_ws_service_provider.zo
+
+
+Using this ``Makefile``, you should be able to run ``make`` from your ZOO Service Provider
+main directory and to get the resulting ``ogr_ws_service_provider.zo`` file located in the ``cgi-env`` directory.
+
+The metadata file and the ZOO Service Shared Object are now both located in the ``cgi-env``
+directory. In order to deploy your new ServicesProvider, you only have to copy the ZOO
+Service Shared Object and its corresponding metadata file in the directory where ZOO
+Kernel is located, so in ``/usr/lib/cgi-bin``. You must use a ``sudo`` command to achieve this task:
+
+.. code-block:: guess
+
+ sudo cp ./cgi-env/* /usr/lib/cgi-bin
+
+You should now understand more clearly the meannings of the ZOO Service Provider source tree !
+The ``cgi-env`` directory will let you deploy your new Services or Services Provider in
+an easy way , simply by copying the whole cgi-env content in your ``cgi-bin`` directory.
+
+Please note that you can add the following lines to your ``Makefile`` to be able to type
+``make install`` directly and to get your new Services Provider available for use from ZOO Kernel:
+
+.. code-block:: none
+
+ install:
+ sudo cp ./cgi-env/* /usr/lib/cgi-bin
+
+Your ZOO Services Provider is now ready to use from an Execute request passed to ZOO Kernel.
+
+Python Version
+*******************************************************************************************************
+
+For those using Python to implement their ZOO Services Provider, the full code to copy in
+``ogr_ws_service_provider.py`` in ``cgi-env`` directory is shown bellow. Indeed, as
+Python is an interpreted language, you do not have to compile anything before deploying
+your service which makes the deployement step much easier:
+
+.. code-block:: guess
+
+ import osgeo.ogr
+ import libxml2
+
+ def createGeometryFromWFS(my_wfs_response):
+ doc=libxml2.parseMemory(my_wfs_response,len(my_wfs_response))
+ ctxt = doc.xpathNewContext()
+ res=ctxt.xpathEval("/*/*/*/*/*[local-name()='Polygon' or local- name()='MultiPolygon']")
+ for node in res:
+ geometry_as_string=node.serialize()
+ geometry=osgeo.ogr.CreateGeometryFromGML(geometry_as_string)
+ return geometry
+ return geometry
+
+ def Boundary(conf,inputs,outputs):
+ if inputs["InputPolygon"]["mimeType"]=="application/json":
+ geometry=osgeo.ogr.CreateGeometryFromJson(inputs["InputPolygon"]["value"])
+ else:
+ geometry=createGeometryFromWFS(inputs["InputPolygon"]["value"])
+ rgeom=geometry.GetBoundary()
+ if outputs["Result"]["mimeType"]=="application/json":
+ outputs["Result"]["value"]=rgeom.ExportToJson()
+ outputs["Result"]["mimeType"]="text/plain"
+ else:
+ outputs["Result"]["value"]=rgeom.ExportToGML()
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+We do not dicuss the functions body here as we already gave all the details before and
+the code was volontary made in a similar way.
+
+As done before, you only have to copy the ``cgi-env`` files into your ``cgi-bin`` directory:
+
+.. code-block:: guess
+
+ sudo cp ./cgi-env/* /usr/lib/cgi-bin
+
+A simple ``Makefile`` containing the install section can be written as the following :
+
+.. code-block:: none
+
+ install:
+ sudo cp ./cgi-env/* /usr/lib/cgi-bin/
+
+Finally, simply run make install from the ZOO Services Provider main directory, in order to deploy your ZOO Service Provider.
+
+
+Testing the Service using Execute Request
+...............................................................................................................................................
+
+**The simple and unreadable way**
+
+Everybody should now get his own copy of the OGR Boundary Service stored as a ZOO
+Services Provider called ``ogr_ws_service_provider`` and deployed in the ZOO Kernel
+tree, so the following Execute request can be used to test the Service:
+
+`link `__
+
+.. code-block:: guess
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Boundary&DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3Fmap%3D%2Fvar%2Fwww%2Fwfs.map%26SERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192
+
+As you can see in the url above, we use an URLEncoded WFS request to the MapServer
+WFS server available on OSGeoLive as a ``xlink:href`` key in the DataInputs KVP value,
+and set the ``InputPolygon`` value to Reference. The corresponding non encoded WFS request is as follow:
+
+::
+
+ http://localhost/cgi-bin/mapserv?map=/var/www/wfs.map&SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&typename=regions&SRS=EPSG:4326&featureid=regions.3192
+
+Please note that you can add ``lineage=true`` to the previous request if you need
+to get information about the input values used to run your Service. Furthermore,
+you may need to store the ExecuteResponse document of your ZOO Service to re-use
+it later. In this case you must add ``storeExecuteResponse=true`` to the previous
+request. Note that is an important thing as the behavior of ZOO Kernel is not
+exactly the same than when running without this parameter settled to true. Indeed,
+in such a request, ZOO Kernel will give you an ExecuteResponse document which will
+contain the attribute statusLocation, which inform the client where the ongoing
+status or the final ExecuteResponse will be located.
+
+Here is an example of what the ExecuteResponse would look like in case ``storeExecuteResponse`` was set to true in the request:
+
+.. image:: ./images/Practical-introduction-to-ZOO-7.png
+ :width: 610px
+ :height: 146px
+ :align: center
+
+Then, according to the statusLocation, you should get the ExecuteResponse as you get
+before using the previous request. Note that can be really useful to provide some
+caching system for a client application.
+
+You didn't specify any ResponseForm in the previous request, it is not requested
+and should return a ResponseDocument per default using the application/json mimeType
+as you defined in you zcfg file. Nevertheless, you can tell ZOO Kernel what kind of
+data you want to get in result of your query adding the attribute ``mimeType=text/xml``
+to your ``ResponseDocument`` parameter. Adding this parameter to the previous request
+will give us the result as its GML representation :
+
+`link `__
+
+.. code-block:: guess
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Boundary&DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3Fmap%3D%2Fvar%2Fwww%2Fwfs.map%26SERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192&ResponseDocument=Result@mimeType=text/xml
+
+As defined by the WPS specifications, you can also ask for a ``RawDataOutput`` to
+get only the data without the full ``ResponseDocument``. To do that, you only have
+to replace the ``ResponseDocument`` of your request by ``RawDataOutput``, like in
+the following request :
+
+`link `__
+
+.. code-block:: guess
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Boundary&DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3Fmap%3D%2Fvar%2Fwww%2Fwfs.map%26SERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192&RawDataOutput=Result@mimeType=application/json
+
+Please note that we go back to the default mimeType to directly obtain the JSON
+string as we will use this kind of request to develop our client application in
+the next section of this workshop.
+
+Now, you know how to ask ZOO Kernel to run service in background, ask for ``RawDataOutput``
+specifying ``mimeType`` or any specific format to be returned by the Kernel. When you
+ask for ``ResponseDocument``, you can also specify to the ZOO Kernel that you want the
+result to be stored on the server side.
+
+To do such a thing, you have to set the attribute ``asReference`` as true and then the
+resulting ExecuteResponse will contain a Reference node including the href attribute
+to let you access the produced file. To be able to handle this, you have to add the
+extension parameter in your ``DataOutputs`` node in the corresponding ZCFG file.
+
+Here is a sample url which provide such a result:
+
+`link `__
+
+.. code-block:: guess
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Boundary&DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3Fmap%3D%2Fvar%2Fwww%2Fwfs.map%26SERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192&ResponseDocument=Result@mimeType=application/json@asReference=true
+
+You can see bellow what kind of result can be expected :
+
+.. image:: ./images/screenshot-ZOO-asReference-attribute.png
+ :width: 620px
+ :height: 217px
+ :align: center
+
+**Simplification and readability of request**
+
+As you can see in the simple example we used since the begining of this workshop,
+it is sometimes hard to write the Execute requests using the GET method as it
+makes really long and complexe URLs. In the next requests examples, we will
+thus use the POST XML requests. First , here is the XML request corresponding
+to the previous Execute we used:
+
+.. code-block:: guess
+
+
+ Boundary
+
+
+ InputPolygon
+ Playground area
+
+
+
+
+
+
+ Result
+ Area serviced by playground.
+ Area within which most users of this playground will live.
+
+
+
+
+
+In order to let you easily run the XML requests, a simple HTML form called
+``test_services.html`` is available in your ``/var/www`` directory. You can
+access it using the following link : http://localhost/test_services.html.
+
+Please open this page in your browser, simply fill the XML request content into
+the textarea field and click the « run using XML Request » submit button. You will
+get exactly the same result as when running your Service using the GET request. The
+screenshot above show the HTML form including the request and the ExecuteResponse
+document displayed in the iframe at the bottom of the page:
+
+.. image:: ./images/Practical-introduction-to-ZOO-8.png
+ :width: 573px
+ :height: 308px
+ :align: center
+
+The xlink:href value is used in the simplest way to deal with such data input. Obviously,
+you can also use a full JSON string of the geometry, as shown in the following XML Request example :
+
+.. code-block:: guess
+
+
+ Boundary
+
+
+ InputPolygon
+
+
+ { "type": "MultiPolygon", "coordinates": [ [ [ [ -105.998360, 31.393818 ], [ -106.212753, 31.478128 ], [ -106.383041, 31.733763 ], [ -106.538971, 31.786198 ], [ -106.614441, 31.817728 ], [ -105.769730, 31.170780 ], [ -105.998360, 31.393818 ] ] ], [ [ [ -94.913429, 29.257572 ], [ -94.767380, 29.342451 ], [ -94.748405, 29.319490 ], [ -95.105415, 29.096958 ], [ -94.913429, 29.257572 ] ] ] ] }
+
+
+
+
+
+
+
+ Result
+ Area serviced by playground.
+ Area within which most users of this playground will live.
+
+
+
+
+
+If everything went well, you should get the Boundary of the JSON geometry passed as
+argument, and so be sure that your Service support both GML and JSON as input data.
+Note that in the previous request, we added a ``mimeType`` attribute to the
+``ComplexData`` node to specify that the input data is not in the default ``text/xml``
+mimeType but passed as an ``application/json`` string directly. It is similar to add
+``@mimeType=application/json`` as we discussed before.
+
+**storeExecuteResponse parameter and GetStatus Service**
+
+If you go in your local ``/home/user/zoows/sources/zoo-services/utils/status``, you'll
+find the code for a ServiceProvider which will provide the GetStatus service and the
+longProcess one. The last is a simple example to learn how to use the status variable
+from lenv section of the main configuration maps and the updateStatus function you
+have to call to take your status value into account. The main service provider is
+the GetStatus one, it is able to give you information about the current status value
+from a service running in background mode.
+
+You have to know that the ZOO Kernel will detect the presence of the GetStatus service
+and if it is available it will then return the link the corresponding Execute request.
+
+So now you will deploy the GetStatus and longProcess service on your local environment.
+As for each services, you shall be able to deploy the services simply by copying the
+cgi-env directory into your Apache ``cgi-bin`` directory. You can use the following command :
+
+.. code-block:: guess
+
+ sudo cp ~user/zoows/sources/zoo-services/utils/status/cgi-env/*{zcfg,zo} /usr/lib/cgi-bin
+
+For simple Services it is the right way to deploy Service Providers. But in this specific
+case you'll have also to add some special parameter in the main section of you main
+configuration file and to copy an xsl file used to replace on the fly in the ResponseDocument
+the percentCompleted attribute of the ProcessStarted node returned by the GetStatus service.
+
+So first edit you ``main.cfg`` file to add the following lines in your main section :
+
+.. code-block:: guess
+
+ rewriteUrl=call
+ dataPath=/var/www/data
+
+Here you define the path where the service is able to find the xsl file, specified in the
+dataPath parameter. You also tell the ZOO Kernel that you want to use the rewriteUrl we
+defined in the previous section.
+
+To finish your deployment, you'll have now to copy the xsl file in the defined dataPath
+directory. You can use the following command :
+
+.. code-block:: guess
+
+ cp ~/zoows/sources/zoo-services/utils/status/cgi-env/*xsl /var/www/data
+
+Now, if you run the following request to run the service longProcess :
+
+http://localhost/zoo/?request=Execute&service=WPS&version=1.0.0&Identifier=longProcess&DataInputs=&storeExecuteResponse=true
+
+You shall get the a XML document looking like the following:
+
+.. image:: ./images/Practical-introduction-to-ZOO-9.png
+ :width: 590px
+ :height: 155px
+ :align: center
+
+If you poll the statusLocation url provider in the answer you'll then be able to view
+the evolution of the percentCompleted attribute value growing, like you can see in the following screenshot.
+
+.. image:: ./images/Practical-introduction-to-ZOO-10.png
+ :width: 589px
+ :height: 146px
+ :align: center
+
+This won't be used during this workshop but can be useful for really time consuming services.
+
+
+Creating Services for other functions (ConvexHull and Centroid)
+.........................................................................................................................................................
+
+
+As the Boundary sample service code is available, you can now easily add ConvexHull and
+Centroid functions as they take exactly the same number of arguments : Only one geometry.
+The details for implementing and deploying the ConvexHull Service are provided bellow,
+and we will let you do the same thing for the Centroid one.
+
+C Version
+*******************************************************************************************************
+Please add first the following code to the service.c source code :
+
+.. code-block:: guess
+
+ int ConvexHull(maps*& conf,maps*& inputs,maps*& outputs){
+ OGRGeometryH geometry,res;
+ map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+ if(tmp==NULL){
+ setMapInMaps(conf,"lenv","message","Unable to fetch InputPolygon value.");
+ return SERVICE_FAILED;
+ }
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0)
+ geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+ else
+ geometry=createGeometryFromWFS(conf,tmp->value);
+ if(geometry==NULL){
+ setMapInMaps(conf,"lenv","message","Unable to parse InputPolygon value.");
+ return SERVICE_FAILED;
+ }
+ res=OGR_G_ConvexHull(geometry);
+ tmp1=getMapFromMaps(outputs,"Result","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0){
+ char* tmp=OGR_G_ExportToJson(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ free(tmp);
+ }
+ else{
+ char* tmp=OGR_G_ExportToGML(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ free(tmp);
+ }
+ OGR_G_DestroyGeometry(geometry);
+ OGR_G_DestroyGeometry(res);
+ return SERVICE_SUCCEEDED;
+ }
+
+
+This new code is exactly the same as for the Boundary Service. The only thing we modified
+is the line where the `OGR_G_ConvexHull `__
+function is called (rather than the OGR_G_GetBoundary you used before). It is better to not copy
+and paste the whole function and find a more generic way to define your new Services as the
+function body will be the same in every case. The following generic function is proposed to make things simpler:
+
+.. code-block:: guess
+
+ int applyOne(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometryH (*myFunc) (OGRGeometryH)){
+ OGRGeometryH geometry,res;
+ map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+ if(tmp==NULL){
+ setMapInMaps(conf,"lenv","message","Unable to fetch InputPolygon value.");
+ return SERVICE_FAILED;
+ }
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0)
+ geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+ else
+ geometry=createGeometryFromWFS(conf,tmp->value);
+ if(geometry==NULL){
+ setMapInMaps(conf,"lenv","message","Unable to parse InputPolygon value.");
+ return SERVICE_FAILED;
+ }
+ res=(*myFunc)(geometry);
+ tmp1=getMapFromMaps(outputs,"Result","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0){
+ char *tmp=OGR_G_ExportToJson(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ free(tmp);
+ }
+ else{
+ char *tmp=OGR_G_ExportToGML(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ free(tmp);
+ }
+ outputs->next=NULL;
+ OGR_G_DestroyGeometry(geometry);
+ OGR_G_DestroyGeometry(res);
+ return SERVICE_SUCCEEDED;
+ }
+
+Then, a function pointer called myFunc rather than the full function name can be used.
+This way we can re-implement our Boundary Service this way:
+
+.. code-block:: guess
+
+ int Boundary(maps*& conf,maps*& inputs,maps*& outputs){
+ return applyOne(conf,inputs,outputs,&OGR_G_GetBoundary);
+ }
+
+Using this applyOne local function defined in the service.c source code, we can define
+other Services this way:
+
+.. code-block:: guess
+
+ int ConvexHull(maps*& conf,maps*& inputs,maps*& outputs){
+ return applyOne(conf,inputs,outputs,&OGR_G_ConvexHull);
+ }
+ int Centroid(maps*& conf,maps*& inputs,maps*& outputs){
+ return applyOne(conf,inputs,outputs,&MY_OGR_G_Centroid);
+ }
+
+The genericity of the applyOne function let you add two new Services in your ZOO Services Provider : ConvexHull and Centroid.
+
+Note that you should define MY_OGR_Centroid function before the Centroid one as `OGR_G_Centroid `__ don't return a geometry object but set the value to an already existing one and support only Polygon as input, so to ensure we use the ConvexHull for MultiPolygon. So please use the code bellow:
+
+.. code-block:: guess
+
+ OGRGeometryH MY_OGR_G_Centroid(OGRGeometryH hTarget){
+ OGRGeometryH res;
+ res=OGR_G_CreateGeometryFromJson("{\"type\": \"Point\", \"coordinates\": [0,0] }");
+ OGRwkbGeometryType gtype=OGR_G_GetGeometryType(hTarget);
+ if(gtype!=wkbPolygon){
+ hTarget=OGR_G_ConvexHull(hTarget);
+ }
+ OGR_G_Centroid(hTarget,res);
+ return res;
+ }
+
+To deploy your Services, you only have to copy the ``Boundary.zcfg`` metadata file from
+your cgi-env directory as ``ConvexHull.zcfg`` and ``Centroid.zcfg``. Then, you must
+rename the Service name on the first line to be able to run and test the Execute request
+in the same way you did before. You only have to set the Identifier value to ConvexHull
+or Centroid in your request depending on the Service you want to run.
+
+Note here that the GetCapabilities and DescribeProcess requests will return odd results
+as we didn't modified any metadata informations, you can edit the ``.zcfg`` files to set
+correct values. By the way it can be used for testing purpose, as the input and output
+get the same name and default/supported formats.
+
+Python Version
+*******************************************************************************************************
+
+.. code-block:: guess
+
+ def ConvexHull(conf,inputs,outputs):
+ if inputs["InputPolygon"]["mimeType"]=="application/json":
+ geometry=osgeo.ogr.CreateGeometryFromJson(inputs["InputPolygon"]["value"])
+ else:
+ geometry=createGeometryFromWFS(inputs["InputPolygon"]["value"])
+ rgeom=geometry.ConvexHull()
+ if outputs["Result"]["mimeType"]=="application/json":
+ outputs["Result"]["value"]=rgeom.ExportToJson()
+ outputs["Result"]["mimeType"]="text/plain"
+ else:
+ outputs["Result"]["value"]=rgeom.ExportToGML()
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+
+Once again, you can easily copy and paste the function for Boundary and simply modify
+the line where the Geometry method was called. Nevertheless, as we did for the C language
+we will give you a simple way to get things more generic.
+
+First of all, the first step which consists in extracting the InputPolygon Geometry as
+it will be used in the same way in each Service functions, so we will first create a
+function which will do that for us. The same thing can also be done for filling the
+output value, so we will define another function to do that automaticaly. Here is the
+code of this two functions (extractInputs and outputResult) :
+
+.. code-block:: guess
+
+ def extractInputs(obj):
+ if obj["mimeType"]=="application/json":
+ return osgeo.ogr.CreateGeometryFromJson(obj["value"])
+ else:
+ return createGeometryFromWFS(obj["value"])
+ return null
+
+ def outputResult(obj,geom):
+ if obj["mimeType"]=="application/json":
+ obj["value"]=geom.ExportToJson()
+ obj["mimeType"]="text/plain"
+ else:
+ obj["value"]=geom.ExportToGML()
+
+We can so minimize the code of the Boundary function to make it simplier using the following function definition :
+
+.. code-block:: guess
+
+ def Boundary(conf,inputs,outputs):
+ geometry=extractInputs(inputs["InputPolygon"])
+ rgeom=geometry.GetBoundary()
+ outputResult(outputs["Result"],rgeom)
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+Then definition of the ConvexHull and Centroid Services can be achieved using the following code:
+
+.. code-block:: guess
+
+ def ConvexHull(conf,inputs,outputs):
+ geometry=extractInputs(inputs["InputPolygon"])
+ rgeom=geometry.ConvexHull()
+ outputResult(outputs["Result"],rgeom)
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+ def Centroid(conf,inputs,outputs):
+ geometry=extractInputs(inputs["InputPolygon"])
+ if geometry.GetGeometryType()!=3:
+ geometry=geometry.ConvexHull()
+ rgeom=geometry.Centroid()
+ outputResult(outputs["Result"],rgeom)
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+Note, that in Python you also need to use ConvexHull to deal with MultiPolygons.
+
+You must now copy the ``Boundary.zcfg`` file as we explained for the C version in ``ConvexHull.zcfg`` and ``Centroid.zcfg`` respectively and then, use make install command to re-deploy and test your Services Provider.
+
+Create the Buffer Service
+
+
+We can now work on the Buffer Service, which takes more arguments than the other ones.
+Indeed, the code is a bit different from the one used to implement the Boundary, ConvexHull and Centroid Services.
+
+The Buffer service also takes an input geometry, but uses a BufferDistance parameter.
+It will also allow you to define LitteralData block as the BufferDistance will be
+simple integer value. The read access to such kind of input value is made using the
+same function as used before.
+
+C Version
+*******************************************************************************************************
+
+If you go back to the first Boundary Service source code, you should not find the
+following very complicated. Indeed, you simply have to add the access of the
+BufferDistance argument and modify the line whenthe `OGR_G_Buffer `__
+must be called (instead of OGR_G_GetBoundary). Here is the ful lcode :
+
+.. code-block:: guess
+
+ int Buffer(maps*& conf,maps*& inputs,maps*& outputs){
+ OGRGeometryH geometry,res;
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","value");
+ if(tmp==NULL){
+ setMapInMaps(conf,"lenv","message","Unable to fetch InputPolygon value.");
+ return SERVICE_FAILED;
+ }
+ map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+ if(strncmp(tmp->value,"application/json",16)==0)
+ geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+ else
+ geometry=createGeometryFromWFS(conf,tmp->value);
+ double bufferDistance=1;
+ tmp=getMapFromMaps(inputs,"BufferDistance","value");
+ if(tmp!=NULL)
+ bufferDistance=atof(tmp->value);
+ res=OGR_G_Buffer(geometry,bufferDistance,30);
+ tmp1=getMapFromMaps(outputs,"Result","mimeType");
+ if(strncmp(tmp1->value,"application/json",16)==0){
+ char *tmp=OGR_G_ExportToJson(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ setMapInMaps(outputs,"Result","mimeType","text/plain");
+ free(tmp);
+ }
+ else{
+ char *tmp=OGR_G_ExportToGML(res);
+ setMapInMaps(outputs,"Result","value",tmp);
+ free(tmp);
+ }
+ outputs->next=NULL;
+ OGR_G_DestroyGeometry(geometry);
+ OGR_G_DestroyGeometry(res);
+ return SERVICE_SUCCEEDED;
+ }
+
+The new code must be inserted in your service.c file and need to be recompiled and
+replace the older version of your ZOO Service Provider in the /usr/lib/cgi-bin/ directory.
+You must of course place the corresponding ZOO Metadata File in the same directory.
+
+As we explained before, ZOO Kernel is permissive in the sense that you can pass more
+arguments than defined in you zcfg file, so let's try using a copy of the ``Boundary.zcfg``
+file renamed as ``Buffer.zcfg`` and containing the Buffer identifier. Then, please
+test your service using an Execute request as you did before. You will obtain the
+buffer result in a ResponseDocument.
+
+You may have noted that the above code check if a BufferDistance input was passed
+to the service. If not, we will use 1 as the default value, which explains why
+you do not have to use one more input to your previous queries.
+
+You can change the BufferDistance value used by your Service to compute Buffer
+of your geometry by adding it to the DataInputs value in your request. Note that
+using KVP syntaxe, each DataInputs are separated by a semicolon.
+
+So, the previous request:
+
+.. code-block:: guess
+
+ DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3FSERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192
+
+Can now be rewritten this way :
+
+.. code-block:: guess
+
+ DataInputs=InputPolygon=Reference@xlink:href=http%3A%2F%2Flocalhost%2Fcgi-bin%2Fmapserv%3FSERVICE%3DWFS%26REQUEST%3DGetFeature%26VERSION%3D1.0.0%26typename%3Dregions%26SRS%3DEPSG%3A4326%26FeatureID%3Dregions.3192;BufferDistance=2
+
+Setting BufferDistance value to 2 would give you a different result, then don't
+pass any other parameter as we defined 1 as the default value in the source code.
+
+Here you can find the same query in XML format to use from the http://localhost/test_services.html HTML form :
+
+.. code-block:: guess
+
+
+ Buffer
+
+
+ InputPolygon
+ Playground area
+
+
+
+ BufferDistance
+
+ 2
+
+
+
+
+
+
+ Buffer
+ Area serviced by playground.
+ Area within which most users of this playground will live.
+
+
+
+
+
+Python Version
+*******************************************************************************************************
+
+As we already defined the utility functions createGeometryFromWFS and outputResult,
+the code is as simple as this:
+
+.. code-block:: guess
+
+ def Buffer(conf,inputs,outputs):
+ geometry=extractInputs(inputs["InputPolygon"])
+ try:
+ bdist=int(inputs["BufferDistance"]["value"])
+ except:
+ bdist=10
+ rgeom=geometry.Buffer(bdist)
+ outputResult(outputs["Result"],rgeom)
+ geometry.Destroy()
+ rgeom.Destroy()
+ return 3
+
+We simply added the use of inputs["BufferDistance"]["value"] as arguments of the
+Geometry instance Buffer method. Once you get this code added to your ogr_ws_service_provider.py
+file, simply copy it in the ZOO Kernel directory (or type make install from your ZOO Service
+Provider root directory). Note that you also need the ``Buffer.zcfg`` file detailled in the next section.
+
+The Buffer MetadataFile file
+*******************************************************************************************************
+
+You must add BufferDistance to the Service Metadata File to let clients know that
+this Service supports this parameter. To do this, please copy your orginal ``Boundary.zcfg``
+file as ``Buffer.zcfg`` and add the following lines to the DataInputs block :
+
+.. code-block:: none
+
+ [BufferDistance]
+ Title = Buffer Distance
+ Abstract = Distance to be used to calculate buffer.
+ minOccurs = 0
+ maxOccurs = 1
+
+ DataType = float
+
+ uom = degree
+ value = 10
+
+
+ uom = meter
+
+
+
+Note that as minOccurs is set to 0 which means that the input parameter is optional
+and don't have to be passed. You must know that ZOO Kernel will pass the default
+value to the Service function for an optional parameter with a default value set.
+
+You can get a full copy of the ``Buffer.zcfg`` file here :
+
+http://zoo-project.org/trac/browser/trunk/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg
+
+You can now ask ZOO Kernel for GetCapabilities, DescribeProcess and Execute for the Buffer Service.
Index: /trunk/workshop/2010/using_zoo_from_osgeolivevm.rst
===================================================================
--- /trunk/workshop/2010/using_zoo_from_osgeolivevm.rst (revision 723)
+++ /trunk/workshop/2010/using_zoo_from_osgeolivevm.rst (revision 723)
@@ -0,0 +1,181 @@
+.. _using_zoo_from_osgeolivevm:
+
+Using ZOO from an OSGeoLive virtual machine
+###########################################
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+`OSGeoLive `__ is a live DVD and virtual machine based on `Xubuntu `__ that allows you to try a wide variety of open source geospatial software without installing anything. It is composed entirely of free software and include ZOO 1.0 this year, for testing purpose.
+
+ZOO Kernel Installation
+***********************
+
+As already said in introduction, an OSGeoLive virtual machine image disk has
+been installed on your computer, allowing you to use ZOO Kernel in a development
+environment directly. Using a virtual machine image disk seems to be the simplest
+way to use ZOO Kernel and to develop ZOO Services locally, as we can ensure that
+everything requested for compiling C Services and running Python ones is available
+and ready to use. Every ZOO related material and source code have been placed in
+``/home/user/zoows`` directory. We will work inside it during this workshop. As
+the binary version of ZOO Kernel is already compiled and stored in ``/home/user/zoows/sources/zoo-kernel``,
+you only have to copy two important files inside the ``/usr/lib/cgi-bin``
+directory : ``zoo_loader.cgi`` and the ``main.cfg`` in order to make ZOO Kernel
+available, using the following commands :
+
+.. code-block:: guess
+
+ sudo cp ~/zoows/sources/zoo-kernel/zoo_loader.cgi /usr/lib/cgi-bin
+ sudo cp ~/zoows/sources/zoo-kernel/main.cfg /usr/lib/cgi-bin
+
+
+Please note that we will talk about ZOO Kernel or ``zoo_loader.cgi`` script without
+any distinction during this workshop.
+
+The ``main.cfg`` file contains metadata informations about the identification and
+provider but also some important settings. The file is composed of various sections,
+namely main, identification and provider per default. Obviously, you are free to add
+new sections to the file if you need them for a specific Service. Nevertheless, you
+have to know that the env and lenv sections name are used in a specific way.
+
+The env section lets you define environment variables that your Service requires
+during its runtime. For instance, if your Service requires to access to a X server
+running on framebuffer, then you will have to set the ``DISPLAY`` environnement
+variably, in this case you would add ``DISPLAY=:1`` line in your env section.
+
+As for the env section, there is the section lenv where specific informations about
+status informations of a running Service will be written by the ZOO Kernel or the
+ZOO Services. For instance, when your service failed, you can set the value for
+message in lenv to see it displayed in the Status node of the ExecuteResponse
+returned back to the client. If your service will take long time and can get
+informations about processing status, you can then set a value between 0 and 100
+to status in lenv to represent the percentage completed of the running Service task,
+we will talk deeper about this later in this workshop.
+
+Please take a look to your local file ``main.cfg`` file. Three important parameters are commented bellow:
+
+ - serverAddress : The url to access to the ZOO Kernel
+ - tmpPath : The full path to store temporary files
+ - tmpUrl : The url path relative to serverAddress to access temporary directory.
+
+The values of the main.cfg file used from the running virtual machine are the following :
+
+.. code-block:: guess
+
+ serverAddress=http://localhost/zoo
+ tmpPath=/var/www/temp
+ tmpUrl=../temp/
+
+You could have noticed that the tmpUrl is a relative url from ``serverAddress``,
+so it must be a directory. Even if ZOO Kernel can be used with the full url of
+the ``zoo_loader.cgi`` script, for better readability and fully functional ZOO Kernel,
+you have to modify the default Apache configuration in order to be able to use the
+http://localhost/zoo/ url directly.
+
+First, please create a ``zoo`` directory in the existing ``/var/www`` which is
+used by Apache as the ``DocumentRoot``. Then, please edit the ``/etc/apache2/sites-available/default``
+configuration file and add the following lines after the ``Directory`` block related to ``/var/www`` directory :
+
+.. code-block:: none
+
+
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ allow from all
+
+
+Now create a small ``.htaccess`` file in the ``/var/www/zoo`` containing the following lines:
+
+.. code-block:: guess
+
+ RewriteEngine on
+ RewriteRule call/(.*)/(.*) /cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=$1&DataInputs=sid=$2&RawDataOutput=Result [L,QSA]
+ RewriteRule (.*)/(.*) /cgi-bin/zoo_loader.cgi?metapath=$1 [L,QSA]
+ RewriteRule (.*) /cgi-bin/zoo_loader.cgi [L,QSA]
+
+For this last file to be taken into account by Apache, you must activate the
+rewrite Apache module by copying a load file as bellow :
+
+.. code-block:: guess
+
+ sudo cp /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/
+
+Or using the ``a2enmod`` tool this way :
+
+.. code-block:: guess
+
+ a2enmod rewrite
+
+Now you should be able to access the ZOO Kernel using a simplified by restarting your Apache Web server :
+
+.. code-block:: guess
+
+ sudo /etc/init.d/apache2 restart
+
+
+Two other softwares form the OSGeoLive environment will be used during this workshop.
+MapServer will first be used to provide WFS input data for the ZOO Services we are
+going to develop. The MapServer dataset providen by Orkney (japanese regions polygons)
+will be passed to our service during `section 4 `__.
+
+OpenLayers library is also available on the OSGeoLive virtual machine image disk,
+and it will be used during `section 4 `__, for building a simple WPS client application able to query the newly developed ZOO Services.
+
+As we planned to use OGR C-API and Python module of the GDAL library, we will need
+the corresponding header files, libraries and associated files. Hopefully everything
+was already available per default and so ready to use on the OSGeoLive packaging.
+
+Testing the ZOO installation with GetCapabilities
+*************************************************
+
+
+You can now simply query ZOO Kernel using the following request from your Internet browser:
+
+http://localhost/cgi-bin/zoo_loader.cgi?Request=GetCapabilities&Service=WPS
+
+You should then get a valid Capabilities XML document, as the following :
+
+.. image:: ./images/Practical-introduction-to-ZOO-2.png
+ :width: 458px
+ :height: 159px
+ :align: center
+
+Please note that no Process node is returned in the ProcessOfferings section, as no
+ZOO Service is available yet. You can also proceed to a GetCapabilities request from
+the command line, using the following command:
+
+.. code-block:: none
+
+ cd /usr/lib/cgi-bin
+ ./zoo_loader.cgi “request=GetCapabilities&service=WPS”
+
+The same result as in your browser will be returned, as shown in the following screenshot:
+
+.. image:: ./images/Practical-introduction-to-ZOO-3.png
+ :width: 395px
+ :height: 251px
+ :align: center
+
+Invoking ZOO Kernel from command line can be helpful during development process of new Services.
+
+Preparing your ZOO Services Provider directory
+**********************************************
+
+In order to simplify the task, we will first comment the directory structure which
+should be used when creating a new Services Provider :
+
+ - The main Services Provider directory including :
+
+ - A ``cgi-env`` directory which will contain all the zcfg metadata files and the service shared object (C Shared Library or Python module)
+ - The ``Makefile`` and the ``*c`` files needed to compile your Services Provider.
+
+Please create a ws_sp main Services Provider directory in the existing zoo-services one located in ``/home/user/zoows/sources/``, respecting the tree above .
+
+.. code-block:: guess
+
+ mkdir -p /home/user/zoows/sources/zoo-services/ws_sp/cgi-env
+
+The Makefile and the code of the C and Python Service Shared Object will be detailed in the next sections.
+
Index: /trunk/workshop/2012/building_blocks_presentation.rst
===================================================================
--- /trunk/workshop/2012/building_blocks_presentation.rst (revision 723)
+++ /trunk/workshop/2012/building_blocks_presentation.rst (revision 723)
@@ -0,0 +1,88 @@
+.. _ogr_base_vect_ops:
+
+*********************************************************
+Presenting building blocks - Using OGR based Web Services
+*********************************************************
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+============
+
+In this section, you will use basic ZOO-Services : ``BufferPy``,
+``IntersectionPy`` and ``DifferencePy`` which use OGR Python module.
+The intended goal of this section is to present and interact with your new building blocks before chaining them in the next section.
+
+First of all, you should use the following link to access a user interface to interact with your service :
+`http://localhost/zoows-demo/spatialtools-py.html `__
+
+Services Provider and configuration files
+=========================================
+
+First you may verify if the ZOO-Services are available from your current setup.
+You can take a look at the ``Buffer.zcfg``, ``Intersection.zcfg`` and
+``DifferencePy.zcfg`` to get details about parameters.
+As you can see from the ZCFG files, you will use ZOO-Services provided by the
+``foss4g_ws`` Python service provider. So if you want to modify the Python code
+you will have to edit this file.
+You are invited to use similar requests as you seen in previous sections to learn about each service.
+
+The Buffer Service
+=========================
+
+First click on a street then once the street is displayed in blue, click the
+'Buffer' button on top, you should get similar result as displayed in the following.
+
+.. image:: ./images/Buffer_Level_15.png
+ :width: 650px
+ :align: center
+
+Since version ZOO-Project 1.2.0, you can run automatically some basic tests to
+make sure that you wrote a correct ZCFG file and your service is validating.
+
+.. note:: the current testing is really simple and should be adapted to each Services
+ Provider, mainly to define input names.
+
+You can use the following command:
+
+.. code-block:: bash
+
+ cd /home/user/zoo/testing
+ ./run.sh http://localhost/cgi-bin/zoo_loader.cgi Buffer
+
+
+.. note:: During or after the test run, you can take a look inside the ``tmp`` directory
+ which contains both the XML requests send to the ZOO Kernel (``*1.xml``) and the
+ responses it gave (``output*.xml``).
+
+The Intersection Service
+=========================
+
+Using the same client interface as before, once you get a Buffer, you can then
+select a street intersecting the Buffer geometry to compute intersection by clicking on the Intersection button.
+
+
+.. image:: ./images/Intersection_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The Difference Service
+=========================
+
+Using the same instructions as for Intersetion, you can get the following result.
+
+.. image:: ./images/Difference_Level_15.png
+ :width: 650px
+ :align: center
+
+
+Conclusion
+========
+
+Now you know this three services, and you get a simple interface to interact
+with your MapServer WFS and your ZOO-Project WPS Servers, you are ready to use
+the Services in a different way by chaining them using the ZOO-API to build
+more complexe and powerfull services.
Index: /trunk/workshop/2012/first_service.rst
===================================================================
--- /trunk/workshop/2012/first_service.rst (revision 723)
+++ /trunk/workshop/2012/first_service.rst (revision 723)
@@ -0,0 +1,353 @@
+.. _first_service:
+
+*******************************
+Creating your first ZOO Service
+*******************************
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+============
+
+In this part, you will create and publish from a simple ZOO Service named
+``Hello`` which will simply return a hello message containing the input value
+provided. It will be usefull to present in deeper details general concept on how ZOO-Kernel works and handles request.
+
+Service and publication process overview
+========================================
+
+Before starting developing a ZOO Service, you should remember that in
+ZOO-Project, a Service is a couple made of:
+
+ * a metadata file: a ZOO Service Configuration File (ZCFG) containing metadata
+ informations about a Service (providing informations about default / supported
+ inputs and outputs for a Service)
+ * a Services Provider: it depends on the programming language used, but for Python it
+ is a module and for JavaScript a script file.
+
+To publish your Service, which means make your ZOO Kernel aware of its presence,
+you should copy a ZCFG file in the directory where ``zoo_loader.cgi`` is located (in this workshop, ``/usr/lib/cgi-bin``).
+
+.. warning:: only the ZCFG file is required for the Service to be considerate as
+ available. So if you don't get the Service Provider, obviously your Execute
+ request will fail as we will discuss later.
+
+Before publication, you should store your ongoing work, so you'll start by
+creating a directory to store the files of your Services Provider:
+
+.. code-block:: none
+
+ mkdir -p /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env
+
+Once both the ZCFG and the Python module are both ready, you can publish simply
+by copying the corresponding files in the same directory as the ZOO-Kernel.
+
+Creating your first ZCFG file
+=============================
+
+You will start by creating the ZCFG file for the ``Hello`` Service. Edit the
+``/home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/Hello.zcfg`` file
+and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Hello]
+ Title = Return a hello message.
+ Abstract = Create a welcome string.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = test_service
+ serviceType = Python
+
+ [name]
+ Title = Input string
+ Abstract = The string to insert in the hello message.
+ minOccurs = 1
+ maxOccurs = 1
+
+ dataType = string
+
+
+
+
+ [Result]
+ Title = The resulting string
+ Abstract = The hello message containing the input string
+
+
+ dataType = string
+
+
+
+
+
+.. note:: the name of the ZCFG file and the name between braket (here ``[Hello]``)
+ should be the same and correspond to the function name you will define in your
+ Services provider.
+
+As you can see in the ZOO Service Configuration File presented above it is divided into
+three distinct sections:
+ #. Main Metadata information (from line 2 to 8)
+ #. List of Inputs metadata information (from 9 line to 20)
+ #. List of Outputs metadata information (from line 21 to 36)
+
+You can get more informations about ZCFG from `the reference documentation
+`__.
+
+If you copy the ``Hello.zcfg`` file in the same directory as your ZOO Kernel
+then you will be able to request for DescribeProcess using the ``Hello``
+``Identifier``. The ``Hello`` service should also be listed from Capabilities
+document.
+
+.. code-block:: none
+ cp /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/Hello.zcfg /usr/lib/cgi-bin
+
+Test requests
+=================
+
+In this section you will tests each WPS requests : GetCapabilities,
+DescribeProcess and Execute. Note that only GetCapabilities and DescribeProcess
+should work at this step.
+
+Test the GetCapabilities request
+--------------------------------
+
+If you run the ``GetCapabilities`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=GetCapabilities&service=WPS
+
+Now, you should find your Hello Service in a ``Process`` node in
+``ProcessOfferings``:
+
+.. code-block:: xml
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+Test the DescribeProcess request
+--------------------------------
+
+You can access the ``ProcessDescription`` of the ``Hello`` service using the
+following ``DescribeProcess`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=DescribeProcess&service=WPS&version=1.0.0&Identifier=Hello
+
+You should get the following response:
+
+.. code-block:: xml
+
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+ name
+ Input string
+ The string to insert in the hello message.
+
+ string
+
+
+
+
+
+
+
+
+
+
+Test the Execute request
+------------------------
+
+Obviously, you cannot run your Service because the Python file was not published
+yet. If you try the following ``Execute`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You should get an ExceptionReport similar to the one provided in the following,
+which is normal behavior:
+
+.. code-block:: xml
+
+
+
+ Python module test_service cannot be loaded.
+
+
+
+Implementing the Python Service
+================================
+
+General Principles
+------------------
+
+The most important thing you must know when implementing a new ZOO-Services
+using the Python language is that the function corresponding to your Service
+returns an integer value representing the status of execution
+(``SERVICE_FAILED`` [#f1]_ or ``SERVICE_SUCCEEDED`` [#f2]_) and takes three
+arguments (`Python dictionaries
+`__):
+
+ - ``conf`` : the main environment configuration (corresponding to the main.cfg content)
+ - ``inputs`` : the requested / default inputs (used to access input values)
+ - ``outputs`` : the requested / default outputs (used to store computation result)
+
+.. note:: when your service return ``SERVICE_FAILED`` you can set
+ ``conf["lenv"]["message"]`` to add a personalized message in the ExceptionReport
+ returned by the ZOO Kernel in such case.
+
+You get in the following a sample ``conf`` value based on the ``main.cfg`` file you
+saw `before `__.
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ "main": {
+ language: "en-US",
+ lang: "fr-FR,ja-JP",
+ version: "1.0.0",
+ encoding: "utf-8",
+ serverAddress: "http://localhost/cgi-bin/zoo_loader.cgi",
+ dataPath: "/var/www/zoows-demo/map/data",
+ tmpPath: "/var/www/temp",
+ tmpUrl: "../temp",
+ cacheDir: "/var/www/temp/"
+ },
+ "identification": {
+ title: "The ZOO-Project OSGeoLiveDVD Server 2012",
+ keywords: "WPS,GIS,buffer",
+ abstract: "Demo version of Zoo-Project for OSGeoLiveDVD 2012. See http://www.zoo-project.org",
+ accessConstraints: "none",
+ fees: "None"
+ },
+ "provider": {
+ positionName: "Developer",
+ providerName: "ZOO-Project",
+ addressAdministrativeArea: "Lattes",
+ addressCountry: "fr",
+ phoneVoice: "False",
+ addressPostalCode: "34970",
+ role: "Dev",
+ providerSite: "http://www.zoo-project.org",
+ phoneFacsimile: "False",
+ addressElectronicMailAddress: "gerald.fenoy@geolabs.fr",
+ addressCity: "Denver",
+ individualName: "Gérald FENOY"
+ }
+
+In the following you get a sample outputs value passed to a Python or a JavaScript Service:
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ 'Result': {
+ 'mimeType': 'application/json',
+ 'inRequest': 'true',
+ 'encoding': 'UTF-8'
+ }
+ }
+
+.. note:: the ``inRequest`` value is set internally by the ZOO-Kernel and can be used to determine from the Service if the key was provided in the request.
+
+The Hello Service
+------------------------
+
+You can copy and paste the following into the
+``/home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/test_service.py`` file.
+
+.. code-block:: python
+
+ def Hello(conf,inputs,outputs):
+ outputs["Result"]["value"]=\
+ "Hello "+inputs["name"]["value"]+" from the ZOO-Project Python world !"
+ return 3
+
+Once you finish editing the file, you should copy it in the ``/usr/lib/cgi-bin`` directory:
+
+.. code-block:: none
+
+ sudo cp /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/* /usr/lib/cgi-bin
+
+
+Interracting with your service using Execute requests
+=====================================================
+
+Now, you can request for Execute using the following basic url:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You can request the WPS Server to return a XML WPS Response containing the result of
+your computation, requesting for ResponseDocument or you can access the data directly
+requesting for RawDataOutput.
+
+* Sample request using the RawDataOutput parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&RawDataOutput=Result
+
+* Sample request using the default ResponseDocument parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result
+
+When you are using ResponseDocument there is specific attribut you can use to ask
+the ZOO Kernel to store the result: ``asReference``. You can use the following example:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result@asReference=true
+
+When computation take long time, the client should request setting both
+``storeExecuteResponse`` and ``status`` parameter to true. This will make the ZOO
+Kernel directly return a response containing a ``statusLocation`` attribut which can be
+used to access the status of an ongoing service or the result when the process ended.
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result&storeExecuteResponse=true&status=true
+
+Conclusion
+==========
+
+Even if this first service was really simple it was useful to illustrate how the
+ZOO-Kernel fill ``conf``, ``inputs`` and ``outputs`` parameter prior to load
+and run your function service, how to write a ZCFG file, how to publish a Services
+Provider by placing the ZCFG and Python files in the same directory as the
+ZOO-Kernel, then how to interract with your service using both
+``GetCapabilities``, ``DescribeProcess`` and ``Execute`` requesr. We will see
+in the `next section `__ how to write similar requests
+using the XML syntax.
+
+.. rubric:: Footnotes
+
+.. [#f1] ``SERVICE_FAILED=4``
+.. [#f2] ``SERVICE_SUCCEEDED=3``
+
Index: /trunk/workshop/2012/index.rst
===================================================================
--- /trunk/workshop/2012/index.rst (revision 723)
+++ /trunk/workshop/2012/index.rst (revision 723)
@@ -0,0 +1,25 @@
+.. _workshop-foss4g-cee-2012:
+
+##########################################
+ZOO-Project Workshop 2012
+##########################################
+
+:Original Title: **Practical Introduction to ZOO-Project by playing with building blocks**
+:Author: Nicolas Bozon, Gérald Fenoy, Venkatesh Raghavan
+:Contact: gerald.fenoy at geolabs.fr, nicolas.bozon at gmail.com
+:Last Updated: $Date$
+:Events: FOSS4G 2012 Prague
+
+.. image:: ./images/foss4gcee2012.png
+
+
+**WorkShop table of content**
+
+.. toctree::
+ :maxdepth: 5
+
+ introduction
+ using_zoo_from_osgeolivevm
+ first_service
+ building_blocks_presentation
+ js_services_chaining
Index: /trunk/workshop/2012/introduction.rst
===================================================================
--- /trunk/workshop/2012/introduction.rst (revision 723)
+++ /trunk/workshop/2012/introduction.rst (revision 723)
@@ -0,0 +1,60 @@
+.. _introduction:
+
+**************
+Introduction
+**************
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+What is ZOO ?
+=============
+
+ZOO-Project is a WPS (Web Processing Service) open source project released under a `MIT/X-11 `__ style license. It provides an OGC WPS compliant developer-friendly framework to create and chain WPS Web services. ZOO is made of three parts:
+
+* `ZOO Kernel `__ : A powerful server-side C Kernel which makes it possible to manage and chain Web services coded in different programming languages.
+* `ZOO Services `__ : A growing suite of example Web Services based on various open source libraries.
+* `ZOO API `__ : A server-side JavaScript API able to call and chain the ZOO Services, which makes the development and chaining processes easier and faster.
+
+ZOO was designed to make the service creation and deployment easy, by providing a powerful system able to understand and execute WPS compliant queries. It supports seven programming languages, thus allowing you to create Web Services using the one you prefer. It also lets you use an existing code and to turn it as a WPS Service.
+The current supported programming languages are the following:
+
+* C/C++
+* Python
+* Perl
+* Java
+* Fortran
+* PHP
+* JavaScript
+
+More information on the project is available on the `ZOO Project official website `__ .
+
+How does ZOO works ?
+====================
+
+ZOO is based on a C Kernel which is the ZOO-Project core system (aka ZOO-Kernel). The latter is able to dynamically load libraries and to handle them as on-demand Web services.
+
+A ZOO-Service is a link composed of a ZOO metadata file (.zcfg) and the code for the corresponding implementation. The metadata file describes all the available functions that can be called using a WPS Execute Request, as well as the desired input/output. Services contain the algorithms and functions, and can be implemented using any of the supported languages.
+
+ZOO-Kernel works as CGI through Apache and can communicate with cartographic engines and Web mapping clients. It simply adds the WPS support to your spatial data infrastructure and your webmapping applications. It can use every GDAL/OGR supported formats as input data and create suitable vector or raster output for your cartographic engine and/or your web-mapping client application.
+
+What are we going to do in this workshop?
+===============================
+
+Participants will then learn how to use ZOO Kernel and how to create ZOO Services using the OSGeo Live 5.5 A pre-compiled ZOO 1.3-dev package is provided inside OSGeoLive, so participants won't have to compile and install it manually. Configuration file and basic ways to run ZOO Kernel and ZOO Service will be presented. Participants will be then invited to start programming their own service using Python language. Some ZOO Services will be presented and individually tested inside a ready-to-use OpenLayers application. Finally, this services will be chained using the server-side Javascript ZOO API.
+
+The whole workshop is organized step-by-step and numerous code snippets are available along with their respective explanations. The instructors will check the ZOO Kernel functioning on each machine and will assist you while coding. Technical questions are of course welcome during the workshop.
+
+Usefull tips for reading
+========================
+
+.. code-block:: guess
+
+ this is a code block
+
+.. warning:: This is a warning message.
+
+.. note:: This is an important note.
+
+**Let's go !**
Index: /trunk/workshop/2012/js_services_chaining.rst
===================================================================
--- /trunk/workshop/2012/js_services_chaining.rst (revision 723)
+++ /trunk/workshop/2012/js_services_chaining.rst (revision 723)
@@ -0,0 +1,536 @@
+.. _ogr_base_vect_ops:
+
+***************************************************************
+Playing with buildign blocks - Creating JavaScript Web Services
+***************************************************************
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+============
+
+
+This section illustrate how you can use JavaScript on the server-side to chain
+services together to build new ones. You will create a ZOO Services Provider
+using the services you seen before and the WFS server using the ZOO-API. The
+final goal is to query all POIs included in a buffer around a feature and
+to highlight them using a mask around this buffer. The following screenshot show
+you the expected result:
+
+.. image:: ./images/BufferMaskAndRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+You can decompose the result above in two different ones: the mask around the
+buffer and the points included in the buffer. So you will create two different
+Services: one called ``BufferMask`` and another one called ``BufferRequest``.
+
+But before implementing any JavaScript Service, you will get an overview of how
+to use ZOO-API from your ZOO-Project installation in the next section.
+
+As before, you first create a new directory to store files for your new Services
+Provider named ``ws2012js``:
+
+.. code-block:: guess
+
+ mkdir -p ~/zoo-ws-2012/zoo-project/zoo-services/ws2012js/cgi-env/
+
+
+ZOO-API Overview
+================
+
+ZOO-API and ZOO-Kernel JavaScript support make you able to run services
+implemented in JavaScript on the server side. JavaScript is a popular programing
+language but mostly used on the client side. Let say from a browser, but here it
+is a bit different.
+
+To support JavaScript language ZOO-Kernel use the
+`SpiderMonkey `__ API to create a
+javascript runtime environment from which it will load your JS file then extract
+the function corresponding to the service to run it using the prefilled
+parameters. The JavaScript runtime environment created by the ZOO-Kernel
+depend on your setup. If you placed the ``ZOO-api.js`` and ``ZOO-proj4js.js`` in
+the same directory as your ZOO-Kernel it means that your environment will
+contains ZOO-API and Proj4js will be loaded before your service. In such case you can access to the Classes defined in the JavaScript ZOO-API
+to manipulate geographic data, for more informations please refer to the
+`ZOO-API Documentation `__.
+
+Even if it can be useful to run JavaScript on the server side, you should
+remember that some basic JavaScript functions you are familiar with does not
+exist or get a different behavior. For instance the simple ``alert``
+function will display messages in apache error logs rather than in a window when
+used from a browser. The ``alert`` function can be used as follow:
+
+.. code-block:: guess
+
+ alert("My alert message");
+
+There is no XMLHttpRequest available in the JavaScript evironement your service
+will run into. Hopefully, the ZOO-Kernel expose a C function to the JavaScript
+world named: ``JSRequest``. This function make you able from your JavaScript
+services to call other WPS services (locally or remotelly) or other kind OGC
+services such as WFS. When you are using the ZOO-API it is possible to call
+Services using a ``ZOO.Process`` instance [#f3]_, to parse WPS Responses using
+``ZOO.Format.WPS``
+(cf. `ref `__).
+
+As for Python services you already seen in previous sections, the functions
+corresponding to a Service should take three arguments: ``conf``, ``inputs`` and
+``outputs`` [#f4]_. Nevertheless, as the ZOO-Kernel is not able to access the
+values modified [#f5]_ by the Service code, rather than returning an integer as
+in Python, here you'll need to return both the integer value representing the
+Status of your Service in a JavaScript Object and the resulting ``outputs``
+values as an Object. You can see in the following an example of a JavaScript
+Service code:
+
+.. code-block:: none
+
+ function SampleService(conf,inputs,outputs){
+ var resultValue=someComputation(inputs);
+ return
+ {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { "mimeType": "application/json", "value": resultValue } }
+ };
+ }
+
+Before starting to implement the Services we will need to get our final
+BufferRequest service, let start with a simplier one.
+
+The Mask Service
+================
+
+In this section you will learn how to create your first JavaScript service which
+will simply return a rectangular mask around a selected feature. To build this
+mask you will use the Buffer service to create a buffer big enough around a
+selected geometry to cover a significant part of your map. You can see the
+expected result in the following screenshot:
+
+.. image:: ./images/Mask_Level_12.png
+ :width: 650px
+ :align: center
+
+As before, you will first start by writting the ZCFG, then you will write the
+JavaScript source code and finish by publishing your Services Provider.
+
+The ZCFG
+--------
+
+Open the file named
+``~/zoo-ws-2012/src/zoo-project/zoo-services/ws2012js/cgi-env/Mask.zcfg``
+with your favorite text editor and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Mask]
+ Title = Compute mask
+ Abstract = Compute mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+Here you simply define one default ``ComplexData`` for both ``inputData`` and
+``Result``: a GML and a GeoJSON respectively [#f6]_.
+
+The JavaScript service
+----------------------
+
+As you will have to request the Buffer service many times from your service, you
+will first define a ``Buffer`` function as follow. It uses the ``ZOO.Process``
+to request the Buffer service you seen in the previous section.
+
+Open a file named
+``~/zoo-ws-2012/src/zoo-project/zoo-services/ws2012js/cgi-env/foss4gws.js`` and
+add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ var zoo_url='http://localhost/cgi-bin/zoo_loader.cgi';
+ var mapserv_url='http://localhost/cgi-bin/mapserv?'+
+ 'map=/var/www/zoows-demo/map/w2011.map&SERVICE=WFS';
+
+ function Buffer(inputData,bDist){
+
+ // Create all required ZOO.formats
+ var fJ=new ZOO.Format.JSON();
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fWPS=new ZOO.Format.WPS();
+
+ // Pass the value as json
+ var myInputs = {
+ InputPolygon: { type: 'complex', value: fGJ.write(inputData), mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs= { Result: { type: 'ResponseDocument', "mimeType": "application/json" } };
+ var myProcess = new ZOO.Process(zoo_url,'BufferPy');
+ var myExecuteResult=myProcess.Execute(myInputs,myOutputs);
+
+ // Parse the result and extract JSON geometry
+ var bufferResult=fWPS.read(myExecuteResult);
+ var bufferResultAsGeoJSON=fJ.read(bufferResult.value);
+ return fGJ.read(bufferResultAsGeoJSON);
+
+ }
+
+From line 12 to 15, you give a GeoJSON string (created from ``inputData``) for
+InputPolygon and, on line 14, you set the BufferDistance value to ``bDist``.
+On line 16, you define Result as a ResponseDocument, so you'll have to parse the
+WPS response using the ZOO.Format.WPS, on line 21.
+
+On line 17, you create a
+`ZOO.Process `__
+instance providing the ZOO-Kernel url and the Service name. Then, on line 18, you
+run the request passing inputs and outputs previously defined (from line 12 to 15).
+
+Now, you get your ``Buffer`` function, it is time to create your first JavaScript
+service. So, edit your ``foss4gws.js`` file you created before and add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ function Mask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX and store its geometry in a ZOO.Feature
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+
+ // Return the created feature
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { mimeType: "application/json", value: fGJ.write(result) } }
+ };
+
+ }
+
+Publish and use your Service
+----------------------------
+
+Now you get both your ZCFG and your service code ready, you need to deploy your
+new Services Provider using the following command:
+
+.. code-block:: bash
+
+ cp ~/zoo-ws-2012/src/zoo-project/zoo-services/ws2012js/cgi-env/* /usr/lib/cgi-bin
+
+Now you are ready to use your JavaScript service by loading the the following `url
+`__, click on a street then click on
+the "Mask" button.
+
+BufferMask Service
+==================
+
+In this section you will implement a simple JavaScript service which will be able create
+a hole in the mask you created in `previous section <#mask-service>`__. This service
+will be used to highlight the buffer zone around a selected fature. You get a preview of
+the expected result in the following screenshot:
+
+.. image:: ./images/BufferMask_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The ZCFG
+--------
+
+Open the file named
+``~/zoo-ws-2012/src/zoo-project/zoo-services/ws2012js/cgi-env/BufferMask.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferMask]
+ Title = Compute buffer mask
+ Abstract = Compute buffer mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+This ZCFG is similar to the previous one. Please, refer to comments in the
+`previous section <#the-zcfg>`__ for more informations.
+
+The JavaScript service
+----------------------
+
+In this Service you will use same source code (until line 19) you used in the
+`previous section <#the-javascript-service>`__. Indeed, you should compute the Mask
+as you did before then compute Buffer for creating a hole in the mask (on line 22) to run
+the Difference service (from line 25 to 40).
+
+.. code-block:: guess
+ :linenos:
+
+ function BufferMask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+
+ // Compute Buffer standard buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Request Difference service using Buffer result and features in the BBOX
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ var myProcess2 = new ZOO.Process(zoo_url,'DifferencePy');
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(finalG),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ }
+ };
+ var myOutputs2= {Result: {type: 'RawDataOutput', mimeType: "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ // Return the bbox
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": {mimeType: "application/json", value: myExecuteResult4 } }
+ };
+
+ }
+
+Publish and use your Service
+----------------------------
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+BufferRequest service
+======================
+
+In this section, you will create a new Service: ``BufferRequest`` which will request
+POIs included in the Buffer around a selected feature [#f7]_. You will use the ``poi``
+layer served as WFS through your local mapserver installation. You can see in the
+following screenshot the expected result:
+
+.. image:: ./images/BufferRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+The ZCFG
+--------
+
+Open the file named
+``~/zoo-ws-2012/zoo-project/zoo-services/ws2011js/cgi-env/BufferRequest.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferRequest]
+ Title = Compute buffer request
+ Abstract = Compute buffer request around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+
+The JavaScript code
+-------------------
+
+As in the previous Service, you will compute a buffer around the input feature. But then
+you will request POIs available in the Buffer extent using a WFS request to use them to
+run ``Intersection`` service using the initial Buffer. The WFS request is useful to limit
+the number of points to use when requesting the ``Intersection`` Service.
+
+.. code-block:: javascript
+ :linenos:
+
+ function BufferRequest(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fGML=new ZOO.Format.GML();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+
+ // Request Intersection service using Buffer result and WFS request using the
+ // BBOX
+ var myProcess2 = new ZOO.Process(zoo_url,'IntersectionPy');
+ var req="&version=1.0.0&request=GetFeature&typename=poi1";
+ req+="&SRS=EPSG:4326&BBOX=";
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ xlink: mapserv_url+req+bbox.left+","+bbox.bottom+","+bbox.right+","+bbox.top,
+ mimeType: "text/xml"
+ }
+ };
+ var myOutputs2= {Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: {name:"Result", mimeType: "application/json", value: myExecuteResult4}
+ };
+
+ }
+
+.. warning:: to take advantage of the ZOO-Kernel cache system, you directly use the WFS
+ request as ``xlink:href`` rather than value for ``InputEntity2`` (from line 31 to 34) and use ``text/xml`` ``mimeType``
+ (on line 40). Indeed, the ZOO-API doesn't use the internal cache mechanisms.
+
+
+Publish and use your Service
+----------------------------
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+.. note:: You can click on "Buffer Request and Mask" to get the same result as presented
+ in `the initial screenshot <#introduction>`__.
+
+Conclusion
+==========
+
+After understanding how basic Geometric Operation Services works, here you built step by
+step new JavaScript services which reuse the previous ones and combine them in
+different ways. This was achieved using the ZOO-API, composed by C functions
+exposed by the ZOO-Kernel to the JavaScript services runtime environement and
+the JS files which can be optionally installed.
+
+.. rubric:: Footnotes
+
+.. [#f3] The ``ZOO.Process`` class uses ``JSRequest`` (cf. `ref
+ `__). You will get example
+ of use `later <#the-javascript-service>`__.
+.. [#f4] So ``conf``, ``inputs`` and ``outputs`` are simple JavaScript objects, similar
+ to the Python dictionaries used in the `previous section `__.
+.. [#f5] Such as ``conf``, ``inputs`` and ``outputs``.
+.. [#f6] Using one of the available ``ZOO.formats`` you are also able to support various
+ ``ComplexData`` for both input and output of the service. To simplify the
+ presentation here, you will use only this default ones.
+.. [#f7] So in the hole you created in the previous section.
Index: /trunk/workshop/2012/using_zoo_from_osgeolivevm.rst
===================================================================
--- /trunk/workshop/2012/using_zoo_from_osgeolivevm.rst (revision 723)
+++ /trunk/workshop/2012/using_zoo_from_osgeolivevm.rst (revision 723)
@@ -0,0 +1,170 @@
+.. _using_zoo_from_osgeolivevm:
+
+********************************************************************
+Configuration and ZOO-Kernel use
+********************************************************************
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+ZOO-Kernel Configuration
+========================
+
+As already said in introduction, an OSGeoLive virtual machine image disk has been installed on your computer, allowing you to use ZOO-Kernel in a development environment directly. Every ZOO-Project related material and source code have been placed in ``/home/user/zoo-ws-2012`` directory. We will work with file included in this directory during this workshop.
+
+.. note:: we will use ZOO-Kernel or ``zoo_loader.cgi`` script without any distinction
+ in this document.
+
+As explained later, the ZOO-Kernel may require to store temporary files in ``/var/www/temp``. Depending on
+parameters set in the ``main.cfg``, cache files would be located in the same directory.
+
+.. code-block:: guess
+
+ sudo mkdir /var/www/tmp
+ sudo chown www-data /var/www/tmp
+
+General ZOO-Kernel settings are made in the ``main.cfg`` file located in the same
+directory as the ZOO-Kernel, so in ``/usr/lib/cgi-bin/``. You can see a typical
+``main.cfg`` content in the following:
+
+.. code-block:: guess
+ :linenos:
+
+ [main]
+ lang=en-US,fr-FR,ja-JP
+ version=1.0.0
+ encoding=utf-8
+ serverAddress=http://localhost/zoo/
+ dataPath=/var/www/data
+ tmpPath=/var/www/tmp
+ tmpUrl=../tmp
+ cacheDir=/var/www/cache/
+ mapserverAddress=http://localhost/cgi-bin/mapserv
+ msOgcVersion=1.0.0
+
+ [identification]
+ title=The ZOO-Project FOSS4G 2012 Prague Workshop
+ keywords=WPS,GIS,buffer
+ abstract=ZOO-Project platform 2012 .See http://www.zoo-project.org for more informations
+ accessConstraints=none
+ fees=None
+
+ [provider]
+ positionName=Developer
+ providerName=ZOO-Project
+ addressAdministrativeArea=Lattes
+ addressDeliveryPoint=1280 Av. des Platanes
+ addressCountry=fr
+ phoneVoice=False
+ addressPostalCode=34970
+ role=Dev
+ providerSite=http://www.zoo-project.org
+ phoneFacsimile=False
+ addressElectronicMailAddress=gerald.fenoy@geolabs.fr
+ addressCity=Lattes
+ individualName=Gérald FENOY
+
+The ``main.cfg`` file contains metadata informations about the identification and provider but also some important settings. The file is composed of various sections, namely ``[main]``, ``[identification]`` and ``[provider]`` per default.
+
+From the ``[main]`` section settings are as follow:
+ * ``lang``: the supported languages separated by a coma (the first is the default one),
+ * ``version``: the supported WPS version,
+ * ``encoding``: the default encoding of WPS Responses,
+ * ``serverAddress``: the url to access your ZOO-Kernel instance,
+ * ``dataPath``: the path to store data files (when MapServer support was activated,
+ this directory is used to store mapfiles and data).
+ * ``tmpPath``: the path to store temporary files (such as ExecuteResponse when
+ storeExecuteResponse was set to true),
+ * ``tmpUrl``: a url relative to ``serverAddress`` to access the temporary file,
+ * ``cacheDir``: the path to store cached request files [#f1]_ (optional),
+ * ``mapservAddress``: your local MapServer address (optional),
+ * ``msOgcVersion``: the version for all supported OGC Web Services output [#f2]_
+ (optional).
+
+The ``[identification]`` and ``[provider]`` section are specific to OGC metadata and
+should be set [#f3]_.
+
+Obviously, you are free to add new sections to this file if you need more. Nevertheless, you have to know
+that there is some specific names you should use only for specific needs: ``[env]``, ``[lenv]`` and
+``[senv]``.
+
+.. warning:: ``[senv]`` and ``[lenv]`` are used / produced on runtime internaly by the ZOO-Kernel and should be defined only from the Service code.
+
+The ``env`` section is used to store specific environment variables you want to be set
+prior to load your Services Provider and run your Service. A typical example, is when your
+Service requires to access to a X server running on framebuffer, then you will have to
+set the ``DISPLAY`` environnement variable, in this case you would add
+``DISPLAY=:1`` line in your ``[env]`` section.
+
+The ``lenv`` is used to store runtime informations automatically set by the
+ZOO-Kernel before running your service and can be accesses / updated from it:
+ * ``sid``: the service unique identifier,
+ * ``status``: the current progress value (value between 0 and 100, percent),
+ * ``cwd``: the current working directory of the ZOO-Kernel,
+ * ``message``: an error message when returning ``SERVICE_FAILED`` (optional),
+ * ``cookie``: the cookie your service want to return to the client (for authentication
+ purpose or tracking).
+
+The ``senv`` is used to store session informations on the server side. You can then access them automatically from service if the server is requested using a valid cookie. The ZOO-Kernel will store on disk the values set in the ``senv`` maps, then load an dynamically added to the env stored in ``main.cfg``:
+ * ``XXX``: the session unique identifier where ``XXX`` is the name included in the
+ returned cookie.
+
+.. _cookie_example:
+
+For instance, if you get the following in your Service source code [#f4]_ :
+
+.. code-block:: python
+
+ conf["lenv"]["cookie"]="XXX=XXX1000000; path=/"
+ conf["senv"]={"XXX": "XXX1000000","login": "demoUser"}
+
+That means that the ZOO-Kernel will create a file ``sess_XXX1000000.cfg`` in the
+``cacheDir`` and return the specified cookie to the client. Each time the client will
+request the ZOO-Kernel using the Cookie, it will automatically load the value stored
+before running your service. You can then easilly access this informations from your
+service source code. This functionality won't be used in the following presentation.
+
+Testing the ZOO installation with GetCapabilities
+=================================================
+
+
+You can request ZOO-Kernel using the following link from your Internet browser:
+
+http://localhost/cgi-bin/zoo_loader.cgi?Request=GetCapabilities&Service=WPS
+
+You should get a valid Capabilities XML document, looking like the following :
+
+.. image:: ./images/GC.png
+ :width: 650px
+ :align: center
+
+Please note that some Process node are returned in the ProcessOfferings section, as somes are available already on OSGeoLive DVD. You can also run a GetCapabilities request from the command line, using the following command:
+
+.. code-block:: bash
+
+ cd /usr/lib/cgi-bin
+ ./zoo_loader.cgi “request=GetCapabilities&service=WPS”
+
+The same result as in your browser will be returned, as shown in the following screenshot:
+
+.. image:: ./images/GC_CL.png
+ :width: 450px
+ :align: center
+
+Invoking ZOO Kernel from command line can be helpful during development process of new Services.
+
+.. rubric:: Footnotes
+
+.. [#f1] when you use GET requests passed through ``xlink:href`` the ZOO-Kernel will
+ execute the request only once, the first time you will ask for this ressource and it will
+ store on disk the result. The next time you will need the same feature, the cached file
+ will be used which make your process running faster. If ``cachedir`` was not
+ specified in the ``main.cfg`` then ``tmpPath`` value will be used.
+.. [#f2] since version 1.3dev, when MapServer is activated, your service can automatically
+ return a WMS, WFS or WCS request to expose your data. Your can set here the specific
+ version number you want to use to request your local MapServer setup. It depends
+ mostly on the client capability to deal with specific OGC Web Services version.
+.. [#f3] since version 1.3dev, when MapServer is activated, the same metadata will be used
+ for setting metadata for OGC Web Services.
+.. [#f4] If you're not familiar with ZOO-Project, you can `pass `__ this part and come to it after the next section.
Index: /trunk/workshop/2013/building_blocks_presentation.rst
===================================================================
--- /trunk/workshop/2013/building_blocks_presentation.rst (revision 723)
+++ /trunk/workshop/2013/building_blocks_presentation.rst (revision 723)
@@ -0,0 +1,149 @@
+.. _ogr_base_vect_ops:
+
+Building blocks presentation - Using OGR and PgRouting based Web Services
+===================================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+------------------
+
+In this section, you will use basic ZOO-Services : ``Buffer``,
+``Intersection`` and ``DifferencePy`` which use OGR and psycopg Python modules.
+The intended goal of this section is to present and interact with your new building blocks before chaining them in the next section.
+
+First of all, you should use the following links to access the user
+interfaces and interact with your services, the first one is used to
+access basic spatial-tools demo client interface and the second to
+access the routing application :
+ * `http://localhost/zoows2013-demo/spatialtools-py.html `__
+ * `http://localhost/zoo-ws2013/ `__
+
+Services Provider and configuration files
+----------------------------------
+
+First you may verify if the ZOO-Services are available from your current setup.
+You can take a look at the ``Buffer.zcfg``, ``Intersection.zcfg`` and
+``DifferencePy.zcfg`` to get details about parameters.
+As you can see from the ZCFG files, you will use ZOO-Services provided by the
+``service`` Python service provider. So if you want to modify the Python code
+you will have to edit the corresponding file (so ``service.py``).
+You are invited to use similar requests as the one used in previous
+sections to learn about each services individually.
+
+The Buffer Service
+------------------------------------
+
+First click on a street then once the street is displayed in blue, click the
+'Buffer' button on top, you should get similar result as displayed in the following.
+
+.. image:: ./images/Buffer_Level_15.png
+ :width: 650px
+ :align: center
+
+Since version ZOO-Project 1.2.0, you can run automatically some basic tests to
+make sure that you wrote a correct ZCFG file and your service is validating.
+
+.. note:: the current testing is really simple and should be adapted to each Services
+ Provider, mainly to define input names.
+
+You can use the following command:
+
+.. code-block:: bash
+
+ cd /home/user/zoo/testing
+ ./run.sh http://localhost/cgi-bin/zoo_loader.cgi Buffer
+
+
+.. note:: During or after the test run, you can take a look inside the ``tmp`` directory
+ which contains both the XML requests send to the ZOO Kernel (``*1.xml``) and the
+ responses it gave (``output*.xml``).
+
+The Intersection Service
+------------------------------------
+
+Using the same client interface as before, once you get a Buffer, you can then
+select a street intersecting the Buffer geometry to compute intersection by clicking on the Intersection button.
+
+
+.. image:: ./images/Intersection_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The DifferencePy Service
+------------------------------------
+
+Using the same instructions as for Intersetion, you can get the following result.
+
+.. image:: ./images/Difference_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The Routing and Profile Services
+------------------------------------
+
+First click on the blue flag then place your starting point on the
+map, do the same with the red flag to get the shortest path computed
+by the dedicated service and then display its profile. Note that when
+you pass the mouse over the profile display then you will see its
+corresponding position displayed on the map. You can also click on a
+specific step in your path to get the corresponding line displayed.
+
+.. image:: ./images/Routing_Basic.png
+ :width: 650px
+ :align: center
+
+If you take a look in the file: ``/usr/lib/cgi-bin/routing/do.zcfg``
+you may notice something new in the supported format which is
+reproduced here after.
+
+.. code-block:: guess
+
+
+ mimeType = image/png
+ asReference = true
+ msStyle = STYLE COLOR 125 0 105 OUTLINECOLOR 0 0 0 WIDTH 3 END
+ useMapServer = true
+ extension = json
+
+
+The ``mimeType`` is defined as ``image/png`` and there is two new
+parameter which are both optional:
+ * ``useMapServer``: which make you able to inform the ZOO-Kernel
+ that it have to use MapServer to publish your result as WMS / WFS or WCS (this last
+ won't be used in this workshop) rather than simply storing the
+ result as a file.
+ * ``msStyle``: which let you define your own MapServer ``STYLE`` block definition.
+
+When you need to access a result many time or for different purpose
+accross other services then it is really useful to ask ZOO-Kernel to
+publish your result as WMS, WFS or WCS.
+
+Note that no modification of the code of the do service was required
+to handle automatic pubilcation of the result as it is a vector format
+supported by OGR, only modification of the zcfg was required.
+
+This routing example is here to illustrate how easy it is to publish
+your result as WMS, WFS or WCS ressource. Indeed, when your routing
+service was called, ZOO-Kernel published the result as WMS and WFS
+ressources which was both used first for the UI purpose, the WMS to
+display the resulting path on the map, the WFS for displaying details
+about each steps. The WFS protocol is also used as the input value
+for the profile computation. So, the computation was run once
+and accessed three times for different purposes and from different
+clients.
+
+For more informations about the MapServer support, please refer to `the
+official ZOO-Project Documentation `_.
+
+Conclusion
+------------------------------------
+
+Now you know this three services, and you get a simple interface to interact
+with your MapServer WFS and your ZOO-Project WPS Servers, you are ready to use
+the Services in a different way, by chaining them using the JavaScript ZOO-API to build
+more complexe and powerfull services.
Index: /trunk/workshop/2013/conf.py
===================================================================
--- /trunk/workshop/2013/conf.py (revision 723)
+++ /trunk/workshop/2013/conf.py (revision 723)
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+#
+# ZOO Project documentation build configuration file
+
+import re
+import sphinx
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo','sphinx.ext.autosummary', 'sphinx.ext.extlinks','sphinx.ext.viewcode']
+master_doc = 'index'
+templates_path = ['_templates']
+exclude_patterns = ['_build']
+
+# General information
+
+project = 'ZOO-Project'
+copyright = '2009-2015, ZOO-Project team'
+version = '1.0'
+release = '1.5'
+show_authors = True
+
+# Options for HTML output
+
+html_theme = 'sphinx_rtd_theme'
+html_theme_path = ['_themes']
+modindex_common_prefix = ['sphinx.']
+html_static_path = ['_static']
+html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
+#html_additional_pages = {'index': 'index.html'}
+html_use_opensearch = 'http://sphinx-doc.org'
+htmlhelp_basename = 'Sphinxdoc'
+
+# Options for epub output
+
+epub_theme = 'epub'
+epub_basename = 'ZOO-Project'
+epub_author = 'ZOO-Project team'
+epub_publisher = 'http://zoo-project.org/'
+epub_scheme = 'url'
+epub_identifier = 'http://zoo-project.org'
+epub_pre_files = [('index.html', 'ZOO-Project documentation')]
+epub_post_files = [('install.html', 'Installing Sphinx'),('develop.html', 'Sphinx development')]
+epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js','_static/jquery.js', '_static/searchtools.js','_static/underscore.js', '_static/basic.css','search.html', '_static/websupport.js']
+epub_fix_images = False
+epub_max_image_width = 0
+epub_show_urls = 'inline'
+epub_use_index = False
+epub_guide = (('toc', 'index.html', u'Table of Contents'),)
+
+# Options for LaTeX output
+
+latex_documents = [('contents', 'ZOO-Project.tex', 'ZOO-Project Documentation','ZOO-Project team', 'manual', 1)]
+latex_logo = '_static/zoo_simple.png'
+latex_elements = {'fontpkg': '\\usepackage{palatino}'}
+latex_show_urls = 'footnote'
+todo_include_todos = True
+man_pages = [('index', 'zooproject', 'ZOO-Project Documentation','ZOO-Project team', 1)]
+
+# -- Extension interface -------------------------------------------------------
+
+from sphinx import addnodes # noqa
+
+event_sig_re = re.compile(r'([a-zA-Z-]+)\s*\((.*)\)')
+
+
+def parse_event(env, sig, signode):
+ m = event_sig_re.match(sig)
+ if not m:
+ signode += addnodes.desc_name(sig, sig)
+ return sig
+ name, args = m.groups()
+ signode += addnodes.desc_name(name, name)
+ plist = addnodes.desc_parameterlist()
+ for arg in args.split(','):
+ arg = arg.strip()
+ plist += addnodes.desc_parameter(arg, arg)
+ signode += plist
+ return name
+
+
+def setup(app):
+ from sphinx.ext.autodoc import cut_lines
+ from sphinx.util.docfields import GroupedField
+ app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
+ app.add_object_type('confval', 'confval',
+ objname='configuration value',
+ indextemplate='pair: %s; configuration value')
+ fdesc = GroupedField('parameter', label='Parameters',
+ names=['param'], can_collapse=True)
+ app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
+ doc_field_types=[fdesc])
Index: /trunk/workshop/2013/first_service.rst
===================================================================
--- /trunk/workshop/2013/first_service.rst (revision 723)
+++ /trunk/workshop/2013/first_service.rst (revision 723)
@@ -0,0 +1,366 @@
+.. _first_service:
+
+Create your first ZOO Service
+=====================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+---------------------
+
+In this part, you will create and publish from a simple ZOO Service named
+``Hello`` which will simply return a hello message containing the input value
+provided. It will be usefull to present in deeper details general concept on how ZOO-Kernel works and handles request.
+
+Service and publication process overview
+-----------------------------------
+
+Before starting developing a ZOO Service, you should remember that in
+ZOO-Project, a Service is a couple made of:
+
+ * a metadata file: a ZOO Service Configuration File (ZCFG) containing metadata
+ informations about a Service (providing informations about default / supported
+ inputs and outputs for a Service)
+ * a Services Provider: it depends on the programming language used, but for Python it
+ is a module and for JavaScript a script file.
+
+To publish your Service, which means make your ZOO Kernel aware of its presence,
+you should copy a ZCFG file in the directory where ``zoo_loader.cgi`` is located (in this workshop, ``/usr/lib/cgi-bin``).
+
+.. warning:: only the ZCFG file is required for the Service to be considerate as
+ available. So if you don't get the Service Provider, obviously your Execute
+ request will fail as we will discuss later.
+
+Before publication, you should store your ongoing work, so you'll start by
+creating a directory to store the files of your Services Provider:
+
+.. code-block:: none
+
+ mkdir -p /home/user/zoo-ws2013/ws_sp/cgi-env
+
+Once the ZCFG and the Python module are both ready, you can publish simply
+by copying the corresponding files in the same directory as the ZOO-Kernel.
+
+Create your first ZCFG file
+--------------------------
+
+You will start by creating the ZCFG file for the ``Hello`` Service. Edit the
+``/home/user/zoo-ws2013/ws_sp/cgi-env/Hello.zcfg`` file
+and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Hello]
+ Title = Return a hello message.
+ Abstract = Create a welcome string.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = test_service
+ serviceType = Python
+
+ [name]
+ Title = Input string
+ Abstract = The string to insert in the hello message.
+ minOccurs = 1
+ maxOccurs = 1
+
+ dataType = string
+
+
+
+
+ [Result]
+ Title = The resulting string
+ Abstract = The hello message containing the input string
+
+ dataType = string
+
+
+
+
+.. note:: the name of the ZCFG file and the name between braket (here ``[Hello]``)
+ should be the same and correspond to the function name you will define in your
+ Services provider.
+
+As you can see in the ZOO Service Configuration File presented above it is divided into
+three distinct sections:
+ #. Main Metadata information (from line 2 to 8)
+ #. List of Inputs metadata information (from 9 line to 19)
+ #. List of Outputs metadata information (from line 20 to 28)
+
+You can get more informations about ZCFG from `the reference documentation
+`__.
+
+If you copy the ``Hello.zcfg`` file in the same directory as your ZOO Kernel
+then you will be able to request for DescribeProcess using the ``Hello``
+``Identifier``. The ``Hello`` service should also be listed from Capabilities
+document.
+
+.. code-block:: none
+ cp /home/user/zoo-ws2013/ws_sp/cgi-env/Hello.zcfg /usr/lib/cgi-bin
+
+Test requests
+---------------------
+
+In this section you will tests each WPS requests : GetCapabilities,
+DescribeProcess and Execute. Note that only GetCapabilities and DescribeProcess
+should work at this step.
+
+Test the GetCapabilities request
+.....................................................
+
+If you run the ``GetCapabilities`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=GetCapabilities&service=WPS
+
+Now, you should find your Hello Service in a ``Process`` node in
+``ProcessOfferings``:
+
+.. code-block:: xml
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+Test the DescribeProcess request
+.....................................................
+
+You can access the ``ProcessDescription`` of the ``Hello`` service using the
+following ``DescribeProcess`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=DescribeProcess&service=WPS&version=1.0.0&Identifier=Hello
+
+You should get the following response:
+
+.. code-block:: xml
+
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+ name
+ Input string
+ The string to insert in the hello message.
+
+ string
+
+
+
+
+
+
+
+
+
+
+Test the Execute request
+.....................................................
+
+Obviously, you cannot run your Service because the Python file was not published
+yet. If you try the following ``Execute`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You should get an ExceptionReport similar to the one provided in the following,
+which is normal behavior:
+
+.. code-block:: xml
+
+
+
+ Python module test_service cannot be loaded.
+
+
+
+Implementing the Python Service
+-------------------------------
+
+General Principles
+.....................................................
+
+The most important thing you must know when implementing a new ZOO-Services
+using the Python language is that the function corresponding to your Service
+returns an integer value representing the status of execution
+(``SERVICE_FAILED`` [#f1]_ or ``SERVICE_SUCCEEDED`` [#f2]_) and takes three
+arguments (`Python dictionaries
+`__):
+
+ - ``conf`` : the main environment configuration (corresponding to the main.cfg content)
+ - ``inputs`` : the requested / default inputs (used to access input values)
+ - ``outputs`` : the requested / default outputs (used to store computation result)
+
+.. note:: when your service return ``SERVICE_FAILED`` you can set
+ ``conf["lenv"]["message"]`` to add a personalized message in the ExceptionReport
+ returned by the ZOO Kernel in such case.
+
+You get in the following a sample ``conf`` value based on the ``main.cfg`` file you
+saw `before `__.
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ "main": {
+ language: "en-US",
+ lang: "fr-FR,ja-JP",
+ version: "1.0.0",
+ encoding: "utf-8",
+ serverAddress: "http://localhost/cgi-bin/zoo_loader.cgi",
+ dataPath: "/var/www/zoows-demo/map/data",
+ tmpPath: "/var/www/temp",
+ tmpUrl: "../temp",
+ cacheDir: "/var/www/temp/"
+ },
+ "identification": {
+ title: "The ZOO-Project WPS Server FOSS4G 2013 Nottingham Workshop",
+ keywords: "WPS,GIS,buffer",
+ abstract: "Demo version of Zoo-Project for OSGeoLiveDVD 2013. See http://www.zoo-project.org",
+ accessConstraints: "none",
+ fees: "None"
+ },
+ "provider": {
+ positionName: "Developer",
+ providerName: "ZOO-Project",
+ addressAdministrativeArea: "Lattes",
+ addressCountry: "fr",
+ phoneVoice: "False",
+ addressPostalCode: "34970",
+ role: "Dev",
+ providerSite: "http://www.zoo-project.org",
+ phoneFacsimile: "False",
+ addressElectronicMailAddress: "gerald.fenoy@geolabs.fr",
+ addressCity: "Denver",
+ individualName: "Gérald FENOY"
+ }
+
+In the following you get a sample outputs value passed to a Python or a JavaScript Service:
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ 'Result': {
+ 'mimeType': 'application/json',
+ 'inRequest': 'true',
+ 'encoding': 'UTF-8'
+ }
+ }
+
+.. note:: the ``inRequest`` value is set internally by the ZOO-Kernel and can be used to determine from the Service if the key was provided in the request.
+
+ZOO-Project provide a ZOO-API which was originally only available for
+JavaScript services, but thanks to the work of the ZOO-Project
+community, now you have also access to a ZOO-API when using
+the Python language. Thanks to the Python ZOO-API you don't have to remember anymore
+the value of SERVICE_SUCCEDED and SERVICE_FAILED, you
+have the capability to translate any string from your Python service
+by calling the ``_`` function (ie: ``zoo._('My string to
+translate')``) or to update the current status of a running service by
+using the ``update_status`` function the same way you use it from
+JavaScript or C services.
+
+The Hello Service
+.....................................................
+
+You can copy and paste the following into the
+``/home/user/zoo-ws2013/ws_sp/cgi-env/test_service.py`` file.
+
+.. code-block:: python
+
+ import zoo
+ def Hello(conf,inputs,outputs):
+ outputs["Result"]["value"]=\
+ "Hello "+inputs["name"]["value"]+" from the ZOO-Project Python world !"
+ return zoo.SERVICE_SUCCEEDED
+
+Once you finish editing the file, you should copy it in the ``/usr/lib/cgi-bin`` directory:
+
+.. code-block:: none
+
+ sudo cp /home/user/zoo-ws2013/ws_sp/cgi-env/* /usr/lib/cgi-bin
+
+
+Interracting with your service using Execute requests
+----------------------------------------------
+
+Now, you can request for Execute using the following basic url:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You can request the WPS Server to return a XML WPS Response containing the result of
+your computation, requesting for ResponseDocument or you can access the data directly
+requesting for RawDataOutput.
+
+* Sample request using the RawDataOutput parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&RawDataOutput=Result
+
+* Sample request using the default ResponseDocument parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result
+
+When you are using ResponseDocument there is specific attribut you can use to ask
+the ZOO Kernel to store the result: ``asReference``. You can use the following example:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result@asReference=true
+
+When computation take long time, the client should request the
+execution of a Service by setting both ``storeExecuteResponse`` and
+``status`` parameter to true to force asynchronous execution. This
+will make the ZOO-Kernel return, without waiting for the Service execution
+completion but after starting another ZOO-Kernel process responsible
+of the Service execution, a ResponseDocument containing a ``statusLocation``
+attribute which can be used to access the status of an ongoing service
+or the result when the process ended [#f3]_.
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result&storeExecuteResponse=true&status=true
+
+Conclusion
+-----------------
+
+Even if this first service was really simple it was useful to illustrate how the
+ZOO-Kernel fill ``conf``, ``inputs`` and ``outputs`` parameter prior to load
+and run your function service, how to write a ZCFG file, how to publish a Services
+Provider by placing the ZCFG and Python files in the same directory as the
+ZOO-Kernel, then how to interract with your service using both
+``GetCapabilities``, ``DescribeProcess`` and ``Execute`` requesr. We will see
+in the `next section `__ how to write similar requests
+using the XML syntax.
+
+.. rubric:: Footnotes
+
+.. [#f1] ``SERVICE_FAILED=4``
+.. [#f2] ``SERVICE_SUCCEEDED=3``
+.. [#f3] To get on-going status url in ``statusLocation``, you'll need to setup the `utils/status `_ Service. If you don't get this service available, the ZOO-Kernel will simply give the url to a flat XML file stored on the server which will contain, at the end of the execution, the result of the Service execution.
Index: /trunk/workshop/2013/index.rst
===================================================================
--- /trunk/workshop/2013/index.rst (revision 723)
+++ /trunk/workshop/2013/index.rst (revision 723)
@@ -0,0 +1,30 @@
+.. _workshop-foss4g-2013:
+
+##########################################
+ZOO-Project Workshop 2013
+##########################################
+
+:Original Title: **ZOO-Project: playing with building blocks to build pgRouting web application**
+:Author: Gérald Fenoy, Nicolas Bozon, Venkatesh Raghavan
+:Contact: gerald.fenoy at geolabs.fr, nicolas.bozon at gmail.com, venka at osgeo.org
+:Last Updated: $Date$
+:Events: FOSS4G 2013 Nottingham, FOSS4G-CEE 2013 Bucharest
+
+.. image:: ./images/foss4g2013-white-300.png
+ :target: http://2013.foss4g.org/
+ :align: center
+
+.. image:: ./images/logo-foss4g-cee-2013.png
+ :target: http://2013.foss4g-cee.org/
+ :align: center
+
+**WorkShop table of content**
+
+.. toctree::
+ :maxdepth: 5
+
+ introduction
+ using_zoo_from_osgeolivevm
+ first_service
+ building_blocks_presentation
+ js_services_chaining
Index: /trunk/workshop/2013/introduction.rst
===================================================================
--- /trunk/workshop/2013/introduction.rst (revision 723)
+++ /trunk/workshop/2013/introduction.rst (revision 723)
@@ -0,0 +1,59 @@
+.. _introduction:
+
+Introduction
+=================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+What is ZOO ?
+---------------------
+
+ZOO-Project is a WPS (Web Processing Service) open source project released under a `MIT/X-11 `__ style license. It provides an OGC WPS compliant developer-friendly framework to create and chain WPS Web services. ZOO is made of three parts:
+
+* `ZOO Kernel `__ : A powerful server-side C Kernel which makes it possible to manage and chain Web services coded in different programming languages.
+* `ZOO Services `__ : A growing suite of example Web Services based on various open source libraries.
+* `ZOO API `__ : A server-side JavaScript API able to call and chain the ZOO Services, which makes the development and chaining processes easier and faster.
+
+ZOO was designed to make the service creation and deployment easy, by providing a powerful system able to understand and execute WPS compliant queries. It supports seven programming languages, thus allowing you to create Web Services using the one you prefer. It also lets you use an existing code and to turn it as a WPS Service.
+The current supported programming languages are the following:
+
+* C/C++
+* Python
+* Perl
+* Java
+* Fortran
+* PHP
+* JavaScript
+
+More information on the project is available on the `ZOO Project official website `__ .
+
+How does ZOO works ?
+---------------------
+
+ZOO is based on a C Kernel which is the ZOO-Project core system (aka ZOO-Kernel). The latter is able to dynamically load libraries and to handle them as on-demand Web services.
+
+A ZOO-Service is a link composed of a ZOO metadata file (.zcfg) and the code for the corresponding implementation. The metadata file describes all the available functions that can be called using a WPS Execute Request, as well as the desired input/output. Services contain the algorithms and functions, and can be implemented using any of the supported languages.
+
+ZOO-Kernel works as CGI through Apache and can communicate with cartographic engines and Web mapping clients. It simply adds the WPS support to your spatial data infrastructure and your webmapping applications. It can use every GDAL/OGR supported formats as input data and create suitable vector or raster output for your cartographic engine and/or your web-mapping client application.
+
+What are we going to do in this workshop?
+-------------------------------------
+
+You will learn how to use ZOO Kernel and how to create ZOO Services using the OSGeo Live 7.0. Despite a pre-compiled ZOO 1.3-dev package is provided inside OSGeoLive, some optional supports are not available in the default setup. So you will be invited to download and uncompress a tarbal containing binary versions of ZOO-Kernel, so there is no need to compile anything, simple steps to install ZOO-Kernel will be introduced. Configuration file and basic ways to run ZOO Kernel and ZOO Service will be presented. Then you will be invited to start programming your own simple service using Python language. Some ZOO Services will be presented and individually tested inside a ready-to-use OpenLayers application. Finally, this services will be chained using the server-side Javascript ZOO API.
+
+The whole workshop is organized step-by-step and numerous code snippets are available. The instructors will check the ZOO-Kernel is functioning on each machine and will assist you while coding. Technical questions are of course welcome during the workshop.
+
+Usefull tips for reading
+---------------------
+
+.. code-block:: guess
+
+ this is a code block
+
+.. warning:: This is a warning message.
+
+.. note:: This is an important note.
+
+**Let's go !**
Index: /trunk/workshop/2013/js_services_chaining.rst
===================================================================
--- /trunk/workshop/2013/js_services_chaining.rst (revision 723)
+++ /trunk/workshop/2013/js_services_chaining.rst (revision 723)
@@ -0,0 +1,592 @@
+.. _ogr_base_vect_ops:
+
+Playing with buildign blocks - Creating JavaScript Web Services
+=========================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+-------------------------------------------
+
+
+This section illustrate how you can use JavaScript on the server-side to chain
+services together to build new ones. You will create a ZOO Services Provider
+using the services you seen before and the WFS server using the ZOO-API. The
+final goal is to query all POIs included in a buffer around a feature and
+to highlight them using a mask around this buffer. The following screenshot show
+you the expected result:
+
+.. image:: ./images/BufferMaskAndRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+For the routing interface result should look like this:
+
+.. image:: ./images/BufferMaskAndRequest_Routing_Level_15.png
+ :width: 650px
+ :align: center
+
+You can decompose the result above in two different ones: the mask around the
+buffer and the points included in the buffer. So you will create two different
+Services: one called ``BufferMask`` and another one called ``BufferRequest``.
+
+But before implementing any JavaScript Service, you will get an overview of how
+to use ZOO-API from your ZOO-Project installation in the next section.
+
+As before, you first create a new directory to store files for your new Services
+Provider:
+
+.. code-block:: guess
+
+ mkdir -p ~/zoo-ws2013/jschains/cgi-env/
+
+
+ZOO-API Overview
+-------------------------------------------
+
+ZOO-API and ZOO-Kernel JavaScript support make you able to run services
+implemented in JavaScript on the server side. JavaScript is a popular programing
+language but mostly used on the client side. Let say from a browser, but here it
+is a bit different.
+
+To support JavaScript language ZOO-Kernel use the
+`SpiderMonkey `__ API to create a
+javascript runtime environment from which it will load your JS file then extract
+the function corresponding to the service to run it using the prefilled
+parameters. The JavaScript runtime environment created by the ZOO-Kernel
+depend on your setup. If you placed the ``ZOO-api.js`` and ``ZOO-proj4js.js`` in
+the same directory as your ZOO-Kernel it means that your environment will
+contains ZOO-API and Proj4js will be loaded before your service. In such case you can access to the Classes defined in the JavaScript ZOO-API
+to manipulate geographic data, for more informations please refer to the
+`ZOO-API Documentation `__.
+
+Even if it can be useful to run JavaScript on the server side, you should
+remember that some basic JavaScript functions you are familiar with does not
+exist or get a different behavior. For instance the simple ``alert``
+function will display messages in apache error logs rather than in a window when
+used from a browser. The ``alert`` function can be used as follow:
+
+.. code-block:: guess
+
+ alert("My alert message");
+
+There is no XMLHttpRequest available in the JavaScript evironement your service
+will run into. Hopefully, the ZOO-Kernel expose a C function to the JavaScript
+world named: ``JSRequest``. This function make you able from your JavaScript
+services to call other WPS services (locally or remotelly) or other kind OGC
+services such as WFS. When you are using the ZOO-API it is possible to call
+Services using a ``ZOO.Process`` instance [#f3]_, to parse WPS Responses using
+``ZOO.Format.WPS``
+(cf. `ref `__).
+
+As for Python services you already seen in previous sections, the functions
+corresponding to a Service should take three arguments: ``conf``, ``inputs`` and
+``outputs`` [#f4]_. Nevertheless, as the ZOO-Kernel is not able to access the
+values modified [#f5]_ by the Service code, rather than returning an integer as
+in Python, here you'll need to return both the integer value representing the
+Status of your Service in a JavaScript Object and the resulting ``outputs``
+values as an Object [#f6]_. You can see in the following an example of a JavaScript
+Service code:
+
+.. code-block:: none
+
+ function SampleService(conf,inputs,outputs){
+ var resultValue=someComputation(inputs);
+ return
+ {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { "mimeType": "application/json", "value": resultValue } }
+ };
+ }
+
+Before starting to implement the Services we will need to get our final
+BufferRequest service, let start with a simplier one.
+
+The Mask Service
+-------------------------------------------
+
+In this section you will learn how to create your first JavaScript service which
+will simply return a rectangular mask around a selected feature. To build this
+mask you will use the Buffer service to create a buffer big enough around a
+selected geometry to cover a significant part of your map. You can see the
+expected result in the following screenshot:
+
+.. image:: ./images/Mask_Level_12.png
+ :width: 650px
+ :align: center
+
+As before, you will first start by writting the ZCFG, then you will write the
+JavaScript source code and finish by publishing your Services Provider.
+
+The ZCFG
+.....................................
+
+Open the file named
+``~/zoo-ws2013/jschains/cgi-env/Mask.zcfg``
+with your favorite text editor and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Mask]
+ Title = Compute mask
+ Abstract = Compute mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+Here you simply define one default ``ComplexData`` for both ``inputData`` and
+``Result``: a GML and a GeoJSON respectively [#f7]_.
+
+The JavaScript service
+.....................................
+
+As you will have to request the Buffer service many times from your service, you
+will first define a ``Buffer`` function as follow. It uses the ``ZOO.Process``
+to request the Buffer service you seen in the previous section.
+
+Open a file named
+``~/zoo-ws2013/jschains/cgi-env/foss4gws.js`` and
+add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ var zoo_url='http://localhost/cgi-bin/zoo_loader.cgi';
+ var mapfile="/var/www/zoows2013-demo/map/w2013_1.map";
+ var mapserv_url="http://localhost/cgi-bin/mapserv?map="+mapfile;
+
+ function Buffer(inputData,bDist){
+
+ // Create all required ZOO.formats
+ var fJ=new ZOO.Format.JSON();
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fWPS=new ZOO.Format.WPS();
+
+ // Pass the value as json
+ var myInputs = {
+ InputPolygon: { type: 'complex', value: fGJ.write(inputData), mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess = new ZOO.Process(zoo_url,'BufferPy');
+ var myExecuteResult=myProcess.Execute(myInputs,myOutputs);
+
+ return fGJ.read(myExecuteResult);
+
+ }
+
+From line 12 to 15, you give a GeoJSON string (created from ``inputData``) for
+InputPolygon and, on line 14, you set the BufferDistance value to ``bDist``.
+On line 16, you define Result as a ResponseDocument, so you'll have to parse the
+WPS response using the ZOO.Format.WPS, on line 21.
+
+On line 17, you create a
+`ZOO.Process `__
+instance providing the ZOO-Kernel url and the Service name. Then, on line 18, you
+run the request passing inputs and outputs previously defined (from line 12 to 15).
+
+Now, you get your ``Buffer`` function, it is time to create your first JavaScript
+service. So, edit your ``foss4gws.js`` file you created before and add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ function Mask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX and store its geometry in a ZOO.Feature
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+
+ // Return the created feature
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { mimeType: "application/json", value: fGJ.write(result) } }
+ };
+
+ }
+
+Publish and use your Service
+..............................................
+
+Now you get both your ZCFG and your service code ready, you need to deploy your
+new Services Provider using the following command:
+
+.. code-block:: bash
+
+ cp ~/zoo-ws2013/jschains/cgi-env/* /usr/lib/cgi-bin
+
+Now you are ready to use your JavaScript service by loading the following `url
+`__, click on a street then click on
+the "Mask" button.
+
+BufferMask Service
+-------------------------------------------
+
+In this section you will implement a simple JavaScript service which will be able create
+a hole in the mask you created in `previous section <#mask-service>`__. This service
+will be used to highlight the buffer zone around a selected fature. You get a preview of
+the expected result in the following screenshot:
+
+.. image:: ./images/BufferMask_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The ZCFG
+..............................................
+
+Open the file named
+``~/zoo-ws2013/jschains/cgi-env/BufferMask.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferMask]
+ Title = Compute buffer mask
+ Abstract = Compute buffer mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+This ZCFG is similar to the previous one. Please, refer to comments in the
+`previous section <#the-zcfg>`__ for more informations.
+
+The JavaScript service
+..............................................
+
+In this Service you will use same source code (until line 19) you used in the
+`previous section <#the-javascript-service>`__. Indeed, you should compute the Mask
+as you did before then compute Buffer for creating a hole in the mask (on line 22) to run
+the Difference service (from line 25 to 40).
+
+.. code-block:: guess
+ :linenos:
+
+ function BufferMask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+
+ // Compute Buffer standard buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Request Difference service using Buffer result and features in the BBOX
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ var myProcess2 = new ZOO.Process(zoo_url,'DifferencePy');
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(finalG),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ }
+ };
+ var myOutputs2= {Result: {type: 'RawDataOutput', mimeType: "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ // Return the bbox
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": {mimeType: "application/json", value: myExecuteResult4 } }
+ };
+
+ }
+
+Publish and use your Service
+..............................................
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+BufferRequest service
+-------------------
+
+In this section, you will create a new Service: ``BufferRequest`` which will request
+POIs included in the Buffer around a selected feature [#f8]_. You will use the ``poi``
+layer served as WFS through your local mapserver installation. You can see in the
+following screenshot the expected result:
+
+.. image:: ./images/BufferRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+The ZCFG
+..............................................
+
+Open the file named
+``~/zoo-ws2013/jschains/cgi-env/BufferRequest.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferRequest]
+ Title = Compute buffer request
+ Abstract = Compute buffer request around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+
+The JavaScript code
+..............................................
+
+As in the previous Service, you will compute a buffer around the input feature. But then
+you will request POIs available in the Buffer extent using a WFS request to use them to
+run ``Intersection`` service using the initial Buffer. The WFS request is useful to limit
+the number of points to use when requesting the ``Intersection`` Service.
+
+.. code-block:: javascript
+ :linenos:
+
+ function BufferRequest(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fGML=new ZOO.Format.GML();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+
+ // Request Intersection service using Buffer result and WFS request using the
+ // BBOX
+ var myProcess2 = new ZOO.Process(zoo_url,'Intersection');
+ var req="&version=1.0.0&request=GetFeature&typename=poi1";
+ req+="&SRS=EPSG:4326&BBOX=";
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ xlink: mapserv_url+req+bbox.left+","+bbox.bottom+","+bbox.right+","+bbox.top,
+ mimeType: "text/xml"
+ }
+ };
+ var myOutputs2= {Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: [ {name:"Result", mimeType: "application/json", value: myExecuteResult4} ]
+ };
+
+ }
+
+.. warning:: to take advantage of the ZOO-Kernel cache system, you directly use the WFS
+ request as ``xlink:href`` rather than value for ``InputEntity2`` (from line 31 to 34) and use ``text/xml`` ``mimeType``
+ (on line 40). Indeed, the ZOO-API doesn't use the internal cache mechanisms.
+
+
+Publish and use your Service
+..............................................
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+.. note:: You can click on "Buffer Request and Mask" to get the same result as presented
+ in `the initial screenshot <#introduction>`__.
+
+
+Add Union into the chain
+------------------------
+
+As you can see in the following screenshot, when using the Buffer
+service using a feature collection containing more than one geometry,
+the result is made of multiple geometries. So, running Buffer service
+on the routing interface will result in multiple buffer:
+
+.. image:: ./images/Buffer_Routing_Level_15.png
+ :width: 650px
+ :align: center
+
+So, to get the same result as you got when selecting a single
+road, you should use Union of geometry (input or the one outputed by the
+``Buffer`` Service). As you are using the JavaScript ZOO-API, you can
+simply update the ``Buffer`` JavaScript function you defined earlier, to
+first call the Union of each geometry avaible in a feature collection
+prior to request (or after requesting) the Buffer Service. Hopefully,
+there is already this Python Service available, its name is
+``UnionOne1``, so you just need to add it in your Service chain.
+
+Here is the final code for the Buffer JavaScript function:
+
+.. code-block:: javascript
+ :linenos:
+
+ function Buffer(inputData,bDist){
+
+ // Create all required ZOO.formats
+ var fJ=new ZOO.Format.JSON();
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fWPS=new ZOO.Format.WPS();
+
+ // Call the UnionOne1 Service
+ var myInputs0 = {
+ InputPolygon: { type: 'complex', value: fGJ.write(inputData), mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs0= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess0 = new ZOO.Process(zoo_url,'UnionOne1');
+ var myExecuteResult0=myProcess0.Execute(myInputs0,myOutputs0);
+
+ // Call the BufferPy Service
+ var myInputs = {
+ InputPolygon: { type: 'complex', value: myExecuteResult0, mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess = new ZOO.Process(zoo_url,'BufferPy');
+ var myExecuteResult=myProcess.Execute(myInputs,myOutputs);
+
+ return fGJ.read(myExecuteResult);
+
+ }
+
+
+Conclusion
+--------------
+
+After understanding how basic Geometric Operation Services works, here you built step by step new JavaScript services which reuse the previous ones and combine them in different ways. This was achieved using the ZOO-API, composed by C functions exposed by the ZOO-Kernel to the JavaScript services runtime environement and the JS files which can be optionally installed.
+
+.. rubric:: Footnotes
+
+.. [#f3] The ``ZOO.Process`` class uses ``JSRequest`` (cf. `ref
+ `__). You will get example
+ of use `later <#the-javascript-service>`__.
+.. [#f4] So ``conf``, ``inputs`` and ``outputs`` are simple JavaScript objects, similar
+ to the Python dictionaries used in the `previous section `__.
+.. [#f5] Such as ``conf``, ``inputs`` and ``outputs``.
+.. [#f6] You can also return a conf Object if you get any informations updated from your JavaScript service (such as cookie for instance)
+.. [#f7] Using one of the available ``ZOO.formats`` you are also able to support various
+ ``ComplexData`` for both input and output of the service. To simplify the
+ presentation here, you will use only this default ones.
+.. [#f8] So in the hole you created in the previous section.
Index: /trunk/workshop/2013/using_zoo_from_osgeolivevm.rst
===================================================================
--- /trunk/workshop/2013/using_zoo_from_osgeolivevm.rst (revision 723)
+++ /trunk/workshop/2013/using_zoo_from_osgeolivevm.rst (revision 723)
@@ -0,0 +1,201 @@
+.. _using_zoo_from_osgeolivevm:
+
+Configuration and ZOO-Kernel use
+==========================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+ZOO-Project Installation
+-------------------------------
+
+To be able to follow the current material, you will have to download
+and uncompress an archive containing the dataset, ZOO-Kernel and
+required services. It was made available specifically for this workshop
+and is available at : http://www.zoo-project.org/dl/ws2013-1.tar.bz2.
+
+You should use the following commands to download then uncompress the archive
+and get it extracted with correct privileges:
+
+.. code-block:: guess
+
+ wget http://www.zoo-project.org/dl/ws2013-1.tar.bz2
+ sudo tar -xvjpf ws2013-1.tar.bz2 -C /
+ psql -f /var/www/temp/ws2013.sql pgrouting
+
+ZOO-Kernel Configuration
+-------------------------------
+
+As already said in introduction, an OSGeoLive has been booted on your computer, allowing you to use ZOO-Kernel in a development environment directly.
+
+.. note:: we will use ZOO-Kernel or ``zoo_loader.cgi`` script without any distinction
+ in this document.
+
+General ZOO-Kernel settings are set in the ``main.cfg`` file located in the same
+directory as the ZOO-Kernel, so in ``/usr/lib/cgi-bin/``. You can see a typical
+``main.cfg`` content in the following:
+
+.. code-block:: guess
+ :linenos:
+
+ [main]
+ lang=en-US,fr-FR,ja-JP
+ version=1.0.0
+ encoding=utf-8
+ serverAddress=http://localhost/zoo/
+ dataPath=/var/www/data
+ tmpPath=/var/www/tmp
+ tmpUrl=../tmp
+ cacheDir=/var/www/cache/
+ mapserverAddress=http://localhost/cgi-bin/mapserv
+ msOgcVersion=1.0.0
+
+ [identification]
+ title=The ZOO-Project WPS Server FOSS4G 2013 Nottingham Workshop
+ keywords=WPS,GIS,buffer
+ abstract=ZOO-Project platform 2013 .See http://www.zoo-project.org for more informations
+ accessConstraints=none
+ fees=None
+
+ [provider]
+ positionName=Developer
+ providerName=ZOO-Project
+ addressAdministrativeArea=Lattes
+ addressDeliveryPoint=1280 Av. des Platanes
+ addressCountry=fr
+ phoneVoice=+33670082539
+ addressPostalCode=34970
+ role=Dev
+ providerSite=http://www.zoo-project.org
+ phoneFacsimile=False
+ addressElectronicMailAddress=gerald.fenoy@geolabs.fr
+ addressCity=Lattes
+ individualName=Gérald FENOY
+
+The ``main.cfg`` file contains metadata informations about the identification and provider but also some important settings. The file is composed of various sections, namely ``[main]``, ``[identification]`` and ``[provider]`` per default.
+
+From the ``[main]`` section settings are as follow:
+ * ``lang``: the supported languages separated by a coma (the first is the default one),
+ * ``version``: the supported WPS version,
+ * ``encoding``: the default encoding of WPS Responses,
+ * ``serverAddress``: the url to access your ZOO-Kernel instance,
+ * ``dataPath``: the path to store data files (when MapServer support was activated,
+ this directory is used to store mapfiles and data).
+ * ``tmpPath``: the path to store temporary files (such as ExecuteResponse when
+ storeExecuteResponse was set to true),
+ * ``tmpUrl``: a url relative to ``serverAddress`` to access the temporary file,
+ * ``cacheDir``: the path to store cached request files [#f1]_ (optional),
+ * ``mapservAddress``: your local MapServer address (optional),
+ * ``msOgcVersion``: the version for all supported OGC Web Services output [#f2]_
+ (optional).
+
+The ``[identification]`` and ``[provider]`` section are specific to OGC metadata and
+should be set [#f3]_.
+
+Obviously, you are free to add new sections to this file if you need more. Nevertheless, you have to know
+that there is some specific names you should use only for specific
+needs: ``[headers]``, ``[mapserver]``, ``[env]``, ``[lenv]`` and ``[senv]``.
+
+.. warning:: ``[senv]`` and ``[lenv]`` are used / produced on runtime internaly by the ZOO-Kernel and should be defined only from the Service code.
+
+The ``headers`` section is used to define your own HTTP Response
+headers. You may take a look at headers returned by web site such as
+http://www.zoo-project.org by using curl command line tool for
+instance and notice the specific heder ``X-Powered-By: Zoo-Project@Trac``.
+
+.. warning:: There is no reason to define basic headers such as
+ ``Content-Type`` or ``encoding`` as they will be overwritten at runtime by the
+ ZOO-Kernel.
+
+The ``mapserver`` section is used to store specific mapserver configuration parameter
+such as PROJ_LIB and GDAL_DATA or any other you want to be set to make
+your MapServer working.
+
+.. note:: the ``mapserver`` section is mainly used on WIN32 platform
+
+
+The ``env`` section is used to store specific environment variables you want to be set
+prior to load your Services Provider and run your Service. A typical example, is when your
+Service requires to access to a X server running on framebuffer, then you will have to
+set the ``DISPLAY`` environnement variable, in this case you would add
+``DISPLAY=:1`` line in your ``[env]`` section.
+
+The ``lenv`` is used to store runtime informations automatically set by the
+ZOO-Kernel before running your service and can be accesses / updated from it:
+ * ``sid``: the service unique identifier,
+ * ``status``: the current progress value (value between 0 and 100, percent),
+ * ``cwd``: the current working directory of the ZOO-Kernel,
+ * ``message``: an error message when returning ``SERVICE_FAILED`` (optional),
+ * ``cookie``: the cookie your service want to return to the client (for authentication
+ purpose or tracking).
+
+The ``senv`` is used to store session informations on the server
+side. You can then access them automatically from service if the
+server is requested using a valid cookie (as defined in ``lenv >
+cookie``). The ZOO-Kernel will store on disk the values set in the
+``senv`` maps, then load it and dynamically add its content to the one
+available in the ``main.cfg``. The ``senv`` section should contain at
+least:
+ * ``XXX``: the session unique identifier where ``XXX`` is the name included in the
+ returned cookie.
+
+.. _cookie_example:
+
+For instance, if you get the following in your Service source code [#f4]_ :
+
+.. code-block:: python
+
+ conf["lenv"]["cookie"]="XXX=XXX1000000; path=/"
+ conf["senv"]={"XXX": "XXX1000000","login": "demoUser"}
+
+That means that the ZOO-Kernel will create a file ``sess_XXX1000000.cfg`` in the
+``cacheDir`` and return the specified cookie to the client. Each time the client will
+request the ZOO-Kernel using the Cookie, it will automatically load the value stored
+before running your service. You can then easilly access this informations from your
+service source code. This functionality won't be used in the following presentation.
+
+Testing the ZOO installation with GetCapabilities
+-------------------------------------------
+
+You can request ZOO-Kernel using the following link from your Internet browser:
+
+http://localhost/cgi-bin/zoo_loader.cgi?Request=GetCapabilities&Service=WPS
+
+You should get a valid Capabilities XML document, looking like the following :
+
+.. image:: ./images/GC.png
+ :width: 650px
+ :align: center
+
+Please note that some Process node are returned in the ProcessOfferings section, as somes are available already on OSGeoLive DVD. You can also run a GetCapabilities request from the command line, using the following command:
+
+.. code-block:: bash
+
+ cd /usr/lib/cgi-bin
+ ./zoo_loader.cgi “request=GetCapabilities&service=WPS”
+
+The same result as in your browser will be returned, as shown in the following screenshot:
+
+.. image:: ./images/GC_CL.png
+ :width: 450px
+ :align: center
+
+Invoking ZOO Kernel from command line can be helpful during development process of new Services.
+
+.. rubric:: Footnotes
+
+.. [#f1] when you use GET requests passed through ``xlink:href`` the ZOO-Kernel will
+ execute the request only once, the first time you will ask for this ressource and it will
+ store on disk the result. The next time you will need the same feature, the cached file
+ will be used which make your process running faster. If ``cachedir`` was not
+ specified in the ``main.cfg`` then ``tmpPath`` value will be used.
+.. [#f2] since version 1.3dev, when MapServer is activated, your service can automatically
+ return a WMS, WFS or WCS request to expose your data. Your can set here the specific
+ version number you want to use to request your local MapServer setup. It depends
+ mostly on the client capability to deal with specific OGC Web Services version.
+.. [#f3] since version 1.3dev, when MapServer is activated, the same
+ metadata will be used for setting metadata for OGC Web Services.
+.. [#f4] If you're not familiar with ZOO-Project, you can pass
+ this part and come to it after the `next section
+ `__.
Index: /trunk/workshop/2014/building_blocks_presentation.rst
===================================================================
--- /trunk/workshop/2014/building_blocks_presentation.rst (revision 723)
+++ /trunk/workshop/2014/building_blocks_presentation.rst (revision 723)
@@ -0,0 +1,149 @@
+.. _ogr_base_vect_ops:
+
+Building blocks presentation - Using OGR and PgRouting based Web Services
+=====================================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+---------------------------------------------------
+
+In this section, you will use basic ZOO-Services : ``Buffer``,
+``Intersection`` and ``DifferencePy`` which use OGR and psycopg Python modules.
+The intended goal of this section is to present and interact with your new building blocks before chaining them in the next section.
+
+First of all, you should use the following links to access the user
+interfaces and interact with your services, the first one is used to
+access basic spatial-tools demo client interface and the second to
+access the routing application :
+ * `http://localhost/zoo-ws/spatialtools-py.html `__
+ * `http://localhost/zoo-ws/ `__
+
+Services Provider and configuration files
+---------------------------------------------------
+
+First you may verify if the ZOO-Services are available from your current setup.
+You can take a look at the ``Buffer.zcfg``, ``Intersection.zcfg`` and
+``DifferencePy.zcfg`` to get details about parameters.
+As you can see from the ZCFG files, you will use ZOO-Services provided by the
+``service`` Python service provider. So if you want to modify the Python code
+you will have to edit the corresponding file (so ``service.py``).
+You are invited to use similar requests as the one used in previous
+sections to learn about each services individually.
+
+The Buffer Service
+---------------------------------------------------
+
+First click on a street then once the street is displayed in blue, click the
+'Buffer' button on top, you should get similar result as displayed in the following.
+
+.. image:: ./images/Buffer_Level_15.png
+ :width: 650px
+ :align: center
+
+Since version ZOO-Project 1.2.0, you can run automatically some basic tests to
+make sure that you wrote a correct ZCFG file and your service is validating.
+
+.. note:: the current testing is really simple and should be adapted to each Services
+ Provider, mainly to define input names.
+
+You can use the following command:
+
+.. code-block:: bash
+
+ cd /home/user/zoo/testing
+ ./run.sh http://localhost/cgi-bin/zoo_loader.cgi Buffer
+
+
+.. note:: During or after the test run, you can take a look inside the ``tmp`` directory
+ which contains both the XML requests send to the ZOO Kernel (``*1.xml``) and the
+ responses it gave (``output*.xml``).
+
+The Intersection Service
+---------------------------------------------------
+
+Using the same client interface as before, once you get a Buffer, you can then
+select a street intersecting the Buffer geometry to compute intersection by clicking on the Intersection button.
+
+
+.. image:: ./images/Intersection_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The DifferencePy Service
+---------------------------------------------------
+
+Using the same instructions as for Intersetion, you can get the following result.
+
+.. image:: ./images/Difference_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The Routing and Profile Services
+---------------------------------------------------
+
+First click on the blue flag then place your starting point on the
+map, do the same with the red flag to get the shortest path computed
+by the dedicated service and then display its profile. Note that when
+you pass the mouse over the profile display then you will see its
+corresponding position displayed on the map. You can also click on a
+specific step in your path to get the corresponding line displayed.
+
+.. image:: ./images/Routing_Basic.png
+ :width: 650px
+ :align: center
+
+If you take a look in the file: ``/usr/lib/cgi-bin/routing/do.zcfg``
+you may notice something new in the supported format which is
+reproduced here after.
+
+.. code-block:: guess
+
+
+ mimeType = image/png
+ asReference = true
+ msStyle = STYLE COLOR 125 0 105 OUTLINECOLOR 0 0 0 WIDTH 3 END
+ useMapServer = true
+ extension = json
+
+
+The ``mimeType`` is defined as ``image/png`` and there is two new
+parameter which are both optional:
+ * ``useMapServer``: which make you able to inform the ZOO-Kernel
+ that it have to use MapServer to publish your result as WMS / WFS or WCS (this last
+ won't be used in this workshop) rather than simply storing the
+ result as a file.
+ * ``msStyle``: which let you define your own MapServer ``STYLE`` block definition.
+
+When you need to access a result many time or for different purpose
+accross other services then it is really useful to ask ZOO-Kernel to
+publish your result as WMS, WFS or WCS.
+
+Note that no modification of the code of the do service was required
+to handle automatic pubilcation of the result as it is a vector format
+supported by OGR, only modification of the zcfg was required.
+
+This routing example is here to illustrate how easy it is to publish
+your result as WMS, WFS or WCS ressource. Indeed, when your routing
+service was called, ZOO-Kernel published the result as WMS and WFS
+ressources which was both used first for the UI purpose, the WMS to
+display the resulting path on the map, the WFS for displaying details
+about each steps. The WFS protocol is also used as the input value
+for the profile computation. So, the computation was run once
+and accessed three times for different purposes and from different
+clients.
+
+For more informations about the MapServer support, please refer to `the
+official ZOO-Project Documentation `_.
+
+Conclusion
+---------------------------------------------------
+
+Now you know this three services, and you get a simple interface to interact
+with your MapServer WFS and your ZOO-Project WPS Servers, you are ready to use
+the Services in a different way, by chaining them using the JavaScript ZOO-API to build
+more complexe and powerfull services.
Index: /trunk/workshop/2014/first_service.rst
===================================================================
--- /trunk/workshop/2014/first_service.rst (revision 723)
+++ /trunk/workshop/2014/first_service.rst (revision 723)
@@ -0,0 +1,375 @@
+.. _first_service:
+
+Creating your first ZOO Service
+========================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+-----------------------------------------------------
+
+In this part, you will create and publish a simple ZOO-Service named ``Hello`` which
+will simply return a hello message containing the input value provided. It will be usefull
+to present in deeper details general concept on how ZOO-Kernel works and handles
+Execute requests.
+
+Service and publication process overview
+-----------------------------------------------------
+
+Before starting developing a ZOO Service, you should remember that in
+ZOO-Project, a Service is a couple made of:
+
+ * a metadata file: a ZOO Service Configuration File (ZCFG) containing metadata
+ informations about a Service (providing informations about default / supported
+ inputs and outputs for a Service)
+ * a Services Provider: it depends on the programming language used, but for Python it
+ is a module and for JavaScript a script file.
+
+To publish your Service, which means make your ZOO Kernel aware of its presence,
+you should copy a ZCFG file in the directory where ``zoo_loader.cgi`` is located (in this workshop, ``/usr/lib/cgi-bin``) or in any subdirectory.
+
+.. warning:: only the ZCFG file is required for the Service to be considerate as
+ available. So if you don't get the Service Provider, obviously your Execute
+ request will fail as we will discuss later.
+
+Before publication, you should store your ongoing work, so you'll start by
+creating a directory to store the files of your Services Provider:
+
+.. code-block:: none
+
+ mkdir -p /home/user/zoo-ws/ws_sp/cgi-env
+
+Once the ZCFG and the Python module are both ready, you can publish simply
+by copying the corresponding files in the same directory as the ZOO-Kernel.
+
+Creating your first ZCFG file
+-----------------------------------------------------
+
+You will start by creating the ZCFG file for the ``Hello`` Service. Edit the
+``/home/user/zoo-ws/ws_sp/cgi-env/Hello.zcfg`` file
+and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Hello]
+ Title = Return a hello message.
+ Abstract = Create a welcome string.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = test_service
+ serviceType = Python
+
+ [name]
+ Title = Input string
+ Abstract = The string to insert in the hello message.
+ minOccurs = 1
+ maxOccurs = 1
+
+ dataType = string
+
+
+
+
+ [Result]
+ Title = The resulting string
+ Abstract = The hello message containing the input string
+
+ dataType = string
+
+
+
+
+.. note:: the name of the ZCFG file and the name between braket (here ``[Hello]``)
+ should be the same and correspond to the function name you will define in your
+ Services provider.
+
+As you can see in the ZOO Service Configuration File presented above it is divided into
+three distinct sections:
+ #. Main Metadata information (from line 2 to 8)
+ #. List of Inputs metadata information (from 9 line to 19)
+ #. List of Outputs metadata information (from line 20 to 28)
+
+You can get more informations about ZCFG from `the reference documentation
+`__.
+
+If you copy the ``Hello.zcfg`` file in the same directory as your ZOO Kernel
+then you will be able to request for DescribeProcess using the ``Hello``
+``Identifier``. The ``Hello`` service should also be listed from Capabilities
+document.
+
+.. code-block:: none
+ cp /home/user/zoo-ws/ws_sp/cgi-env/Hello.zcfg /usr/lib/cgi-bin
+
+Test requests
+-----------------------------------------------------
+
+In this section you will tests each WPS requests : GetCapabilities,
+DescribeProcess and Execute. Note that only GetCapabilities and DescribeProcess
+should work at this step.
+
+Test the GetCapabilities request
+.......................................................
+
+If you run the ``GetCapabilities`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=GetCapabilities&service=WPS
+
+Now, you should find your Hello Service in a ``Process`` node in
+``ProcessOfferings``:
+
+.. code-block:: xml
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+Test the DescribeProcess request
+.......................................................
+
+You can access the ``ProcessDescription`` of the ``Hello`` service using the
+following ``DescribeProcess`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=DescribeProcess&service=WPS&version=1.0.0&Identifier=Hello
+
+You should get the following response:
+
+.. code-block:: xml
+
+
+
+ Hello
+ Return a hello message.
+ Create a welcome string.
+
+
+ name
+ Input string
+ The string to insert in the hello message.
+
+ string
+
+
+
+
+
+
+
+
+
+
+Test the Execute request
+.......................................................
+
+Obviously, you cannot run your Service because the Python file was not published
+yet. If you try the following ``Execute`` request:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You should get an ExceptionReport similar to the one provided in the following,
+which is normal behavior:
+
+.. code-block:: xml
+
+
+
+ Python module test_service cannot be loaded.
+
+
+
+Implementing the Python Service
+-----------------------------------------------------
+
+General Principles
+.......................................................
+
+The most important thing you must know when implementing a new ZOO-Services
+using the Python language is that the function corresponding to your Service
+returns an integer value representing the status of execution
+(``SERVICE_FAILED`` [#f1]_ or ``SERVICE_SUCCEEDED`` [#f2]_) and takes three
+arguments (`Python dictionaries
+`__):
+
+ - ``conf`` : the main environment configuration (corresponding to the main.cfg content)
+ - ``inputs`` : the requested / default inputs (used to access input values)
+ - ``outputs`` : the requested / default outputs (used to store computation result)
+
+.. note:: when your service return ``SERVICE_FAILED`` you can set
+ ``conf["lenv"]["message"]`` to add a personalized message in the ExceptionReport
+ returned by the ZOO Kernel in such case.
+
+You get in the following a sample ``conf`` value based on the ``main.cfg`` file you
+saw `before `__.
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ "main": {
+ language: "en-US",
+ lang: "fr-FR,ja-JP",
+ version: "1.0.0",
+ encoding: "utf-8",
+ serverAddress: "http://localhost/cgi-bin/zoo_loader.cgi",
+ dataPath: "/var/data",
+ tmpPath: "/var/www/temp",
+ tmpUrl: "../temp",
+ cacheDir: "/var/www/temp/"
+ },
+ "identification": {
+ title: "ZOO-Project Workshop - FOSS4G 2014",
+ keywords: "WPS,GIS,buffer",
+ abstract: "Deploying Web Processing Services using ZOO-Project – Examples of Python based WPS using PgRouting",
+ accessConstraints: "none",
+ fees: "None"
+ },
+ "provider": {
+ positionName: "Developer",
+ providerName: "ZOO-Project",
+ addressAdministrativeArea: "Lattes",
+ addressCountry: "fr",
+ phoneVoice: "False",
+ addressPostalCode: "34970",
+ role: "Dev",
+ providerSite: "http://www.zoo-project.org",
+ phoneFacsimile: "False",
+ addressElectronicMailAddress: "gerald.fenoy@geolabs.fr",
+ addressCity: "Denver",
+ individualName: "Gérald FENOY"
+ }
+
+In the following you get a sample outputs value passed to a Python or a JavaScript Service:
+
+.. code-block:: javascript
+ :linenos:
+
+ {
+ 'Result': {
+ 'mimeType': 'application/json',
+ 'inRequest': 'true',
+ 'encoding': 'UTF-8'
+ }
+ }
+
+.. note:: the ``inRequest`` value is set internally by the ZOO-Kernel and can be used to determine from the Service if the key was provided in the request.
+
+ZOO-Project provide a ZOO-API which was originally only available for
+JavaScript services, but thanks to the work of the ZOO-Project
+community, now you have also access to a ZOO-API when using
+the Python language. Thanks to the Python ZOO-API you don't have to remember anymore
+the value of SERVICE_SUCCEDED and SERVICE_FAILED, you
+have the capability to translate any string from your Python service
+by calling the ``_`` function (ie: ``zoo._('My string to
+translate')``) or to update the current status of a running service by
+using the ``update_status`` [#f4]_ function the same way you use it from
+JavaScript or C services.
+
+The Hello Service
+.......................................................
+
+You can copy and paste the following into the
+``/home/user/zoo-ws/ws_sp/cgi-env/test_service.py`` file.
+
+.. code-block:: python
+
+ import zoo
+ def Hello(conf,inputs,outputs):
+ outputs["Result"]["value"]=\
+ "Hello "+inputs["name"]["value"]+" from the ZOO-Project Python world !"
+ return zoo.SERVICE_SUCCEEDED
+
+Once you finish editing the file, you should copy it in the ``/usr/lib/cgi-bin`` directory:
+
+.. code-block:: none
+
+ sudo cp /home/user/zoo-ws/ws_sp/cgi-env/* /usr/lib/cgi-bin
+
+
+Interracting with your service using Execute requests
+
+
+Now, you can request for Execute using the following basic url:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto
+
+You can request the WPS Server to return a XML WPS Response containing the result of
+your computation, requesting for ResponseDocument or you can access the data directly
+requesting for RawDataOutput.
+
+* Sample request using the RawDataOutput parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&RawDataOutput=Result
+
+* Sample request using the default ResponseDocument parameter:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result
+
+When you are using ResponseDocument there is specific attribut you can use to ask
+the ZOO Kernel to store the result: ``asReference``. You can use the following example:
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result@asReference=true
+
+When computation take long time, the client should request the
+execution of a Service by setting both ``storeExecuteResponse`` and
+``status`` parameter to true to force asynchronous execution. This
+will make the ZOO-Kernel return, without waiting for the Service execution
+completion but after starting another ZOO-Kernel process responsible
+of the Service execution, a ResponseDocument containing a ``statusLocation``
+attribute which can be used to access the status of an ongoing service
+or the result when the process ended [#f3]_.
+
+.. code-block:: none
+
+ http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result&storeExecuteResponse=true&status=true
+
+Conclusion
+-----------------------------------------------------
+
+Even if this first service was really simple it was useful to illustrate how the
+ZOO-Kernel fill ``conf``, ``inputs`` and ``outputs`` parameter prior to load
+and run your function service, how to write a ZCFG file, how to publish a Services
+Provider by placing the ZCFG and Python files in the same directory as the
+ZOO-Kernel, then how to interract with your service using both
+``GetCapabilities``, ``DescribeProcess`` and ``Execute`` requests. We will see
+in the `next section `__ how to write similar requests
+using the XML syntax.
+
+.. rubric:: Footnotes
+
+.. [#f1] ``SERVICE_FAILED=4``
+.. [#f2] ``SERVICE_SUCCEEDED=3``
+.. [#f4] sample use of update_status is available `here `_
+.. [#f3] To get on-going status url in ``statusLocation``, you'll
+ need to setup the `utils/status
+ `_
+ Service. If you don't get this service available, the ZOO-Kernel will
+ simply give the url to a flat XML file stored on the server which will
+ contain, at the end of the execution, the result of the Service
+ execution. For more informations please take a look into the
+ reference `documentation `__.
Index: /trunk/workshop/2014/index.rst
===================================================================
--- /trunk/workshop/2014/index.rst (revision 723)
+++ /trunk/workshop/2014/index.rst (revision 723)
@@ -0,0 +1,27 @@
+.. _workshop-foss4g-2014:
+
+##########################################
+ZOO-Project workshop 2014
+##########################################
+
+:Original Title: **Deploying Web Processing Services using ZOO-Project –
+ Examples of Python based WPS using PgRouting**
+:Author: Gérald Fenoy, Nicolas Bozon, Venkatesh Raghavan
+:Contact: gerald.fenoy at geolabs.fr, nicolas.bozon at gmail.com, venka at osgeo.org
+:Last Updated: $Date$
+:Events: FOSS4G 2014 Portland
+
+.. image:: ./images/FOSS4G_Ad_200x100_2x.jpg
+ :target: http://2014.foss4g.org/
+ :align: center
+
+**WorkShop table of content**
+
+.. toctree::
+ :maxdepth: 5
+
+ introduction
+ using_zoo_from_osgeolivevm
+ first_service
+ building_blocks_presentation
+ js_services_chaining
Index: /trunk/workshop/2014/introduction.rst
===================================================================
--- /trunk/workshop/2014/introduction.rst (revision 723)
+++ /trunk/workshop/2014/introduction.rst (revision 723)
@@ -0,0 +1,59 @@
+.. _introduction:
+
+Introduction
+=======================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+What is ZOO ?
+-------------------------------------------------
+
+ZOO-Project is a WPS (Web Processing Service) open source project released under a `MIT/X-11 `__ style license. It provides an OGC WPS compliant developer-friendly framework to create and chain WPS Web services. ZOO is made of three parts:
+
+* `ZOO Kernel `__ : A powerful server-side C Kernel which makes it possible to manage and chain Web services coded in different programming languages.
+* `ZOO Services `__ : A growing suite of example Web Services based on various open source libraries.
+* `ZOO API `__ : A server-side JavaScript API able to call and chain the ZOO Services, which makes the development and chaining processes easier and faster.
+
+ZOO was designed to make the service creation and deployment easy, by providing a powerful system able to understand and execute WPS compliant queries. It supports seven programming languages, thus allowing you to create Web Services using the one you prefer. It also lets you use an existing code and to turn it as a WPS Service.
+The current supported programming languages are the following:
+
+* C/C++
+* Python
+* Perl
+* Java
+* Fortran
+* PHP
+* JavaScript
+
+More information on the project is available on the `ZOO-Project official website `__ .
+
+How does ZOO works ?
+-------------------------------------------------
+
+ZOO is based on a C Kernel which is the ZOO-Project core system (aka ZOO-Kernel). The latter is able to dynamically load libraries and to handle them as on-demand Web services.
+
+A ZOO-Service is a link composed of a ZOO metadata file (.zcfg) and the code for the corresponding implementation. The metadata file describes the function that can be called using a WPS Execute Request, as well as the supported input/output formats. Service contains the algorithms and functions, and can be implemented using any of the supported languages.
+
+ZOO-Kernel works as CGI through Apache and can communicate with cartographic engines and Web mapping clients. It simply adds the WPS support to your spatial data infrastructure and your webmapping applications. It can use every GDAL/OGR supported formats as input data and create suitable vector or raster output for your cartographic engine and/or your web-mapping client application.
+
+What are we going to do in this workshop?
+-------------------------------------------------
+
+You will learn how to use ZOO-Kernel and how to create ZOO-Services using the OSGeoLiveDVD 7.9 `iso image `_ provided at the begining of this workshop on MapMint USB Sticks. Despite a pre-compiled ZOO 1.3.0 package is provided inside the official OSGeoLive, some optional supports are not available in the default setup and the ZOO-Kernel made available correspond to the 1.4-dev version, so let say the current version. So you will use the binary version of ZOO-Kernel available on the iso image provided. Configuration file and basic ways to use ZOO-Kernel and ZOO-Service will be presented. Then you will be invited to start programming your own simple service using Python language. Some ZOO-Services will be presented and individually tested inside a ready-to-use OpenLayers application. Finally, this services will be chained using the server-side Javascript ZOO-API.
+
+The whole workshop is organized step-by-step and numerous code snippets are available. The instructors will check the ZOO-Kernel is functioning on each machine and will assist you while coding. Technical questions are of course welcome during the workshop.
+
+Usefull tips for reading
+-------------------------------------------------
+
+.. code-block:: guess
+
+ this is a code block
+
+.. warning:: This is a warning message.
+
+.. note:: This is an important note.
+
+**Let's go !**
Index: /trunk/workshop/2014/js_services_chaining.rst
===================================================================
--- /trunk/workshop/2014/js_services_chaining.rst (revision 723)
+++ /trunk/workshop/2014/js_services_chaining.rst (revision 723)
@@ -0,0 +1,594 @@
+.. _ogr_base_vect_ops:
+
+Playing with buildign blocks - Creating JavaScript Web Services
+=============================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+Introduction
+-------------------------------------------------
+
+This section illustrate how you can use JavaScript on the server-side to chain
+services together to build new ones. You will create a ZOO Services Provider
+using the services you seen before and the WFS server using the ZOO-API. The
+final goal is to query all POIs included in a buffer around a feature and
+to highlight them using a mask around this buffer. The following screenshot show
+you the expected result:
+
+.. image:: ./images/BufferMaskAndRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+For the routing interface result should look like this:
+
+.. image:: ./images/BufferMaskAndRequest_Routing_Level_15.png
+ :width: 650px
+ :align: center
+
+You can decompose the result above in two different ones: the mask around the
+buffer and the points included in the buffer. So you will create two different
+Services: one called ``BufferMask`` and another one called ``BufferRequest``.
+
+But before implementing any JavaScript Service, you will get an overview of how
+to use ZOO-API from your ZOO-Project installation in the next section.
+
+As before, you first create a new directory to store files for your new Services
+Provider:
+
+.. code-block:: guess
+
+ mkdir -p ~/zoo-ws/jschains/cgi-env/
+
+
+ZOO-API Overview
+-------------------------------------------------
+
+ZOO-API and ZOO-Kernel JavaScript support make you able to run services
+implemented in JavaScript on the server side. JavaScript is a popular programing
+language but mostly used on the client side. Let say from a browser, but here it
+is a bit different.
+
+To support JavaScript language ZOO-Kernel use the
+`SpiderMonkey `__ API to create a
+javascript runtime environment from which it will load your JS file then extract
+the function corresponding to the service to run it using the prefilled
+parameters. The JavaScript runtime environment created by the ZOO-Kernel
+depend on your setup. If you placed the ``ZOO-api.js`` and ``ZOO-proj4js.js`` in
+the same directory as your ZOO-Kernel it means that your environment will
+contains ZOO-API and Proj4js which will be loaded before your service. In such case you can access to the Classes defined in the JavaScript ZOO-API
+to manipulate geographic data, for more informations please refer to the
+`ZOO-API Documentation `__.
+
+Even if it can be useful to run JavaScript on the server side, you should
+remember that some basic JavaScript functions you are familiar with does not
+exist or get a different behavior. For instance the simple ``alert``
+function will display messages in apache error logs rather than in a window when
+used from a browser. The ``alert`` function can be used as follow:
+
+.. code-block:: guess
+
+ alert("My alert message");
+
+There is no XMLHttpRequest available in the JavaScript evironement your service
+will run into. Hopefully, the ZOO-Kernel expose a C function to the JavaScript
+world named: ``JSRequest``. This function make you able from your JavaScript
+services to call other WPS services (locally or remotelly) or other kind OGC
+services such as WFS. When you are using the ZOO-API it is possible to call
+Services using a ``ZOO.Process`` instance [#f3]_, to parse WPS Responses using
+``ZOO.Format.WPS``
+(cf. `ref `__).
+
+As for Python services you already seen in previous sections, the functions
+corresponding to a Service should take three arguments: ``conf``, ``inputs`` and
+``outputs`` [#f4]_. Nevertheless, as the ZOO-Kernel is not able to access the
+values modified [#f5]_ by the Service code, rather than returning an integer as
+in Python, here you'll need to return both the integer value representing the
+Status of your Service in a JavaScript Object and the resulting ``outputs``
+values as an Object [#f6]_. You can see in the following an example of a JavaScript
+Service code:
+
+.. code-block:: none
+
+ function SampleService(conf,inputs,outputs){
+ var resultValue=someComputation(inputs);
+ return
+ {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { "mimeType": "application/json", "value": resultValue } }
+ };
+ }
+
+Before starting to implement the Services we will need to get our final
+BufferRequest service, let start with a simplier one.
+
+The Mask Service
+-------------------------------------------------
+
+In this section you will learn how to create your first JavaScript service which
+will simply return a rectangular mask around a selected feature. To build this
+mask you will use the Buffer service to create a buffer big enough around a
+selected geometry to cover a significant part of your map. You can see the
+expected result in the following screenshot:
+
+.. image:: ./images/Mask_Level_12.png
+ :width: 650px
+ :align: center
+
+As before, you will first start by writting the ZCFG, then you will write the
+JavaScript source code and finish by publishing your Services Provider.
+
+The ZCFG
+......................
+
+Open a file named
+``~/zoo-ws/jschains/cgi-env/Mask.zcfg``
+with your favorite text editor and add the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [Mask]
+ Title = Compute mask
+ Abstract = Compute mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+Here you simply define one default ``ComplexData`` for both ``inputData`` and
+``Result``: a GML and a GeoJSON respectively [#f7]_.
+
+The JavaScript service
+...........................................
+
+As you will have to request the Buffer service many times from your service, you
+will first define a ``Buffer`` function as follow. It uses the ``ZOO.Process``
+to request the Buffer service you seen in the previous section.
+
+Open a file named
+``~/zoo-ws/jschains/cgi-env/foss4gws.js`` and
+add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ var zoo_url='http://localhost/cgi-bin/zoo_loader.cgi';
+ var mapfile="/var/data/maps/project_WS2014.map";
+ var mapserv_url="http://localhost/cgi-bin/mapserv?map="+mapfile;
+
+ function Buffer(inputData,bDist){
+
+ // Create all required ZOO.formats
+ var fJ=new ZOO.Format.JSON();
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fWPS=new ZOO.Format.WPS();
+
+ // Pass the value as json
+ var myInputs = {
+ InputPolygon: { type: 'complex', value: fGJ.write(inputData), mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess = new ZOO.Process(zoo_url,'BufferPy');
+ var myExecuteResult=myProcess.Execute(myInputs,myOutputs);
+
+ return fGJ.read(myExecuteResult);
+
+ }
+
+From line 12 to 16, you give a GeoJSON string (created from ``inputData``) for
+InputPolygon and, on line 15, you set the BufferDistance value to ``bDist``.
+On line 17, you define Result as a RawDataOutput, so you won'tl have to parse the
+WPS response using the ZOO.Format.WPS.
+
+On line 18, you create a
+`ZOO.Process `__
+instance providing the ZOO-Kernel url and the Service name. Then, on line 19, you
+run the request passing inputs and outputs previously defined (from line 12 to 15). On line 21 you return the GeoJSON red.
+
+Now, you get your ``Buffer`` function, it is time to create your first JavaScript
+service. So, edit your ``foss4gws.js`` file you created before and add the following content:
+
+.. code-block:: javascript
+ :linenos:
+
+ function Mask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX and store its geometry in a ZOO.Feature
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+
+ // Return the created feature
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": { mimeType: "application/json", value: fGJ.write(result) } }
+ };
+
+ }
+
+Publish and use your Service
+................................................................
+
+Now you get both your ZCFG and your service code ready, you need to deploy your
+new Services Provider using the following command:
+
+.. code-block:: bash
+
+ sudo cp ~/zoo-ws/jschains/cgi-env/* /usr/lib/cgi-bin
+
+Now you are ready to use your JavaScript service by loading the following `url
+`__, click on a street then click on
+the "Mask" button.
+
+BufferMask Service
+-------------------------------------------------
+
+In this section you will implement a simple JavaScript service which will be able create
+a hole in the mask you created in `previous section <#mask-service>`__. This service
+will be used to highlight the buffer zone around a selected fature. You get a preview of
+the expected result in the following screenshot:
+
+.. image:: ./images/BufferMask_Level_15.png
+ :width: 650px
+ :align: center
+
+
+The ZCFG
+................................................................
+
+Open the file named
+``~/zoo-ws/jschains/cgi-env/BufferMask.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferMask]
+ Title = Compute buffer mask
+ Abstract = Compute buffer mask around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+This ZCFG is similar to the previous one. Please, refer to comments in the
+`previous section <#the-zcfg>`__ for more informations.
+
+The JavaScript service
+................................................................
+
+In this Service you will use same source code (until line 19) you used in the
+`previous section <#the-javascript-service>`__. Indeed, you should compute the Mask
+as you did before then compute Buffer for creating a hole in the mask (on line 22) to run
+the Difference service (from line 25 to 40).
+
+.. code-block:: guess
+ :linenos:
+
+ function BufferMask(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGML=new ZOO.Format.GML();
+ var fGJ=new ZOO.Format.GeoJSON();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+ var finalG=bbox.toGeometry();
+
+ // Compute Buffer standard buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Request Difference service using Buffer result and features in the BBOX
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ var myProcess2 = new ZOO.Process(zoo_url,'DifferencePy');
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(finalG),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ }
+ };
+ var myOutputs2= {Result: {type: 'RawDataOutput', mimeType: "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ // Return the bbox
+ var result=new ZOO.Feature(finalG,{"name": "Result1000"});
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: { "Result": {mimeType: "application/json", value: myExecuteResult4 } }
+ };
+
+ }
+
+Publish and use your Service
+................................................................
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+BufferRequest service
+----------------------------
+
+In this section, you will create a new Service: ``BufferRequest`` which will request
+POIs included in the Buffer around a selected feature [#f8]_. You will use the ``poi``
+layer served as WFS through your local mapserver installation. You can see in the
+following screenshot the expected result:
+
+.. image:: ./images/BufferRequest_Level_15.png
+ :width: 650px
+ :align: center
+
+The ZCFG
+................................................................
+
+
+Open the file named
+``~/zoo-ws/jschains/cgi-env/BufferRequest.zcfg``
+with your favorite text editor and copy / paste the following content:
+
+.. code-block:: none
+ :linenos:
+
+ [BufferRequest]
+ Title = Compute buffer request
+ Abstract = Compute buffer request around a geometry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = foss4gws.js
+ serviceType = JS
+
+ [InputData]
+ Title = The feature
+ Abstract = The feature to run the service with
+ minOccurs = 1
+ maxOccurs = 1
+
+
+ mimeType = text/xml
+ encoding = utf-8
+
+
+
+
+ [Result]
+ Title = The resulting feature
+ Abstract = The feature created by the service.
+
+
+ mimeType = application/json
+
+
+
+
+
+The JavaScript code
+................................................................
+
+
+As in the previous Service, you will compute a buffer around the input feature. But then
+you will request POIs available in the Buffer extent using a WFS request to use them to
+run ``Intersection`` service using the initial Buffer. The WFS request is useful to limit
+the number of points to use when requesting the ``Intersection`` Service.
+
+.. code-block:: javascript
+ :linenos:
+
+ function BufferRequest(conf,inputs,outputs){
+
+ // Create all required ZOO.formats
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fGML=new ZOO.Format.GML();
+
+ // Read the input GML
+ var inputData=fGML.read(inputs["InputData"]["value"]);
+
+ // Compute Buffer
+ var bufferResultAsJSON=Buffer(inputData,0.0015);
+
+ // Create the Buffer result BBOX
+ var bbox = new ZOO.Bounds();
+ var bounds=bufferResultAsJSON[0].geometry.getVertices();
+ for(var t in bounds){
+ bbox.extend(bounds[t]);
+ }
+
+ // Request Intersection service using Buffer result and WFS request using the
+ // BBOX
+ var myProcess2 = new ZOO.Process(zoo_url,'Intersection');
+ var req="&SERVICE=WFS&version=1.0.0&request=GetFeature&typename=poi1";
+ req+="&SRS=EPSG:4326&BBOX=";
+ var myInputs2 = {
+ InputEntity1: {
+ type: 'complex',
+ value: fGJ.write(bufferResultAsJSON),
+ mimeType: "application/json"
+ },
+ InputEntity2: {
+ type: 'complex',
+ xlink: mapserv_url+req+bbox.left+","+bbox.bottom+","+bbox.right+","+bbox.top,
+ mimeType: "text/xml"
+ }
+ };
+ var myOutputs2= {Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myExecuteResult4=myProcess2.Execute(myInputs2,myOutputs2);
+
+ return {
+ result: ZOO.SERVICE_SUCCEEDED,
+ outputs: [ {name:"Result", mimeType: "application/json", value: myExecuteResult4} ]
+ };
+
+ }
+
+.. warning:: to take advantage of the ZOO-Kernel cache system, you directly use the WFS
+ request as ``xlink:href`` rather than value for ``InputEntity2`` (from line 31 to 34) and use ``text/xml`` ``mimeType``
+ (on line 40). Indeed, the ZOO-API doesn't use the internal cache mechanisms.
+
+
+Publish and use your Service
+................................................................
+
+
+Now, you can publish your service as you did `before <#publish-your-service>`__. To
+use your service, please use the following `url
+`__.
+
+.. note:: You can click on "Buffer Request and Mask" to get the same result as presented
+ in `the initial screenshot <#introduction>`__.
+
+
+Add Union into the chain
+----------------------------
+
+As you can see in the following screenshot, when using the Buffer
+service using a feature collection containing more than one geometry,
+the result is made of multiple geometries. So, running Buffer service
+on the routing interface will result in multiple buffer:
+
+.. image:: ./images/Buffer_Routing_Level_15.png
+ :width: 650px
+ :align: center
+
+So, to get the same result as you got when selecting a single
+road, you should use Union of geometry (input or the one outputed by the
+``Buffer`` Service). As you are using the JavaScript ZOO-API, you can
+simply update the ``Buffer`` JavaScript function you defined earlier, to
+first call the Union of each geometry avaible in a feature collection
+prior to request (or after requesting) the Buffer Service. Hopefully,
+there is already this Python Service available, its name is
+``UnionOne1``, so you just need to add it in your Service chain.
+
+Here is the final code for the Buffer JavaScript function:
+
+.. code-block:: javascript
+ :linenos:
+
+ function Buffer(inputData,bDist){
+
+ // Create all required ZOO.formats
+ var fJ=new ZOO.Format.JSON();
+ var fGJ=new ZOO.Format.GeoJSON();
+ var fWPS=new ZOO.Format.WPS();
+
+ // Call the UnionOne1 Service
+ var myInputs0 = {
+ InputPolygon: { type: 'complex', value: fGJ.write(inputData), mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs0= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess0 = new ZOO.Process(zoo_url,'UnionOne1');
+ var myExecuteResult0=myProcess0.Execute(myInputs0,myOutputs0);
+
+ // Call the BufferPy Service
+ var myInputs = {
+ InputPolygon: { type: 'complex', value: myExecuteResult0, mimeType: "application/json"},
+ BufferDistance: {type: 'float', "value": bDist }
+ };
+ var myOutputs= { Result: { type: 'RawDataOutput', "mimeType": "application/json" } };
+ var myProcess = new ZOO.Process(zoo_url,'BufferPy');
+ var myExecuteResult=myProcess.Execute(myInputs,myOutputs);
+
+ return fGJ.read(myExecuteResult);
+
+ }
+
+
+Conclusion
+----------------------------
+
+After understanding how basic Geometric Operation Services works, here you built step by step new JavaScript services which reuse the previous ones and combine them in different ways. This was achieved using the ZOO-API, composed by C functions exposed by the ZOO-Kernel to the JavaScript services runtime environement and the JS files which can be optionally installed.
+
+.. rubric:: Footnotes
+
+.. [#f3] The ``ZOO.Process`` class uses ``JSRequest`` (cf. `ref
+ `__). You will get example
+ of use `later <#the-javascript-service>`__.
+.. [#f4] So ``conf``, ``inputs`` and ``outputs`` are simple JavaScript objects, similar
+ to the Python dictionaries used in the `previous section `__.
+.. [#f5] Such as ``conf``, ``inputs`` and ``outputs``.
+.. [#f6] You can also return a conf Object if you get any informations updated from your JavaScript service (such as cookie for instance)
+.. [#f7] Using one of the available ``ZOO.formats`` you are also able to support various
+ ``ComplexData`` for both input and output of the service. To simplify the
+ presentation here, you will use only this default ones.
+.. [#f8] So in the hole you created in the previous section.
Index: /trunk/workshop/2014/using_zoo_from_osgeolivevm.rst
===================================================================
--- /trunk/workshop/2014/using_zoo_from_osgeolivevm.rst (revision 723)
+++ /trunk/workshop/2014/using_zoo_from_osgeolivevm.rst (revision 723)
@@ -0,0 +1,219 @@
+.. _using_zoo_from_osgeolivevm:
+
+Configuration and ZOO-Kernel use
+=====================================================
+
+.. contents:: Table of Contents
+ :depth: 5
+ :backlinks: top
+
+ZOO-Kernel Configuration
+---------------------------------------------------
+
+
+As already said in introduction, an OSGeoLive Virtual Machine has been booted on your computer, allowing you to use ZOO-Kernel in a development environment directly.
+
+.. note:: we will use ZOO-Kernel or ``zoo_loader.cgi`` script without any distinction
+ in this document.
+
+General ZOO-Kernel settings are set in the ``main.cfg`` file located in the same directory as the ZOO-Kernel, so in ``/usr/lib/cgi-bin/``. This informations will be accessible from each services at runtime, so when you wil use Execute requests. You can see a typical ``main.cfg`` content in the following:
+
+.. code-block:: guess
+ :linenos:
+
+ [headers]
+ X-Powered-By=ZOO-Project@MapMint
+
+ [main]
+ encoding=utf-8
+ dataPath=/var/data
+ tmpPath=/var/www/temp
+ cacheDir=/var/www/cache
+ version=1.0.0
+ sessPath=/tmp
+ msOgcVersion=1.0.0
+ serverAddress=http://localhost/cgi-bin/mm/zoo_loader.cgi
+ lang=fr-FR,ja-JP
+ language=en-US
+ mapserverAddress=http://localhost/cgi-bin/mapserv.cgi
+ tmpUrl=http://127.0.0.1/temp/
+
+ [identification]
+ keywords=WPS,GIS,buffer,MapMint,ZOO-Project
+ title=ZOO-Project Workshop - FOSS4G 2014
+ abstract= Deploying Web Processing Services using ZOO-Project – Examples of Python based WPS using PgRouting
+ accessConstraints=none
+ fees=None
+
+ [provider]
+ positionName=Developer
+ providerName=GeoLabs SARL
+ addressAdministrativeArea=False
+ addressDeliveryPoint=1280, avenue des Platanes
+ addressCountry=fr
+ phoneVoice=+33467430995
+ addressPostalCode=34970
+ role=Dev
+ providerSite=http://www.geolabs.fr
+ phoneFacsimile=False
+ addressElectronicMailAddress=gerald@geolabs.fr
+ addressCity=Lattes
+ individualName=Gérald FENOY
+
+
+The ``main.cfg`` file contains metadata informations about the identification and provider but also some important settings. The file is composed of various sections, namely ``[main]``, ``[identification]`` and ``[provider]`` per default.
+
+From the ``[main]`` section settings are as follow:
+ * ``lang``: the supported languages separated by a coma (the first is the default one),
+ * ``version``: the supported WPS version,
+ * ``encoding``: the default encoding of WPS Responses,
+ * ``serverAddress``: the url to access your ZOO-Kernel instance,
+ * ``dataPath``: the path to store data files (when MapServer support was activated,
+ this directory is used to store mapfiles and data).
+ * ``tmpPath``: the path to store temporary files (such as ExecuteResponse when
+ storeExecuteResponse was set to true),
+ * ``tmpUrl``: a url relative to ``serverAddress`` to access the temporary file,
+ * ``cacheDir``: the path to store cached request files [#f1]_ (optional),
+ * ``mapservAddress``: your local MapServer address (optional),
+ * ``msOgcVersion``: the version for all supported OGC Web Services output [#f2]_
+ (optional).
+
+The ``[identification]`` and ``[provider]`` section are specific to OGC metadata and
+should be set [#f3]_.
+
+Obviously, you are free to add new sections to this file if you need
+more [#f8]_. Nevertheless, you have to know
+that there is some specific names you should use only for specific
+purposes: ``[headers]``, ``[mapserver]``, ``[env]``, ``[lenv]`` and ``[senv]``.
+
+.. warning:: ``[senv]`` and ``[lenv]`` are used / produced on runtime internaly by the ZOO-Kernel and should be defined only from the Service code.
+
+The ``headers`` section is used to define your own HTTP Response
+headers. You may take a look at headers returned by web site such as
+http://www.zoo-project.org by using curl command line tool for
+instance and notice the specific heder ``X-Powered-By: Zoo-Project@Trac``.
+
+.. warning:: There is no reason to define basic headers such as
+ ``Content-Type`` or ``encoding`` as they will be overwritten at runtime by the
+ ZOO-Kernel.
+
+The ``mapserver`` section is used to store specific mapserver configuration
+parameters such as `PROJ_LIB` and `GDAL_DATA` or any other you want to be set to
+make your MapServer working.
+
+.. note:: the ``mapserver`` section is mainly used on WIN32 platform
+
+
+The ``env`` section is used to store specific environment variables you want to be set
+prior to load your Services Provider and run your Service. A typical example, is when your
+Service requires to access to a X server running on framebuffer, then you will have to
+set the ``DISPLAY`` environnement variable, in this case you would add
+``DISPLAY=:1`` line in your ``[env]`` section.
+
+The ``lenv`` is used to store runtime informations automatically set by the
+ZOO-Kernel before running your service and can be accesses / updated from it:
+ * ``sid`` (r): the service unique identifier,
+ * ``status`` (rw): the current progress value (value between 0 and 100, percent),
+ * ``cwd`` (r): the current working directory of the ZOO-Kernel,
+ * ``message`` (rw): an error message when returning ``SERVICE_FAILED`` (optional),
+ * ``cookie`` (rw): the cookie your service want to return to the client (for authentication
+ purpose or tracking).
+
+The ``senv`` is used to store session informations on the server
+side. You can then access them automatically from service if the
+server is requested using a valid cookie (as defined in ``lenv >
+cookie``). The ZOO-Kernel will store on disk the values set in the
+``senv`` maps, then load it and dynamically add its content to the one
+available in the ``main.cfg``. The ``senv`` section should contain at
+least:
+ * ``XXX``: the session unique identifier where ``XXX`` is the name included in the
+ returned cookie.
+
+.. _cookie_example:
+
+For instance, if you get the following in your Service source code [#f4]_ :
+
+.. code-block:: python
+
+ conf["lenv"]["cookie"]="XXX=XXX1000000; path=/"
+ conf["senv"]={"XXX": "XXX1000000","login": "demoUser"}
+
+That means that the ZOO-Kernel will create a file ``sess_XXX1000000.cfg`` in the
+``cacheDir`` and return the specified cookie to the client. Each time the client will
+request the ZOO-Kernel using the Cookie, it will automatically load the value stored
+before running your service. You can then easilly access this informations from your
+service source code. This functionality won't be used in the following presentation.
+
+Testing the ZOO installation with GetCapabilities
+---------------------------------------------------
+
+
+Once you have a main.cfg file available in the same directory as your
+ZOO-Kernel, then you can use `GetCapablities`. Indeed, to answer such
+kind of requests, the ZOO-Kernel will simply parse the `main.cfg` file
+(to gather global informations), then parse individually each zcfg
+files (if any) contained in the same directory or in sub-directories
+[#f9]_, then return a well formed `Capabilities` document.
+
+You can request ZOO-Kernel using the following link from your Internet browser:
+
+http://localhost/cgi-bin/zoo_loader.cgi?Request=GetCapabilities&Service=WPS
+
+You should get a valid Capabilities XML document, looking like the following :
+
+.. image:: ./images/GC.png
+ :width: 650px
+ :align: center
+
+Please note that some Process nodes are returned in the
+ProcessOfferings section, as somes are available already on OSGeoLive
+DVD. You can also run a GetCapabilities request from the command line,
+using the following command:
+
+.. code-block:: bash
+
+ cd /usr/lib/cgi-bin
+ ./zoo_loader.cgi “request=GetCapabilities&service=WPS” | less
+
+The same result as in your browser will be returned, as shown in the following screenshot:
+
+.. image:: ./images/GC_CL.png
+ :width: 450px
+ :align: center
+
+Invoking ZOO Kernel from the command line can be helpful during
+development process of new Services for debugging purpose. If you
+need to simulate POST request from the command line, then you can use
+the following:
+
+.. code-block:: bash
+
+ cd /usr/lib/cgi-bin
+ # Download the sample GetCapabilities request
+ curl -o /tmp/10_wpsGetCapabilities_request.xml http://schemas.opengis.net/wps/1.0.0/examples/10_wpsGetCapabilities_request.xml
+ # Define required environment settings
+ export REQUEST_METHOD=POST
+ export CONTENT_TYPE=text/xml
+ # Run the request downloaded
+ ./zoo_loader.cgi < /tmp/10_wpsGetCapabilities_request.xml | less
+
+You should have the same result as presented before.
+
+.. rubric:: Footnotes
+
+.. [#f1] when you use GET requests passed through ``xlink:href`` the ZOO-Kernel will
+ execute the request only once, the first time you will ask for this ressource and it will
+ store on disk the result. The next time you will need the same feature, the cached file
+ will be used which make your process running faster. If ``cachedir`` was not
+ specified in the ``main.cfg`` then ``tmpPath`` value will be used.
+.. [#f2] since version 1.3.0, when MapServer is activated, your service can automatically
+ return a WMS, WFS or WCS request to expose your data. Your can set here the specific
+ version number you want to use to request your local MapServer setup. It depends
+ mostly on the client capability to deal with specific OGC Web Services version.
+.. [#f3] since version 1.3.0, when MapServer is activated, the same metadata will be used
+ for setting metadata for OGC Web Services.
+.. [#f8] you can take a quick look into the mapmint ``main.cfg`` file
+ which is available in `/usr/lib/cgi-bin/mm/` directory to have
+ example of sections use.
+.. [#f4] If you're not familiar with ZOO-Project, you can `pass `__ this part and come to it after the next section.
+.. [#f9] sub-directories listing is available from `revision 469 `__.
Index: /trunk/workshop/Makefile
===================================================================
--- /trunk/workshop/Makefile (revision 723)
+++ /trunk/workshop/Makefile (revision 723)
@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+ @echo "Please use \`make ' where is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ZOOProject.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ZOOProject.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/ZOOProject"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ZOOProject"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
Index: /trunk/workshop/_static/doctools.js
===================================================================
--- /trunk/workshop/_static/doctools.js (revision 723)
+++ /trunk/workshop/_static/doctools.js (revision 723)
@@ -0,0 +1,263 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+if (!window.console || !console.firebug) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
+ "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
+ "profile", "profileEnd"];
+ window.console = {};
+ for (var i = 0; i < names.length; ++i)
+ window.console[names[i]] = function() {};
+}
+ */
+
+/**
+ * small helper function to urldecode strings
+ */
+jQuery.urldecode = function(x) {
+ return decodeURIComponent(x).replace(/\+/g, ' ');
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+ if (typeof s == 'undefined')
+ s = document.location.search;
+ var parts = s.substr(s.indexOf('?') + 1).split('&');
+ var result = {};
+ for (var i = 0; i < parts.length; i++) {
+ var tmp = parts[i].split('=', 2);
+ var key = jQuery.urldecode(tmp[0]);
+ var value = jQuery.urldecode(tmp[1]);
+ if (key in result)
+ result[key].push(value);
+ else
+ result[key] = [value];
+ }
+ return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+ function highlight(node) {
+ if (node.nodeType == 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
+ var span = document.createElement("span");
+ span.className = className;
+ span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+ node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+ document.createTextNode(val.substr(pos + text.length)),
+ node.nextSibling));
+ node.nodeValue = val.substr(0, pos);
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this);
+ });
+ }
+ }
+ return this.each(function() {
+ highlight(this);
+ });
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+ init : function() {
+ this.fixFirefoxAnchorBug();
+ this.highlightSearchWords();
+ this.initIndexTable();
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS : {},
+ PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
+ LOCALE : 'unknown',
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext : function(string) {
+ var translated = Documentation.TRANSLATIONS[string];
+ if (typeof translated == 'undefined')
+ return string;
+ return (typeof translated == 'string') ? translated : translated[0];
+ },
+
+ ngettext : function(singular, plural, n) {
+ var translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated == 'undefined')
+ return (n == 1) ? singular : plural;
+ return translated[Documentation.PLURALEXPR(n)];
+ },
+
+ addTranslations : function(catalog) {
+ for (var key in catalog.messages)
+ this.TRANSLATIONS[key] = catalog.messages[key];
+ this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+ this.LOCALE = catalog.locale;
+ },
+
+ /**
+ * add context elements like header anchor links
+ */
+ addContextElements : function() {
+ $('div[id] > :header:first').each(function() {
+ $('\u00B6').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this headline')).
+ appendTo(this);
+ });
+ $('dt[id]').each(function() {
+ $('\u00B6').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this definition')).
+ appendTo(this);
+ });
+ },
+
+ /**
+ * workaround a firefox stupidity
+ * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
+ */
+ fixFirefoxAnchorBug : function() {
+ if (document.location.hash)
+ window.setTimeout(function() {
+ document.location.href += '';
+ }, 10);
+ },
+
+ /**
+ * highlight the search words provided in the url in the text
+ */
+ highlightSearchWords : function() {
+ var params = $.getQueryParameters();
+ var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+ if (terms.length) {
+ var body = $('div.body');
+ if (!body.length) {
+ body = $('body');
+ }
+ window.setTimeout(function() {
+ $.each(terms, function() {
+ body.highlightText(this.toLowerCase(), 'highlighted');
+ });
+ }, 10);
+ $('
+{%- endblock %}
+
+
+
Index: /trunk/workshop/_themes/sphinx_rtd_theme/search.html
===================================================================
--- /trunk/workshop/_themes/sphinx_rtd_theme/search.html (revision 723)
+++ /trunk/workshop/_themes/sphinx_rtd_theme/search.html (revision 723)
@@ -0,0 +1,50 @@
+{#
+ basic/search.html
+ ~~~~~~~~~~~~~~~~~
+
+ Template for the search page.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "layout.html" %}
+{% set title = _('Search') %}
+{% set script_files = script_files + ['_static/searchtools.js'] %}
+{% block footer %}
+
+ {# this is used when loading the search index using $.ajax fails,
+ such as on Chrome for documents on localhost #}
+
+ {{ super() }}
+{% endblock %}
+{% block body %}
+
+
+ {% if search_performed %}
+
{{ _('Search Results') }}
+ {% if not search_results %}
+
{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}
+ {% endif %}
+ {% endif %}
+
+ {% if search_results %}
+
+ {% for href, caption, context in search_results %}
+