Repository: olingo-odata2
Updated Branches:
  refs/heads/master 83d537713 -> 13cfd0a50


[OLINGO-844][OLINGO-850] add additional flags

I added two flags for this called clientRequest and
IncludeMetadataInContentOnly. Both flags are handled during serialization.
Tests for this are added as well. The deserialization can consume the new
payloads constructed with these flags.


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/270720a0
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/270720a0
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/270720a0

Branch: refs/heads/master
Commit: 270720a07d4328439a3775057c9c60a0ce2e83fd
Parents: 83d5377
Author: Christian Amend <[email protected]>
Authored: Wed Jan 20 15:44:01 2016 +0100
Committer: Christian Amend <[email protected]>
Committed: Wed Jan 20 15:44:01 2016 +0100

----------------------------------------------------------------------
 .../api/ep/EntityProviderWriteProperties.java   |  26 ++-
 .../ep/producer/JsonEntryEntityProducer.java    |  26 ++-
 .../ep/producer/JsonFeedEntityProducer.java     |  57 +++--
 .../odata2/core/batch/BatchRequestTest.java     |   2 -
 .../ep/ODataEntityProviderPropertiesTest.java   |  41 +++-
 .../consumer/JsonEntryDeepInsertFeedTest.java   |  29 +++
 .../producer/JsonEntryEntityProducerTest.java   | 215 ++++++++++++++++++-
 .../ep/producer/JsonFeedEntityProducerTest.java |  33 +++
 .../JsonBuildingWithInlineRoomsClientCase.json  |  35 +++
 9 files changed, 430 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
 
