This is an automated email from the ASF dual-hosted git repository.

rareddy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/olingo-odata4.git


The following commit(s) were added to refs/heads/master by this push:
     new 7da68d1  OLINGO-1389 adding support for posting to a navigation
     new 9e94d95  Merge branch 'pr54'
7da68d1 is described below

commit 7da68d113891bc9f175c417da4021d6cffdb9c39
Author: Steven Hawkins <[email protected]>
AuthorDate: Tue Aug 27 20:30:11 2019 -0400

    OLINGO-1389 adding support for posting to a navigation
---
 .../olingo/server/core/requests/DataRequest.java   |  46 +++++++--
 .../olingo/server/example/TripPinDataModel.java    |   2 +-
 .../olingo/server/example/TripPinHandler.java      |  26 ++++-
 .../olingo/server/example/TripPinServiceTest.java  | 114 +++++++++++++++++++++
 4 files changed, 175 insertions(+), 13 deletions(-)

diff --git 
a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
 
b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
index 11a092f..a52e178 100644
--- 
a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
+++ 
b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/DataRequest.java
@@ -277,10 +277,20 @@ public class DataRequest extends ServiceRequest {
     public boolean assertHttpMethod(ODataResponse response) throws 
ODataHandlerException {
       // the create/update/delete to navigation property is done through 
references
       // see # 11.4.6
-      if (!getNavigations().isEmpty() && !isGET()) {
-        return methodNotAllowed(response, httpMethod(), 
-            "create/update/delete to navigation property is done through 
references", 
-            allowedMethods());
+      if (!getNavigations().isEmpty()) {
+        if (isPOST()) {
+          UriResourceNavigation last = getNavigations().getLast();
+          if 
(!(getEntitySet().getRelatedBindingTarget(last.getProperty().getName()) 
+              instanceof EdmEntitySet)) {
+            return methodNotAllowed(response, httpMethod(), 
+                "navigation updates must be to an entity contained in an 
entity set", 
+                allowedMethods());
+          }
+        } else if (!isGET()) {
+          return methodNotAllowed(response, httpMethod(), 
+              "update/delete to navigation property is done through 
references", 
+              allowedMethods());
+        }
       }
       
       if ((isGET() || isDELETE()) && getReturnRepresentation() != 
ReturnRepresentation.NONE) {
@@ -315,13 +325,14 @@ public class DataRequest extends ServiceRequest {
     public void execute(ServiceHandler handler, ODataResponse response)
         throws ODataLibraryException, ODataApplicationException {
 
+      ContextURL contextURL = getContextURL(odata);
       EntityResponse entityResponse = 
EntityResponse.getInstance(DataRequest.this,
-          getContextURL(odata), false, response);
+          contextURL, false, response);
 
       if (isGET()) {
         if (isCollection()) {
           handler.read(DataRequest.this,
-              EntitySetResponse.getInstance(DataRequest.this, 
getContextURL(odata), false, response));
+              EntitySetResponse.getInstance(DataRequest.this, contextURL, 
false, response));
         } else {
           handler.read(DataRequest.this,entityResponse);
         }
@@ -338,24 +349,37 @@ public class DataRequest extends ServiceRequest {
         } else if (ifNoneMatch) {
           // 11.4.4
           entityResponse = EntityResponse.getInstance(DataRequest.this,
-              getContextURL(odata), false, response, 
getReturnRepresentation());
+              contextURL, false, response, getReturnRepresentation());
           handler.createEntity(DataRequest.this, getEntityFromClient(), 
entityResponse);
         } else {
           handler.upsertEntity(DataRequest.this, getEntityFromClient(), 
isPATCH(), getETag(),
               entityResponse);
         }
       } else if (isPOST()) {
-        entityResponse = EntityResponse.getInstance(DataRequest.this,
-            getContextURL(odata), false, response, getReturnRepresentation());
-        handler.createEntity(DataRequest.this, 
getEntityFromClient(),entityResponse);
+        if (!getNavigations().isEmpty()) {
+          entityResponse = EntityResponse.getInstance(DataRequest.this,
+              contextURL, false, response, getReturnRepresentation());
+          UriResourceNavigation last = getNavigations().getLast();
+          EdmEntityType navigationType = last.getProperty().getType();
+          Entity entity = getEntityFromClient(navigationType);
+          handler.createEntity(DataRequest.this, entity,entityResponse);
+        } else {
+          entityResponse = EntityResponse.getInstance(DataRequest.this,
+              contextURL, false, response, getReturnRepresentation());
+          handler.createEntity(DataRequest.this, 
getEntityFromClient(),entityResponse);
+        }
       } else if (isDELETE()) {
         handler.deleteEntity(DataRequest.this, getETag(), entityResponse);
       }
     }
 
     private Entity getEntityFromClient() throws DeserializerException {
+      return getEntityFromClient(getEntitySet().getEntityType());
+    }
+    
+    private Entity getEntityFromClient(EdmEntityType entityType) throws 
DeserializerException {
       ODataDeserializer deserializer = 
odata.createDeserializer(getRequestContentType(), getServiceMetaData());
-      return deserializer.entity(getODataRequest().getBody(), 
getEntitySet().getEntityType()).getEntity();
+      return deserializer.entity(getODataRequest().getBody(), 
entityType).getEntity();
     }
 
     @Override
diff --git 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
index 562eac0..cde9b74 100644
--- 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
+++ 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
@@ -493,7 +493,7 @@ public class TripPinDataModel {
         map = new HashMap<String, Object>();
         this.peopleLinks.put((String) 
parentEntity.getProperty(key).getValue(), map);
       }
-      map.put("Photo", childEntity.getProperty(key).getValue());
+      map.put("Photo", 
((Long)childEntity.getProperty("Id").getValue()).intValue());
       setLink(parentEntity, navigation, childEntity);
     } else if (type.getName().equals("Trip") && 
navigation.equals("PlanItems")) {
       Map<String, Object> map = 
this.tripLinks.get(parentEntity.getProperty(key).getValue());
diff --git 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
index 4a92198..19b2898 100644
--- 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
+++ 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinHandler.java
@@ -238,7 +238,12 @@ public class TripPinHandler implements ServiceHandler {
   public void createEntity(DataRequest request, Entity entity, EntityResponse 
response)
       throws ODataLibraryException, ODataApplicationException {
     EdmEntitySet edmEntitySet = request.getEntitySet();
-
+    
+    if (!request.getNavigations().isEmpty()) {
+      UriResourceNavigation lastNavigation = 
request.getNavigations().getLast();
+      edmEntitySet = 
(EdmEntitySet)edmEntitySet.getRelatedBindingTarget(lastNavigation.getProperty().getName());
+    }
+    
     Entity created = this.dataModel.createEntity(edmEntitySet, entity, 
request.getODataRequest().getRawBaseUri());
 
     try {
@@ -271,6 +276,25 @@ public class TripPinHandler implements ServiceHandler {
     } catch (URISyntaxException e) {
       throw new ODataApplicationException(e.getMessage(), 500, 
Locale.getDefault());
     }
+    
+    if (!request.getNavigations().isEmpty()) {
+      UriResourceNavigation lastNavigation = 
request.getNavigations().getLast();
+      
+      String parentRequest = request.getODataRequest().getRawRequestUri();
+      parentRequest = parentRequest.substring(0, 
parentRequest.lastIndexOf('/'));
+      
+      DataRequest bindingRequest;
+      try {
+        bindingRequest = request.parseLink(new URI(parentRequest));
+      } catch (URISyntaxException e) {
+        throw new ODataApplicationException(e.getMessage(), 500, 
Locale.getDefault());
+      }
+
+      Entity reference = 
this.dataModel.getEntity(bindingRequest.getEntitySet().getName(),
+          bindingRequest.getKeyPredicates());
+
+      this.dataModel.addNavigationLink(lastNavigation.getProperty().getName(), 
reference, created);
+    }
 
     response.writeCreatedEntity(edmEntitySet, created);
   }
diff --git 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
index fa32eef..53a21e6 100644
--- 
a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
+++ 
b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServiceTest.java
@@ -552,6 +552,46 @@ public class TripPinServiceTest {
     assertTrue(node.get("value").isArray());
     assertEquals("scottketchum", 
((ArrayNode)node.get("value")).get(1).get("UserName").asText());
   }
+  
+  @Ignore("4.01 style binding not supported")
+  @Test
+  public void testCreateEntityWithLinkToRelatedEntitiesIds() throws Exception {
+    String payload = "{\n" +
+        "         \"UserName\":\"olingo\",\n" +
+        "         \"FirstName\":\"Olingo\",\n" +
+        "         \"LastName\":\"Apache\",\n" +
+        "         \"Emails\":[\n" +
+        "            \"[email protected]\"\n" +
+        "         ],\n" +
+        "         \"AddressInfo\":[\n" +
+        "            {\n" +
+        "               \"Address\":\"100 apache Ln.\",\n" +
+        "               \"City\":{\n" +
+        "                  \"CountryRegion\":\"United States\",\n" +
+        "                  \"Name\":\"Boise\",\n" +
+        "                  \"Region\":\"ID\"\n" +
+        "               }\n" +
+        "            }\n" +
+        "         ],\n" +
+        "         \"Gender\":\"0\",\n" +
+        "         \"Concurrency\":635585295719432047,\n" +
+        "\"Friends\":[" +
+        "{\"@id\": \"People('russellwhyte')\"},\n" + 
+        "{\"@id\": \"People('scottketchum')\"}\n" +
+        "]"+
+        "}";
+    HttpPost postRequest = new HttpPost(baseURL + "/People");
+    postRequest.setEntity(new StringEntity(payload, 
ContentType.APPLICATION_JSON));
+    postRequest.setHeader("Prefer", "return=minimal");
+    HttpResponse response = httpSend(postRequest, 204);
+    EntityUtils.consumeQuietly(response.getEntity());
+    
+    response = httpGET(baseURL+"/People('olingo')/Friends", 200);
+    JsonNode node = getJSONNode(response);
+    assertEquals(baseURL+"/$metadata#People", 
node.get("@odata.context").asText());
+    assertTrue(node.get("value").isArray());
+    assertEquals("scottketchum", 
((ArrayNode)node.get("value")).get(1).get("UserName").asText());
+  }
 
   @Test
   public void testUpdatePrimitiveProperty() throws Exception {
@@ -779,6 +819,80 @@ public class TripPinServiceTest {
     node = getJSONNode(response);
     assertNull("/People('russellwhyte')", ((ArrayNode) 
node.get("value")).get(2));
   }
+  
+  @Test
+  public void testAddEntityToNavigationFailsNotEntitySet() throws Exception {
+    // adding to an entity that is not part of an entity set
+    // goes against a few assumptions in downstream code, so 
+    // not handling for now
+    String msg = "{\n" +
+        "\"TripId\": 1010,\n" +
+        "\"Description\": \"The trip of a lifetime.\",\n" +
+        "\"Name\": \"Grand Prize\",\n" +
+        "\"Budget\": 100000\n" +
+        "}";
+    String editUrl = baseURL + "/People('vincentcalabrese')/Trips";
+    HttpPost postRequest = new HttpPost(editUrl);
+    postRequest.setEntity(new StringEntity(msg, ContentType.APPLICATION_JSON));
+    postRequest.addHeader("Content-Type", 
"application/json;odata.metadata=minimal");
+    HttpResponse response = httpSend(postRequest, 405);
+    EntityUtils.consumeQuietly(response.getEntity());
+  }
+  
+  @Test
+  public void testAddEntityToNavigation() throws Exception {
+    String msg = "{\n" +
+        "\"Id\": 1010,\n" +
+        "\"Name\": \"Grand Prize\"\n" +
+        "}";
+    String editUrl = baseURL + "/People('vincentcalabrese')/Photo";
+    HttpPost postRequest = new HttpPost(editUrl);
+    postRequest.setEntity(new StringEntity(msg, ContentType.APPLICATION_JSON));
+    postRequest.addHeader("Content-Type", 
"application/json;odata.metadata=minimal");
+    HttpResponse response = httpSend(postRequest, 201);
+    EntityUtils.consumeQuietly(response.getEntity());
+    
+    response = httpGET(baseURL+"/People('vincentcalabrese')/Photo", 200);
+    JsonNode node = getJSONNode(response);
+    assertEquals(baseURL+"/$metadata#Photos/$entity", 
node.get("@odata.context").asText());
+    assertEquals("Grand Prize", node.get("Name").asText());
+  }
+  
+  @Test
+  public void testAddEntityToNavigationSelf() throws Exception {
+    String payload = "{\n" +
+        "         \"UserName\":\"olingo\",\n" +
+        "         \"FirstName\":\"Olingo\",\n" +
+        "         \"LastName\":\"Apache\",\n" +
+        "         \"Emails\":[\n" +
+        "            \"[email protected]\"\n" +
+        "         ],\n" +
+        "         \"AddressInfo\":[\n" +
+        "            {\n" +
+        "               \"Address\":\"100 apache Ln.\",\n" +
+        "               \"City\":{\n" +
+        "                  \"CountryRegion\":\"United States\",\n" +
+        "                  \"Name\":\"Boise\",\n" +
+        "                  \"Region\":\"ID\"\n" +
+        "               }\n" +
+        "            }\n" +
+        "         ],\n" +
+        "         \"Gender\":\"0\",\n" +
+        "         \"Concurrency\":635585295719432047\n" +
+        "}";
+    String editUrl = baseURL + "/People('vincentcalabrese')/Friends";
+    HttpPost postRequest = new HttpPost(editUrl);
+    postRequest.setEntity(new StringEntity(payload, 
ContentType.APPLICATION_JSON));
+    postRequest.addHeader("Content-Type", 
"application/json;odata.metadata=minimal");
+    HttpResponse response = httpSend(postRequest, 201);
+    EntityUtils.consumeQuietly(response.getEntity());
+    
+    response = httpGET(baseURL+"/People('vincentcalabrese')/Friends", 200);
+    JsonNode node = getJSONNode(response);
+    assertEquals(baseURL+"/$metadata#People", 
node.get("@odata.context").asText());
+    assertTrue(node.get("value").isArray());
+    assertEquals("olingo", 
((ArrayNode)node.get("value")).get(2).get("UserName").asText());
+  }
 
   @Test
   public void testDeleteReference() throws Exception {

Reply via email to