[OLINGO-545] Single valued navigation properties can be null

Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/4768048f
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/4768048f
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/4768048f

Branch: refs/heads/master
Commit: 4768048fba0546fdd26632e5ea4d9640f4632275
Parents: f6fa1ee
Author: Christian Holzer <[email protected]>
Authored: Wed Mar 11 17:21:21 2015 +0100
Committer: Christian Holzer <[email protected]>
Committed: Thu Mar 12 16:52:40 2015 +0100

----------------------------------------------------------------------
 .../olingo/fit/tecsvc/client/BindingITCase.java | 48 ++++++++++++++++++++
 .../olingo/server/tecsvc/data/DataProvider.java | 36 +++++++++++++--
 2 files changed, 81 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/4768048f/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
index 09dcaa0..82280bc 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BindingITCase.java
@@ -36,6 +36,7 @@ import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.commons.api.domain.ODataEntity;
 import org.apache.olingo.commons.api.domain.ODataLink;
 import org.apache.olingo.commons.api.domain.ODataObjectFactory;
+import org.apache.olingo.commons.api.domain.ODataProperty;
 import org.apache.olingo.commons.api.domain.ODataValue;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
@@ -261,6 +262,53 @@ public class BindingITCase extends AbstractBaseTestITCase {
     }
   }
 
+  @Test
+  public void testUpdateSingleNavigationPropertyWithNull() {
+    final ODataClient client = getClient();
+    final URI entityURI =
+        
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(1).build();
+    final ODataObjectFactory of = client.getObjectFactory();
+
+    // Request to single (non collection) navigation property
+    ODataEntity entity = of.newEntity(ET_KEY_NAV);
+    final ODataProperty navPropery = 
of.newComplexProperty(NAV_PROPERTY_ET_KEY_NAV_ONE, null);
+    entity.getProperties().add(navPropery);
+
+    ODataEntityUpdateResponse<ODataEntity> updateResponse =
+        client.getCUDRequestFactory().getEntityUpdateRequest(entityURI, 
UpdateType.PATCH, entity).execute();
+    assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), 
updateResponse.getStatusCode());
+
+    final ODataEntityRequest<ODataEntity> getRequest =
+        client.getRetrieveRequestFactory().getEntityRequest(
+            
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(1).expand(
+                NAV_PROPERTY_ET_KEY_NAV_ONE).build());
+    getRequest.addCustomHeader(HttpHeader.COOKIE, 
updateResponse.getHeader(HttpHeader.SET_COOKIE).iterator().next());
+    final ODataRetrieveResponse<ODataEntity> getResponse = 
getRequest.execute();
+
+    ODataProperty property = 
getResponse.getBody().getProperty(NAV_PROPERTY_ET_KEY_NAV_ONE);
+    assertEquals(null, property.getPrimitiveValue());
+  }
+  
+  @Test
+  public void testUpdateCollectionNavigationPropertyWithNull() {
+    final ODataClient client = getClient();
+    final URI entityURI =
+        
client.newURIBuilder(SERVICE_URI).appendEntitySetSegment(ES_KEY_NAV).appendKeySegment(1).build();
+    final ODataObjectFactory of = client.getObjectFactory();
+
+    // Request to single (non collection) navigation property
+    ODataEntity entity = of.newEntity(ET_KEY_NAV);
+    final ODataProperty navPropery = 
of.newComplexProperty(NAV_PROPERTY_ET_KEY_NAV_MANY, null);
+    entity.getProperties().add(navPropery);
+
+    try {
+      client.getCUDRequestFactory().getEntityUpdateRequest(entityURI, 
UpdateType.PATCH, entity).execute();
+      fail();
+    } catch(ODataClientErrorException e) {
+      assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), 
e.getStatusLine().getStatusCode());
+    }
+  }
+  
   @Override
   protected ODataClient getClient() {
     ODataClient odata = ODataClientFactory.getClient();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/4768048f/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index f18a0de..61b763c 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -236,6 +236,8 @@ public class DataProvider {
     // Deep insert (only if not an update)
     if (isInsert) {
       handleDeepInsert(rawBaseUri, edmEntitySet, entity, changedEntity);
+    } else {
+      handleDeleteSingleNavigationProperties(edmEntitySet, entity, 
changedEntity);
     }
 
     final boolean navigationBindingsAvailable = 
!changedEntity.getNavigationBindings().isEmpty();
@@ -244,6 +246,28 @@ public class DataProvider {
     }
   }
 
+  private void handleDeleteSingleNavigationProperties(EdmEntitySet 
edmEntitySet, Entity entity, Entity changedEntity)
+      throws DataProviderException {
+    final EdmEntityType entityType = edmEntitySet.getEntityType();
+    final List<String> navigationPropertyNames = 
entityType.getNavigationPropertyNames();
+
+    for (final String navPropertyName : navigationPropertyNames) {
+      final Link navigationLink = 
changedEntity.getNavigationLink(navPropertyName);
+      final EdmNavigationProperty navigationProperty = 
entityType.getNavigationProperty(navPropertyName);
+      if (!navigationProperty.isCollection() && navigationLink != null && 
navigationLink.getInlineEntity() == null) {
+        
+        // Check if partner is available
+        if (navigationProperty.getPartner() != null && 
entity.getNavigationLink(navPropertyName) != null) {
+          Entity partnerEntity =  
entity.getNavigationLink(navPropertyName).getInlineEntity();
+          removeLink(navigationProperty.getPartner(), partnerEntity);
+        }
+        
+        // Remove link
+        removeLink(navigationProperty, entity);
+      }
+    }
+  }
+
   private void applyNavigationBinding(final String rawBaseUri, final 
EdmEntitySet edmEntitySet,
       final Entity entity, final List<Link> navigationBindings) throws 
DataProviderException {
 
@@ -303,15 +327,21 @@ public class DataProvider {
           for (final Entity inlineEntity : entities) {
             createLink(navigationProperty, entity, inlineEntity);
           }
-        } else {
-          final Entity inlineEntity =
-              createInlineEntity(rawBaseUri, target, 
navigationLink.getInlineEntity());
+        } else if (!navigationProperty.isCollection() && 
navigationLink.getInlineEntity() != null) {
+          final Entity inlineEntity = createInlineEntity(rawBaseUri, target, 
navigationLink.getInlineEntity());
           createLink(navigationProperty, entity, inlineEntity);
         }
       }
     }
   }
 
+  private void removeLink(EdmNavigationProperty navigationProperty, Entity 
entity) {
+    final Link link = entity.getNavigationLink(navigationProperty.getName());
+    if(link != null) {
+      entity.getNavigationLinks().remove(link);
+    }
+  }
+
   private List<Entity> createInlineEntities(final String rawBaseUri, final 
EdmEntitySet targetEntitySet,
       final EntitySet changedEntitySet) throws DataProviderException {
     List<Entity> entities = new ArrayList<Entity>();

Reply via email to