b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
index f1333d2..a65d473 100644
--- 
a/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
+++ 
b/odata2-lib/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
@@ -47,6 +47,9 @@ public class EntityProviderWriteProperties {
   private boolean omitETag;
   private boolean validatingFacets = true;
 
+  private boolean isClientRequest = false;
+  private boolean includeMetadataInContentOnly = false;
+
   private EntityProviderWriteProperties() {}
 
   public final boolean isOmitETag() {
@@ -140,6 +143,14 @@ public class EntityProviderWriteProperties {
     return validatingFacets;
   }
 
+  public boolean isClientRequest() {
+    return isClientRequest;
+  }
+
+  public boolean isIncludeMetadataInContentOnly() {
+    return includeMetadataInContentOnly;
+  }
+
   public static class ODataEntityProviderPropertiesBuilder {
     private final EntityProviderWriteProperties properties = new 
EntityProviderWriteProperties();
 
@@ -234,7 +245,7 @@ public class EntityProviderWriteProperties {
       properties.contentOnly = contentOnly;
       return this;
     }
-    
+
     public ODataEntityProviderPropertiesBuilder omitETag(final boolean 
omitETag) {
       properties.omitETag = omitETag;
       return this;
@@ -245,6 +256,17 @@ public class EntityProviderWriteProperties {
       return this;
     }
 
+    public ODataEntityProviderPropertiesBuilder clientRequest(final boolean 
isClientRequest) {
+      properties.isClientRequest = isClientRequest;
+      return this;
+    }
+
+    public ODataEntityProviderPropertiesBuilder
+        includeMetadataInContentOnly(final boolean 
includeMetadataInContentOnly) {
+      properties.includeMetadataInContentOnly = includeMetadataInContentOnly;
+      return this;
+    }
+
     public ODataEntityProviderPropertiesBuilder fromProperties(final 
EntityProviderWriteProperties properties) {
       this.properties.inlineCountType = properties.getInlineCountType();
       this.properties.inlineCount = properties.getInlineCount();
@@ -258,6 +280,8 @@ public class EntityProviderWriteProperties {
       this.properties.contentOnly = properties.contentOnly;
       this.properties.omitETag = properties.omitETag;
       this.properties.validatingFacets = properties.validatingFacets;
+      this.properties.isClientRequest = properties.isClientRequest;
+      this.properties.includeMetadataInContentOnly = 
properties.includeMetadataInContentOnly;
       return this;
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
index df563b0..d844f80 100644
--- 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
+++ 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
@@ -77,11 +77,13 @@ public class JsonEntryEntityProducer {
 
       jsonStreamWriter.beginObject();
 
-      if (!properties.isContentOnly()) {
+      boolean containsMetadata = false;
+      if (!properties.isContentOnly() || (properties.isContentOnly() && 
properties.isIncludeMetadataInContentOnly())) {
         writeMetadata(entityInfo, data, type);
+        containsMetadata = true;
       }
 
-      writeProperties(entityInfo, data, type);
+      writeProperties(entityInfo, data, type, containsMetadata);
 
       if (!properties.isContentOnly()) {
         writeNavigationProperties(writer, entityInfo, data, type);
@@ -158,7 +160,13 @@ public class JsonEntryEntityProducer {
         final EntityProviderWriteProperties inlineProperties = 
result.getInlineProperties();
         final EntityInfoAggregator inlineEntityInfo =
             EntityInfoAggregator.create(inlineEntitySet, 
inlineProperties.getExpandSelectTree());
-        new JsonFeedEntityProducer(inlineProperties).append(writer, 
inlineEntityInfo, inlineData, false);
+
+        JsonFeedEntityProducer jsonFeedEntityProducer = new 
JsonFeedEntityProducer(inlineProperties);
+        if (properties.isClientRequest()) {
+          jsonFeedEntityProducer.appendAsPlainArray(writer, inlineEntityInfo, 
inlineData);
+        } else {
+          jsonFeedEntityProducer.append(writer, inlineEntityInfo, inlineData, 
false);
+        }
 
       } else {
         final WriteEntryCallbackResult result =
@@ -180,11 +188,11 @@ public class JsonEntryEntityProducer {
   }
 
   private void writeProperties(final EntityInfoAggregator entityInfo, final 
Map<String, Object> data,
-      final EdmEntityType type) throws EdmException, EntityProviderException, 
IOException {
-    boolean omitComma = false;
-    if (properties.isContentOnly()) {
-      omitComma = true;
-    }
+      final EdmEntityType type, boolean containsMetadata) throws EdmException, 
EntityProviderException, IOException {
+    // if the payload contains metadata we must not omit the first comm as it 
separates the _metadata object form the
+    // properties
+    boolean omitComma = !containsMetadata;
+
     for (final String propertyName : type.getPropertyNames()) {
       if (entityInfo.getSelectedPropertyNames().contains(propertyName)) {
         if (omitComma) {
@@ -205,7 +213,7 @@ public class JsonEntryEntityProducer {
   private void writeMetadata(final EntityInfoAggregator entityInfo, final 
Map<String, Object> data,
       final EdmEntityType type) throws IOException, EntityProviderException, 
EdmException {
     if (properties.getServiceRoot() == null) {
-      location =  "";
+      location = "";
     } else {
       location = properties.getServiceRoot().toASCIIString() +
           AtomEntryEntityProducer.createSelfLink(entityInfo, data, null);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
index ed47f4a..4754af7 100644
--- 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
+++ 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
@@ -65,24 +65,11 @@ public class JsonFeedEntityProducer {
 
       jsonStreamWriter.name(FormatJson.RESULTS)
           .beginArray();
-      JsonEntryEntityProducer entryProducer = new 
JsonEntryEntityProducer(properties);
-      boolean first = true;
-      for (final Map<String, Object> entryData : data) {
-        if (first) {
-          first = false;
-        } else {
-          jsonStreamWriter.separator();
-        }
-        entryProducer.append(writer, entityInfo, entryData, false);
-      }
+
+      appendEntries(writer, entityInfo, data, jsonStreamWriter);
 
       if (callback != null) {
-        JsonDeletedEntryEntityProducer deletedEntryProducer = new 
JsonDeletedEntryEntityProducer(properties);
-        TombstoneCallbackResult callbackResult = 
callback.getTombstoneCallbackResult();
-        List<Map<String, Object>> deletedEntries = 
callbackResult.getDeletedEntriesData();
-        if (deletedEntries != null) {
-          deletedEntryProducer.append(writer, entityInfo, deletedEntries, 
data.isEmpty());
-        }
+        appendDeletedEntries(writer, entityInfo, data, callback);
       }
 
       jsonStreamWriter.endArray();
@@ -101,6 +88,44 @@ public class JsonFeedEntityProducer {
     }
   }
 
+  public void appendAsPlainArray(final Writer writer, final 
EntityInfoAggregator entityInfo,
+      final List<Map<String, Object>> data) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+    try {
+      jsonStreamWriter.beginArray();
+      appendEntries(writer, entityInfo, data, jsonStreamWriter);
+      jsonStreamWriter.endArray();
+    } catch (final IOException e) {
+      throw new 
EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass()
+          .getSimpleName()), e);
+    }
+  }
+
+  private void appendDeletedEntries(final Writer writer, final 
EntityInfoAggregator entityInfo,
+      final List<Map<String, Object>> data, TombstoneCallback callback) throws 
EntityProviderException {
+    JsonDeletedEntryEntityProducer deletedEntryProducer = new 
JsonDeletedEntryEntityProducer(properties);
+    TombstoneCallbackResult callbackResult = 
callback.getTombstoneCallbackResult();
+    List<Map<String, Object>> deletedEntries = 
callbackResult.getDeletedEntriesData();
+    if (deletedEntries != null) {
+      deletedEntryProducer.append(writer, entityInfo, deletedEntries, 
data.isEmpty());
+    }
+  }
+
+  private void appendEntries(final Writer writer, final EntityInfoAggregator 
entityInfo,
+      final List<Map<String, Object>> data, JsonStreamWriter jsonStreamWriter) 
throws EntityProviderException,
+      IOException {
+    JsonEntryEntityProducer entryProducer = new 
JsonEntryEntityProducer(properties);
+    boolean first = true;
+    for (final Map<String, Object> entryData : data) {
+      if (first) {
+        first = false;
+      } else {
+        jsonStreamWriter.separator();
+      }
+      entryProducer.append(writer, entityInfo, entryData, false);
+    }
+  }
+
   private TombstoneCallback getTombstoneCallback() {
     if (properties.getCallbacks() != null
         && 
properties.getCallbacks().containsKey(TombstoneCallback.CALLBACK_KEY_TOMBSTONE))
 {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
index e6abfa0..77e344e 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestTest.java
@@ -154,8 +154,6 @@ public class BatchRequestTest {
     checkMimeHeaders(requestBody);
     checkHeaders(headers, requestBody);
 
-    System.out.println(requestBody);
-
     assertTrue(requestBody.contains("--batch_"));
     assertTrue(requestBody.contains("--changeset_"));
     assertTrue(requestBody.contains("PUT Employees('2') HTTP/1.1"));

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
index a484eef..be1998b 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
@@ -19,6 +19,9 @@
 package org.apache.olingo.odata2.core.ep;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.net.URI;
@@ -56,7 +59,28 @@ public class ODataEntityProviderPropertiesTest extends 
BaseTest {
   }
 
   @Test
-  public void buildPropertiesDefaults() throws Exception {
+  public void buildPropertiesDefault() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/";);
+    final EntityProviderWriteProperties properties = 
EntityProviderWriteProperties.serviceRoot(serviceRoot).build();
+    assertNotNull(properties.getCallbacks());
+    assertTrue("Default callbacks should be empty", 
properties.getCallbacks().isEmpty());
+    assertNull(properties.getExpandSelectTree());
+    assertNull(properties.getSelfLink());
+    assertNull(properties.getInlineCount());
+    assertNull(properties.getInlineCountType());
+    assertNull(properties.getNextLink());
+    assertNull(properties.getAdditionalLinks());
+
+    assertFalse(properties.isIncludeSimplePropertyType());
+    assertFalse(properties.isOmitJsonWrapper());
+    assertFalse(properties.isContentOnly());
+    assertFalse(properties.isOmitETag());
+    assertFalse(properties.isIncludeMetadataInContentOnly());
+    assertFalse(properties.isClientRequest());
+  }
+
+  @Test
+  public void buildPropertiesAllSet() throws Exception {
     URI serviceRoot = new URI("http://localhost:80/";);
     Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
     callbacks.put("aCallback", new MyCallback(null, null));
@@ -76,6 +100,8 @@ public class ODataEntityProviderPropertiesTest extends 
BaseTest {
         .omitJsonWrapper(true)
         .contentOnly(true)
         .omitETag(true)
+        .includeMetadataInContentOnly(true)
+        .clientRequest(true)
         .build();
 
     assertEquals("Wrong amount of callbacks.", 1, 
properties.getCallbacks().size());
@@ -91,6 +117,9 @@ public class ODataEntityProviderPropertiesTest extends 
BaseTest {
     assertTrue("Json Wrapper should be omitted", 
properties.isOmitJsonWrapper());
     assertTrue("ContentOnlyFlag should be set", properties.isContentOnly());
     assertTrue("OmitETag should be set", properties.isOmitETag());
+
+    assertTrue("includeMetadataInContentOnly should be set", 
properties.isIncludeMetadataInContentOnly());
+    assertTrue("clientRequest flag should be set", 
properties.isClientRequest());
   }
 
   @Test
@@ -114,6 +143,8 @@ public class ODataEntityProviderPropertiesTest extends 
BaseTest {
         .omitJsonWrapper(true)
         .contentOnly(true)
         .omitETag(true)
+        .includeMetadataInContentOnly(true)
+        .clientRequest(true)
         .build();
 
     //
@@ -131,8 +162,10 @@ public class ODataEntityProviderPropertiesTest extends 
BaseTest {
     assertEquals("Wrong nextLink", "http://localhost";, 
fromProperties.getNextLink());
     assertTrue("Simple property types should be true", 
fromProperties.isIncludeSimplePropertyType());
     assertEquals(Collections.emptyMap(), 
fromProperties.getAdditionalLinks().get("aNavigationProperty"));
-    assertTrue("Json Wrapper should be omitted", 
properties.isOmitJsonWrapper());
-    assertTrue("ContentOnlyFlag should be set", properties.isContentOnly());
-    assertTrue("OmitETag should be set", properties.isOmitETag());
+    assertTrue("Json Wrapper should be omitted", 
fromProperties.isOmitJsonWrapper());
+    assertTrue("ContentOnlyFlag should be set", 
fromProperties.isContentOnly());
+    assertTrue("OmitETag should be set", fromProperties.isOmitETag());
+    assertTrue("includeMetadataInContentOnly should be set", 
fromProperties.isIncludeMetadataInContentOnly());
+    assertTrue("clientRequest flag should be set", 
fromProperties.isClientRequest());
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryDeepInsertFeedTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryDeepInsertFeedTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryDeepInsertFeedTest.java
index 3fec7f9..180fd62 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryDeepInsertFeedTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryDeepInsertFeedTest.java
@@ -45,10 +45,39 @@ import org.junit.Test;
 public class JsonEntryDeepInsertFeedTest extends AbstractConsumerTest {
 
   private static final String BUILDING_WITH_INLINE_ROOMS = 
"JsonBuildingWithInlineRooms.json";
+  private static final String BUILDING_WITH_INLINE_ROOMS_CLIENT_CASE = 
"JsonBuildingWithInlineRoomsClientCase.json";
   private static final String TEAM_WITH_INLINE_EMPLOYEES = 
"JsonTeamsWithInlineEmployees.json";
   private static final String BUILDING_WITH_INLINE_ROOMS_NEXTLINK_AND_COUNT =
       "JsonBuildingWithInlineRoomsAndNextLinkAndCount.json";
 
+  public void innerFeedWithoutResultsWrapperClientUseCase() throws Exception {
+    ODataEntry outerEntry = 
prepareAndExecuteEntry(BUILDING_WITH_INLINE_ROOMS_CLIENT_CASE, "Buildings", 
DEFAULT_PROPERTIES);
+
+    ODataFeed innerRoomFeed = (ODataFeed) 
outerEntry.getProperties().get("nb_Rooms");
+    assertNotNull(innerRoomFeed);
+
+    List<ODataEntry> rooms = innerRoomFeed.getEntries();
+    assertNotNull(rooms);
+    assertEquals(1, rooms.size());
+
+    ODataEntry room = rooms.get(0);
+    Map<String, Object> roomProperties = room.getProperties();
+
+    assertEquals(4, roomProperties.size());
+    assertEquals("1", roomProperties.get("Id"));
+    assertEquals("Room 1", roomProperties.get("Name"));
+    assertEquals(Short.valueOf("1"), roomProperties.get("Version"));
+    assertEquals(Short.valueOf("1"), roomProperties.get("Seats"));
+
+    List<String> associationUris = 
room.getMetadata().getAssociationUris("nr_Employees");
+    assertEquals(1, associationUris.size());
+    
assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Employees",
 associationUris.get(0));
+
+    associationUris = room.getMetadata().getAssociationUris("nr_Building");
+    assertEquals(1, associationUris.size());
+    
assertEquals("http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Building",
 associationUris.get(0));
+  }
+  
   @Test
   public void innerFeedNoMediaResourceWithoutCallback() throws Exception {
     ODataEntry outerEntry = prepareAndExecuteEntry(BUILDING_WITH_INLINE_ROOMS, 
"Buildings", DEFAULT_PROPERTIES);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducerTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducerTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducerTest.java
index 519ba0d..215f39c 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducerTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducerTest.java
@@ -157,6 +157,78 @@ public class JsonEntryEntityProducerTest extends BaseTest {
 
   @SuppressWarnings("unchecked")
   @Test
+  public void includeMetadataWithoutContentOnlyMustMakeNoDifference() throws 
Exception {
+    HashMap<String, Object> employeeData = new HashMap<String, Object>();
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+    employeeData.put("EmployeeId", "1");
+    employeeData.put("ImmageUrl", null);
+    employeeData.put("ManagerId", "1");
+    employeeData.put("Age", new Integer(52));
+    employeeData.put("RoomId", "1");
+    employeeData.put("EntryDate", date);
+    employeeData.put("TeamId", "42");
+    employeeData.put("EmployeeName", "Walter Winter");
+    Map<String, Object> locationData = new HashMap<String, Object>();
+    Map<String, Object> cityData = new HashMap<String, Object>();
+    cityData.put("PostalCode", "33470");
+    cityData.put("CityName", "Duckburg");
+    locationData.put("City", cityData);
+    locationData.put("Country", "Calisota");
+    employeeData.put("Location", locationData);
+
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EntityProviderWriteProperties properties =
+        
EntityProviderWriteProperties.fromProperties(DEFAULT_PROPERTIES).omitJsonWrapper(true)
+            .includeMetadataInContentOnly(true).build();
+    final ODataResponse response = new 
JsonEntityProvider().writeEntry(entitySet, employeeData, properties);
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new 
InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNotNull(employee.get("__metadata"));
+    assertNotNull(employee.get("ne_Manager"));
+    assertNotNull(employee.get("ne_Team"));
+    assertNotNull(employee.get("ne_Room"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void contentOnlyWithMetadata() throws Exception {
+    HashMap<String, Object> employeeData = new HashMap<String, Object>();
+    Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    date.clear();
+    date.set(1999, 0, 1);
+    employeeData.put("EmployeeId", "1");
+    employeeData.put("ImmageUrl", null);
+    employeeData.put("ManagerId", "1");
+    employeeData.put("Age", new Integer(52));
+    employeeData.put("RoomId", "1");
+    employeeData.put("EntryDate", date);
+    employeeData.put("TeamId", "42");
+    employeeData.put("EmployeeName", "Walter Winter");
+    Map<String, Object> locationData = new HashMap<String, Object>();
+    Map<String, Object> cityData = new HashMap<String, Object>();
+    cityData.put("PostalCode", "33470");
+    cityData.put("CityName", "Duckburg");
+    locationData.put("City", cityData);
+    locationData.put("Country", "Calisota");
+    employeeData.put("Location", locationData);
+
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    EntityProviderWriteProperties properties =
+        
EntityProviderWriteProperties.fromProperties(DEFAULT_PROPERTIES).omitJsonWrapper(true).contentOnly(true)
+            .includeMetadataInContentOnly(true).build();
+    final ODataResponse response = new 
JsonEntityProvider().writeEntry(entitySet, employeeData, properties);
+    Map<String, Object> employee =
+        (Map<String, Object>) new Gson().fromJson(new 
InputStreamReader((InputStream) response.getEntity()), Map.class);
+    assertNotNull(employee.get("__metadata"));
+    assertNull(employee.get("ne_Manager"));
+    assertNull(employee.get("ne_Team"));
+    assertNull(employee.get("ne_Room"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
   public void contentOnly() throws Exception {
     HashMap<String, Object> employeeData = new HashMap<String, Object>();
     Calendar date = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
@@ -585,7 +657,7 @@ public class JsonEntryEntityProducerTest extends BaseTest {
         json);
   }
 
-  @Test(expected=EntityProviderException.class)
+  @Test(expected = EntityProviderException.class)
   public void entryWithExpandedEntryWithFacets() throws Exception {
     Edm edm = MockFacade.getMockEdm();
     EdmTyped imageUrlProperty = edm.getEntityType("RefScenario", 
"Employee").getProperty("ImageUrl");
@@ -673,7 +745,6 @@ public class JsonEntryEntityProducerTest extends BaseTest {
     Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
     callbacks.put("nr_Employees", callback);
 
-
     EdmEntitySet entitySet = 
edm.getDefaultEntityContainer().getEntitySet("Rooms");
     final ODataResponse response =
         new JsonEntityProvider().writeEntry(entitySet, roomData,
@@ -789,6 +860,52 @@ public class JsonEntryEntityProducerTest extends BaseTest {
         json);
   }
 
+  @Test
+  public void entryWithExpandedFeedInClientUseCase() throws Exception {
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    Map<String, Object> buildingData = new HashMap<String, Object>();
+    buildingData.put("Id", "1");
+
+    ExpandSelectTreeNode node2 = Mockito.mock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> links = new HashMap<String, 
ExpandSelectTreeNode>();
+    links.put("nb_Rooms", node2);
+    ExpandSelectTreeNode node1 = Mockito.mock(ExpandSelectTreeNode.class);
+    Mockito.when(node1.getLinks()).thenReturn(links);
+
+    class FeedCallback implements OnWriteFeedContent {
+      @Override
+      public WriteFeedCallbackResult retrieveFeedResult(final 
WriteFeedCallbackContext context)
+          throws ODataApplicationException {
+        Map<String, Object> roomData = new HashMap<String, Object>();
+        roomData.put("Id", "1");
+        roomData.put("Version", 1);
+        List<Map<String, Object>> roomsData = new ArrayList<Map<String, 
Object>>();
+        roomsData.add(roomData);
+        WriteFeedCallbackResult result = new WriteFeedCallbackResult();
+        result.setFeedData(roomsData);
+        result.setInlineProperties(DEFAULT_PROPERTIES);
+        return result;
+      }
+    }
+    FeedCallback callback = new FeedCallback();
+    Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
+    callbacks.put("nb_Rooms", callback);
+
+    final ODataResponse response =
+        new JsonEntityProvider().writeEntry(entitySet, buildingData,
+            
EntityProviderWriteProperties.serviceRoot(URI.create(BASE_URI)).expandSelectTree(node1)
+                .callbacks(callbacks).clientRequest(true).build());
+    final String json = verifyResponse(response);
+    assertEquals("{\"d\":{\"__metadata\":{\"id\":\"" + BASE_URI + 
"Buildings('1')\","
+        + "\"uri\":\"" + BASE_URI + 
"Buildings('1')\",\"type\":\"RefScenario.Building\"},"
+        + "\"nb_Rooms\":[{\"__metadata\":{\"id\":\"" + BASE_URI + 
"Rooms('1')\","
+        + "\"uri\":\"" + BASE_URI + 
"Rooms('1')\",\"type\":\"RefScenario.Room\",\"etag\":\"W/\\\"1\\\"\"},"
+        + "\"Id\":\"1\",\"Name\":null,\"Seats\":null,\"Version\":1,"
+        + "\"nr_Employees\":{\"__deferred\":{\"uri\":\"" + BASE_URI + 
"Rooms('1')/nr_Employees\"}},"
+        + "\"nr_Building\":{\"__deferred\":{\"uri\":\"" + BASE_URI + 
"Rooms('1')/nr_Building\"}}}]}}",
+        json);
+  }
+
   @SuppressWarnings("unchecked")
   @Test
   public void entryWithExpandedFeedButNullData() throws Exception {
@@ -838,6 +955,53 @@ public class JsonEntryEntityProducerTest extends BaseTest {
 
   @SuppressWarnings("unchecked")
   @Test
+  public void entryWithExpandedFeedButNullDataClientUseCase() throws Exception 
{
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    Map<String, Object> buildingData = new HashMap<String, Object>();
+    buildingData.put("Id", "1");
+
+    ExpandSelectTreeNode node2 = Mockito.mock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> links = new HashMap<String, 
ExpandSelectTreeNode>();
+    links.put("nb_Rooms", node2);
+    ExpandSelectTreeNode node1 = Mockito.mock(ExpandSelectTreeNode.class);
+    Mockito.when(node1.getLinks()).thenReturn(links);
+
+    class FeedCallback implements OnWriteFeedContent {
+      @Override
+      public WriteFeedCallbackResult retrieveFeedResult(final 
WriteFeedCallbackContext context)
+          throws ODataApplicationException {
+        WriteFeedCallbackResult result = new WriteFeedCallbackResult();
+        result.setFeedData(null);
+        result.setInlineProperties(DEFAULT_PROPERTIES);
+        return result;
+      }
+    }
+    FeedCallback callback = new FeedCallback();
+    Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
+    callbacks.put("nb_Rooms", callback);
+
+    final ODataResponse response =
+        new JsonEntityProvider().writeEntry(entitySet, buildingData,
+            
EntityProviderWriteProperties.serviceRoot(URI.create(BASE_URI)).expandSelectTree(node1)
+                .callbacks(callbacks).clientRequest(true).build());
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", 
response.getContentHeader());
+
+    Map<String, Object> buildingEntry =
+        new Gson().fromJson(new InputStreamReader((InputStream) 
response.getEntity()), Map.class);
+    // remove d wrapper
+    buildingEntry = (Map<String, Object>) buildingEntry.get("d");
+    assertEquals(2, buildingEntry.size());
+
+    assertTrue(buildingEntry.containsKey("nb_Rooms"));
+    List<Object> roomsFeed = (List<Object>) buildingEntry.get("nb_Rooms");
+    assertNotNull(roomsFeed);
+    assertEquals(0, roomsFeed.size());
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
   public void entryWithExpandedFeedButEmptyData() throws Exception {
     final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
     Map<String, Object> buildingData = new HashMap<String, Object>();
@@ -883,6 +1047,53 @@ public class JsonEntryEntityProducerTest extends BaseTest 
{
     assertEquals(0, roomsFeedEntries.size());
   }
 
+  @SuppressWarnings("unchecked")
+  @Test
+  public void entryWithExpandedFeedButEmptyDataClientCase() throws Exception {
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");
+    Map<String, Object> buildingData = new HashMap<String, Object>();
+    buildingData.put("Id", "1");
+
+    ExpandSelectTreeNode node2 = Mockito.mock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> links = new HashMap<String, 
ExpandSelectTreeNode>();
+    links.put("nb_Rooms", node2);
+    ExpandSelectTreeNode node1 = Mockito.mock(ExpandSelectTreeNode.class);
+    Mockito.when(node1.getLinks()).thenReturn(links);
+
+    class FeedCallback implements OnWriteFeedContent {
+      @Override
+      public WriteFeedCallbackResult retrieveFeedResult(final 
WriteFeedCallbackContext context)
+          throws ODataApplicationException {
+        WriteFeedCallbackResult result = new WriteFeedCallbackResult();
+        result.setFeedData(new ArrayList<Map<String, Object>>());
+        result.setInlineProperties(DEFAULT_PROPERTIES);
+        return result;
+      }
+    }
+    FeedCallback callback = new FeedCallback();
+    Map<String, ODataCallback> callbacks = new HashMap<String, 
ODataCallback>();
+    callbacks.put("nb_Rooms", callback);
+
+    final ODataResponse response =
+        new JsonEntityProvider().writeEntry(entitySet, buildingData,
+            
EntityProviderWriteProperties.serviceRoot(URI.create(BASE_URI)).expandSelectTree(node1)
+                .callbacks(callbacks).clientRequest(true).build());
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", 
response.getContentHeader());
+
+    Map<String, Object> buildingEntry =
+        new Gson().fromJson(new InputStreamReader((InputStream) 
response.getEntity()), Map.class);
+    // remove d wrapper
+    buildingEntry = (Map<String, Object>) buildingEntry.get("d");
+    assertEquals(2, buildingEntry.size());
+
+    assertTrue(buildingEntry.containsKey("nb_Rooms"));
+    List<Object> roomsFeed = (List<Object>) buildingEntry.get("nb_Rooms");
+    assertNotNull(roomsFeed);
+    assertEquals(0, roomsFeed.size());
+  }
+
   @Test
   public void entryWithExpandedFeedButNoRegisteredCallback() throws Exception {
     final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Buildings");

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducerTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducerTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducerTest.java
index 418dc8a..37d9225 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducerTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducerTest.java
@@ -110,6 +110,39 @@ public class JsonFeedEntityProducerTest extends BaseTest {
         + "\"nt_Employees\":{\"__deferred\":{\"uri\":\"" + BASE_URI + 
"Teams('2')/nt_Employees\"}}}]}}",
         json);
   }
+  
+  @Test
+  public void clientFlagMustNotHaveAnEffect() throws Exception {
+    final EdmEntitySet entitySet = 
MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    Map<String, Object> team1Data = new HashMap<String, Object>();
+    team1Data.put("Id", "1");
+    team1Data.put("isScrumTeam", true);
+    Map<String, Object> team2Data = new HashMap<String, Object>();
+    team2Data.put("Id", "2");
+    team2Data.put("isScrumTeam", false);
+    List<Map<String, Object>> teamsData = new ArrayList<Map<String, Object>>();
+    teamsData.add(team1Data);
+    teamsData.add(team2Data);
+
+    EntityProviderWriteProperties properties =
+        
EntityProviderWriteProperties.fromProperties(DEFAULT_PROPERTIES).clientRequest(true).build();
+    final ODataResponse response = new 
JsonEntityProvider().writeFeed(entitySet, teamsData, properties);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertNull("EntitypProvider must not set content header", 
response.getContentHeader());
+
+    final String json = StringHelper.inputStreamToString((InputStream) 
response.getEntity());
+    assertNotNull(json);
+    assertEquals("{\"d\":{\"results\":[{\"__metadata\":{\"id\":\"" + BASE_URI 
+ "Teams('1')\","
+        + "\"uri\":\"" + BASE_URI + 
"Teams('1')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"1\",\"Name\":null,\"isScrumTeam\":true,"
+        + "\"nt_Employees\":{\"__deferred\":{\"uri\":\"" + BASE_URI + 
"Teams('1')/nt_Employees\"}}},"
+        + "{\"__metadata\":{\"id\":\"" + BASE_URI + "Teams('2')\","
+        + "\"uri\":\"" + BASE_URI + 
"Teams('2')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"2\",\"Name\":null,\"isScrumTeam\":false,"
+        + "\"nt_Employees\":{\"__deferred\":{\"uri\":\"" + BASE_URI + 
"Teams('2')/nt_Employees\"}}}]}}",
+        json);
+  }
 
   @Test
   public void inlineCount() throws Exception {

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/270720a0/odata2-lib/odata-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
 
b/odata2-lib/odata-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
new file mode 100644
index 0000000..68de707
--- /dev/null
+++ 
b/odata2-lib/odata-core/src/test/resources/JsonBuildingWithInlineRoomsClientCase.json
@@ -0,0 +1,35 @@
+{
+       "d" : {
+               "__metadata" : {
+                       "id" : 
"http://localhost:8080/ReferenceScenario.svc/Buildings('1')",
+                       "uri" : 
"http://localhost:8080/ReferenceScenario.svc/Buildings('1')",
+                       "type" : "RefScenario.Building"
+               },
+               "Id" : "1",
+               "Name" : "Building 1",
+               "Image" : null,
+               "nb_Rooms" : [{
+                                       "__metadata" : {
+                                               "id" : 
"http://localhost:8080/ReferenceScenario.svc/Rooms('1')",
+                                               "uri" : 
"http://localhost:8080/ReferenceScenario.svc/Rooms('1')",
+                                               "type" : "RefScenario.Room",
+                                               "etag" : "W/\"1\""
+                                       },
+                                       "Id" : "1",
+                                       "Name" : "Room 1",
+                                       "Seats" : 1,
+                                       "Version" : 1,
+                                       "nr_Employees" : {
+                                               "__deferred" : {
+                                                       "uri" : 
"http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Employees"
+                                               }
+                                       },
+                                       "nr_Building" : {
+                                               "__deferred" : {
+                                                       "uri" : 
"http://localhost:8080/ReferenceScenario.svc/Rooms('1')/nr_Building"
+                                               }
+                                       }
+                               }
+                       ]
+       }
+}

Reply via email to