Author: chrish
Date: Tue Nov 17 14:25:31 2015
New Revision: 1714791

URL: http://svn.apache.org/viewvc?rev=1714791&view=rev
Log:
CMS commit to olingo by chrish

Modified:
    
olingo/site/trunk/content/doc/odata4/tutorials/deep_insert/tutorial_deep_insert.mdtext

Modified: 
olingo/site/trunk/content/doc/odata4/tutorials/deep_insert/tutorial_deep_insert.mdtext
URL: 
http://svn.apache.org/viewvc/olingo/site/trunk/content/doc/odata4/tutorials/deep_insert/tutorial_deep_insert.mdtext?rev=1714791&r1=1714790&r2=1714791&view=diff
==============================================================================
--- 
olingo/site/trunk/content/doc/odata4/tutorials/deep_insert/tutorial_deep_insert.mdtext
 (original)
+++ 
olingo/site/trunk/content/doc/odata4/tutorials/deep_insert/tutorial_deep_insert.mdtext
 Tue Nov 17 14:25:31 2015
@@ -28,7 +28,7 @@ In the present tutorial, we will impleme
 **Note:**
 The final source code can be found in the project [git 
repository](https://git-wip-us.apache.org/repos/asf/olingo-odata4).
 A detailed description how to checkout the tutorials can be found 
[here](/doc/odata4/tutorials/prerequisites/prerequisites.html).   
-This tutorial can be found in subdirectory /samples/tutorials/p11_batch
+This tutorial can be found in subdirectory /samples/tutorials/p12_deep_insert
 
 
 **Table of Contents**
@@ -54,24 +54,24 @@ In this example, a new Category "Food" a
 
 
     POST /Categories HTTP/1.1
-       Content-Type: application/json
+    Content-Type: application/json
 
-       {
-               "name": "Food",
-               "[email protected]": [
-                       "Products(5)"
-               ],
-               "Products": [
-                       {
-                               "Name": "Bread",
-                               "Description": "Whole grain bread"
-                       },
-                       {
-                               "Name": "Milk",
-                               "Description": "Low fat milk"
-                       }
-               ]
-       }
+    {
+        "name": "Food",
+        "[email protected]": [
+            "Products(5)"
+        ],
+        "Products": [
+            {
+                "Name": "Bread",
+                "Description": "Whole grain bread"
+            },
+            {
+                "Name": "Milk",
+                "Description": "Low fat milk"
+            }
+        ]
+    }
 
 # 2. Preparation
 
@@ -83,23 +83,163 @@ Afterwards do a Deploy and run: it shoul
 
 # 2. Implementation
 
-Before we start with the implementation, please have a look at the class 
`myservice.mynamespace.data.Storage`. In difference to the [navigation 
tutorial](http://olingo.apache.org/doc/odata4/tutorials/navigation/tutorial_navigation.html)
 the relations between two entities can not be hard coded because we would like 
to create and change relations between entities. In the constructor of the data 
storage the sample data is created. After that the method 
`linkProductsAndCategories`is called. This methods sets a few links between the 
just created entities.
+Before we start with the implementation, please have a look at the class 
`myservice.mynamespace.data.Storage`. In difference to the [navigation 
tutorial](http://olingo.apache.org/doc/odata4/tutorials/navigation/tutorial_navigation.html)
 the relations between two entities can not be hard coded because we would like 
to create and change relations between entities dynamically. In the constructor 
of the data storage the sample data is created. After that the method 
`linkProductsAndCategories`is called. This methods sets a few links between the 
just created entities.
 
-To express the relation between two entities, Olingo uses the class 
[Link](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html).
 This class is used for related entites (directly connected via Java 
references) and bindings (which are actually strings) to other entities 
dynamically. To get the related entites for a particual navigation property, 
you can ask an entity with the method [`getNavigationLink(String 
name)`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Linked.html#getNavigationLink(java.lang.String))
 for an navigation property. The link will contain either an entity or a 
collection of entities dependenting on the type of the navigation property. To 
get the actual entities use the methods 
[`getInlineEntity()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getInlineEntity())
 or 
[`getInlineEntitySet()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/L
 ink.html#getInlineEntitySet())
-The same can be done for bindings via the method [`getNavigationBinding(String 
name)`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Linked.html#getNavigationBinding(java.lang.String)).
 The values of the Binding can be got by the methods 
[`getBindingLink()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getBindingLink())
 and 
[`getBindingLinks()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getBindingLinks()).
 
+To express the relation between two entities, Olingo uses the class 
[Link](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html).
 This class is used for related entites (directly connected via Java 
references) and bindings (which are actually strings) to other entities. To get 
the related entites for a particual navigation property, you can ask an entity 
with the method [`getNavigationLink(String 
name)`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Linked.html#getNavigationLink(java.lang.String))
 for an navigation property. The link will contain either an entity or a 
collection of entities dependenting on the type of the navigation property. To 
get the actual entities use the methods 
[`getInlineEntity()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getInlineEntity())
 or 
[`getInlineEntitySet()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#get
 InlineEntitySet())
+The same can be done for bindings via the method [`getNavigationBinding(String 
name)`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Linked.html#getNavigationBinding(java.lang.String)).
 The values of the Binding can be gotten by the methods 
[`getBindingLink()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getBindingLink())
 and 
[`getBindingLinks()`](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/commons/api/data/Link.html#getBindingLinks()).
 
 
 The point is that the Entity deserializer uses the same concept to represent 
the payload as Java objects.
 In the previous tutorials the entity object returned by the deserializer is 
passed to the data store. Please open the class 
`myservice.mynamespace.data.Storage` and jump the method `createEntity`.
 
+The implementation should look like the following:
 
-
+    ::::java
+    private Entity createEntity(EdmEntitySet edmEntitySet, EdmEntityType 
edmEntityType, Entity entity, 
+        List<Entity> entityList, final String rawServiceUri) throws 
ODataApplicationException {
+
+        // 1.) Create the entity
+        final Entity newEntity = new Entity();
+        newEntity.setType(entity.getType());
+
+        // Create the new key of the entity
+        int newId = 1;
+        while (entityIdExists(newId, entityList)) {
+            newId++;
+        }
+
+        // Add all provided properties
+        newEntity.getProperties().addAll(entity.getProperties());
+
+        // Add the key property
+        newEntity.getProperties().add(new Property(null, "ID", 
ValueType.PRIMITIVE, newId));
+        newEntity.setId(createId(newEntity, "ID"));
+
+           // --> Implement Deep Insert handling here <--
+
+        entityList.add(newEntity);
+        return newEntity;
+    }
+
+The implementation is split in two steps:
+   * Handle entity bindings
+   * Handle related entities
+
+## Handle entity bindings
+
+To handle entity bindings we need two helper methods.
+
+The first method takes an entity-Id and returns the addressed entity. The 
OData objects provides a helper object to parse entity-ids. (See 
[UriHelper](http://olingo.apache.org/javadoc/odata4/org/apache/olingo/server/api/uri/UriHelper.html)).
 After parsing the id we have to check if the addressed entity set fits to the 
entity set the navigation property points to. After that the data is read by 
calling `readEntityData`.
+
+    private Entity readEntityByBindingLink(final String entityId, final 
EdmEntitySet edmEntitySet, 
+        final String rawServiceUri) throws ODataApplicationException {
+
+        UriResourceEntitySet entitySetResource = null;
+        try {
+            entitySetResource = odata.createUriHelper().parseEntityId(edm, 
entityId, rawServiceUri);
+
+            
if(!entitySetResource.getEntitySet().getName().equals(edmEntitySet.getName())) {
+                throw new ODataApplicationException("Execpted an entity-id for 
entity set " + edmEntitySet.getName() +
+                    " but found id for entity set " + 
entitySetResource.getEntitySet().getName(), 
+                    HttpStatusCode.BAD_REQUEST.getStatusCode(), 
Locale.ENGLISH);
+            }
+        } catch (DeserializerException e) {
+            throw new ODataApplicationException(entityId + " is not a valid 
entity-Id", 
+                HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH);
+        }
+
+        return readEntityData(entitySetResource.getEntitySet(), 
entitySetResource.getKeyPredicates());
+    }
+
+The second method helps us to link entities together. If the navigation 
property has partner navigation property the link is set in both directions.
+
+    private void createLink(final EdmNavigationProperty navigationProperty, 
final Entity srcEntity,
+        final Entity destEntity) {
+
+        setLink(navigationProperty, srcEntity, destEntity);
+
+        final EdmNavigationProperty partnerNavigationProperty = 
navigationProperty.getPartner();
+        if (partnerNavigationProperty != null) {
+            setLink(partnerNavigationProperty, destEntity, srcEntity);
+        }
+    }
+
+If the client has used the `odata.bind` property annotation, we can get the 
bindings by calling `getNavigationBindings()`. The implementation loops over 
all bindings and links the addressed entity to the new created one.
+
+    // 2.1.) Apply binding links
+    for(final Link link : entity.getNavigationBindings()) {
+        final EdmNavigationProperty edmNavigationProperty = 
edmEntityType.getNavigationProperty(link.getTitle());
+        final EdmEntitySet targetEntitySet = (EdmEntitySet) 
edmEntitySet.getRelatedBindingTarget(link.getTitle());
+
+        if(edmNavigationProperty.isCollection() && link.getBindingLinks() != 
null) {
+            for(final String bindingLink : link.getBindingLinks()) {
+                final Entity relatedEntity = 
readEntityByBindingLink(bindingLink, targetEntitySet, rawServiceUri);
+                createLink(edmNavigationProperty, newEntity, relatedEntity);
+            }
+        } else if(!edmNavigationProperty.isCollection() && 
link.getBindingLink() != null) {
+            final Entity relatedEntity = 
readEntityByBindingLink(link.getBindingLink(), targetEntitySet, rawServiceUri);
+            createLink(edmNavigationProperty, newEntity, relatedEntity);
+        }
+    }
+
+## Handle related entities
+
+The creation of related entities is similar. First the implementation loops 
over all navigation properties with related entites in the payload. The 
simplest way to create releated entities is to call the method 
`createEntityData`. So the the implementation is called recursively and can 
handle deep inserts with arbitrary depth.
+
+    // 2.2.) Create nested entities
+    for(final Link link : entity.getNavigationLinks()) {
+        final EdmNavigationProperty edmNavigationProperty = 
edmEntityType.getNavigationProperty(link.getTitle());
+        final EdmEntitySet targetEntitySet = (EdmEntitySet) 
edmEntitySet.getRelatedBindingTarget(link.getTitle());
+
+        if(edmNavigationProperty.isCollection() && link.getInlineEntitySet() 
!= null) {
+            for(final Entity nestedEntity : 
link.getInlineEntitySet().getEntities()) {
+                final Entity newNestedEntity = 
createEntityData(targetEntitySet, nestedEntity, rawServiceUri);
+                createLink(edmNavigationProperty, newEntity, newNestedEntity);
+                   }
+        } else if(!edmNavigationProperty.isCollection() && 
link.getInlineEntity() != null){
+            final Entity newNestedEntity = createEntityData(targetEntitySet, 
link.getInlineEntity(), rawServiceUri);
+            createLink(edmNavigationProperty, newEntity, newNestedEntity);
+        }
+       }
 
 
 # 4. Run the implemented service
 
 After building and deploying your service to your server, you can try the 
following requests:
 
+URI: 
[`http://localhost:8080/DemoService-DeepInsert/DemoService.svc/Categories`](http://localhost:8080/DemoService-DeepInsert/DemoService.svc/Categories)
     
+Http-Verb: POST    
+Content-Type: application/json
+Body:
+
+    {
+        "name": "Food",
+        "[email protected]": [
+            "Products(5)"
+        ],
+        "Products": [
+            {
+                "Name": "Bread",
+                "Description": "Whole grain bread"
+            },
+            {
+                "Name": "Milk",
+                "Description": "Low fat milk"
+            }
+        ]
+    }
+
+After sending this requests, let us see if the enties have been created and 
linked togetger.
+Send an GET request to 
`http://localhost:8080/DemoService-DeepInsert/DemoService.svc/Categories`.
+If it is the first category you created. The new entity should have the key `3`
+
+![Entity Set Categories](categories_entity_set.png)
+
+So send a request to fetch all related products for the "Food" category.
+[`http://localhost:8080/DemoService-DeepInsert/DemoService.svc/Categories(3)/Products`]()
+
+As you can see the two products are created and linked to the category.
 
+![Related products for category "Food"](related_products.PNG)
 
 # 5. Links
 


Reply via email to