Repository: olingo-odata2 Updated Branches: refs/heads/OLINGO-850 [created] 270720a07
[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/OLINGO-850 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" + } + } + } + ] + } +}
