You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/08/12 08:32:21 UTC

svn commit: r1695424 - in /olingo/site/trunk/content/doc/odata4/tutorials: sqo_es/ sqo_tcs/

Author: mibo
Date: Wed Aug 12 06:32:21 2015
New Revision: 1695424

URL: http://svn.apache.org/r1695424
Log:
Added system query options expand/select tutorial

Added:
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/metadataNav.JPG   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_expandCat.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_navCat.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_Full.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_SelectName.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_expandCat.jpg   (with props)
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext   (with props)
Modified:
    olingo/site/trunk/content/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.mdtext

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/metadataNav.JPG
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/metadataNav.JPG?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/metadataNav.JPG
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/metadataNav.JPG
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_expandCat.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_expandCat.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_expandCat.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_expandCat.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_navCat.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_navCat.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_navCat.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_1_navCat.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_Full.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_Full.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_Full.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_Full.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_SelectName.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_SelectName.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_SelectName.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_SelectName.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_expandCat.jpg
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_expandCat.jpg?rev=1695424&view=auto
==============================================================================
Binary file - no diff available.

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_expandCat.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/responseProducts_expandCat.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext?rev=1695424&view=auto
==============================================================================
--- olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext (added)
+++ olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext Wed Aug 12 06:32:21 2015
@@ -0,0 +1,440 @@
+# How to build an OData Service with Olingo V4
+
+# Part 5.2: System Query Options: `$select`, `$expand`
+
+## Introduction
+
+In the present tutorial, we will continue implementing **OData system query options**.
+After we have learned the rather simple system query options `$top`, `$skip` and `$count` in the previous tutorial, we’re going to deal with `$select` and `$expand` in the present tutorial.
+
+
+**Note:**  
+The full implementation of the OData service as described in the present tutorial can be found in the [attached zip file](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip) that contains an Eclipse project that can be imported into your Eclipse workspace.
+
+
+**Disclaimer:**  
+Again, in the present tutorial, we’ll focus only on the relevant implementation, in order to keep the code small and simple. The sample code as it is, shouldn’t be reused for advanced scenarios.
+
+**Table of Contents**
+
+  1. Prerequisites
+  2. Preparation
+  3. Implementating system query options
+     1. Implement `$select`
+     2. Implement `$expand`
+  4. Run the implemented service
+  5. Summary
+  6. Links
+
+
+___
+
+# 1. Prerequisites
+
+Same prerequisites as in [Tutorial Part 4: Navigation](http://olingo.apache.org/doc/odata4/tutorials/navigation/tutorial_navigation.html) as well as basic knowledge about the concepts presented there.
+
+Furthermore, basic knowledge about *System Query Options* (see [Tutorial Part 5.1](doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.html)) is helpful.
+
+___
+
+# 2. Preparation
+
+Follow [Tutorial Part 4: Navigation](http://olingo.apache.org/doc/odata4/tutorials/navigation/tutorial_navigation.html) or as shortcut import the [attached  project](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip) into your Eclipse workspace.
+
+Afterwards do a _Deploy and run_: it should be working.
+
+
+___
+
+
+# 3. Implementation
+
+Open the class `myservice.mynamespace.service.DemoEntityProcessor`  
+The method `readEntity()` contains the code for navigation which was treated in Tutorial Part 4. In the current tutorial we want to focus on query options and to keep the code as simple as possible, we delete the code of the `readEntity()` method and start from scratch.
+
+## 3.1. Implement `$select`
+
+**Background**  
+When requesting an entity collection from the backend, the OData service returns a list of entities and each entity contains a list of properties.  
+In some cases, the user might not actually need all the properties. As such, he wants to tell the server to return only those properties that he is interested in.  
+OData supports this requirement with the system query option `$select`.  
+This parameter can be specified in the following ways:  
+
+  * Specify one property name only: `$select=Name`  
+  * Specify a comma-separated list of properties: `$select=Name,Description`
+  * Specify a star to include all properties: `$select=*`
+
+**Example**
+First, just to remember how the full payload looks like, the “normal” query of the product without query options:  
+<http://localhost:8080/DemoService/DemoService.svc/Products>
+
+![AllProductsNoQueryOption](responseProducts_Full.jpg "The full list of Products")
+
+The following request provides only one property for each entry in the collection:  
+<http://localhost:8080/DemoService/DemoService.svc/Products?$select=Name>  
+
+![AllProductsSelectName](responseProducts_SelectName.jpg "The full list of Products, but displayling only the Name property")
+
+**Implementation**  
+The following section describes how to enable the `EntityProcessor` class and the `readEntity()` method for `$select`.
+
+Because we start from scratch with the empty `readEntity()` method, we have to write a bit preparation code before we start with the implementation of the `$select`.  
+The following lines are a copy of the Tutorial Part 2 and are necessary to fetch the data for a single entity.
+
+    :::java
+    // 1. retrieve the Entity Type
+    List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+    UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
+    EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
+    // 2. retrieve the data from backend
+    List<UriParameter> keyPredicates = uriResourceEntitySet.getKeyPredicates();
+    Entity entity = storage.readEntityData(edmEntitySet, keyPredicates);
+
+
+
+The Olingo library parses the `$select` option from the request and provides support in the serializer to serialize only the selected properties.  
+Based on that the simplest implementation for `$select` is to get the `SelectOption` from the request (via `UriInfo` object) and pass this together with the enties to the serializer.  
+The drawback of this implementation is, that the full payload is fetched from the backend and afterwards the unnecessary properties are removed. From performance point of view, this is not optimal. It would be better to fetch only the requested properties from the backend. Which of course depends on the backend.  
+
+In this tutorial we use the simple implementation to show the concept for `$select` so that there are only a few steps that have to be done by us.  
+
+  * We have to get the SelectOption from the UriInfo:
+
+        // 3rd: apply system query options
+        SelectOption selectOption = uriInfo.getSelectOption();
+
+
+  * We have to take care about the context URL, which is different in case that `$select` is used.
+  Again, the Olingo library provides some support, which we use to build the select list that has to be passed to the ContextURL builder:
+
+        :::java
+        // we need the property names of the $select, in order to build the context URL
+        String selectList = odata.createUriHelper().buildContextURLSelectList(
+        edmEntityType, null, selectOption);
+        ContextURL contextUrl = ContextURL.with()
+                  .entitySet(edmEntitySet)
+                  .selectList(selectList)
+                  .build();
+
+
+  * Furthermore, the serializer has to know about the usage of `$select`.
+  Therefore, the serializer options instance is initialized with the selectOption object that we’ve obtained above. If this object is not null, then the serializer will take care to consider the `$select` statement
+
+        :::java
+        EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with()
+                  .contextURL(contextUrl)
+                  .select(selectOption)
+                  .build();
+
+
+
+**The full implementation of the `readEntityCollection()` method:**
+
+
+    public void readEntityCollection(ODataRequest request, ODataResponse response,
+                        UriInfo uriInfo, ContentType responseFormat)
+                        throws ODataApplicationException, SerializerException {
+
+      // 1st retrieve the requested EdmEntitySet from the uriInfo
+      List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+      UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
+      EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
+
+      // 2nd: fetch the data from backend for this requested EntitySetName  
+      EntityCollection entityCollection = storage.readEntitySetData(edmEntitySet);
+
+      // 3rd: apply system query options
+      // Note: $select is handled by the lib, we only configure ContextURL + SerializerOptions
+      // for performance reasons, it might be necessary to implement the $select manually
+      SelectOption selectOption = uriInfo.getSelectOption();
+
+      // 4th: create a serializer based on the requested format (json)
+      ODataFormat format = ODataFormat.fromContentType(responseFormat);
+      ODataSerializer serializer = odata.createSerializer(format);
+
+      // and serialize the content: transform from the EntitySet object to InputStream
+      EdmEntityType edmEntityType = edmEntitySet.getEntityType();
+      // we need the property names of the $select, in order to build the context URL
+      String selectList = odata.createUriHelper().buildContextURLSelectList(
+                        edmEntityType, null, selectOption);
+      ContextURL contextUrl = ContextURL.with()
+            .entitySet(edmEntitySet)
+            .selectList(selectList)
+            .build();
+
+
+      // adding the selectOption to the serializerOpts will tell the lib to do the job
+      EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with()
+            .contextURL(contextUrl)
+            .select(selectOption)
+            .build();
+      SerializerResult serializerResult = serializer.entityCollection(srvMetadata,
+                        edmEntityType, entityCollection, opts);
+
+      // 5th: configure the response object: set the body, headers and status code
+      response.setContent(serializerResult.getContent());
+      response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+      response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
+    }
+
+
+
+
+## 3.2. Implement $expand
+
+**Background**
+
+In order to understand the $expand system query option, let’s first quickly recap what we’ve learned in the navigation-tutorial:
+
+  1. In order to be able to navigate from one entity to another entity, we need at least 2 EntityTypes and at least one NavigationProperty
+
+![Metadata](metadataNav.jpg "Declaring the navigation in the metadata")
+
+ 1. We can invoke one single entity, e.g. display one product:
+
+![Products(1)SingleRead](responseProducts_1.jpg "The result of a single read")
+
+  1. And we can follow the navigation to the second entity, by appending the navigation property name, e.g. invoke the category of that product.
+  As we’ve seen in the metadata above, the name of the navigation property is *Category*
+
+![Products(1)NavToCat](responseProducts_1_navCat.jpg "Navigating from a Product to its Category")
+
+We have executed two requests to our OData service, in order to obtain the data for the product and for its related category.  
+Now, since the category info is so tightly bound to the selected product, we’d like to get the same info by executing only **one** request.
+
+This can be achieved with the $expand  
+
+The URL is built as follows:  
+
+  * specify the request URI for the single read operation: <http://localhost:8080/DemoService/DemoService.svc/Products(1)>  
+  * append the `?` to indicate that system query options will follow  
+  * append the `$expand`  
+  * specify the name of the desired navigation property:  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category>  
+
+As a result, the data of both entities is provided within one payload.  
+The data of the target entity is presented *“inline”*, which means as a child element of the source entity.  
+
+![Products(1)Expanded](responseProducts_1_expandCat.jpg "The Product with its expanded Category")
+
+One more advantage is that the system query option `$expand` can also be applied to an entity collection:
+
+![AllProductsExpanded](responseProducts_expandCat.jpg "All Products with expanded Category")
+
+More details can be found in the [OData specification - Protocol](http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part1-protocol/odata-v4.0-errata02-os-part1-protocol-complete.html#_Toc406398298) and [OData specification - Url Conventions](http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part2-url-conventions/odata-v4.0-errata02-os-part2-url-conventions-complete.html#_Toc406398162)
+
+
+**Implementation**  
+
+In the following section, we’ll focus on the implementation of the `$expand` for a single entity request e.g. <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category>
+
+**Note:**  
+The implementation for the entity collection is the same, just that we have to loop over all entities and apply the below code to each of them.
+
+In brief, what we have to do is: fetch the data for both entities and merge into one entity
+
+We can distinguish the following steps:  
+
+  1. Retrieve the ExpandOption from Uri  
+  In our example: `$expand=Category`  
+  2. Retrieve the (target) EdmEntityType which corresponds to the expand
+  In our example: *Category*  
+  3. Build the response data for the entity, enriched with the data of the expand entity  
+  In our example: *product1* merged with *category1*  
+
+Let's have a detailed look.
+
+##### Step 1: Retrieve the ExpandOption from Uri  
+
+We need the retrieve the ExpandOption from the UriInfo:  
+
+    :::java
+    ExpandOption expandOption = uriInfo.getExpandOption();
+
+As usual, if this object is `null`, then the user hasn’t used the `$expand` in his request, and we don’t need to do anything.
+
+
+##### Step 2: Retrieve the EdmEntityType corresponding to the expand
+
+
+In brief: `ExpandOption` -> `NavigationProperty` -> `EdmEntityType`  
+
+From the `ExpandOption`, we can get the ExpandItems.  
+An `ExpandItem` corresponds to the name of the navigation property.  
+So for the URL <http://localhost:8080/DemoService/DemoService.svc/Products?$expand=Category> we get one ExpandItem, which corresponds to the navigation property *Category*.  
+
+In the present tutorial, we’re keeping the implementation as simple as possible.
+So we’re relying on the fact that our example service only contains one navigation property per entity type.
+Therefore, we can directly access the first `ExpandItem`.  
+
+    :::java
+    ExpandItem expandItem = expandOption.getExpandItems().get(0);
+
+**Note:**  
+Most OData services will have more entity types and more navigation possibilities. In such services, it might be desired to invoke `$expand` with more than one navigation property, like for example: <http://localhost:8080/DemoService/DemoService.svc/Products?$expand=Category,Supplier,Sales>
+Such `$expand` expression is not considered in our example.  
+
+
+Now that we have the `ExpandItem`, the next step is to extract the navigation property from it.  
+For that, we have to ask the ExpandItem for its list if resource segments.  
+The reason why an ExpandItem can be formed by multiple segments is that a navigation property can be in a `ComplexType`, such that it would be required to address it by a path.  
+
+In our simple example, we don’t need to specify a path, therefore we can safely write  
+
+    :::java
+    UriResource uriResource = expandItem.getResourcePath().getUriResourceParts().get(0);
+
+This `uriResource` corresponds to the navigation property that we want to extract.  
+We expect that the `uriResource` is of type `UriResourceNavigation`, such that we can cast.  
+The `UriResourceNavigation` can then be asked for the `NavigationProperty` which in turn delivers the corresponding `EdmEntityType`, which we’re interested in:  
+
+    :::java
+    if(uriResource instanceof UriResourceNavigation){
+    EdmNavigationProperty edmNavigationProperty = ((UriResourceNavigation)uriResource).getProperty();
+    EdmEntityType expandEdmEntityType = edmNavigationProperty.getType();
+
+
+##### Step 3: Build the response data
+
+Lets follow our example.
+As we have said, we have to merge the data of two entities.  
+The first one, the product, is already fetched, as we’ve done that earlier in the code:  
+
+    :::java
+    Entity entity = storage.readEntityData(edmEntitySet, keyPredicates);
+
+This entity corresponds to the product.
+
+Now we’re ready to fetch the category, as we’ve already retrieved the `EdmEntityType` from the expand expression.  
+We can invoke a helper method that we created in Tutorial Part 4 (Navigation), a helper method that is located in our database-mock and that returns the category entity corresponding to a given product entity:  
+
+    :::java
+    Entity expandEntity = storage.getRelatedEntity(entity, expandEdmEntityType);
+
+In our example, this `expandEntity` contains the data of the related category.  
+
+Now we have to merge both entities.  
+This is done via a `Link` object that contains the inline entity object.  
+And the link is added to the source entity.  
+The relevant code is:  
+
+    :::java
+    Link link = new Link();
+    link.setTitle(navPropName);
+    link.setInlineEntity(expandEntity);
+    entity.getNavigationLinks().add(link);
+
+**Note:**  
+It is important to set the correct navigation property name, otherwise the linking doesn’t work and the inline data cannot be displayed.
+
+
+##### Final step
+Now that the response data has been built, we need to tell the serializer to consider the expand, otherwise the data will not be displayed.  
+Also, the `expandOption` has to be considered while building the `ContextUrl`.  
+
+    :::java
+    String selectList = odata.createUriHelper().buildContextURLSelectList(
+                                                edmEntityType, expandOption, selectOption);
+    ContextURL contextUrl = ContextURL.with()
+                                      .entitySet(edmEntitySet)
+                                      .selectList(selectList)
+                                      .suffix(Suffix.ENTITY).build();
+
+    // make sure that $expand and $select are considered by the serializer
+    // adding the selectOption to the serializerOpts will actually tell the lib to do the job
+    EntitySerializerOptions opts = EntitySerializerOptions.with()
+                                                          .contextURL(contextUrl)
+                                                          .select(selectOption)
+                                                          .expand(expandOption)
+                                                          .build();
+
+## 3.3. Implement $expand with options
+
+**Background**
+
+As of OData v4 spec, the expand can also be further refined with system query options  
+
+Example:  
+<http://localhost:8080/DemoService/DemoService.svc/Categories?$expand=Products($top=1)>
+
+A common use case would be the following request, where all products are displayed along with their corresponding category, but only the interesting properties:  
+<http://localhost:8080/DemoService/DemoService.svc/Products?$select=Name,Description&$expand=Category($select=Name)>  
+
+With respect to the system query options that are applied to the expand, multiple options are allowed, which are separated by semicolon, e.g.  
+<http://localhost:8080/DemoService/DemoService.svc/Categories(1)?$expand=Products($top=1;$select=Name)>  
+
+The $select option can itself define a list of comma-separated properties:  
+<http://localhost:8080/DemoService/DemoService.svc/Categories(1)?$expand=NavToProducts($top=1;$select=Name,Description)>  
+
+
+**Implementation**
+
+The code for applying system query options to the `$expand` is similar to what is described in the Tutorial Part 5.1.
+We only need to know from where to get the information about the query options used in the request URL:   It is located in the `ExpandItem` instance.
+
+The procedure is:
+
+  * Get the data for the navigation property (the normal expand)  
+  * Refine the result by applying the system query options  
+
+**Support for `$select` with `$expand`**
+Like described in section 3.1, the Olingo library provides support and convenience methods for `$select` implementation. So the necessary creation and pass of the `selectList` to the creation of `ContextURL` and pass of the `selectOptions` to the `EntitySerializerOptions` is already done (see also code sample in the final step in section 3.2).  
+
+---
+
+# 4. Run the implemented service
+
+After building and deploying your service to your server, you can try the following URLs:  
+
+  * The “normal” payload without query option  
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)>
+
+  * Using `$select`  
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=Name>
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=Description>
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=Name,Description>
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=*>
+  <http://localhost:8080/DemoService/DemoService.svc/Categories(1)?$select=Name>
+
+  * Using `$expand`
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category>
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category>
+  <http://localhost:8080/DemoService/DemoService.svc/Categories(1)?$expand=Products>
+
+  * Using `$select` and $expand  
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=Name&$expand=Category>  
+
+  * Using $expand with nested `$select`  
+  We’re interested in Product and the name of its Category
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category($select=Name)>
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category($select=Name,ID)>
+
+  * Using `$select` and $expand with nested $select  
+  We’re interested in Product and its Category, but only the name of both  
+  <http://localhost:8080/DemoService/DemoService.svc/Products(1)?$select=Name&$expand=Category($select=Name)>
+
+
+**Note:**
+The same system query option expressions can be applied to entity collections  
+
+---
+
+# 5. Summary
+
+In this tutorial we have learned the basics of the `$select` and $expand system query options within the OData context as well as how to implement those features with Apache Olingo library by using the provided convenience and support methods.
+
+---
+
+# 6. Links
+
+### Tutorials
+  * Tutorial OData V4 service part 1: [Read Entity Collection](/doc/odata4/tutorials/read/tutorial_read.html) | [sample project](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.asc)).
+  * Tutorial OData V4 service part 2: [Read Entity, Read Property](/doc/odata4/tutorials/readep/tutorial_readep.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.asc))  
+  * Tutorial OData V4 service part 3: [Write (Create, Update, Delete Entity)](/doc/odata4/tutorials/write/tutorial_write.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.asc))  
+  * Tutorial OData V4 service, part 4: [Navigation (this page)](/doc/odata4/tutorials/navigation/tutorial_navigation.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.asc))
+  * Tutorial OData V4 service, part 5.1: [System Query Options $top, $skip, $count](/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.asc))  
+  * Tutorial OData V4 service, part 5.2: [ System Query Options $select, $expand (this page)](/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.asc))  
+  * Tutorial OData V4 service, part 5.3: System Query Options $orderby, $filter (to be announced)
+
+### Further reading
+  * OData specification: [http://odata.org/](http://odata.org/)
+  * [Olingo Javadoc](/javadoc/odata4/index.html)

Propchange: olingo/site/trunk/content/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.mdtext
------------------------------------------------------------------------------
    svn:executable = *

Modified: olingo/site/trunk/content/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.mdtext
URL: http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.mdtext?rev=1695424&r1=1695423&r2=1695424&view=diff
==============================================================================
--- olingo/site/trunk/content/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.mdtext (original)
+++ olingo/site/trunk/content/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.mdtext Wed Aug 12 06:32:21 2015
@@ -85,7 +85,8 @@ ___
 
 # 2. Preparation
 
-Follow _Tutorial Part 1: Read Entity Collection_ and _Tutorial Part 2: Read Entity_ or as shortcut import the project attached to Tutorial Part 2 into your Eclipse workspace.
+Follow [Tutorial Part 1: Read Entity Collection](/doc/odata4/tutorials/read/tutorial_read.html)
+ and [Tutorial Part 2: Read Entity](/doc/odata4/tutorials/readep/tutorial_readep.html) or as shortcut import the project attached to Tutorial Part 2 into your Eclipse workspace.
 
 Afterwards do a _Deploy and run_: it should be working.
 
@@ -98,7 +99,7 @@ ___
 The system query options we’re focusing on are applied to the entity collection only (for example, it doesn’t make sense to apply a $top to a READ request of a single entity)
 
 Therefore our implementation for all three query options is done in the class  
-_myservice.mynamespace.service.DemoEntityCollectionProcessor_
+`myservice.mynamespace.service.DemoEntityCollectionProcessor`
 
 The general sequence of the implementation remains unchanged:
 
@@ -358,25 +359,25 @@ So now we can finally have a look at the
 
 After building and deploying your service to your server, you can try the following URLs:  
 
-* The full collection, no query option  
-<http://localhost:8080/DemoService/DemoService.svc/Products>
+  * The full collection, no query option  
+  <http://localhost:8080/DemoService/DemoService.svc/Products>
 
-* First 2 products only  
-<http://localhost:8080/DemoService/DemoService.svc/Products?$top=2>
+  * First 2 products only  
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$top=2>
 
-* Exclude the first 2 products  
-<http://localhost:8080/DemoService/DemoService.svc/Products?$skip=2>
+  * Exclude the first 2 products  
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$skip=2>
 
-* Add the full number of all products to the response payload  
-<http://localhost:8080/DemoService/DemoService.svc/Products?$count=true>
+  * Add the full number of all products to the response payload  
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$count=true>
 
-* Combine $top and `$skip`
-<http://localhost:8080/DemoService/DemoService.svc/Products?$skip=1&$top=1>  
-<http://localhost:8080/DemoService/DemoService.svc/Products?$top=1&$skip=1>  
-Regardless of the order, the result should be the same
+  * Combine $top and `$skip`
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$skip=1&$top=1>  
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$top=1&$skip=1>  
+  Regardless of the order, the result should be the same
 
-* Combine all 3 query options  
-<http://localhost:8080/DemoService/DemoService.svc/Products?$skip=1&$top=1&$count=true>
+  * Combine all 3 query options  
+  <http://localhost:8080/DemoService/DemoService.svc/Products?$skip=1&$top=1&$count=true>
 
 ---
 
@@ -389,6 +390,7 @@ More system query options will be treate
 ---
 
 # 6. Links
+
 ### Tutorials
   * Tutorial OData V4 service part 1: [Read Entity Collection](/doc/odata4/tutorials/read/tutorial_read.html) | [sample project](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.asc)).
   * Tutorial OData V4 service part 2: [Read Entity, Read Property](/doc/odata4/tutorials/readep/tutorial_readep.html) | [sample project zip](http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip) ([md5](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.md5), [sha512](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.sha512), [pgp](https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.asc))