You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/05/09 14:47:18 UTC

[5/6] [OLINGO-231] Several refactorings

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/cb1ba468/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
new file mode 100644
index 0000000..fbaa71b
--- /dev/null
+++ b/odata2-android/src/test/java/org/apache/olingo/odata2/android/xml/XmlEntityConsumerTest.java
@@ -0,0 +1,2420 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.android.xml;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.edm.*;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
+import org.apache.olingo.odata2.api.ep.callback.ReadEntryResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadFeedResult;
+import org.apache.olingo.odata2.api.ep.callback.ReadResult;
+import org.apache.olingo.odata2.api.ep.entry.EntryMetadata;
+import org.apache.olingo.odata2.api.ep.entry.MediaMetadata;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.FeedMetadata;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.ep.consumer.XmlEntityConsumer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.robolectric.annotation.Config;
+
+import java.io.InputStream;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.*;
+
+/**
+ *  
+ */
+@Config(manifest=Config.NONE)
+public class XmlEntityConsumerTest extends AndroidTestBase {
+
+  private static final Logger LOG = Logger.getLogger(XmlEntityConsumerTest.class.getName());
+  static {
+    LOG.setLevel(Level.OFF);
+  }
+
+  public static final String EMPLOYEE_1_XML =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+          +
+          "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xml:base=\"http://localhost:19000/\"  " +
+          "m:etag=\"W/&quot;1&quot;\">"
+          +
+          "  <id>http://localhost:19000/Employees('1')</id>"
+          +
+          "  <title type=\"text\">Walter Winter</title>"
+          +
+          "  <updated>1999-01-01T00:00:00Z</updated>"
+          +
+          "  <category term=\"RefScenario.Employee\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+          +
+          "  <link href=\"Employees('1')/$value\" rel=\"edit-media\" " +
+          "type=\"application/octet-stream\" m:etag=\"mmEtag\"/>"
+          +
+          "  <link href=\"Employees('1')/ne_Room\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" " +
+          "type=\"application/atom+xml; type=entry\" title=\"ne_Room\"/>"
+          +
+          "  <link href=\"Employees('1')/ne_Manager\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Manager\" " +
+          "type=\"application/atom+xml; type=entry\" title=\"ne_Manager\"/>"
+          +
+          "  <link href=\"Employees('1')/ne_Team\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Team\" " +
+          "type=\"application/atom+xml; type=entry\" title=\"ne_Team\"/>"
+          +
+          "  <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+          "  <m:properties>" +
+          "    <d:EmployeeId>1</d:EmployeeId>" +
+          "    <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+          "    <d:ManagerId>1</d:ManagerId>" +
+          "    <d:RoomId>1</d:RoomId>" +
+          "    <d:TeamId>1</d:TeamId>" +
+          "    <d:Location m:type=\"RefScenario.c_Location\">" +
+          "      <d:Country>Germany</d:Country>" +
+          "      <d:City m:type=\"RefScenario.c_City\">" +
+          "        <d:PostalCode>69124</d:PostalCode>" +
+          "        <d:CityName>Heidelberg</d:CityName>" +
+          "      </d:City>" +
+          "    </d:Location>" +
+          "    <d:Age>52</d:Age>" +
+          "    <d:EntryDate>1999-01-01T00:00:00</d:EntryDate>" +
+          "    <d:ImageUrl>/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png</d:ImageUrl>" +
+          "  </m:properties>" +
+          "</entry>";
+
+  public static final String EMPLOYEE_1_ROOM_XML =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+          +
+          "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xml:base=\"http://localhost:19000/\"  " +
+          "m:etag=\"W/&quot;1&quot;\">"
+          +
+          "  <id>http://localhost:19000/Employees('1')</id>"
+          +
+          "  <title type=\"text\">Walter Winter</title>"
+          +
+          "  <updated>1999-01-01T00:00:00Z</updated>"
+          +
+          "  <category term=\"RefScenario.Employee\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+          +
+          "  <link href=\"Employees('1')/$value\" rel=\"edit-media\" type=\"application/octet-stream\" " +
+          "m:etag=\"mmEtag\"/>"
+          +
+          "  <link href=\"Employees('1')/ne_Room\" "
+          +
+          "       rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" "
+          +
+          "       type=\"application/atom+xml; type=entry\" title=\"ne_Room\">"
+          +
+          "  <m:inline>"
+          +
+          "  <entry m:etag=\"W/1\" xml:base=\"http://some.host.com/service.root/\">"
+          +
+          "  <id>http://some.host.com/service.root/Rooms('1')</id><title " +
+          "type=\"text\">Room 1</title><updated>2013-04-10T10:19:12Z</updated>"
+          +
+          "  <content type=\"application/xml\">" +
+          "    <m:properties>" +
+          "    <d:Id>1</d:Id>" +
+          "    <d:Name>Room 1</d:Name>" +
+          "    <d:Seats>1</d:Seats>" +
+          "    <d:Version>1</d:Version>" +
+          "    </m:properties>" +
+          "    </content>" +
+          "    </entry>" +
+          "  </m:inline>" +
+          " </link>" +
+          "  <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+          "  <m:properties>" +
+          "    <d:EmployeeId>1</d:EmployeeId>" +
+          "    <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+          "  </m:properties>" +
+          "</entry>";
+
+  public static final String EMPLOYEE_1_NULL_ROOM_XML =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+          +
+          "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xml:base=\"http://localhost:19000/\"  " +
+          "m:etag=\"W/&quot;1&quot;\">"
+          +
+          "  <id>http://localhost:19000/Employees('1')</id>"
+          +
+          "  <title type=\"text\">Walter Winter</title>"
+          +
+          "  <updated>1999-01-01T00:00:00Z</updated>"
+          +
+          "  <category term=\"RefScenario.Employee\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Employees('1')\" rel=\"edit\" title=\"Employee\"/>"
+          +
+          "  <link href=\"Employees('1')/$value\" rel=\"edit-media\" type=\"application/octet-stream\" " +
+          "m:etag=\"mmEtag\"/>"
+          +
+          "  <link href=\"Employees('1')/ne_Room\" " +
+          "       rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/ne_Room\" " +
+          "       type=\"application/atom+xml; type=entry\" title=\"ne_Room\">" +
+          "  <m:inline/>" +
+          " </link>" +
+          "  <content type=\"application/octet-stream\" src=\"Employees('1')/$value\"/>" +
+          "  <m:properties>" +
+          "    <d:EmployeeId>1</d:EmployeeId>" +
+          "    <d:EmployeeName>Walter Winter</d:EmployeeName>" +
+          "  </m:properties>" +
+          "</entry>";
+
+  private static final String ROOM_1_XML =
+      "<?xml version='1.0' encoding='UTF-8'?>"
+          +
+          "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+          "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+          +
+          "  <id>http://localhost:19000/test/Rooms('1')</id>"
+          +
+          "  <title type=\"text\">Room 1</title>"
+          +
+          "  <updated>2013-01-11T13:50:50.541+01:00</updated>"
+          +
+          "  <category term=\"RefScenario.Room\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Rooms('1')\" rel=\"edit\" title=\"Room\"/>"
+          +
+          "  <link href=\"Rooms('1')/nr_Employees\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees\" " +
+          "type=\"application/atom+xml; type=feed\" title=\"nr_Employees\"/>"
+          +
+          "  <link href=\"Rooms('1')/nr_Building\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building\" " +
+          "type=\"application/atom+xml; type=entry\" title=\"nr_Building\"/>"
+          +
+          "  <content type=\"application/xml\">" +
+          "    <m:properties>" +
+          "      <d:Id>1</d:Id>" +
+          "    </m:properties>" +
+          "  </content>" +
+          "</entry>";
+
+  private static final String ROOM_1_NULL_EMPLOYEE_XML =
+      "<?xml version='1.0' encoding='UTF-8'?>"
+          +
+          "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+          "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+          +
+          "  <id>http://localhost:19000/test/Rooms('1')</id>"
+          +
+          "  <title type=\"text\">Room 1</title>"
+          +
+          "  <updated>2013-01-11T13:50:50.541+01:00</updated>"
+          +
+          "  <category term=\"RefScenario.Room\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Rooms('1')\" rel=\"edit\" title=\"Room\"/>"
+          +
+          "  <link href=\"Rooms('1')/nr_Employees\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Employees\" "
+          +
+          "        type=\"application/atom+xml; type=feed\" title=\"nr_Employees\">"
+          +
+          " <m:inline/> </link> "
+          +
+          "  <link href=\"Rooms('1')/nr_Building\" " +
+          "rel=\"http://schemas.microsoft.com/ado/2007/08/dataservices/related/nr_Building\" " +
+          "type=\"application/atom+xml; type=entry\" title=\"nr_Building\"/>"
+          +
+          "  <content type=\"application/xml\">" +
+          "    <m:properties>" +
+          "      <d:Id>1</d:Id>" +
+          "    </m:properties>" +
+          "  </content>" +
+          "</entry>";
+
+  private static final String PHOTO_XML =
+      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+          +
+          "<entry m:etag=\"W/&quot;1&quot;\" xml:base=\"http://localhost:19000/test\" "
+          +
+          "xmlns=\"http://www.w3.org/2005/Atom\" "
+          +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" "
+          +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\">"
+          +
+          "  <id>http://localhost:19000/test/Container2.Photos(Id=1,Type='image%2Fpng')</id>"
+          +
+          "  <title type=\"text\">Photo1</title><updated>2013-01-16T12:57:43Z</updated>"
+          +
+          "  <category term=\"RefScenario2.Photo\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')\" rel=\"edit\" title=\"Photo\"/>" +
+          "  <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\" rel=\"edit-media\" type=\"image/png\"/>" +
+          "  <ру:Содержание xmlns:ру=\"http://localhost\">Образ</ру:Содержание>" +
+          "  <content type=\"image/png\" src=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\"/>" +
+          "  <m:properties>" +
+          "    <d:Id>1</d:Id>" +
+          "    <d:Name>Photo1</d:Name>" +
+          "    <d:Type>image/png</d:Type>" +
+          "  </m:properties>" +
+          "</entry>";
+
+  private static final String PHOTO_XML_INVALID_MAPPING =
+      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+          +
+          "<entry m:etag=\"W/&quot;1&quot;\" xml:base=\"http://localhost:19000/test\" "
+          +
+          "xmlns=\"http://www.w3.org/2005/Atom\" "
+          +
+          "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" "
+          +
+          "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\">"
+          +
+          "  <id>http://localhost:19000/test/Container2.Photos(Id=1,Type='image%2Fpng')</id>"
+          +
+          "  <title type=\"text\">Photo1</title><updated>2013-01-16T12:57:43Z</updated>"
+          +
+          "  <category term=\"RefScenario2.Photo\" " +
+          "scheme=\"http://schemas.microsoft.com/ado/2007/08/dataservices/scheme\"/>"
+          +
+          "  <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')\" rel=\"edit\" title=\"Photo\"/>" +
+          "  <link href=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\" rel=\"edit-media\" type=\"image/png\"/>" +
+          "  <ру:Содержание xmlns:ру=\"http://localhost\">Образ</ру:Содержание>" +
+          "  <ig:ignore xmlns:ig=\"http://localhost\">ignore</ig:ignore>" + // 406 Bad Request
+          "  <content type=\"image/png\" src=\"Container2.Photos(Id=1,Type='image%2Fpng')/$value\"/>" +
+          "  <m:properties>" +
+          "    <d:Id>1</d:Id>" +
+          "    <d:Name>Photo1</d:Name>" +
+          "    <d:Type>image/png</d:Type>" +
+          "  </m:properties>" +
+          "</entry>";
+
+  private static class EmployeeCallback implements OnReadInlineContent {
+    List<ODataEntry> employees;
+
+    @Override
+    public void handleReadEntry(final ReadEntryResult context) {
+      handleEntry(context);
+    }
+
+    @Override
+    public void handleReadFeed(final ReadFeedResult context) {
+      handleEntry(context);
+    }
+
+    private void handleEntry(final ReadResult context) {
+      try {
+        String navigationPropertyName = context.getNavigationProperty().getName();
+        if (navigationPropertyName.contains("Employees")) {
+          employees = ((ReadFeedResult) context).getResult().getEntries();
+        } else {
+          throw new RuntimeException("Invalid title");
+        }
+      } catch (EdmException e) {
+        throw new RuntimeException("Invalid title");
+      }
+    }
+
+    @Override
+    public EntityProviderReadProperties receiveReadProperties(final EntityProviderReadProperties readProperties,
+        final EdmNavigationProperty navString) {
+      Map<String, Object> typeMappings = new HashMap<String, Object>();
+      typeMappings.put("EmployeeName", String.class);
+      return EntityProviderReadProperties.initFrom(readProperties).addTypeMappings(typeMappings).build();
+    }
+  }
+
+  private static class DefaultCallback implements OnReadInlineContent {
+    private final Map<String, ReadResult> propName2Context = new HashMap<String, ReadResult>();
+
+    @Override
+    public void handleReadEntry(final ReadEntryResult context) {
+      handle(context);
+    }
+
+    @Override
+    public void handleReadFeed(final ReadFeedResult context) {
+      handle(context);
+    }
+
+    private void handle(final ReadResult context) {
+      try {
+        String navigationPropertyName = context.getNavigationProperty().getName();
+        if (navigationPropertyName != null) {
+          propName2Context.put(navigationPropertyName, context);
+        } else {
+          throw new RuntimeException("Invalid title");
+        }
+      } catch (EdmException e) {
+        throw new RuntimeException("Invalid title");
+      }
+    }
+
+    public Object getObject(final String name) {
+      ReadResult context = propName2Context.get(name);
+      if (context == null) {
+        return null;
+      } else {
+        return context.getResult();
+      }
+    }
+
+    public ODataEntry asEntry(final String name) {
+      return (ODataEntry) getObject(name);
+    }
+
+    public ODataFeed asFeed(final String name) {
+      return (ODataFeed) getObject(name);
+    }
+
+    @Override
+    public EntityProviderReadProperties receiveReadProperties(final EntityProviderReadProperties readProperties,
+        final EdmNavigationProperty navigationProperty) {
+      return readProperties;
+    }
+  }
+
+  @Test
+  public void readDeltaLink() throws Exception {
+    // prepare
+    String content = readFile("feed_with_delta_link.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false).build();
+
+    ODataFeed feed = xec.readFeed(entitySet, reqContent, consumerProperties);
+    assertNotNull(feed);
+
+    FeedMetadata feedMetadata = feed.getFeedMetadata();
+    assertNotNull(feedMetadata);
+
+    String deltaLink = feedMetadata.getDeltaLink();
+    // Null means no deltaLink found
+    assertNotNull(deltaLink);
+
+    assertEquals("http://thisisadeltalink", deltaLink);
+  }
+
+  /** Teams('1')?$expand=nt_Employees */
+  @Test
+  public void readWithInlineContentAndCallback() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    EmployeeCallback defaultCallback = new EmployeeCallback();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false)
+        .callback(defaultCallback)
+        .build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+    //
+    final List<ODataEntry> employees = defaultCallback.employees;
+    assertEquals(3, employees.size());
+    //
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+  }
+
+  @Test
+  public void readWithInlineContentAndCallback_DEFAULT() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    DefaultCallback defaultCallback = new DefaultCallback();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false)
+        .callback(defaultCallback)
+        .build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    assertNull(properties.get("nt_Employees"));
+    //
+    ODataFeed employeesFeed = defaultCallback.asFeed("nt_Employees");
+    List<ODataEntry> employees = employeesFeed.getEntries();
+    assertEquals(3, employees.size());
+    //
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+  }
+
+  @Test
+  public void readInlineBuildingEntry() throws Exception {
+    // prepare
+    String content = readFile("expandedBuilding.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false).build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Room 1", properties.get("Name"));
+    assertEquals((short) 1, properties.get("Seats"));
+    assertEquals((short) 1, properties.get("Version"));
+    //
+    ExpandSelectTreeNode expandTree = entry.getExpandSelectTree();
+    assertNotNull(expandTree);
+
+    ODataEntry inlineBuilding = (ODataEntry) properties.get("nr_Building");
+    Map<String, Object> inlineBuildingProps = inlineBuilding.getProperties();
+    assertEquals("1", inlineBuildingProps.get("Id"));
+    assertEquals("Building 1", inlineBuildingProps.get("Name"));
+    assertNull(inlineBuildingProps.get("Image"));
+    assertNull(inlineBuildingProps.get("nb_Rooms"));
+
+    assertEquals("Rooms('1')/nr_Employees", entry.getMetadata().getAssociationUris("nr_Employees").get(0));
+    assertEquals("Rooms('1')/nr_Building", entry.getMetadata().getAssociationUris("nr_Building").get(0));
+  }
+
+  /** Teams('1')?$expand=nt_Employees */
+  @Test
+  public void readWithInlineContent() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false).build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    //
+    ExpandSelectTreeNode expandTree = entry.getExpandSelectTree();
+    assertNotNull(expandTree);
+    // TODO: do more testing here
+    //
+    ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+    List<ODataEntry> employees = employeesFeed.getEntries();
+    assertEquals(3, employees.size());
+    //
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+  }
+
+  /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+  @Test
+  public void readWithDoubleInlineContent() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init().mergeSemantic(false).build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    //
+    ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+    List<ODataEntry> employees = employeesFeed.getEntries();
+    assertEquals(3, employees.size());
+    //
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+
+    ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+    assertEquals("1", inlinedTeam.getProperties().get("Id"));
+    assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+  }
+
+  /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+  @Test
+  @Ignore("Implementation doesn't support callback AND deep map")
+  public void readWithDoubleInlineContentAndResendCallback() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    DefaultCallback callbackHandler = new DefaultCallback();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false)
+        .callback(callbackHandler).build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    //
+    @SuppressWarnings("unchecked")
+    List<ODataEntry> employees = (List<ODataEntry>) properties.get("nt_Employees");
+    assertEquals(3, employees.size());
+    //
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    @SuppressWarnings("unchecked")
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+
+    ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+    assertEquals("1", inlinedTeam.getProperties().get("Id"));
+    assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+  }
+
+  /** Teams('1')?$expand=nt_Employees,nt_Employees/ne_Team */
+  @SuppressWarnings("unchecked")
+  @Test
+  public void readWithDoubleInlineContentAndCallback() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    DefaultCallback callbackHandler = new DefaultCallback();
+    EntityProviderReadProperties consumerProperties = EntityProviderReadProperties.init()
+        .mergeSemantic(false)
+        .callback(callbackHandler)
+        .build();
+
+    ODataEntry entry = xec.readEntry(entitySet, reqContent, consumerProperties);
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+    // teams has no inlined content set
+    ODataFeed employeesFeed = (ODataFeed) properties.get("nt_Employees");
+    assertNull(employeesFeed);
+
+    // get inlined employees feed from callback
+    employeesFeed = callbackHandler.asFeed("nt_Employees");
+    List<ODataEntry> employees = employeesFeed.getEntries();
+    assertEquals(3, employees.size());
+    ODataEntry employeeNo2 = employees.get(1);
+    Map<String, Object> employessNo2Props = employeeNo2.getProperties();
+    assertEquals("Frederic Fall", employessNo2Props.get("EmployeeName"));
+    assertEquals("2", employessNo2Props.get("RoomId"));
+    assertEquals(32, employessNo2Props.get("Age"));
+    Map<String, Object> emp2Location = (Map<String, Object>) employessNo2Props.get("Location");
+    Map<String, Object> emp2City = (Map<String, Object>) emp2Location.get("City");
+    assertEquals("69190", emp2City.get("PostalCode"));
+    assertEquals("Walldorf", emp2City.get("CityName"));
+
+    // employees has no inlined content set
+    ODataEntry inlinedTeam = (ODataEntry) employessNo2Props.get("ne_Team");
+    assertNull(inlinedTeam);
+    // get inlined team from callback
+    inlinedTeam = callbackHandler.asEntry("ne_Team");
+    assertEquals("1", inlinedTeam.getProperties().get("Id"));
+    assertEquals("Team 1", inlinedTeam.getProperties().get("Name"));
+  }
+
+  @Test
+  public void readWithInlineContentIgnored() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    assertEquals("Team 1", properties.get("Name"));
+    assertEquals(Boolean.FALSE, properties.get("isScrumTeam"));
+  }
+
+  /**
+   * Read an inline Room at an Employee
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void readWithInlineContentEmployeeRoomEntry() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_ROOM_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    ODataEntry room = (ODataEntry) properties.get("ne_Room");
+    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("Seats"));
+    assertEquals(Short.valueOf("1"), roomProperties.get("Version"));
+  }
+
+  /**
+   * Reads an inline Room at an Employee with specially formatted XML (see issue ODATAFORSAP-92).
+   */
+  @Test
+  public void readWithInlineContentEmployeeRoomEntrySpecialXml() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_ROOM_XML, true);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    ODataEntry room = (ODataEntry) properties.get("ne_Room");
+    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("Seats"));
+    assertEquals(Short.valueOf("1"), roomProperties.get("Version"));
+  }
+
+  /**
+   * Reads an employee with inlined but <code>NULL</code> room navigation property
+   * (which has EdmMultiplicity#ONE).
+   */
+  @Test
+  public void readWithInlineContentEmployeeNullRoomEntry() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    ODataEntry room = (ODataEntry) properties.get("ne_Room");
+    assertNull(room);
+  }
+
+  /**
+   * Reads an employee with inlined but <code>NULL</code> room navigation property
+   * (which has EdmMultiplicity#ONE).
+   */
+  @Test
+  public void readWithInlineContentEmployeeNullRoomEntrySpecialXmlFormat() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(EMPLOYEE_1_NULL_ROOM_XML, true);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    ODataEntry room = (ODataEntry) properties.get("ne_Room");
+    assertNull(room);
+  }
+
+  /**
+   * Reads a room with inlined but <code>NULL</code> employees navigation property
+   */
+  @Test
+  public void readWithInlineContentRoomNullEmployeesEntry() throws Exception {
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(ROOM_1_NULL_EMPLOYEE_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry entry =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // validate
+    assertNotNull(entry);
+    Map<String, Object> properties = entry.getProperties();
+    assertEquals("1", properties.get("Id"));
+    ODataEntry room = (ODataEntry) properties.get("ne_Employees");
+    assertNull(room);
+  }
+
+  /**
+   * Teams('1')?$expand=nt_Employees
+   * -> Remove 'feed' start and end tags around expanded/inlined employees
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validateFeedForInlineContent() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml")
+        .replace("<feed xml:base=\"http://some.host.com/service.root/\">", "")
+        .replace("</feed>", "");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    readAndExpectException(entitySet, reqContent,
+        EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+  }
+
+  /**
+   * Teams('1')?$expand=nt_Employees
+   * -> Remove 'type' attribute at expanded/inlined employees link tag
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validateMissingTypeAttributeForInlineContent() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml")
+        .replace("type=\"application/atom+xml;type=feed\"", "");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    readAndExpectException(entitySet, reqContent,
+        EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+  }
+
+  /**
+   * Teams('1')?$expand=nt_Employees
+   * -> Replaced parameter 'type=feed' with 'type=entry' attribute at expanded/inlined employees link tag
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validateWrongTypeAttributeForInlineContent() throws Exception {
+    // prepare
+    String content = readFile("expanded_team.xml")
+        .replace("type=\"application/atom+xml;type=feed\"", "type=\"application/atom+xml;type=entry\"");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_INLINE_CONTENT.addContent("feed"));
+  }
+
+  /**
+   * Teams('1')?$expand=nt_Employees
+   * -> Replaced parameter 'type=feed' with 'type=entry' attribute at expanded/inlined employees link tag
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validateWrongTypeAttributeForInlineContentMany() throws Exception {
+    // prepare
+    String content = readFile("double_expanded_team.xml")
+        .replace("type=\"application/atom+xml;type=entry\"", "type=\"application/atom+xml;type=feed\"");
+    assertNotNull(content);
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    InputStream reqContent = createContentAsStream(content);
+
+    // execute
+    readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_INLINE_CONTENT.addContent("entry"));
+  }
+
+  /**
+   * We only support <code>UTF-8</code> as character encoding.
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validationOfWrongXmlEncodingUtf32() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-32'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING
+        .addContent("UTF-32"));
+  }
+
+  /**
+   * We only support <code>UTF-8</code> as character encoding.
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validationOfWrongXmlEncodingIso8859_1() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='iso-8859-1'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING
+        .addContent("iso-8859-1"));
+  }
+
+  /**
+   * Character encodings are case insensitive.
+   * Hence <code>uTf-8</code> should work as well as <code>UTF-8</code>.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationCaseInsensitiveXmlEncodingUtf8() throws Exception {
+    String room =
+        "<?xml version='1.0' encoding='uTf-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(room);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    assertNotNull(result);
+    assertEquals("1", result.getProperties().get("Id"));
+  }
+
+  /**
+   * For none media resource if <code>properties</code> tag is not within <code>content</code> tag it results in an
+   * exception.
+   * 
+   * OData specification v2: 2.2.6.2.2 Entity Type (as an Atom Entry Element)
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validationOfWrongPropertiesTagPositionForNoneMediaLinkEntry() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\"" +
+            " xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\" />" +
+            "  <m:properties>" +
+            "    <d:Id>1</d:Id>" +
+            "  </m:properties>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_PARENT_TAG.addContent("content")
+        .addContent("properties"));
+  }
+
+  /**
+   * For media resource if <code>properties</code> tag is within <code>content</code> tag it results in an exception.
+   * 
+   * OData specification v2: 2.2.6.2.2 Entity Type (as an Atom Entry Element)
+   * And RFC5023 [section 4.2]
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validationOfWrongPropertiesTagPositionForMediaLinkEntry() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Employees('1')</id>" +
+            "  <title type=\"text\">Walter Winter</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:EmployeeId>1</d:EmployeeId>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.INVALID_PARENT_TAG.addContent("properties")
+        .addContent("content"));
+  }
+
+  @Test
+  public void validationOfNamespacesSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+    assertNotNull(result);
+  }
+
+  @Test
+  public void validationOfNamespaceAtPropertiesSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" xml:base=\"http://localhost:19000/test/\">" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">" +
+            "      <d:Id xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\">1</d:Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+    assertNotNull(result);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void validationOfNamespaceAtTagsMissing() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" xml:base=\"http://localhost:19000/test/\">" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+        .addContent("WstxParsingException"));
+  }
+
+  /**
+   * Use different namespace prefixes for <code>metadata (m)</code> and <code>data (d)</code>.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfDifferentNamespacesPrefixSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:meta=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:data=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    meta:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <meta:properties>" +
+            "      <data:Id>1</data:Id>" +
+            "      <data:Seats>11</data:Seats>" +
+            "      <data:Name>Room 42</data:Name>" +
+            "      <data:Version>4711</data:Version>" +
+            "    </meta:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Add <code>unknown property</code> in own namespace which is defined in entry tag.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfUnknownPropertyOwnNamespaceSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xmlns:more=\"http://sample.com/more\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    m:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "      <more:somePropertyToBeIgnored>ignore me</more:somePropertyToBeIgnored>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Is allowed because <code>Id</code> is in default namespace (<code>xmlns=\"http://www.w3.org/2005/Atom\"</code>)
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfUnknownPropertyDefaultNamespaceSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <Id>1</Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(true).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Add <code>unknown property</code> in own namespace which is defined directly in unknown tag.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfUnknownPropertyInlineNamespaceSuccess() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" "
+            +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" "
+            +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" "
+            +
+            "    xml:base=\"http://localhost:19000/test/\" "
+            +
+            "    m:etag=\"W/&quot;1&quot;\">"
+            +
+            ""
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>"
+            +
+            "  <title type=\"text\">Room 1</title>"
+            +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>"
+            +
+            "  <content type=\"application/xml\">"
+            +
+            "    <m:properties>"
+            +
+            "      <d:Id>1</d:Id>"
+            +
+            "      <more:somePropertyToBeIgnored " +
+            "xmlns:more=\"http://sample.com/more\">ignore me</more:somePropertyToBeIgnored>"
+            +
+            "      <d:Seats>11</d:Seats>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void validationOfNamespacesMissingXmlns() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry etag=\"W/&quot;1&quot;\">" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+        .addContent("WstxParsingException"));
+  }
+
+  /**
+   * Double occurrence of <code>d:Name</code> tag must result in an exception.
+   * 
+   * @throws Exception
+   */
+  @Test(expected = EntityProviderException.class)
+  public void validationOfDuplicatedPropertyException() throws Exception {
+    String room =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    m:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(room);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.DOUBLE_PROPERTY.addContent("Name"));
+  }
+
+  /**
+   * Double occurrence of <code>Name</code> tag within different namespace is allowed.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfDoublePropertyDifferentNamespace() throws Exception {
+    String room =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    m:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <o:Name xmlns:o=\"http://sample.org/own\">Room 42</o:Name>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(room);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Double occurrence of <code>Name</code> tag within ignored/unknown property AND different namespace is allowed.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfDoublePropertyDifferentTagHierachy() throws Exception {
+    String room =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    m:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <SomeProp>" +
+            "        <Name>Room 42</Name>" +
+            "      </SomeProp>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(room);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Double occurrence of <code>d:Name</code> tag within an unknown (and hence ignored) property is allowed.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfDoublePropertyDifferentTagHierachyD_Namespace() throws Exception {
+    String room =
+        "<?xml version='1.0' encoding='UTF-8'?>" +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "    xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "    xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "    xml:base=\"http://localhost:19000/test/\" " +
+            "    m:etag=\"W/&quot;1&quot;\">" +
+            "" +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Id>1</d:Id>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <SomeProp>" +
+            "        <d:Name>Room 42</d:Name>" +
+            "      </SomeProp>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(room);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void validationOfNamespacesMissingM_NamespaceAtProperties() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <properties>" +
+            "      <d:Id>1</d:Id>" +
+            "    </properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    readAndExpectException(entitySet, reqContent, EntityProviderException.EXCEPTION_OCCURRED
+        .addContent("WstxParsingException"));
+  }
+
+  /**
+   * Missing _d_ namespace at key property/tag (_id_) is allowed.
+   * 
+   * @throws Exception
+   */
+  @Test
+  public void validationOfNamespacesMissingD_NamespaceAtKeyPropertyTag() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <Id>1</Id>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <d:Version>4711</d:Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(false).build());
+    assertNotNull(result);
+  }
+
+  /**
+   * Missing _d_ namespace at non-nullable property/tag (_Version_) is allowed.
+   * @throws Exception
+   */
+  public void validationOfNamespacesMissingD_NamespaceAtNonNullableTag() throws Exception {
+    String roomWithValidNamespaces =
+        "<?xml version='1.0' encoding='UTF-8'?>"
+            +
+            "<entry xmlns=\"http://www.w3.org/2005/Atom\" " +
+            "xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" " +
+            "xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" " +
+            "xml:base=\"http://localhost:19000/test/\" m:etag=\"W/&quot;1&quot;\">"
+            +
+            "  <id>http://localhost:19000/test/Rooms('1')</id>" +
+            "  <title type=\"text\">Room 1</title>" +
+            "  <updated>2013-01-11T13:50:50.541+01:00</updated>" +
+            "  <content type=\"application/xml\">" +
+            "    <m:properties>" +
+            "      <d:Seats>11</d:Seats>" +
+            "      <d:Name>Room 42</d:Name>" +
+            "      <Version>4711</Version>" +
+            "    </m:properties>" +
+            "  </content>" +
+            "</entry>";
+
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    final EdmProperty property = (EdmProperty) entitySet.getEntityType().getProperty("Version");
+    EdmFacets facets = property.getFacets();
+    Mockito.when(facets.isNullable()).thenReturn(false);
+
+    InputStream reqContent = createContentAsStream(roomWithValidNamespaces);
+    final ODataEntry result =
+        new XmlEntityConsumer().readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(
+            false).build());
+    assertNotNull(result);
+  }
+
+  private void readAndExpectException(final EdmEntitySet entitySet, final InputStream reqContent,
+      final MessageReference messageReference) throws ODataMessageException {
+    readAndExpectException(entitySet, reqContent, true, messageReference);
+  }
+
+  private void readAndExpectException(final EdmEntitySet entitySet, final InputStream reqContent, final boolean merge,
+      final MessageReference messageReference) throws ODataMessageException {
+    try {
+      XmlEntityConsumer xec = new XmlEntityConsumer();
+      ODataEntry result =
+          xec.readEntry(entitySet, reqContent, EntityProviderReadProperties.init().mergeSemantic(merge).build());
+      assertNotNull(result);
+      Assert.fail("Expected exception with MessageReference '" + messageReference.getKey() + "' was not thrown.");
+    } catch (ODataMessageException e) {
+      assertEquals(messageReference.getKey(), e.getMessageReference().getKey());
+      // assertEquals(messageReference.getContent(), e.getMessageReference().getContent());
+      throw e;
+    }
+  }
+
+  @Test
+  public void readEntryAtomProperties() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // verify
+    EntryMetadata metadata = result.getMetadata();
+    assertEquals("http://localhost:19000/Employees('1')", metadata.getId());
+    assertEquals("W/\"1\"", metadata.getEtag());
+    List<String> associationUris = metadata.getAssociationUris("ne_Room");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Room", associationUris.get(0));
+    associationUris = metadata.getAssociationUris("ne_Manager");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Manager", associationUris.get(0));
+    associationUris = metadata.getAssociationUris("ne_Team");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Team", associationUris.get(0));
+
+    assertEquals(null, metadata.getUri());
+
+    MediaMetadata mm = result.getMediaMetadata();
+    assertEquals("Employees('1')/$value", mm.getSourceLink());
+    assertEquals("mmEtag", mm.getEtag());
+    assertEquals("application/octet-stream", mm.getContentType());
+    assertEquals("Employees('1')/$value", mm.getEditLink());
+
+    Map<String, Object> data = result.getProperties();
+    assertEquals(9, data.size());
+    assertEquals("1", data.get("EmployeeId"));
+    assertEquals("Walter Winter", data.get("EmployeeName"));
+    assertEquals("1", data.get("ManagerId"));
+    assertEquals("1", data.get("RoomId"));
+    assertEquals("1", data.get("TeamId"));
+  }
+
+  @Test
+  public void readEntryLinks() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(true).build());
+
+    // verify
+    List<String> associationUris = result.getMetadata().getAssociationUris("ne_Room");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Room", associationUris.get(0));
+    associationUris = result.getMetadata().getAssociationUris("ne_Manager");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Manager", associationUris.get(0));
+    associationUris = result.getMetadata().getAssociationUris("ne_Team");
+    assertEquals(1, associationUris.size());
+    assertEquals("Employees('1')/ne_Team", associationUris.get(0));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testReadFeed() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    String content = readFile("feed_employees.xml");
+    InputStream contentAsStream = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataFeed feedResult =
+        xec.readFeed(entitySet, contentAsStream, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // verify feed result
+    // metadata
+    FeedMetadata metadata = feedResult.getFeedMetadata();
+    assertNull(metadata.getInlineCount());
+    assertNull(metadata.getNextLink());
+    assertNull(metadata.getDeltaLink());
+    // entries
+    List<ODataEntry> entries = feedResult.getEntries();
+    assertEquals(6, entries.size());
+    // verify first employee
+    ODataEntry firstEmployee = entries.get(0);
+    Map<String, Object> properties = firstEmployee.getProperties();
+    assertEquals(9, properties.size());
+
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    assertEquals("1", properties.get("ManagerId"));
+    assertEquals("1", properties.get("RoomId"));
+    assertEquals("1", properties.get("TeamId"));
+    Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+    assertEquals(2, location.size());
+    assertEquals("Germany", location.get("Country"));
+    Map<String, Object> city = (Map<String, Object>) location.get("City");
+    assertEquals(2, city.size());
+    assertEquals("69124", city.get("PostalCode"));
+    assertEquals("Heidelberg", city.get("CityName"));
+    assertEquals(Integer.valueOf(52), properties.get("Age"));
+    Calendar entryDate = (Calendar) properties.get("EntryDate");
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
+    assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+    assertEquals("Employees('1')/$value", properties.get("ImageUrl"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testReadFeedWithInlineCountAndNextLink() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    String content = readFile("feed_employees_full.xml");
+    InputStream contentAsStream = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataFeed feedResult =
+        xec.readFeed(entitySet, contentAsStream, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // verify feed result
+    // metadata
+    FeedMetadata metadata = feedResult.getFeedMetadata();
+    assertEquals(Integer.valueOf(6), metadata.getInlineCount());
+    assertEquals("http://thisisanextlink", metadata.getNextLink());
+    assertNull(metadata.getDeltaLink());
+    // entries
+    List<ODataEntry> entries = feedResult.getEntries();
+    assertEquals(6, entries.size());
+    // verify first employee
+    ODataEntry firstEmployee = entries.get(0);
+    Map<String, Object> properties = firstEmployee.getProperties();
+    assertEquals(9, properties.size());
+
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    assertEquals("1", properties.get("ManagerId"));
+    assertEquals("1", properties.get("RoomId"));
+    assertEquals("1", properties.get("TeamId"));
+    Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+    assertEquals(2, location.size());
+    assertEquals("Germany", location.get("Country"));
+    Map<String, Object> city = (Map<String, Object>) location.get("City");
+    assertEquals(2, city.size());
+    assertEquals("69124", city.get("PostalCode"));
+    assertEquals("Heidelberg", city.get("CityName"));
+    assertEquals(Integer.valueOf(52), properties.get("Age"));
+    Calendar entryDate = (Calendar) properties.get("EntryDate");
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
+    assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+    assertEquals("Employees('1')/$value", properties.get("ImageUrl"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testReadEntry() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // verify
+    Map<String, Object> properties = result.getProperties();
+    assertEquals(9, properties.size());
+
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    assertEquals("1", properties.get("ManagerId"));
+    assertEquals("1", properties.get("RoomId"));
+    assertEquals("1", properties.get("TeamId"));
+    Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+    assertEquals(2, location.size());
+    assertEquals("Germany", location.get("Country"));
+    Map<String, Object> city = (Map<String, Object>) location.get("City");
+    assertEquals(2, city.size());
+    assertEquals("69124", city.get("PostalCode"));
+    assertEquals("Heidelberg", city.get("CityName"));
+    assertEquals(Integer.valueOf(52), properties.get("Age"));
+    Calendar entryDate = (Calendar) properties.get("EntryDate");
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
+    assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+    assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testReadEntryWithLargeProperty() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    String newName = StringHelper.generateData(81920);
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML.replaceAll("Walter Winter", newName));
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // verify
+    Map<String, Object> properties = result.getProperties();
+    assertEquals(9, properties.size());
+
+    assertEquals("1", properties.get("EmployeeId"));
+    assertEquals(newName, properties.get("EmployeeName"));
+    assertEquals("1", properties.get("ManagerId"));
+    assertEquals("1", properties.get("RoomId"));
+    assertEquals("1", properties.get("TeamId"));
+    Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+    assertEquals(2, location.size());
+    assertEquals("Germany", location.get("Country"));
+    Map<String, Object> city = (Map<String, Object>) location.get("City");
+    assertEquals(2, city.size());
+    assertEquals("69124", city.get("PostalCode"));
+    assertEquals("Heidelberg", city.get("CityName"));
+    assertEquals(Integer.valueOf(52), properties.get("Age"));
+    Calendar entryDate = (Calendar) properties.get("EntryDate");
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
+    assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+    assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+  }
+
+  /**
+   * Missing 'key' properties are allowed for validation against Edm model.
+   * @throws Exception
+   */
+  @Test
+  @SuppressWarnings("unchecked")
+  public void testReadEntryMissingKeyProperty() throws Exception {
+    // prepare
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream contentBody = createContentAsStream(EMPLOYEE_1_XML.replace("<d:EmployeeId>1</d:EmployeeId>", ""));
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(false).build());
+
+    // verify
+    Map<String, Object> properties = result.getProperties();
+    assertEquals(8, properties.size());
+
+    assertNull(properties.get("EmployeeId"));
+    assertEquals("Walter Winter", properties.get("EmployeeName"));
+    assertEquals("1", properties.get("ManagerId"));
+    assertEquals("1", properties.get("RoomId"));
+    assertEquals("1", properties.get("TeamId"));
+    Map<String, Object> location = (Map<String, Object>) properties.get("Location");
+    assertEquals(2, location.size());
+    assertEquals("Germany", location.get("Country"));
+    Map<String, Object> city = (Map<String, Object>) location.get("City");
+    assertEquals(2, city.size());
+    assertEquals("69124", city.get("PostalCode"));
+    assertEquals("Heidelberg", city.get("CityName"));
+    assertEquals(Integer.valueOf(52), properties.get("Age"));
+    Calendar entryDate = (Calendar) properties.get("EntryDate");
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
+    assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
+    assertEquals("/SAP/PUBLIC/BC/NWDEMO_MODEL/IMAGES/Employee_1.png", properties.get("ImageUrl"));
+  }
+
+  @Test
+  public void readEntryNullProperty() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    final String content = EMPLOYEE_1_XML.replace("<d:EntryDate>1999-01-01T00:00:00</d:EntryDate>",
+        "<d:EntryDate m:null='true' />");
+    InputStream contentBody = createContentAsStream(content);
+
+    final ODataEntry result =
+        new XmlEntityConsumer().readEntry(entitySet, contentBody, EntityProviderReadProperties.init().mergeSemantic(
+            true).build());
+
+    final Map<String, Object> properties = result.getProperties();
+    assertEquals(9, properties.size());
+    assertTrue(properties.containsKey("EntryDate"));
+    assertNull(properties.get("EntryDate"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void readEntryTooManyValues() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    String content =
+        EMPLOYEE_1_XML.replace("<d:Age>52</d:Age>",
+            "<d:Age>52</d:Age><d:SomeUnknownTag>SomeUnknownValue</d:SomeUnknownTag>");
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    try {
+      new XmlEntityConsumer().readEntry(entitySet, contentBody, EntityProviderReadProperties.init()
+          .mergeSemantic(false).build());
+    } catch (EntityProviderException e) {
+      // do some assertions...
+      assertEquals(EntityProviderException.INVALID_PROPERTY.getKey(), e.getMessageReference().getKey());
+      assertEquals("SomeUnknownTag", e.getMessageReference().getContent().get(0));
+      // ...and then re-throw
+      throw e;
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testReadEntryWithMerge() throws Exception {
+    // prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    String content = EMPLOYEE_1_XML.replace("<d:Age>52</d:Age>", "");
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    ODataEntry result =
+        xec.readEntry(entitySet, contentBody, EntityProvide

<TRUNCATED>